// VMM.Timeline.js
/ * * C o d e K i t I m p o r t
* http : //incident57.com/codekit/
=== === === === === === === === === === === === === === === === == * /
// @codekit-prepend "Core/VMM.StoryJS.js";
// @codekit-append "VMM.Timeline.TimeNav.js";
// @codekit-append "VMM.Timeline.DataObj.js";
/ * T i m e l i n e
=== === === === === === === === === === === === === === === === == * /
if ( typeof VMM != 'undefined' && typeof VMM . Timeline == 'undefined' ) {
VMM . Timeline = function ( _timeline _id , w , h ) {
var $timeline ,
$container ,
$feature ,
$feedback ,
$slider ,
$navigation ,
slider ,
timenav ,
version = "2.x" ,
timeline _id = "#timelinejs" ,
events = { } ,
data = { } ,
_dates = [ ] ,
config = { } ,
has _width = false ,
has _height = false ,
ie7 = false ,
is _moving = false ;
if ( type . of ( _timeline _id ) == "string" ) {
if ( _timeline _id . match ( "#" ) ) {
timeline _id = _timeline _id ;
} else {
timeline _id = "#" + _timeline _id ;
}
} else {
timeline _id = "#timelinejs" ;
}
/ * C O N F I G
=== === === === === === === === === === === === === === === === == * /
config = {
embed : false ,
events : {
data _ready : "DATAREADY" ,
messege : "MESSEGE" ,
headline : "HEADLINE" ,
slide _change : "SLIDE_CHANGE" ,
resize : "resize"
} ,
id : timeline _id ,
source : "nothing" ,
type : "timeline" ,
touch : false ,
orientation : "normal" ,
maptype : "" ,
version : "2.x" ,
preload : 4 ,
current _slide : 0 ,
hash _bookmark : false ,
start _at _end : false ,
start _at _slide : 0 ,
start _zoom _adjust : 0 ,
start _page : false ,
api _keys : {
google : "" ,
flickr : "" ,
twitter : ""
} ,
interval : 10 ,
something : 0 ,
width : 960 ,
height : 540 ,
spacing : 15 ,
loaded : {
slider : false ,
timenav : false ,
percentloaded : 0
} ,
nav : {
start _page : false ,
interval _width : 200 ,
density : 4 ,
minor _width : 0 ,
minor _left : 0 ,
constraint : {
left : 0 ,
right : 0 ,
right _min : 0 ,
right _max : 0
} ,
zoom : {
adjust : 0
} ,
multiplier : {
current : 6 ,
min : . 1 ,
max : 50
} ,
rows : [ 1 , 1 , 1 ] ,
width : 960 ,
height : 200 ,
marker : {
width : 150 ,
height : 50
}
} ,
feature : {
width : 960 ,
height : 540
} ,
slider : {
width : 720 ,
height : 400 ,
content : {
width : 720 ,
height : 400 ,
padding : 130 ,
padding _default : 130
} ,
nav : {
width : 100 ,
height : 200
}
} ,
ease : "easeInOutExpo" ,
duration : 1000 ,
gmap _key : "" ,
language : VMM . Language ,
tagSortFunction : function ( arr ) {
arr . sort ( function ( a , b ) {
return a . localeCompare ( b ) ;
} )
}
} ;
if ( w != null && w != "" ) {
config . width = w ;
has _width = true ;
}
if ( h != null && h != "" ) {
config . height = h ;
has _height = true ;
}
if ( window . location . hash ) {
var hash = window . location . hash . substring ( 1 ) ;
if ( ! isNaN ( hash ) ) {
config . current _slide = parseInt ( hash ) ;
}
}
window . onhashchange = function ( ) {
var hash = window . location . hash . substring ( 1 ) ;
if ( config . hash _bookmark ) {
if ( is _moving ) {
goToEvent ( parseInt ( hash ) ) ;
} else {
is _moving = false ;
}
} else {
goToEvent ( parseInt ( hash ) ) ;
}
}
/ * C R E A T E C O N F I G
=== === === === === === === === === === === === === === === === == * /
function createConfig ( conf ) {
// APPLY SUPPLIED CONFIG TO TIMELINE CONFIG
if ( typeof embed _config == 'object' ) {
timeline _config = embed _config ;
}
if ( typeof timeline _config == 'object' ) {
trace ( "HAS TIMELINE CONFIG" ) ;
config = VMM . Util . mergeConfig ( config , timeline _config ) ;
} else if ( typeof conf == 'object' ) {
config = VMM . Util . mergeConfig ( config , conf ) ;
}
if ( VMM . Browser . device == "mobile" || VMM . Browser . device == "tablet" ) {
config . touch = true ;
}
config . nav . width = config . width ;
config . nav . height = 200 ;
config . feature . width = config . width ;
config . feature . height = config . height - config . nav . height ;
config . nav . zoom . adjust = parseInt ( config . start _zoom _adjust , 10 ) ;
VMM . Timeline . Config = config ;
VMM . master _config . Timeline = VMM . Timeline . Config ;
this . events = config . events ;
if ( config . gmap _key != "" ) {
config . api _keys . google = config . gmap _key ;
}
trace ( "VERSION " + config . version ) ;
version = config . version ;
}
/ * C R E A T E T I M E L I N E S T R U C T U R E
=== === === === === === === === === === === === === === === === == * /
function createStructure ( ) {
// CREATE DOM STRUCTURE
$timeline = VMM . getElement ( timeline _id ) ;
VMM . Lib . addClass ( $timeline , "vco-timeline" ) ;
VMM . Lib . addClass ( $timeline , "vco-storyjs" ) ;
$container = VMM . appendAndGetElement ( $timeline , "<div>" , "vco-container vco-main" ) ;
$feature = VMM . appendAndGetElement ( $container , "<div>" , "vco-feature" ) ;
$slider = VMM . appendAndGetElement ( $feature , "<div>" , "vco-slider" ) ;
$navigation = VMM . appendAndGetElement ( $container , "<div>" , "vco-navigation" ) ;
$feedback = VMM . appendAndGetElement ( $timeline , "<div>" , "vco-feedback" , "" ) ;
if ( typeof config . language . right _to _left != 'undefined' ) {
VMM . Lib . addClass ( $timeline , "vco-right-to-left" ) ;
}
slider = new VMM . Slider ( $slider , config ) ;
timenav = new VMM . Timeline . TimeNav ( $navigation ) ;
if ( ! has _width ) {
config . width = VMM . Lib . width ( $timeline ) ;
} else {
VMM . Lib . width ( $timeline , config . width ) ;
}
if ( ! has _height ) {
config . height = VMM . Lib . height ( $timeline ) ;
} else {
VMM . Lib . height ( $timeline , config . height ) ;
}
if ( config . touch ) {
VMM . Lib . addClass ( $timeline , "vco-touch" ) ;
} else {
VMM . Lib . addClass ( $timeline , "vco-notouch" ) ;
}
}
/ * O N E V E N T
=== === === === === === === === === === === === === === === === == * /
function onDataReady ( e , d ) {
trace ( "onDataReady" ) ;
data = d . timeline ;
if ( type . of ( data . era ) != "array" ) {
data . era = [ ] ;
}
buildDates ( ) ;
} ;
function reSize ( ) {
updateSize ( ) ;
slider . setSize ( config . feature . width , config . feature . height ) ;
timenav . setSize ( config . width , config . height ) ;
if ( orientationChange ( ) ) {
setViewport ( ) ;
}
} ;
function onSliderLoaded ( e ) {
config . loaded . slider = true ;
onComponentLoaded ( ) ;
} ;
function onComponentLoaded ( e ) {
config . loaded . percentloaded = config . loaded . percentloaded + 25 ;
if ( config . loaded . slider && config . loaded . timenav ) {
hideMessege ( ) ;
}
}
function onTimeNavLoaded ( e ) {
config . loaded . timenav = true ;
onComponentLoaded ( ) ;
}
function onSlideUpdate ( e ) {
is _moving = true ;
config . current _slide = slider . getCurrentNumber ( ) ;
setHash ( config . current _slide ) ;
timenav . setMarker ( config . current _slide , config . ease , config . duration ) ;
} ;
function onMarkerUpdate ( e ) {
is _moving = true ;
config . current _slide = timenav . getCurrentNumber ( ) ;
setHash ( config . current _slide ) ;
slider . setSlide ( config . current _slide ) ;
} ;
function goToEvent ( n ) {
if ( n <= _dates . length - 1 && n >= 0 ) {
config . current _slide = n ;
slider . setSlide ( config . current _slide ) ;
timenav . setMarker ( config . current _slide , config . ease , config . duration ) ;
}
}
function setHash ( n ) {
if ( config . hash _bookmark ) {
window . location . hash = "#" + n . toString ( ) ;
}
}
function getViewport ( ) {
}
function setViewport ( ) {
var viewport _content = "" ,
viewport _orientation = searchOrientation ( window . orientation ) ;
if ( VMM . Browser . device == "mobile" ) {
if ( viewport _orientation == "portrait" ) {
//viewport_content = "width=device-width; initial-scale=0.75, maximum-scale=0.75";
viewport _content = "width=device-width; initial-scale=0.5, maximum-scale=0.5" ;
} else if ( viewport _orientation == "landscape" ) {
viewport _content = "width=device-width; initial-scale=0.5, maximum-scale=0.5" ;
} else {
viewport _content = "width=device-width, initial-scale=1, maximum-scale=1.0" ;
}
} else if ( VMM . Browser . device == "tablet" ) {
//viewport_content = "width=device-width, initial-scale=1, maximum-scale=1.0";
}
if ( document . getElementById ( "viewport" ) ) {
//VMM.Lib.attr("#viewport", "content", viewport_content);
} else {
//VMM.appendElement("head", "<meta id='viewport' name='viewport' content=" + viewport_content + "/>");
}
}
/ * O R I E N T A T I O N
=== === === === === === === === === === === === === === === === == * /
function searchOrientation ( orientation ) {
var orient = "" ;
if ( orientation == 0 || orientation == 180 ) {
orient = "portrait" ;
} else if ( orientation == 90 || orientation == - 90 ) {
orient = "landscape" ;
} else {
orient = "normal" ;
}
return orient ;
}
function orientationChange ( ) {
var orientation = searchOrientation ( window . orientation ) ;
if ( orientation == config . orientation ) {
return false ;
} else {
config . orientation = orientation ;
return true ;
}
}
/ * P U B L I C F U N C T I O N S
=== === === === === === === === === === === === === === === === == * /
this . init = function ( c , _data ) {
trace ( 'INIT' ) ;
setViewport ( ) ;
createConfig ( c ) ;
createStructure ( ) ;
if ( type . of ( _data ) == "string" ) {
config . source = _data ;
}
// LANGUAGE
VMM . Date . setLanguage ( config . language ) ;
VMM . master _config . language = config . language ;
// EXTERNAL API
VMM . ExternalAPI . setKeys ( config . api _keys ) ;
VMM . ExternalAPI . googlemaps . setMapType ( config . maptype ) ;
// EVENTS
VMM . bindEvent ( global , onDataReady , config . events . data _ready ) ;
VMM . bindEvent ( global , showMessege , config . events . messege ) ;
VMM . fireEvent ( global , config . events . messege , config . language . messages . loading _timeline ) ;
/ * G E T D A T A
=== === === === === === === === === === === === === === === === == * /
if ( VMM . Browser . browser == "Explorer" || VMM . Browser . browser == "MSIE" ) {
if ( parseInt ( VMM . Browser . version , 10 ) <= 7 && ( VMM . Browser . tridentVersion == null || VMM . Browser . tridentVersion < 4 ) ) {
ie7 = true ;
}
}
if ( type . of ( config . source ) == "string" || type . of ( config . source ) == "object" ) {
VMM . Timeline . DataObj . getData ( config . source ) ;
} else {
VMM . fireEvent ( global , config . events . messege , "No data source provided" ) ;
//VMM.Timeline.DataObj.getData(VMM.getElement(timeline_id));
}
} ;
this . iframeLoaded = function ( ) {
trace ( "iframeLoaded" ) ;
} ;
this . reload = function ( _d ) {
trace ( "Load new timeline data" + _d ) ;
VMM . fireEvent ( global , config . events . messege , config . language . messages . loading _timeline ) ;
data = { } ;
VMM . Timeline . DataObj . getData ( _d ) ;
config . current _slide = 0 ;
slider . setSlide ( 0 ) ;
timenav . setMarker ( 0 , config . ease , config . duration ) ;
} ;
/ * D A T A
=== === === === === === === === === === === === === === === === == * /
function getData ( url ) {
VMM . getJSON ( url , function ( d ) {
data = VMM . Timeline . DataObj . getData ( d ) ;
VMM . fireEvent ( global , config . events . data _ready ) ;
} ) ;
} ;
/ * M E S S E G E S
=== === === === === === === === === === === === === === === === == * /
function showMessege ( e , msg , other ) {
trace ( "showMessege " + msg ) ;
//VMM.attachElement($timeline, $feedback);
if ( other ) {
VMM . attachElement ( $feedback , msg ) ;
} else {
VMM . attachElement ( $feedback , VMM . MediaElement . loadingmessage ( msg ) ) ;
}
} ;
function hideMessege ( ) {
VMM . Lib . animate ( $feedback , config . duration , config . ease * 4 , { "opacity" : 0 } , detachMessege ) ;
} ;
function detachMessege ( ) {
VMM . Lib . detach ( $feedback ) ;
}
/ * B U I L D D I S P L A Y
=== === === === === === === === === === === === === === === === == * /
function build ( ) {
// START AT SLIDE
if ( parseInt ( config . start _at _slide ) > 0 && config . current _slide == 0 ) {
config . current _slide = parseInt ( config . start _at _slide ) ;
}
// START AT END
if ( config . start _at _end && config . current _slide == 0 ) {
config . current _slide = _dates . length - 1 ;
}
// IE7
if ( ie7 ) {
ie7 = true ;
VMM . fireEvent ( global , config . events . messege , "Internet Explorer " + VMM . Browser . version + " is not supported by TimelineJS. Please update your browser to version 8 or higher. If you are using a recent version of Internet Explorer you may need to disable compatibility mode in your browser." ) ;
} else {
detachMessege ( ) ;
reSize ( ) ;
// EVENT LISTENERS
VMM . bindEvent ( $slider , onSliderLoaded , "LOADED" ) ;
VMM . bindEvent ( $navigation , onTimeNavLoaded , "LOADED" ) ;
VMM . bindEvent ( $slider , onSlideUpdate , "UPDATE" ) ;
VMM . bindEvent ( $navigation , onMarkerUpdate , "UPDATE" ) ;
// INITIALIZE COMPONENTS
slider . init ( _dates ) ;
timenav . init ( _dates , data . era ) ;
// RESIZE EVENT LISTENERS
VMM . bindEvent ( global , reSize , config . events . resize ) ;
}
} ;
function updateSize ( ) {
trace ( "UPDATE SIZE" ) ;
config . width = VMM . Lib . width ( $timeline ) ;
config . height = VMM . Lib . height ( $timeline ) ;
config . nav . width = config . width ;
config . feature . width = config . width ;
config . feature . height = config . height - config . nav . height - 3 ;
if ( VMM . Browser . device == "mobile" ) {
/ *
if ( VMM . Browser . orientation == "portrait" ) {
config . feature . height = 480 ;
config . height = 480 + config . nav . height ;
} else if ( VMM . Browser . orientation == "landscape" ) {
config . feature . height = 320 ;
config . height = 320 + config . nav . height ;
} else {
config . feature . height = config . height - config . nav . height - 3 ;
}
* /
}
if ( config . width < 641 ) {
VMM . Lib . addClass ( $timeline , "vco-skinny" ) ;
} else {
VMM . Lib . removeClass ( $timeline , "vco-skinny" ) ;
}
} ;
// BUILD DATE OBJECTS
// called from onDataReady, passes to function build
function buildDates ( ) {
_dates = [ ] ;
VMM . fireEvent ( global , config . events . messege , "Building Dates" ) ;
updateSize ( ) ;
for ( var i = 0 ; i < data . date . length ; i ++ ) {
if ( data . date [ i ] . startDate != null && data . date [ i ] . startDate != "" ) {
var _date = { } ,
do _start = VMM . Date . parse ( data . date [ i ] . startDate , true ) ,
do _end ;
_date . startdate = do _start . date ;
_date . precisiondate = do _start . precision ;
if ( isNaN ( _date . startdate ) ) {
trace ( "Failed to parse start date " + data . date [ i ] . startDate ) ;
} else {
// END DATE
if ( data . date [ i ] . endDate != null && data . date [ i ] . endDate != "" ) {
_date . enddate = VMM . Date . parse ( data . date [ i ] . endDate ) ;
} else {
_date . enddate = _date . startdate ;
}
_date . needs _slug = false ;
if ( data . date [ i ] . headline == "" ) {
if ( data . date [ i ] . slug != null && data . date [ i ] . slug != "" ) {
_date . needs _slug = true ;
}
}
_date . title = data . date [ i ] . headline ;
_date . headline = data . date [ i ] . headline ;
_date . type = data . date [ i ] . type ;
_date . date = VMM . Date . prettyDate ( _date . startdate , false , _date . precisiondate ) ;
_date . asset = data . date [ i ] . asset ;
_date . fulldate = _date . startdate . getTime ( ) ;
_date . text = data . date [ i ] . text ;
_date . content = "" ;
_date . tag = data . date [ i ] . tag ;
_date . slug = data . date [ i ] . slug ;
_date . uniqueid = VMM . Util . unique _ID ( 7 ) ;
_date . classname = data . date [ i ] . classname ;
_dates . push ( _date ) ;
}
}
} ;
if ( data . date . length != _dates . length ) {
showMessege ( null , "Error processing data. Check for invalid date formats." )
return ;
}
/ * C U S T O M S O R T
=== === === === === === === === === === === === === === === === == * /
if ( data . type != "storify" ) {
_dates . sort ( function ( a , b ) {
return a . fulldate - b . fulldate
} ) ;
}
/ * C R E A T E S T A R T P A G E I F A V A I L A B L E
=== === === === === === === === === === === === === === === === == * /
if ( data . headline != null && data . headline != "" && data . text != null && data . text != "" ) {
var startpage _date ,
do _start ,
_date = { } ,
td _num = 0 ,
td ;
if ( typeof data . startDate != 'undefined' ) {
do _start = VMM . Date . parse ( data . startDate , true ) ;
startpage _date = do _start . date ;
} else {
startpage _date = false ;
}
trace ( "HAS STARTPAGE" ) ;
trace ( startpage _date ) ;
if ( startpage _date && startpage _date < _dates [ 0 ] . startdate ) {
_date . startdate = new Date ( startpage _date ) ;
} else {
td = _dates [ 0 ] . startdate ;
_date . startdate = new Date ( _dates [ 0 ] . startdate ) ;
if ( td . getMonth ( ) === 0 && td . getDate ( ) == 1 && td . getHours ( ) === 0 && td . getMinutes ( ) === 0 ) {
// trace("YEAR ONLY");
_date . startdate . setFullYear ( td . getFullYear ( ) - 1 ) ;
} else if ( td . getDate ( ) <= 1 && td . getHours ( ) === 0 && td . getMinutes ( ) === 0 ) {
// trace("YEAR MONTH");
_date . startdate . setMonth ( td . getMonth ( ) - 1 ) ;
} else if ( td . getHours ( ) === 0 && td . getMinutes ( ) === 0 ) {
// trace("YEAR MONTH DAY");
_date . startdate . setDate ( td . getDate ( ) - 1 ) ;
} else if ( td . getMinutes ( ) === 0 ) {
// trace("YEAR MONTH DAY HOUR");
_date . startdate . setHours ( td . getHours ( ) - 1 ) ;
} else {
// trace("YEAR MONTH DAY HOUR MINUTE");
_date . startdate . setMinutes ( td . getMinutes ( ) - 1 ) ;
}
}
_date . uniqueid = VMM . Util . unique _ID ( 7 ) ;
_date . enddate = _date . startdate ;
_date . precisiondate = do _start . precision ;
_date . title = data . headline ;
_date . headline = data . headline ;
_date . text = data . text ;
_date . type = "start" ;
_date . date = VMM . Date . prettyDate ( data . startDate , false , _date . precisiondate ) ;
_date . asset = data . asset ;
_date . slug = false ;
_date . needs _slug = false ;
_date . fulldate = _date . startdate . getTime ( ) ;
if ( config . embed ) {
VMM . fireEvent ( global , config . events . headline , _date . headline ) ;
}
_dates . unshift ( _date ) ;
}
/ * C U S T O M S O R T
=== === === === === === === === === === === === === === === === == * /
if ( data . type != "storify" ) {
_dates . sort ( function ( a , b ) {
return a . fulldate - b . fulldate
} ) ;
}
build ( ) ;
}
} ;
VMM . Timeline . Config = { } ;
} ;