Le repo des sources pour le site web des JM2L
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 

10084 строки
303 KiB

  1. /*
  2. TimelineJS - ver. 2015-01-12-18-13-19 - 2015-01-12
  3. Copyright (c) 2012-2013 Northwestern University
  4. a project of the Northwestern University Knight Lab, originally created by Zach Wise
  5. https://github.com/NUKnightLab/TimelineJS
  6. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
  7. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  8. */
  9. /* **********************************************
  10. Begin VMM.js
  11. ********************************************** */
  12. /**
  13. * VéritéCo JS Core
  14. * Designed and built by Zach Wise at VéritéCo zach@verite.co
  15. * This Source Code Form is subject to the terms of the Mozilla Public
  16. * License, v. 2.0. If a copy of the MPL was not distributed with this
  17. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  18. */
  19. /* Simple JavaScript Inheritance
  20. By John Resig http://ejohn.org/
  21. MIT Licensed.
  22. ================================================== */
  23. (function() {
  24. var initializing = false,
  25. fnTest = /xyz/.test(function() {
  26. xyz;
  27. }) ? /\b_super\b/: /.*/;
  28. // The base Class implementation (does nothing)
  29. this.Class = function() {};
  30. // Create a new Class that inherits from this class
  31. Class.extend = function(prop) {
  32. var _super = this.prototype;
  33. // Instantiate a base class (but only create the instance,
  34. // don't run the init constructor)
  35. initializing = true;
  36. var prototype = new this();
  37. initializing = false;
  38. // Copy the properties over onto the new prototype
  39. for (var name in prop) {
  40. // Check if we're overwriting an existing function
  41. prototype[name] = typeof prop[name] == "function" &&
  42. typeof _super[name] == "function" && fnTest.test(prop[name]) ?
  43. (function(name, fn) {
  44. return function() {
  45. var tmp = this._super;
  46. // Add a new ._super() method that is the same method
  47. // but on the super-class
  48. this._super = _super[name];
  49. // The method only need to be bound temporarily, so we
  50. // remove it when we're done executing
  51. var ret = fn.apply(this, arguments);
  52. this._super = tmp;
  53. return ret;
  54. };
  55. })(name, prop[name]) :
  56. prop[name];
  57. }
  58. // The dummy class constructor
  59. function Class() {
  60. // All construction is actually done in the init method
  61. if (!initializing && this.init)
  62. this.init.apply(this, arguments);
  63. }
  64. // Populate our constructed prototype object
  65. Class.prototype = prototype;
  66. // Enforce the constructor to be what we expect
  67. Class.prototype.constructor = Class;
  68. // And make this class extendable
  69. Class.extend = arguments.callee;
  70. return Class;
  71. };
  72. })();
  73. /* Access to the Global Object
  74. access the global object without hard-coding the identifier window
  75. ================================================== */
  76. var global = (function () {
  77. return this || (1,eval)('this');
  78. }());
  79. /* VMM
  80. ================================================== */
  81. if (typeof VMM == 'undefined') {
  82. /* Main Scope Container
  83. ================================================== */
  84. //var VMM = {};
  85. var VMM = Class.extend({});
  86. /* Debug
  87. ================================================== */
  88. VMM.debug = true;
  89. /* Master Config
  90. ================================================== */
  91. VMM.master_config = ({
  92. init: function() {
  93. return this;
  94. },
  95. sizes: {
  96. api: {
  97. width: 0,
  98. height: 0
  99. }
  100. },
  101. vp: "Pellentesque nibh felis, eleifend id, commodo in, interdum vitae, leo",
  102. api_keys_master: {
  103. flickr: "RAIvxHY4hE/Elm5cieh4X5ptMyDpj7MYIxziGxi0WGCcy1s+yr7rKQ==",
  104. //google: "jwNGnYw4hE9lmAez4ll0QD+jo6SKBJFknkopLS4FrSAuGfIwyj57AusuR0s8dAo=",
  105. google: "uQKadH1VMlCsp560gN2aOiMz4evWkl1s34yryl3F/9FJOsn+/948CbBUvKLN46U=",
  106. twitter: ""
  107. },
  108. timers: {
  109. api: 7000
  110. },
  111. api: {
  112. pushques: []
  113. },
  114. twitter: {
  115. active: false,
  116. array: [],
  117. api_loaded: false,
  118. que: []
  119. },
  120. flickr: {
  121. active: false,
  122. array: [],
  123. api_loaded: false,
  124. que: []
  125. },
  126. youtube: {
  127. active: false,
  128. array: [],
  129. api_loaded: false,
  130. que: []
  131. },
  132. vimeo: {
  133. active: false,
  134. array: [],
  135. api_loaded: false,
  136. que: []
  137. },
  138. vine: {
  139. active: false,
  140. array: [],
  141. api_loaded: false,
  142. que: []
  143. },
  144. webthumb: {
  145. active: false,
  146. array: [],
  147. api_loaded: false,
  148. que: []
  149. },
  150. googlemaps: {
  151. active: false,
  152. map_active: false,
  153. places_active: false,
  154. array: [],
  155. api_loaded: false,
  156. que: []
  157. },
  158. googledocs: {
  159. active: false,
  160. array: [],
  161. api_loaded: false,
  162. que: []
  163. },
  164. googleplus: {
  165. active: false,
  166. array: [],
  167. api_loaded: false,
  168. que: []
  169. },
  170. wikipedia: {
  171. active: false,
  172. array: [],
  173. api_loaded: false,
  174. que: [],
  175. tries: 0
  176. },
  177. soundcloud: {
  178. active: false,
  179. array: [],
  180. api_loaded: false,
  181. que: []
  182. }
  183. }).init();
  184. //VMM.createElement(tag, value, cName, attrs, styles);
  185. VMM.createElement = function(tag, value, cName, attrs, styles) {
  186. var ce = "";
  187. if (tag != null && tag != "") {
  188. // TAG
  189. ce += "<" + tag;
  190. if (cName != null && cName != "") {
  191. ce += " class='" + cName + "'";
  192. };
  193. if (attrs != null && attrs != "") {
  194. ce += " " + attrs;
  195. };
  196. if (styles != null && styles != "") {
  197. ce += " style='" + styles + "'";
  198. };
  199. ce += ">";
  200. if (value != null && value != "") {
  201. ce += value;
  202. }
  203. // CLOSE TAG
  204. ce = ce + "</" + tag + ">";
  205. }
  206. return ce;
  207. };
  208. VMM.createMediaElement = function(media, caption, credit) {
  209. var ce = "";
  210. var _valid = false;
  211. ce += "<div class='media'>";
  212. if (media != null && media != "") {
  213. valid = true;
  214. ce += "<img src='" + media + "'>";
  215. // CREDIT
  216. if (credit != null && credit != "") {
  217. ce += VMM.createElement("div", credit, "credit");
  218. }
  219. // CAPTION
  220. if (caption != null && caption != "") {
  221. ce += VMM.createElement("div", caption, "caption");
  222. }
  223. }
  224. ce += "</div>";
  225. return ce;
  226. };
  227. // Hide URL Bar for iOS and Android by Scott Jehl
  228. // https://gist.github.com/1183357
  229. VMM.hideUrlBar = function () {
  230. var win = window,
  231. doc = win.document;
  232. // If there's a hash, or addEventListener is undefined, stop here
  233. if( !location.hash || !win.addEventListener ){
  234. //scroll to 1
  235. window.scrollTo( 0, 1 );
  236. var scrollTop = 1,
  237. //reset to 0 on bodyready, if needed
  238. bodycheck = setInterval(function(){
  239. if( doc.body ){
  240. clearInterval( bodycheck );
  241. scrollTop = "scrollTop" in doc.body ? doc.body.scrollTop : 1;
  242. win.scrollTo( 0, scrollTop === 1 ? 0 : 1 );
  243. }
  244. }, 15 );
  245. win.addEventListener( "load", function(){
  246. setTimeout(function(){
  247. //reset to hide addr bar at onload
  248. win.scrollTo( 0, scrollTop === 1 ? 0 : 1 );
  249. }, 0);
  250. }, false );
  251. }
  252. };
  253. }
  254. /* Trace (console.log)
  255. ================================================== */
  256. function trace( msg ) {
  257. if (VMM.debug) {
  258. if (window.console) {
  259. console.log(msg);
  260. } else if ( typeof( jsTrace ) != 'undefined' ) {
  261. jsTrace.send( msg );
  262. } else {
  263. //alert(msg);
  264. }
  265. }
  266. }
  267. /* Extending Date to include Week
  268. ================================================== */
  269. Date.prototype.getWeek = function() {
  270. var onejan = new Date(this.getFullYear(),0,1);
  271. return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7);
  272. }
  273. /* Extending Date to include Day of Year
  274. ================================================== */
  275. Date.prototype.getDayOfYear = function() {
  276. var onejan = new Date(this.getFullYear(),0,1);
  277. return Math.ceil((this - onejan) / 86400000);
  278. }
  279. /* A MORE SPECIFIC TYPEOF();
  280. // http://rolandog.com/archives/2007/01/18/typeof-a-more-specific-typeof/
  281. ================================================== */
  282. // type.of()
  283. var is={
  284. Null:function(a){return a===null;},
  285. Undefined:function(a){return a===undefined;},
  286. nt:function(a){return(a===null||a===undefined);},
  287. Function:function(a){return(typeof(a)==="function")?a.constructor.toString().match(/Function/)!==null:false;},
  288. String:function(a){return(typeof(a)==="string")?true:(typeof(a)==="object")?a.constructor.toString().match(/string/i)!==null:false;},
  289. Array:function(a){return(typeof(a)==="object")?a.constructor.toString().match(/array/i)!==null||a.length!==undefined:false;},
  290. Boolean:function(a){return(typeof(a)==="boolean")?true:(typeof(a)==="object")?a.constructor.toString().match(/boolean/i)!==null:false;},
  291. Date:function(a){return(typeof(a)==="date")?true:(typeof(a)==="object")?a.constructor.toString().match(/date/i)!==null:false;},
  292. HTML:function(a){return(typeof(a)==="object")?a.constructor.toString().match(/html/i)!==null:false;},
  293. Number:function(a){return(typeof(a)==="number")?true:(typeof(a)==="object")?a.constructor.toString().match(/Number/)!==null:false;},
  294. Object:function(a){return(typeof(a)==="object")?a.constructor.toString().match(/object/i)!==null:false;},
  295. RegExp:function(a){return(typeof(a)==="function")?a.constructor.toString().match(/regexp/i)!==null:false;}
  296. };
  297. var type={
  298. of:function(a){
  299. for(var i in is){
  300. if(is[i](a)){
  301. return i.toLowerCase();
  302. }
  303. }
  304. }
  305. };
  306. /* **********************************************
  307. Begin VMM.Library.js
  308. ********************************************** */
  309. /* * LIBRARY ABSTRACTION
  310. ================================================== */
  311. if(typeof VMM != 'undefined') {
  312. VMM.smoothScrollTo = function(elem, duration, ease) {
  313. if( typeof( jQuery ) != 'undefined' ){
  314. var _ease = "easein",
  315. _duration = 1000;
  316. if (duration != null) {
  317. if (duration < 1) {
  318. _duration = 1;
  319. } else {
  320. _duration = Math.round(duration);
  321. }
  322. }
  323. if (ease != null && ease != "") {
  324. _ease = ease;
  325. }
  326. if (jQuery(window).scrollTop() != VMM.Lib.offset(elem).top) {
  327. VMM.Lib.animate('html,body', _duration, _ease, {scrollTop: VMM.Lib.offset(elem).top})
  328. }
  329. }
  330. };
  331. VMM.attachElement = function(element, content) {
  332. if( typeof( jQuery ) != 'undefined' ){
  333. jQuery(element).html(content);
  334. }
  335. };
  336. VMM.appendElement = function(element, content) {
  337. if( typeof( jQuery ) != 'undefined' ){
  338. jQuery(element).append(content);
  339. }
  340. };
  341. VMM.getHTML = function(element) {
  342. var e;
  343. if( typeof( jQuery ) != 'undefined' ){
  344. e = jQuery(element).html();
  345. return e;
  346. }
  347. };
  348. VMM.getElement = function(element, p) {
  349. var e;
  350. if( typeof( jQuery ) != 'undefined' ){
  351. if (p) {
  352. e = jQuery(element).parent().get(0);
  353. } else {
  354. e = jQuery(element).get(0);
  355. }
  356. return e;
  357. }
  358. };
  359. VMM.bindEvent = function(element, the_handler, the_event_type, event_data) {
  360. var e;
  361. var _event_type = "click";
  362. var _event_data = {};
  363. if (the_event_type != null && the_event_type != "") {
  364. _event_type = the_event_type;
  365. }
  366. if (_event_data != null && _event_data != "") {
  367. _event_data = event_data;
  368. }
  369. if( typeof( jQuery ) != 'undefined' ){
  370. jQuery(element).bind(_event_type, _event_data, the_handler);
  371. //return e;
  372. }
  373. };
  374. VMM.unbindEvent = function(element, the_handler, the_event_type) {
  375. var e;
  376. var _event_type = "click";
  377. var _event_data = {};
  378. if (the_event_type != null && the_event_type != "") {
  379. _event_type = the_event_type;
  380. }
  381. if( typeof( jQuery ) != 'undefined' ){
  382. jQuery(element).unbind(_event_type, the_handler);
  383. //return e;
  384. }
  385. };
  386. VMM.fireEvent = function(element, the_event_type, the_data) {
  387. var e;
  388. var _event_type = "click";
  389. var _data = [];
  390. if (the_event_type != null && the_event_type != "") {
  391. _event_type = the_event_type;
  392. }
  393. if (the_data != null && the_data != "") {
  394. _data = the_data;
  395. }
  396. if( typeof( jQuery ) != 'undefined' ){
  397. jQuery(element).trigger(_event_type, _data);
  398. //return e;
  399. }
  400. };
  401. VMM.getJSON = function(url, data, callback) {
  402. if( typeof( jQuery ) != 'undefined' ){
  403. jQuery.ajaxSetup({
  404. timeout: 3000
  405. });
  406. /* CHECK FOR IE
  407. ================================================== */
  408. if ( VMM.Browser.browser == "Explorer" &&
  409. parseInt(VMM.Browser.version, 10) >= 7 &&
  410. window.XDomainRequest &&
  411. url.match('^https?://')) {
  412. trace("old IE JSON doesn't like retrieving from different protocol");
  413. var colon = url.indexOf(':');
  414. url = url.substr(colon+1);
  415. }
  416. return jQuery.getJSON(url, data, callback);
  417. }
  418. }
  419. VMM.parseJSON = function(the_json) {
  420. if( typeof( jQuery ) != 'undefined' ){
  421. return jQuery.parseJSON(the_json);
  422. }
  423. }
  424. // ADD ELEMENT AND RETURN IT
  425. VMM.appendAndGetElement = function(append_to_element, tag, cName, content) {
  426. var e,
  427. _tag = "<div>",
  428. _class = "",
  429. _content = "",
  430. _id = "";
  431. if (tag != null && tag != "") {
  432. _tag = tag;
  433. }
  434. if (cName != null && cName != "") {
  435. _class = cName;
  436. }
  437. if (content != null && content != "") {
  438. _content = content;
  439. }
  440. if( typeof( jQuery ) != 'undefined' ){
  441. e = jQuery(tag);
  442. e.addClass(_class);
  443. e.html(_content);
  444. jQuery(append_to_element).append(e);
  445. }
  446. return e;
  447. };
  448. VMM.Lib = {
  449. init: function() {
  450. return this;
  451. },
  452. hide: function(element, duration) {
  453. if (duration != null && duration != "") {
  454. if( typeof( jQuery ) != 'undefined' ){
  455. jQuery(element).hide(duration);
  456. }
  457. } else {
  458. if( typeof( jQuery ) != 'undefined' ){
  459. jQuery(element).hide();
  460. }
  461. }
  462. },
  463. remove: function(element) {
  464. if( typeof( jQuery ) != 'undefined' ){
  465. jQuery(element).remove();
  466. }
  467. },
  468. detach: function(element) {
  469. if( typeof( jQuery ) != 'undefined' ){
  470. jQuery(element).detach();
  471. }
  472. },
  473. append: function(element, value) {
  474. if( typeof( jQuery ) != 'undefined' ){
  475. jQuery(element).append(value);
  476. }
  477. },
  478. prepend: function(element, value) {
  479. if( typeof( jQuery ) != 'undefined' ){
  480. jQuery(element).prepend(value);
  481. }
  482. },
  483. show: function(element, duration) {
  484. if (duration != null && duration != "") {
  485. if( typeof( jQuery ) != 'undefined' ){
  486. jQuery(element).show(duration);
  487. }
  488. } else {
  489. if( typeof( jQuery ) != 'undefined' ){
  490. jQuery(element).show();
  491. }
  492. }
  493. },
  494. load: function(element, callback_function, event_data) {
  495. var _event_data = {elem:element}; // return element by default
  496. if (_event_data != null && _event_data != "") {
  497. _event_data = event_data;
  498. }
  499. if( typeof( jQuery ) != 'undefined' ){
  500. jQuery(element).load(_event_data, callback_function);
  501. }
  502. },
  503. addClass: function(element, cName) {
  504. if( typeof( jQuery ) != 'undefined' ){
  505. jQuery(element).addClass(cName);
  506. }
  507. },
  508. removeClass: function(element, cName) {
  509. if( typeof( jQuery ) != 'undefined' ){
  510. jQuery(element).removeClass(cName);
  511. }
  512. },
  513. attr: function(element, aName, value) {
  514. if (value != null && value != "") {
  515. if( typeof( jQuery ) != 'undefined' ){
  516. jQuery(element).attr(aName, value);
  517. }
  518. } else {
  519. if( typeof( jQuery ) != 'undefined' ){
  520. return jQuery(element).attr(aName);
  521. }
  522. }
  523. },
  524. prop: function(element, aName, value) {
  525. if (typeof jQuery == 'undefined' || !/[1-9]\.[3-9].[1-9]/.test(jQuery.fn.jquery)) {
  526. VMM.Lib.attribute(element, aName, value);
  527. } else {
  528. jQuery(element).prop(aName, value);
  529. }
  530. },
  531. attribute: function(element, aName, value) {
  532. if (value != null && value != "") {
  533. if( typeof( jQuery ) != 'undefined' ){
  534. jQuery(element).attr(aName, value);
  535. }
  536. } else {
  537. if( typeof( jQuery ) != 'undefined' ){
  538. return jQuery(element).attr(aName);
  539. }
  540. }
  541. },
  542. visible: function(element, show) {
  543. if (show != null) {
  544. if( typeof( jQuery ) != 'undefined' ){
  545. if (show) {
  546. jQuery(element).show(0);
  547. } else {
  548. jQuery(element).hide(0);
  549. }
  550. }
  551. } else {
  552. if( typeof( jQuery ) != 'undefined' ){
  553. if ( jQuery(element).is(':visible')){
  554. return true;
  555. } else {
  556. return false;
  557. }
  558. }
  559. }
  560. },
  561. css: function(element, prop, value) {
  562. if (value != null && value != "") {
  563. if( typeof( jQuery ) != 'undefined' ){
  564. jQuery(element).css(prop, value);
  565. }
  566. } else {
  567. if( typeof( jQuery ) != 'undefined' ){
  568. return jQuery(element).css(prop);
  569. }
  570. }
  571. },
  572. cssmultiple: function(element, propval) {
  573. if( typeof( jQuery ) != 'undefined' ){
  574. return jQuery(element).css(propval);
  575. }
  576. },
  577. offset: function(element) {
  578. var p;
  579. if( typeof( jQuery ) != 'undefined' ){
  580. p = jQuery(element).offset();
  581. }
  582. return p;
  583. },
  584. position: function(element) {
  585. var p;
  586. if( typeof( jQuery ) != 'undefined' ){
  587. p = jQuery(element).position();
  588. }
  589. return p;
  590. },
  591. width: function(element, s) {
  592. if (s != null && s != "") {
  593. if( typeof( jQuery ) != 'undefined' ){
  594. jQuery(element).width(s);
  595. }
  596. } else {
  597. if( typeof( jQuery ) != 'undefined' ){
  598. return jQuery(element).width();
  599. }
  600. }
  601. },
  602. height: function(element, s) {
  603. if (s != null && s != "") {
  604. if( typeof( jQuery ) != 'undefined' ){
  605. jQuery(element).height(s);
  606. }
  607. } else {
  608. if( typeof( jQuery ) != 'undefined' ){
  609. return jQuery(element).height();
  610. }
  611. }
  612. },
  613. toggleClass: function(element, cName) {
  614. if( typeof( jQuery ) != 'undefined' ){
  615. jQuery(element).toggleClass(cName);
  616. }
  617. },
  618. each:function(element, return_function) {
  619. if( typeof( jQuery ) != 'undefined' ){
  620. jQuery(element).each(return_function);
  621. }
  622. },
  623. html: function(element, str) {
  624. var e;
  625. if( typeof( jQuery ) != 'undefined' ){
  626. e = jQuery(element).html();
  627. return e;
  628. }
  629. if (str != null && str != "") {
  630. if( typeof( jQuery ) != 'undefined' ){
  631. jQuery(element).html(str);
  632. }
  633. } else {
  634. var e;
  635. if( typeof( jQuery ) != 'undefined' ){
  636. e = jQuery(element).html();
  637. return e;
  638. }
  639. }
  640. },
  641. find: function(element, selec) {
  642. if( typeof( jQuery ) != 'undefined' ){
  643. return jQuery(element).find(selec);
  644. }
  645. },
  646. stop: function(element) {
  647. if( typeof( jQuery ) != 'undefined' ){
  648. jQuery(element).stop();
  649. }
  650. },
  651. delay_animate: function(delay, element, duration, ease, att, callback_function) {
  652. if (VMM.Browser.device == "mobile" || VMM.Browser.device == "tablet") {
  653. var _tdd = Math.round((duration/1500)*10)/10,
  654. __duration = _tdd + 's';
  655. VMM.Lib.css(element, '-webkit-transition', 'all '+ __duration + ' ease');
  656. VMM.Lib.css(element, '-moz-transition', 'all '+ __duration + ' ease');
  657. VMM.Lib.css(element, '-o-transition', 'all '+ __duration + ' ease');
  658. VMM.Lib.css(element, '-ms-transition', 'all '+ __duration + ' ease');
  659. VMM.Lib.css(element, 'transition', 'all '+ __duration + ' ease');
  660. VMM.Lib.cssmultiple(element, _att);
  661. } else {
  662. if( typeof( jQuery ) != 'undefined' ){
  663. jQuery(element).delay(delay).animate(att, {duration:duration, easing:ease} );
  664. }
  665. }
  666. },
  667. animate: function(element, duration, ease, att, que, callback_function) {
  668. var _ease = "easein",
  669. _que = false,
  670. _duration = 1000,
  671. _att = {};
  672. if (duration != null) {
  673. if (duration < 1) {
  674. _duration = 1;
  675. } else {
  676. _duration = Math.round(duration);
  677. }
  678. }
  679. if (ease != null && ease != "") {
  680. _ease = ease;
  681. }
  682. if (que != null && que != "") {
  683. _que = que;
  684. }
  685. if (att != null) {
  686. _att = att
  687. } else {
  688. _att = {opacity: 0}
  689. }
  690. if (VMM.Browser.device == "mobile" || VMM.Browser.device == "tablet") {
  691. var _tdd = Math.round((_duration/1500)*10)/10,
  692. __duration = _tdd + 's';
  693. _ease = " cubic-bezier(0.33, 0.66, 0.66, 1)";
  694. //_ease = " ease-in-out";
  695. for (x in _att) {
  696. if (Object.prototype.hasOwnProperty.call(_att, x)) {
  697. trace(x + " to " + _att[x]);
  698. VMM.Lib.css(element, '-webkit-transition', x + ' ' + __duration + _ease);
  699. VMM.Lib.css(element, '-moz-transition', x + ' ' + __duration + _ease);
  700. VMM.Lib.css(element, '-o-transition', x + ' ' + __duration + _ease);
  701. VMM.Lib.css(element, '-ms-transition', x + ' ' + __duration + _ease);
  702. VMM.Lib.css(element, 'transition', x + ' ' + __duration + _ease);
  703. }
  704. }
  705. VMM.Lib.cssmultiple(element, _att);
  706. } else {
  707. if( typeof( jQuery ) != 'undefined' ){
  708. if (callback_function != null && callback_function != "") {
  709. jQuery(element).animate(_att, {queue:_que, duration:_duration, easing:_ease, complete:callback_function} );
  710. } else {
  711. jQuery(element).animate(_att, {queue:_que, duration:_duration, easing:_ease} );
  712. }
  713. }
  714. }
  715. }
  716. }
  717. }
  718. if( typeof( jQuery ) != 'undefined' ){
  719. /* XDR AJAX EXTENTION FOR jQuery
  720. https://github.com/jaubourg/ajaxHooks/blob/master/src/ajax/xdr.js
  721. ================================================== */
  722. (function( jQuery ) {
  723. if ( window.XDomainRequest ) {
  724. jQuery.ajaxTransport(function( s ) {
  725. if ( s.crossDomain && s.async ) {
  726. if ( s.timeout ) {
  727. s.xdrTimeout = s.timeout;
  728. delete s.timeout;
  729. }
  730. var xdr;
  731. return {
  732. send: function( _, complete ) {
  733. function callback( status, statusText, responses, responseHeaders ) {
  734. xdr.onload = xdr.onerror = xdr.ontimeout = jQuery.noop;
  735. xdr = undefined;
  736. complete( status, statusText, responses, responseHeaders );
  737. }
  738. xdr = new XDomainRequest();
  739. xdr.open( s.type, s.url );
  740. xdr.onload = function() {
  741. callback( 200, "OK", { text: xdr.responseText }, "Content-Type: " + xdr.contentType );
  742. };
  743. xdr.onerror = function() {
  744. callback( 404, "Not Found" );
  745. };
  746. if ( s.xdrTimeout ) {
  747. xdr.ontimeout = function() {
  748. callback( 0, "timeout" );
  749. };
  750. xdr.timeout = s.xdrTimeout;
  751. }
  752. xdr.send( ( s.hasContent && s.data ) || null );
  753. },
  754. abort: function() {
  755. if ( xdr ) {
  756. xdr.onerror = jQuery.noop();
  757. xdr.abort();
  758. }
  759. }
  760. };
  761. }
  762. });
  763. }
  764. })( jQuery );
  765. /* jQuery Easing v1.3
  766. http://gsgd.co.uk/sandbox/jquery/easing/
  767. ================================================== */
  768. jQuery.easing['jswing'] = jQuery.easing['swing'];
  769. jQuery.extend( jQuery.easing, {
  770. def: 'easeOutQuad',
  771. swing: function (x, t, b, c, d) {
  772. //alert(jQuery.easing.default);
  773. return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
  774. },
  775. easeInExpo: function (x, t, b, c, d) {
  776. return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
  777. },
  778. easeOutExpo: function (x, t, b, c, d) {
  779. return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
  780. },
  781. easeInOutExpo: function (x, t, b, c, d) {
  782. if (t==0) return b;
  783. if (t==d) return b+c;
  784. if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
  785. return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
  786. },
  787. easeInQuad: function (x, t, b, c, d) {
  788. return c*(t/=d)*t + b;
  789. },
  790. easeOutQuad: function (x, t, b, c, d) {
  791. return -c *(t/=d)*(t-2) + b;
  792. },
  793. easeInOutQuad: function (x, t, b, c, d) {
  794. if ((t/=d/2) < 1) return c/2*t*t + b;
  795. return -c/2 * ((--t)*(t-2) - 1) + b;
  796. }
  797. });
  798. }
  799. /* **********************************************
  800. Begin VMM.Browser.js
  801. ********************************************** */
  802. /* * DEVICE AND BROWSER DETECTION
  803. ================================================== */
  804. if(typeof VMM != 'undefined' && typeof VMM.Browser == 'undefined') {
  805. VMM.Browser = {
  806. init: function () {
  807. this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
  808. this.version = this.searchVersion(navigator.userAgent)
  809. || this.searchVersion(navigator.appVersion)
  810. || "an unknown version";
  811. this.tridentVersion = this.searchTridentVersion(navigator.userAgent);
  812. this.OS = this.searchString(this.dataOS) || "an unknown OS";
  813. this.device = this.searchDevice(navigator.userAgent);
  814. this.orientation = this.searchOrientation(window.orientation);
  815. },
  816. searchOrientation: function(orientation) {
  817. var orient = "";
  818. if ( orientation == 0 || orientation == 180) {
  819. orient = "portrait";
  820. } else if ( orientation == 90 || orientation == -90) {
  821. orient = "landscape";
  822. } else {
  823. orient = "normal";
  824. }
  825. return orient;
  826. },
  827. searchDevice: function(d) {
  828. var device = "";
  829. if (d.match(/Android/i) || d.match(/iPhone|iPod/i)) {
  830. device = "mobile";
  831. } else if (d.match(/iPad/i)) {
  832. device = "tablet";
  833. } else if (d.match(/BlackBerry/i) || d.match(/IEMobile/i)) {
  834. device = "other mobile";
  835. } else {
  836. device = "desktop";
  837. }
  838. return device;
  839. },
  840. searchString: function (data) {
  841. for (var i=0;i<data.length;i++) {
  842. var dataString = data[i].string,
  843. dataProp = data[i].prop;
  844. this.versionSearchString = data[i].versionSearch || data[i].identity;
  845. if (dataString) {
  846. if (dataString.indexOf(data[i].subString) != -1) {
  847. return data[i].identity;
  848. }
  849. } else if (dataProp) {
  850. return data[i].identity;
  851. }
  852. }
  853. },
  854. searchVersion: function (dataString) {
  855. var index = dataString.indexOf(this.versionSearchString);
  856. if (index == -1) return;
  857. return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
  858. },
  859. searchTridentVersion: function (dataString) {
  860. var index = dataString.indexOf("Trident/");
  861. if (index == -1) return 0;
  862. return parseFloat(dataString.substring(index + 8));
  863. },
  864. dataBrowser: [
  865. {
  866. string: navigator.userAgent,
  867. subString: "Chrome",
  868. identity: "Chrome"
  869. },
  870. { string: navigator.userAgent,
  871. subString: "OmniWeb",
  872. versionSearch: "OmniWeb/",
  873. identity: "OmniWeb"
  874. },
  875. {
  876. string: navigator.vendor,
  877. subString: "Apple",
  878. identity: "Safari",
  879. versionSearch: "Version"
  880. },
  881. {
  882. prop: window.opera,
  883. identity: "Opera",
  884. versionSearch: "Version"
  885. },
  886. {
  887. string: navigator.vendor,
  888. subString: "iCab",
  889. identity: "iCab"
  890. },
  891. {
  892. string: navigator.vendor,
  893. subString: "KDE",
  894. identity: "Konqueror"
  895. },
  896. {
  897. string: navigator.userAgent,
  898. subString: "Firefox",
  899. identity: "Firefox"
  900. },
  901. {
  902. string: navigator.vendor,
  903. subString: "Camino",
  904. identity: "Camino"
  905. },
  906. { // for newer Netscapes (6+)
  907. string: navigator.userAgent,
  908. subString: "Netscape",
  909. identity: "Netscape"
  910. },
  911. {
  912. string: navigator.userAgent,
  913. subString: "MSIE",
  914. identity: "Explorer",
  915. versionSearch: "MSIE"
  916. },
  917. {
  918. string: navigator.userAgent,
  919. subString: "Gecko",
  920. identity: "Mozilla",
  921. versionSearch: "rv"
  922. },
  923. { // for older Netscapes (4-)
  924. string: navigator.userAgent,
  925. subString: "Mozilla",
  926. identity: "Netscape",
  927. versionSearch: "Mozilla"
  928. }
  929. ],
  930. dataOS : [
  931. {
  932. string: navigator.platform,
  933. subString: "Win",
  934. identity: "Windows"
  935. },
  936. {
  937. string: navigator.platform,
  938. subString: "Mac",
  939. identity: "Mac"
  940. },
  941. {
  942. string: navigator.userAgent,
  943. subString: "iPhone",
  944. identity: "iPhone/iPod"
  945. },
  946. {
  947. string: navigator.userAgent,
  948. subString: "iPad",
  949. identity: "iPad"
  950. },
  951. {
  952. string: navigator.platform,
  953. subString: "Linux",
  954. identity: "Linux"
  955. }
  956. ]
  957. }
  958. VMM.Browser.init();
  959. }
  960. /* **********************************************
  961. Begin VMM.FileExtention.js
  962. ********************************************** */
  963. /* * File Extention
  964. ================================================== */
  965. if(typeof VMM != 'undefined' && typeof VMM.FileExtention == 'undefined') {
  966. VMM.FileExtention = {
  967. googleDocType: function(url) {
  968. var fileName = url.replace(/\s\s*$/, ''),
  969. fileExtension = "",
  970. validFileExtensions = ["DOC","DOCX","XLS","XLSX","PPT","PPTX","PDF","PAGES","AI","PSD","TIFF","DXF","SVG","EPS","PS","TTF","XPS","ZIP","RAR"],
  971. flag = false;
  972. fileExtension = fileName.substr(fileName.length - 5, 5);
  973. for (var i = 0; i < validFileExtensions.length; i++) {
  974. if (fileExtension.toLowerCase().match(validFileExtensions[i].toString().toLowerCase()) || fileName.match("docs.google.com") ) {
  975. flag = true;
  976. }
  977. }
  978. return flag;
  979. }
  980. }
  981. }
  982. /* **********************************************
  983. Begin VMM.Date.js
  984. ********************************************** */
  985. /* * Utilities and Useful Functions
  986. ================================================== */
  987. if(typeof VMM != 'undefined' && typeof VMM.Date == 'undefined') {
  988. VMM.Date = ({
  989. init: function() {
  990. return this;
  991. },
  992. dateformats: {
  993. year: "yyyy",
  994. month_short: "mmm",
  995. month: "mmmm yyyy",
  996. full_short: "mmm d",
  997. full: "mmmm d',' yyyy",
  998. time_short: "h:MM:ss TT",
  999. time_no_seconds_short: "h:MM TT",
  1000. time_no_seconds_small_date: "h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",
  1001. full_long: "mmm d',' yyyy 'at' hh:MM TT",
  1002. full_long_small_date: "hh:MM TT'<br/><small>mmm d',' yyyy'</small>'"
  1003. },
  1004. month: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  1005. month_abbr: ["Jan.", "Feb.", "March", "April", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec."],
  1006. day: ["Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
  1007. day_abbr: ["Sun.", "Mon.", "Tues.", "Wed.", "Thurs.", "Fri.", "Sat."],
  1008. hour: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
  1009. hour_suffix: ["am"],
  1010. //B.C.
  1011. bc_format: {
  1012. year: "yyyy",
  1013. month_short: "mmm",
  1014. month: "mmmm yyyy",
  1015. full_short: "mmm d",
  1016. full: "mmmm d',' yyyy",
  1017. time_no_seconds_short: "h:MM TT",
  1018. time_no_seconds_small_date: "dddd', 'h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",
  1019. full_long: "dddd',' mmm d',' yyyy 'at' hh:MM TT",
  1020. full_long_small_date: "hh:MM TT'<br/><small>'dddd',' mmm d',' yyyy'</small>'"
  1021. },
  1022. setLanguage: function(lang) {
  1023. trace("SET DATE LANGUAGE");
  1024. VMM.Date.dateformats = lang.dateformats;
  1025. VMM.Date.month = lang.date.month;
  1026. VMM.Date.month_abbr = lang.date.month_abbr;
  1027. VMM.Date.day = lang.date.day;
  1028. VMM.Date.day_abbr = lang.date.day_abbr;
  1029. dateFormat.i18n.dayNames = lang.date.day_abbr.concat(lang.date.day);
  1030. dateFormat.i18n.monthNames = lang.date.month_abbr.concat(lang.date.month);
  1031. },
  1032. parse: function(d, precision) {
  1033. "use strict";
  1034. var date,
  1035. date_array,
  1036. time_array,
  1037. time_parse,
  1038. p = {
  1039. year: false,
  1040. month: false,
  1041. day: false,
  1042. hour: false,
  1043. minute: false,
  1044. second: false,
  1045. millisecond: false
  1046. };
  1047. if (type.of(d) == "date") {
  1048. trace("DEBUG THIS, ITs A DATE");
  1049. date = d;
  1050. } else {
  1051. date = new Date(0);
  1052. date.setMonth(0); date.setDate(1); date.setHours(0); date.setMinutes(0); date.setSeconds(0); date.setMilliseconds(0);
  1053. if ( d.match(/,/gi) ) {
  1054. date_array = d.split(",");
  1055. for(var i = 0; i < date_array.length; i++) {
  1056. date_array[i] = parseInt(date_array[i], 10);
  1057. }
  1058. if (date_array[0]) {
  1059. date.setFullYear(date_array[0]);
  1060. p.year = true;
  1061. }
  1062. if (date_array[1]) {
  1063. date.setMonth(date_array[1] - 1);
  1064. p.month = true;
  1065. }
  1066. if (date_array[2]) {
  1067. date.setDate(date_array[2]);
  1068. p.day = true;
  1069. }
  1070. if (date_array[3]) {
  1071. date.setHours(date_array[3]);
  1072. p.hour = true;
  1073. }
  1074. if (date_array[4]) {
  1075. date.setMinutes(date_array[4]);
  1076. p.minute = true;
  1077. }
  1078. if (date_array[5]) {
  1079. date.setSeconds(date_array[5]);
  1080. if (date_array[5] >= 1) {
  1081. p.second = true;
  1082. }
  1083. }
  1084. if (date_array[6]) {
  1085. date.setMilliseconds(date_array[6]);
  1086. if (date_array[6] >= 1) {
  1087. p.millisecond = true;
  1088. }
  1089. }
  1090. } else if (d.match("/")) {
  1091. if (d.match(" ")) {
  1092. time_parse = d.split(" ");
  1093. if (d.match(":")) {
  1094. time_array = time_parse[1].split(":");
  1095. if (time_array[0] >= 0 ) {
  1096. date.setHours(time_array[0]);
  1097. p.hour = true;
  1098. }
  1099. if (time_array[1] >= 0) {
  1100. date.setMinutes(time_array[1]);
  1101. p.minute = true;
  1102. }
  1103. if (time_array[2] >= 0) {
  1104. date.setSeconds(time_array[2]);
  1105. p.second = true;
  1106. }
  1107. if (time_array[3] >= 0) {
  1108. date.setMilliseconds(time_array[3]);
  1109. p.millisecond = true;
  1110. }
  1111. }
  1112. date_array = time_parse[0].split("/");
  1113. } else {
  1114. date_array = d.split("/");
  1115. }
  1116. if (date_array[2]) {
  1117. date.setFullYear(date_array[2]);
  1118. p.year = true;
  1119. }
  1120. if (date_array[0] >= 0) {
  1121. var month = date_array[0] - 1;
  1122. date.setMonth(month);
  1123. // if (date.getMonth() != month) {
  1124. // date.setMonth(month); // WTF javascript?
  1125. // }
  1126. p.month = true;
  1127. }
  1128. if (date_array[1] >= 0) {
  1129. if (date_array[1].length > 2) {
  1130. date.setFullYear(date_array[1]);
  1131. p.year = true;
  1132. } else {
  1133. date.setDate(date_array[1]);
  1134. p.day = true;
  1135. }
  1136. }
  1137. } else if (d.match("now")) {
  1138. var now = new Date();
  1139. date.setFullYear(now.getFullYear());
  1140. p.year = true;
  1141. date.setMonth(now.getMonth());
  1142. p.month = true;
  1143. date.setDate(now.getDate());
  1144. p.day = true;
  1145. if (d.match("hours")) {
  1146. date.setHours(now.getHours());
  1147. p.hour = true;
  1148. }
  1149. if (d.match("minutes")) {
  1150. date.setHours(now.getHours());
  1151. date.setMinutes(now.getMinutes());
  1152. p.hour = true;
  1153. p.minute = true;
  1154. }
  1155. if (d.match("seconds")) {
  1156. date.setHours(now.getHours());
  1157. date.setMinutes(now.getMinutes());
  1158. date.setSeconds(now.getSeconds());
  1159. p.hour = true;
  1160. p.minute = true;
  1161. p.second = true;
  1162. }
  1163. if (d.match("milliseconds")) {
  1164. date.setHours(now.getHours());
  1165. date.setMinutes(now.getMinutes());
  1166. date.setSeconds(now.getSeconds());
  1167. date.setMilliseconds(now.getMilliseconds());
  1168. p.hour = true;
  1169. p.minute = true;
  1170. p.second = true;
  1171. p.millisecond = true;
  1172. }
  1173. } else if (d.length <= 8) {
  1174. p.year = true;
  1175. date.setFullYear(parseInt(d, 10));
  1176. date.setMonth(0);
  1177. date.setDate(1);
  1178. date.setHours(0);
  1179. date.setMinutes(0);
  1180. date.setSeconds(0);
  1181. date.setMilliseconds(0);
  1182. } else if (d.match("T")) {
  1183. if (navigator.userAgent.match(/MSIE\s(?!9.0)/)) {
  1184. // IE 8 < Won't accept dates with a "-" in them.
  1185. time_parse = d.split("T");
  1186. if (d.match(":")) {
  1187. time_array = time_parse[1].split(":");
  1188. if (time_array[0] >= 1) {
  1189. date.setHours(time_array[0]);
  1190. p.hour = true;
  1191. }
  1192. if (time_array[1] >= 1) {
  1193. date.setMinutes(time_array[1]);
  1194. p.minute = true;
  1195. }
  1196. if (time_array[2] >= 1) {
  1197. date.setSeconds(time_array[2]);
  1198. if (time_array[2] >= 1) {
  1199. p.second = true;
  1200. }
  1201. }
  1202. if (time_array[3] >= 1) {
  1203. date.setMilliseconds(time_array[3]);
  1204. if (time_array[3] >= 1) {
  1205. p.millisecond = true;
  1206. }
  1207. }
  1208. }
  1209. date_array = time_parse[0].split("-");
  1210. if (date_array[0]) {
  1211. date.setFullYear(date_array[0]);
  1212. p.year = true;
  1213. }
  1214. if (date_array[1] >= 0) {
  1215. date.setMonth(date_array[1] - 1);
  1216. p.month = true;
  1217. }
  1218. if (date_array[2] >= 0) {
  1219. date.setDate(date_array[2]);
  1220. p.day = true;
  1221. }
  1222. } else {
  1223. date = new Date(Date.parse(d));
  1224. p.year = true;
  1225. p.month = true;
  1226. p.day = true;
  1227. p.hour = true;
  1228. p.minute = true;
  1229. if (date.getSeconds() >= 1) {
  1230. p.second = true;
  1231. }
  1232. if (date.getMilliseconds() >= 1) {
  1233. p.millisecond = true;
  1234. }
  1235. }
  1236. } else {
  1237. date = new Date(
  1238. parseInt(d.slice(0,4), 10),
  1239. parseInt(d.slice(4,6), 10) - 1,
  1240. parseInt(d.slice(6,8), 10),
  1241. parseInt(d.slice(8,10), 10),
  1242. parseInt(d.slice(10,12), 10)
  1243. );
  1244. p.year = true;
  1245. p.month = true;
  1246. p.day = true;
  1247. p.hour = true;
  1248. p.minute = true;
  1249. if (date.getSeconds() >= 1) {
  1250. p.second = true;
  1251. }
  1252. if (date.getMilliseconds() >= 1) {
  1253. p.millisecond = true;
  1254. }
  1255. }
  1256. }
  1257. if (precision != null && precision != "") {
  1258. return {
  1259. date: date,
  1260. precision: p
  1261. };
  1262. } else {
  1263. return date;
  1264. }
  1265. },
  1266. prettyDate: function(d, is_abbr, p, d2) {
  1267. var _date,
  1268. _date2,
  1269. format,
  1270. bc_check,
  1271. is_pair = false,
  1272. bc_original,
  1273. bc_number,
  1274. bc_string;
  1275. if (d2 != null && d2 != "" && typeof d2 != 'undefined') {
  1276. is_pair = true;
  1277. trace("D2 " + d2);
  1278. }
  1279. if (type.of(d) == "date") {
  1280. if (type.of(p) == "object") {
  1281. if (p.millisecond || p.second && d.getSeconds() >= 1) {
  1282. // YEAR MONTH DAY HOUR MINUTE
  1283. if (is_abbr){
  1284. format = VMM.Date.dateformats.time_short;
  1285. } else {
  1286. format = VMM.Date.dateformats.time_short;
  1287. }
  1288. } else if (p.minute) {
  1289. // YEAR MONTH DAY HOUR MINUTE
  1290. if (is_abbr){
  1291. format = VMM.Date.dateformats.time_no_seconds_short;
  1292. } else {
  1293. format = VMM.Date.dateformats.time_no_seconds_small_date;
  1294. }
  1295. } else if (p.hour) {
  1296. // YEAR MONTH DAY HOUR
  1297. if (is_abbr) {
  1298. format = VMM.Date.dateformats.time_no_seconds_short;
  1299. } else {
  1300. format = VMM.Date.dateformats.time_no_seconds_small_date;
  1301. }
  1302. } else if (p.day) {
  1303. // YEAR MONTH DAY
  1304. if (is_abbr) {
  1305. format = VMM.Date.dateformats.full_short;
  1306. } else {
  1307. format = VMM.Date.dateformats.full;
  1308. }
  1309. } else if (p.month) {
  1310. // YEAR MONTH
  1311. if (is_abbr) {
  1312. format = VMM.Date.dateformats.month_short;
  1313. } else {
  1314. format = VMM.Date.dateformats.month;
  1315. }
  1316. } else if (p.year) {
  1317. format = VMM.Date.dateformats.year;
  1318. } else {
  1319. format = VMM.Date.dateformats.year;
  1320. }
  1321. } else {
  1322. if (d.getMonth() === 0 && d.getDate() == 1 && d.getHours() === 0 && d.getMinutes() === 0 ) {
  1323. // YEAR ONLY
  1324. format = VMM.Date.dateformats.year;
  1325. } else if (d.getDate() <= 1 && d.getHours() === 0 && d.getMinutes() === 0) {
  1326. // YEAR MONTH
  1327. if (is_abbr) {
  1328. format = VMM.Date.dateformats.month_short;
  1329. } else {
  1330. format = VMM.Date.dateformats.month;
  1331. }
  1332. } else if (d.getHours() === 0 && d.getMinutes() === 0) {
  1333. // YEAR MONTH DAY
  1334. if (is_abbr) {
  1335. format = VMM.Date.dateformats.full_short;
  1336. } else {
  1337. format = VMM.Date.dateformats.full;
  1338. }
  1339. } else if (d.getMinutes() === 0) {
  1340. // YEAR MONTH DAY HOUR
  1341. if (is_abbr) {
  1342. format = VMM.Date.dateformats.time_no_seconds_short;
  1343. } else {
  1344. format = VMM.Date.dateformats.time_no_seconds_small_date;
  1345. }
  1346. } else {
  1347. // YEAR MONTH DAY HOUR MINUTE
  1348. if (is_abbr){
  1349. format = VMM.Date.dateformats.time_no_seconds_short;
  1350. } else {
  1351. format = VMM.Date.dateformats.full_long;
  1352. }
  1353. }
  1354. }
  1355. _date = dateFormat(d, format, false);
  1356. //_date = "Jan"
  1357. bc_check = _date.split(" ");
  1358. // BC TIME SUPPORT
  1359. for(var i = 0; i < bc_check.length; i++) {
  1360. if ( parseInt(bc_check[i], 10) < 0 ) {
  1361. trace("YEAR IS BC");
  1362. bc_original = bc_check[i];
  1363. bc_number = Math.abs( parseInt(bc_check[i], 10) );
  1364. bc_string = bc_number.toString() + " B.C.";
  1365. _date = _date.replace(bc_original, bc_string);
  1366. }
  1367. }
  1368. if (is_pair) {
  1369. _date2 = dateFormat(d2, format, false);
  1370. bc_check = _date2.split(" ");
  1371. // BC TIME SUPPORT
  1372. for(var j = 0; j < bc_check.length; j++) {
  1373. if ( parseInt(bc_check[j], 10) < 0 ) {
  1374. trace("YEAR IS BC");
  1375. bc_original = bc_check[j];
  1376. bc_number = Math.abs( parseInt(bc_check[j], 10) );
  1377. bc_string = bc_number.toString() + " B.C.";
  1378. _date2 = _date2.replace(bc_original, bc_string);
  1379. }
  1380. }
  1381. }
  1382. } else {
  1383. trace("NOT A VALID DATE?");
  1384. trace(d);
  1385. }
  1386. if (is_pair) {
  1387. return _date + " &mdash; " + _date2;
  1388. } else {
  1389. return _date;
  1390. }
  1391. }
  1392. }).init();
  1393. /*
  1394. * Date Format 1.2.3
  1395. * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
  1396. * MIT license
  1397. *
  1398. * Includes enhancements by Scott Trenda <scott.trenda.net>
  1399. * and Kris Kowal <cixar.com/~kris.kowal/>
  1400. *
  1401. * Accepts a date, a mask, or a date and a mask.
  1402. * Returns a formatted version of the given date.
  1403. * The date defaults to the current date/time.
  1404. * The mask defaults to dateFormat.masks.default.
  1405. */
  1406. var dateFormat = function () {
  1407. var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[WLloSZ]|"[^"]*"|'[^']*'/g,
  1408. timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
  1409. timezoneClip = /[^-+\dA-Z]/g,
  1410. pad = function (val, len) {
  1411. val = String(val);
  1412. len = len || 2;
  1413. while (val.length < len) val = "0" + val;
  1414. return val;
  1415. };
  1416. // Regexes and supporting functions are cached through closure
  1417. return function (date, mask, utc) {
  1418. var dF = dateFormat;
  1419. // You can't provide utc if you skip other args (use the "UTC:" mask prefix)
  1420. if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
  1421. mask = date;
  1422. date = undefined;
  1423. }
  1424. // Passing date through Date applies Date.parse, if necessary
  1425. // Caused problems in IE
  1426. // date = date ? new Date(date) : new Date;
  1427. if (isNaN(date)) {
  1428. trace("invalid date " + date);
  1429. //return "";
  1430. }
  1431. mask = String(dF.masks[mask] || mask || dF.masks["default"]);
  1432. // Allow setting the utc argument via the mask
  1433. if (mask.slice(0, 4) == "UTC:") {
  1434. mask = mask.slice(4);
  1435. utc = true;
  1436. }
  1437. var _ = utc ? "getUTC" : "get",
  1438. d = date[_ + "Date"](),
  1439. D = date[_ + "Day"](),
  1440. m = date[_ + "Month"](),
  1441. y = date[_ + "FullYear"](),
  1442. H = date[_ + "Hours"](),
  1443. M = date[_ + "Minutes"](),
  1444. s = date[_ + "Seconds"](),
  1445. L = date[_ + "Milliseconds"](),
  1446. W = date.getWeek(),
  1447. o = utc ? 0 : date.getTimezoneOffset(),
  1448. flags = {
  1449. d: d,
  1450. dd: pad(d),
  1451. ddd: dF.i18n.dayNames[D],
  1452. dddd: dF.i18n.dayNames[D + 7],
  1453. m: m + 1,
  1454. mm: pad(m + 1),
  1455. mmm: dF.i18n.monthNames[m],
  1456. mmmm: dF.i18n.monthNames[m + 12],
  1457. yy: String(y).slice(2),
  1458. yyyy: y,
  1459. h: H % 12 || 12,
  1460. hh: pad(H % 12 || 12),
  1461. H: H,
  1462. HH: pad(H),
  1463. M: M,
  1464. MM: pad(M),
  1465. s: s,
  1466. ss: pad(s),
  1467. l: pad(L, 3),
  1468. L: pad(L > 99 ? Math.round(L / 10) : L),
  1469. t: H < 12 ? "a" : "p",
  1470. tt: H < 12 ? "am" : "pm",
  1471. T: H < 12 ? "A" : "P",
  1472. TT: H < 12 ? "AM" : "PM",
  1473. Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
  1474. o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
  1475. S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10],
  1476. W: W
  1477. };
  1478. return mask.replace(token, function ($0) {
  1479. return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
  1480. });
  1481. };
  1482. }();
  1483. // Some common format strings
  1484. dateFormat.masks = {
  1485. "default": "ddd mmm dd yyyy HH:MM:ss",
  1486. shortDate: "m/d/yy",
  1487. mediumDate: "mmm d, yyyy",
  1488. longDate: "mmmm d, yyyy",
  1489. fullDate: "dddd, mmmm d, yyyy",
  1490. shortTime: "h:MM TT",
  1491. mediumTime: "h:MM:ss TT",
  1492. longTime: "h:MM:ss TT Z",
  1493. isoDate: "yyyy-mm-dd",
  1494. isoTime: "HH:MM:ss",
  1495. isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
  1496. isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
  1497. };
  1498. // Internationalization strings
  1499. dateFormat.i18n = {
  1500. dayNames: [
  1501. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
  1502. "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
  1503. ],
  1504. monthNames: [
  1505. "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  1506. "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
  1507. ]
  1508. };
  1509. // For convenience...
  1510. Date.prototype.format = function (mask, utc) {
  1511. return dateFormat(this, mask, utc);
  1512. };
  1513. }
  1514. /* **********************************************
  1515. Begin VMM.Util.js
  1516. ********************************************** */
  1517. /* * Utilities and Useful Functions
  1518. ================================================== */
  1519. if(typeof VMM != 'undefined' && typeof VMM.Util == 'undefined') {
  1520. VMM.Util = ({
  1521. init: function() {
  1522. return this;
  1523. },
  1524. removeRange: function(array, from, to) { // rather than change Array.prototype; Thanks Jeff McWhirter for nudge
  1525. var rest = array.slice((to || from) + 1 || array.length);
  1526. array.length = from < 0 ? array.length + from : from;
  1527. return array.push.apply(array, rest);
  1528. },
  1529. /* * CORRECT PROTOCOL (DOES NOT WORK)
  1530. ================================================== */
  1531. correctProtocol: function(url) {
  1532. var loc = (window.parent.location.protocol).toString(),
  1533. prefix = "",
  1534. the_url = url.split("://", 2);
  1535. if (loc.match("http")) {
  1536. prefix = loc;
  1537. } else {
  1538. prefix = "https";
  1539. }
  1540. return prefix + "://" + the_url[1];
  1541. },
  1542. /* * MERGE CONFIG
  1543. ================================================== */
  1544. mergeConfig: function(config_main, config_to_merge) {
  1545. var x;
  1546. for (x in config_to_merge) {
  1547. if (Object.prototype.hasOwnProperty.call(config_to_merge, x)) {
  1548. config_main[x] = config_to_merge[x];
  1549. }
  1550. }
  1551. return config_main;
  1552. },
  1553. /* * GET OBJECT ATTRIBUTE BY INDEX
  1554. ================================================== */
  1555. getObjectAttributeByIndex: function(obj, index) {
  1556. if(typeof obj != 'undefined') {
  1557. var i = 0;
  1558. for (var attr in obj){
  1559. if (index === i){
  1560. return obj[attr];
  1561. }
  1562. i++;
  1563. }
  1564. return "";
  1565. } else {
  1566. return "";
  1567. }
  1568. },
  1569. /* * ORDINAL
  1570. ================================================== */
  1571. ordinal: function(n) {
  1572. return ["th","st","nd","rd"][(!( ((n%10) >3) || (Math.floor(n%100/10)==1)) ) * (n%10)];
  1573. },
  1574. /* * RANDOM BETWEEN
  1575. ================================================== */
  1576. //VMM.Util.randomBetween(1, 3)
  1577. randomBetween: function(min, max) {
  1578. return Math.floor(Math.random() * (max - min + 1) + min);
  1579. },
  1580. /* * AVERAGE
  1581. * http://jsfromhell.com/array/average
  1582. * var x = VMM.Util.average([2, 3, 4]);
  1583. * VMM.Util.average([2, 3, 4]).mean
  1584. ================================================== */
  1585. average: function(a) {
  1586. var r = {mean: 0, variance: 0, deviation: 0}, t = a.length;
  1587. for(var m, s = 0, l = t; l--; s += a[l]);
  1588. for(m = r.mean = s / t, l = t, s = 0; l--; s += Math.pow(a[l] - m, 2));
  1589. return r.deviation = Math.sqrt(r.variance = s / t), r;
  1590. },
  1591. /* * CUSTOM SORT
  1592. ================================================== */
  1593. customSort: function(a, b) {
  1594. var a1= a, b1= b;
  1595. if(a1== b1) return 0;
  1596. return a1> b1? 1: -1;
  1597. },
  1598. /* * Remove Duplicates from Array
  1599. ================================================== */
  1600. deDupeArray: function(arr) {
  1601. var i,
  1602. len=arr.length,
  1603. out=[],
  1604. obj={};
  1605. for (i=0;i<len;i++) {
  1606. obj[arr[i]]=0;
  1607. }
  1608. for (i in obj) {
  1609. out.push(i);
  1610. }
  1611. return out;
  1612. },
  1613. /* * Returns a word count number
  1614. ================================================== */
  1615. wordCount: function(s) {
  1616. var fullStr = s + " ";
  1617. var initial_whitespace_rExp = /^[^A-Za-z0-9\'\-]+/gi;
  1618. var left_trimmedStr = fullStr.replace(initial_whitespace_rExp, "");
  1619. var non_alphanumerics_rExp = /[^A-Za-z0-9\'\-]+/gi;
  1620. var cleanedStr = left_trimmedStr.replace(non_alphanumerics_rExp, " ");
  1621. var splitString = cleanedStr.split(" ");
  1622. var word_count = splitString.length -1;
  1623. if (fullStr.length <2) {
  1624. word_count = 0;
  1625. }
  1626. return word_count;
  1627. },
  1628. ratio: {
  1629. fit: function(w, h, ratio_w, ratio_h) {
  1630. //VMM.Util.ratio.fit(w, h, ratio_w, ratio_h).width;
  1631. var _fit = {width:0,height:0};
  1632. // TRY WIDTH FIRST
  1633. _fit.width = w;
  1634. //_fit.height = Math.round((h / ratio_h) * ratio_w);
  1635. _fit.height = Math.round((w / ratio_w) * ratio_h);
  1636. if (_fit.height > h) {
  1637. _fit.height = h;
  1638. //_fit.width = Math.round((w / ratio_w) * ratio_h);
  1639. _fit.width = Math.round((h / ratio_h) * ratio_w);
  1640. if (_fit.width > w) {
  1641. trace("FIT: DIDN'T FIT!!! ")
  1642. }
  1643. }
  1644. return _fit;
  1645. },
  1646. r16_9: function(w,h) {
  1647. //VMM.Util.ratio.r16_9(w, h) // Returns corresponding number
  1648. if (w !== null && w !== "") {
  1649. return Math.round((h / 16) * 9);
  1650. } else if (h !== null && h !== "") {
  1651. return Math.round((w / 9) * 16);
  1652. }
  1653. },
  1654. r4_3: function(w,h) {
  1655. if (w !== null && w !== "") {
  1656. return Math.round((h / 4) * 3);
  1657. } else if (h !== null && h !== "") {
  1658. return Math.round((w / 3) * 4);
  1659. }
  1660. }
  1661. },
  1662. doubledigit: function(n) {
  1663. return (n < 10 ? '0' : '') + n;
  1664. },
  1665. /* * Returns a truncated segement of a long string of between min and max words. If possible, ends on a period (otherwise goes to max).
  1666. ================================================== */
  1667. truncateWords: function(s, min, max) {
  1668. if (!min) min = 30;
  1669. if (!max) max = min;
  1670. var initial_whitespace_rExp = /^[^A-Za-z0-9\'\-]+/gi;
  1671. var left_trimmedStr = s.replace(initial_whitespace_rExp, "");
  1672. var words = left_trimmedStr.split(" ");
  1673. var result = [];
  1674. min = Math.min(words.length, min);
  1675. max = Math.min(words.length, max);
  1676. for (var i = 0; i<min; i++) {
  1677. result.push(words[i]);
  1678. }
  1679. for (var j = min; i<max; i++) {
  1680. var word = words[i];
  1681. result.push(word);
  1682. if (word.charAt(word.length-1) == '.') {
  1683. break;
  1684. }
  1685. }
  1686. return (result.join(' '));
  1687. },
  1688. /* * Turns plain text links into real links
  1689. ================================================== */
  1690. linkify: function(text,targets,is_touch) {
  1691. // http://, https://, ftp://
  1692. var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;
  1693. // www. sans http:// or https://
  1694. var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
  1695. // Email addresses
  1696. var emailAddressPattern = /(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim;
  1697. return text
  1698. .replace(urlPattern, "<a target='_blank' href='$&' onclick='void(0)'>$&</a>")
  1699. .replace(pseudoUrlPattern, "$1<a target='_blank' onclick='void(0)' href='http://$2'>$2</a>")
  1700. .replace(emailAddressPattern, "<a target='_blank' onclick='void(0)' href='mailto:$1'>$1</a>");
  1701. },
  1702. linkify_with_twitter: function(text,targets,is_touch) {
  1703. // http://, https://, ftp://
  1704. var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;
  1705. var url_pattern = /(\()((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\))|(\[)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\])|(\{)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\})|(<|&(?:lt|#60|#x3c);)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(>|&(?:gt|#62|#x3e);)|((?:^|[^=\s'"\]])\s*['"]?|[^=\s]\s+)(\b(?:ht|f)tps?:\/\/[a-z0-9\-._~!$'()*+,;=:\/?#[\]@%]+(?:(?!&(?:gt|#0*62|#x0*3e);|&(?:amp|apos|quot|#0*3[49]|#x0*2[27]);[.!&',:?;]?(?:[^a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]|$))&[a-z0-9\-._~!$'()*+,;=:\/?#[\]@%]*)*[a-z0-9\-_~$()*+=\/#[\]@%])/img;
  1706. var url_replace = '$1$4$7$10$13<a href="$2$5$8$11$14" target="_blank" class="hyphenate">$2$5$8$11$14</a>$3$6$9$12';
  1707. // www. sans http:// or https://
  1708. var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
  1709. function replaceURLWithHTMLLinks(text) {
  1710. var exp = /(\b(https?|ftp|file):\/\/([-A-Z0-9+&@#%?=~_|!:,.;]*)([-A-Z0-9+&@#%?\/=~_|!:,.;]*)[-A-Z0-9+&@#\/%=~_|])/ig;
  1711. return text.replace(exp, "<a href='$1' target='_blank'>$3</a>");
  1712. }
  1713. // Email addresses
  1714. var emailAddressPattern = /([a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)/gim;
  1715. var twitterHandlePattern = /\B@([\w-]+)/gm;
  1716. var twitterSearchPattern = /(#([\w]+))/g;
  1717. return text
  1718. .replace(emailAddressPattern, "<a target='_blank' onclick='void(0)' href='mailto:$1'>$1</a>")
  1719. .replace(twitterHandlePattern, "<a href='http://twitter.com/$1' target='_blank' onclick='void(0)'>@$1</a>");
  1720. // TURN THIS BACK ON TO AUTOMAGICALLY LINK HASHTAGS TO TWITTER SEARCH
  1721. //.replace(twitterSearchPattern, "<a href='http://twitter.com/search?q=%23$2' target='_blank' 'void(0)'>$1</a>");
  1722. },
  1723. linkify_wikipedia: function(text) {
  1724. var urlPattern = /<i[^>]*>(.*?)<\/i>/gim;
  1725. return text
  1726. .replace(urlPattern, "<a target='_blank' href='http://en.wikipedia.org/wiki/$&' onclick='void(0)'>$&</a>")
  1727. .replace(/<i\b[^>]*>/gim, "")
  1728. .replace(/<\/i>/gim, "")
  1729. .replace(/<b\b[^>]*>/gim, "")
  1730. .replace(/<\/b>/gim, "");
  1731. },
  1732. /* * Turns plain text links into real links
  1733. ================================================== */
  1734. // VMM.Util.unlinkify();
  1735. unlinkify: function(text) {
  1736. if(!text) return text;
  1737. text = text.replace(/<a\b[^>]*>/i,"");
  1738. text = text.replace(/<\/a>/i, "");
  1739. return text;
  1740. },
  1741. untagify: function(text) {
  1742. if (!text) {
  1743. return text;
  1744. }
  1745. text = text.replace(/<\/?\s*\w.*?>/g,"");
  1746. return text;
  1747. },
  1748. /* * TK
  1749. ================================================== */
  1750. nl2br: function(text) {
  1751. return text.replace(/(\r\n|[\r\n]|\\n|\\r)/g,"<br/>");
  1752. },
  1753. /* * Generate a Unique ID
  1754. ================================================== */
  1755. // VMM.Util.unique_ID(size);
  1756. unique_ID: function(size) {
  1757. var getRandomNumber = function(range) {
  1758. return Math.floor(Math.random() * range);
  1759. };
  1760. var getRandomChar = function() {
  1761. var chars = "abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ";
  1762. return chars.substr( getRandomNumber(62), 1 );
  1763. };
  1764. var randomID = function(size) {
  1765. var str = "";
  1766. for(var i = 0; i < size; i++) {
  1767. str += getRandomChar();
  1768. }
  1769. return str;
  1770. };
  1771. return randomID(size);
  1772. },
  1773. /* * Tells you if a number is even or not
  1774. ================================================== */
  1775. // VMM.Util.isEven(n)
  1776. isEven: function(n){
  1777. return (n%2 === 0) ? true : false;
  1778. },
  1779. /* * Get URL Variables
  1780. ================================================== */
  1781. // var somestring = VMM.Util.getUrlVars(str_url)["varname"];
  1782. getUrlVars: function(string) {
  1783. var str = string.toString();
  1784. if (str.match('&#038;')) {
  1785. str = str.replace("&#038;", "&");
  1786. } else if (str.match('&#38;')) {
  1787. str = str.replace("&#38;", "&");
  1788. } else if (str.match('&amp;')) {
  1789. str = str.replace("&amp;", "&");
  1790. }
  1791. var vars = [], hash;
  1792. var hashes = str.slice(str.indexOf('?') + 1).split('&');
  1793. for(var i = 0; i < hashes.length; i++) {
  1794. hash = hashes[i].split('=');
  1795. vars.push(hash[0]);
  1796. vars[hash[0]] = hash[1];
  1797. }
  1798. return vars;
  1799. },
  1800. /* * Cleans up strings to become real HTML
  1801. ================================================== */
  1802. toHTML: function(text) {
  1803. text = this.nl2br(text);
  1804. text = this.linkify(text);
  1805. return text.replace(/\s\s/g,"&nbsp;&nbsp;");
  1806. },
  1807. /* * Returns text strings as CamelCase
  1808. ================================================== */
  1809. toCamelCase: function(s,forceLowerCase) {
  1810. if(forceLowerCase !== false) forceLowerCase = true;
  1811. var sps = ((forceLowerCase) ? s.toLowerCase() : s).split(" ");
  1812. for(var i=0; i<sps.length; i++) {
  1813. sps[i] = sps[i].substr(0,1).toUpperCase() + sps[i].substr(1);
  1814. }
  1815. return sps.join(" ");
  1816. },
  1817. /* * Replaces dumb quote marks with smart ones
  1818. ================================================== */
  1819. properQuotes: function(str) {
  1820. return str.replace(/\"([^\"]*)\"/gi,"&#8220;$1&#8221;");
  1821. },
  1822. /* * Add Commas to numbers
  1823. ================================================== */
  1824. niceNumber: function(nStr){
  1825. nStr += '';
  1826. x = nStr.split('.');
  1827. x1 = x[0];
  1828. x2 = x.length > 1 ? '.' + x[1] : '';
  1829. var rgx = /(\d+)(\d{3})/;
  1830. while (rgx.test(x1)) {
  1831. x1 = x1.replace(rgx, '$1' + ',' + '$2');
  1832. }
  1833. return x1 + x2;
  1834. },
  1835. /* * Transform text to Title Case
  1836. ================================================== */
  1837. toTitleCase: function(t){
  1838. if ( VMM.Browser.browser == "Explorer" && parseInt(VMM.Browser.version, 10) >= 7) {
  1839. return t.replace("_", "%20");
  1840. } else {
  1841. var __TitleCase = {
  1842. __smallWords: ['a', 'an', 'and', 'as', 'at', 'but','by', 'en', 'for', 'if', 'in', 'of', 'on', 'or','the', 'to', 'v[.]?', 'via', 'vs[.]?'],
  1843. init: function() {
  1844. this.__smallRE = this.__smallWords.join('|');
  1845. this.__lowerCaseWordsRE = new RegExp('\\b(' + this.__smallRE + ')\\b', 'gi');
  1846. this.__firstWordRE = new RegExp('^([^a-zA-Z0-9 \\r\\n\\t]*)(' + this.__smallRE + ')\\b', 'gi');
  1847. this.__lastWordRE = new RegExp('\\b(' + this.__smallRE + ')([^a-zA-Z0-9 \\r\\n\\t]*)$', 'gi');
  1848. },
  1849. toTitleCase: function(string) {
  1850. var line = '';
  1851. var split = string.split(/([:.;?!][ ]|(?:[ ]|^)["“])/);
  1852. for (var i = 0; i < split.length; ++i) {
  1853. var s = split[i];
  1854. s = s.replace(/\b([a-zA-Z][a-z.'’]*)\b/g,this.__titleCaseDottedWordReplacer);
  1855. // lowercase the list of small words
  1856. s = s.replace(this.__lowerCaseWordsRE, this.__lowerReplacer);
  1857. // if the first word in the title is a small word then capitalize it
  1858. s = s.replace(this.__firstWordRE, this.__firstToUpperCase);
  1859. // if the last word in the title is a small word, then capitalize it
  1860. s = s.replace(this.__lastWordRE, this.__firstToUpperCase);
  1861. line += s;
  1862. }
  1863. // special cases
  1864. line = line.replace(/ V(s?)\. /g, ' v$1. ');
  1865. line = line.replace(/(['’])S\b/g, '$1s');
  1866. line = line.replace(/\b(AT&T|Q&A)\b/ig, this.__upperReplacer);
  1867. return line;
  1868. },
  1869. __titleCaseDottedWordReplacer: function (w) {
  1870. return (w.match(/[a-zA-Z][.][a-zA-Z]/)) ? w : __TitleCase.__firstToUpperCase(w);
  1871. },
  1872. __lowerReplacer: function (w) { return w.toLowerCase() },
  1873. __upperReplacer: function (w) { return w.toUpperCase() },
  1874. __firstToUpperCase: function (w) {
  1875. var split = w.split(/(^[^a-zA-Z0-9]*[a-zA-Z0-9])(.*)$/);
  1876. if (split[1]) {
  1877. split[1] = split[1].toUpperCase();
  1878. }
  1879. return split.join('');
  1880. }
  1881. };
  1882. __TitleCase.init();
  1883. t = t.replace(/_/g," ");
  1884. t = __TitleCase.toTitleCase(t);
  1885. return t;
  1886. }
  1887. }
  1888. }).init();
  1889. }
  1890. /* **********************************************
  1891. Begin LazyLoad.js
  1892. ********************************************** */
  1893. /*jslint browser: true, eqeqeq: true, bitwise: true, newcap: true, immed: true, regexp: false */
  1894. /*
  1895. LazyLoad makes it easy and painless to lazily load one or more external
  1896. JavaScript or CSS files on demand either during or after the rendering of a web
  1897. page.
  1898. Supported browsers include Firefox 2+, IE6+, Safari 3+ (including Mobile
  1899. Safari), Google Chrome, and Opera 9+. Other browsers may or may not work and
  1900. are not officially supported.
  1901. Visit https://github.com/rgrove/lazyload/ for more info.
  1902. Copyright (c) 2011 Ryan Grove <ryan@wonko.com>
  1903. All rights reserved.
  1904. Permission is hereby granted, free of charge, to any person obtaining a copy of
  1905. this software and associated documentation files (the 'Software'), to deal in
  1906. the Software without restriction, including without limitation the rights to
  1907. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  1908. the Software, and to permit persons to whom the Software is furnished to do so,
  1909. subject to the following conditions:
  1910. The above copyright notice and this permission notice shall be included in all
  1911. copies or substantial portions of the Software.
  1912. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  1913. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  1914. FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  1915. COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  1916. IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  1917. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  1918. @module lazyload
  1919. @class LazyLoad
  1920. @static
  1921. @version 2.0.3 (git)
  1922. */
  1923. LazyLoad = (function (doc) {
  1924. // -- Private Variables ------------------------------------------------------
  1925. // User agent and feature test information.
  1926. var env,
  1927. // Reference to the <head> element (populated lazily).
  1928. head,
  1929. // Requests currently in progress, if any.
  1930. pending = {},
  1931. // Number of times we've polled to check whether a pending stylesheet has
  1932. // finished loading. If this gets too high, we're probably stalled.
  1933. pollCount = 0,
  1934. // Queued requests.
  1935. queue = {css: [], js: []},
  1936. // Reference to the browser's list of stylesheets.
  1937. styleSheets = doc.styleSheets;
  1938. // -- Private Methods --------------------------------------------------------
  1939. /**
  1940. Creates and returns an HTML element with the specified name and attributes.
  1941. @method createNode
  1942. @param {String} name element name
  1943. @param {Object} attrs name/value mapping of element attributes
  1944. @return {HTMLElement}
  1945. @private
  1946. */
  1947. function createNode(name, attrs) {
  1948. var node = doc.createElement(name), attr;
  1949. for (attr in attrs) {
  1950. if (attrs.hasOwnProperty(attr)) {
  1951. node.setAttribute(attr, attrs[attr]);
  1952. }
  1953. }
  1954. return node;
  1955. }
  1956. /**
  1957. Called when the current pending resource of the specified type has finished
  1958. loading. Executes the associated callback (if any) and loads the next
  1959. resource in the queue.
  1960. @method finish
  1961. @param {String} type resource type ('css' or 'js')
  1962. @private
  1963. */
  1964. function finish(type) {
  1965. var p = pending[type],
  1966. callback,
  1967. urls;
  1968. if (p) {
  1969. callback = p.callback;
  1970. urls = p.urls;
  1971. urls.shift();
  1972. pollCount = 0;
  1973. // If this is the last of the pending URLs, execute the callback and
  1974. // start the next request in the queue (if any).
  1975. if (!urls.length) {
  1976. callback && callback.call(p.context, p.obj);
  1977. pending[type] = null;
  1978. queue[type].length && load(type);
  1979. }
  1980. }
  1981. }
  1982. /**
  1983. Populates the <code>env</code> variable with user agent and feature test
  1984. information.
  1985. @method getEnv
  1986. @private
  1987. */
  1988. function getEnv() {
  1989. var ua = navigator.userAgent;
  1990. env = {
  1991. // True if this browser supports disabling async mode on dynamically
  1992. // created script nodes. See
  1993. // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
  1994. async: doc.createElement('script').async === true
  1995. };
  1996. (env.webkit = /AppleWebKit\//.test(ua))
  1997. || (env.ie = /MSIE/.test(ua))
  1998. || (env.opera = /Opera/.test(ua))
  1999. || (env.gecko = /Gecko\//.test(ua))
  2000. || (env.unknown = true);
  2001. }
  2002. /**
  2003. Loads the specified resources, or the next resource of the specified type
  2004. in the queue if no resources are specified. If a resource of the specified
  2005. type is already being loaded, the new request will be queued until the
  2006. first request has been finished.
  2007. When an array of resource URLs is specified, those URLs will be loaded in
  2008. parallel if it is possible to do so while preserving execution order. All
  2009. browsers support parallel loading of CSS, but only Firefox and Opera
  2010. support parallel loading of scripts. In other browsers, scripts will be
  2011. queued and loaded one at a time to ensure correct execution order.
  2012. @method load
  2013. @param {String} type resource type ('css' or 'js')
  2014. @param {String|Array} urls (optional) URL or array of URLs to load
  2015. @param {Function} callback (optional) callback function to execute when the
  2016. resource is loaded
  2017. @param {Object} obj (optional) object to pass to the callback function
  2018. @param {Object} context (optional) if provided, the callback function will
  2019. be executed in this object's context
  2020. @private
  2021. */
  2022. function load(type, urls, callback, obj, context) {
  2023. var _finish = function () { finish(type); },
  2024. isCSS = type === 'css',
  2025. nodes = [],
  2026. i, len, node, p, pendingUrls, url;
  2027. env || getEnv();
  2028. if (urls) {
  2029. // If urls is a string, wrap it in an array. Otherwise assume it's an
  2030. // array and create a copy of it so modifications won't be made to the
  2031. // original.
  2032. urls = typeof urls === 'string' ? [urls] : urls.concat();
  2033. // Create a request object for each URL. If multiple URLs are specified,
  2034. // the callback will only be executed after all URLs have been loaded.
  2035. //
  2036. // Sadly, Firefox and Opera are the only browsers capable of loading
  2037. // scripts in parallel while preserving execution order. In all other
  2038. // browsers, scripts must be loaded sequentially.
  2039. //
  2040. // All browsers respect CSS specificity based on the order of the link
  2041. // elements in the DOM, regardless of the order in which the stylesheets
  2042. // are actually downloaded.
  2043. if (isCSS || env.async || env.gecko || env.opera) {
  2044. // Load in parallel.
  2045. queue[type].push({
  2046. urls : urls,
  2047. callback: callback,
  2048. obj : obj,
  2049. context : context
  2050. });
  2051. } else {
  2052. // Load sequentially.
  2053. for (i = 0, len = urls.length; i < len; ++i) {
  2054. queue[type].push({
  2055. urls : [urls[i]],
  2056. callback: i === len - 1 ? callback : null, // callback is only added to the last URL
  2057. obj : obj,
  2058. context : context
  2059. });
  2060. }
  2061. }
  2062. }
  2063. // If a previous load request of this type is currently in progress, we'll
  2064. // wait our turn. Otherwise, grab the next item in the queue.
  2065. if (pending[type] || !(p = pending[type] = queue[type].shift())) {
  2066. return;
  2067. }
  2068. head || (head = doc.head || doc.getElementsByTagName('head')[0]);
  2069. pendingUrls = p.urls;
  2070. for (i = 0, len = pendingUrls.length; i < len; ++i) {
  2071. url = pendingUrls[i];
  2072. if (isCSS) {
  2073. node = env.gecko ? createNode('style') : createNode('link', {
  2074. href: url,
  2075. rel : 'stylesheet'
  2076. });
  2077. } else {
  2078. node = createNode('script', {src: url});
  2079. node.async = false;
  2080. }
  2081. node.className = 'lazyload';
  2082. node.setAttribute('charset', 'utf-8');
  2083. if (env.ie && !isCSS) {
  2084. node.onreadystatechange = function () {
  2085. if (/loaded|complete/.test(node.readyState)) {
  2086. node.onreadystatechange = null;
  2087. _finish();
  2088. }
  2089. };
  2090. } else if (isCSS && (env.gecko || env.webkit)) {
  2091. // Gecko and WebKit don't support the onload event on link nodes.
  2092. if (env.webkit) {
  2093. // In WebKit, we can poll for changes to document.styleSheets to
  2094. // figure out when stylesheets have loaded.
  2095. p.urls[i] = node.href; // resolve relative URLs (or polling won't work)
  2096. pollWebKit();
  2097. } else {
  2098. // In Gecko, we can import the requested URL into a <style> node and
  2099. // poll for the existence of node.sheet.cssRules. Props to Zach
  2100. // Leatherman for calling my attention to this technique.
  2101. node.innerHTML = '@import "' + url + '";';
  2102. pollGecko(node);
  2103. }
  2104. } else {
  2105. node.onload = node.onerror = _finish;
  2106. }
  2107. nodes.push(node);
  2108. }
  2109. for (i = 0, len = nodes.length; i < len; ++i) {
  2110. head.appendChild(nodes[i]);
  2111. }
  2112. }
  2113. /**
  2114. Begins polling to determine when the specified stylesheet has finished loading
  2115. in Gecko. Polling stops when all pending stylesheets have loaded or after 10
  2116. seconds (to prevent stalls).
  2117. Thanks to Zach Leatherman for calling my attention to the @import-based
  2118. cross-domain technique used here, and to Oleg Slobodskoi for an earlier
  2119. same-domain implementation. See Zach's blog for more details:
  2120. http://www.zachleat.com/web/2010/07/29/load-css-dynamically/
  2121. @method pollGecko
  2122. @param {HTMLElement} node Style node to poll.
  2123. @private
  2124. */
  2125. function pollGecko(node) {
  2126. var hasRules;
  2127. try {
  2128. // We don't really need to store this value or ever refer to it again, but
  2129. // if we don't store it, Closure Compiler assumes the code is useless and
  2130. // removes it.
  2131. hasRules = !!node.sheet.cssRules;
  2132. } catch (ex) {
  2133. // An exception means the stylesheet is still loading.
  2134. pollCount += 1;
  2135. if (pollCount < 200) {
  2136. setTimeout(function () { pollGecko(node); }, 50);
  2137. } else {
  2138. // We've been polling for 10 seconds and nothing's happened. Stop
  2139. // polling and finish the pending requests to avoid blocking further
  2140. // requests.
  2141. hasRules && finish('css');
  2142. }
  2143. return;
  2144. }
  2145. // If we get here, the stylesheet has loaded.
  2146. finish('css');
  2147. }
  2148. /**
  2149. Begins polling to determine when pending stylesheets have finished loading
  2150. in WebKit. Polling stops when all pending stylesheets have loaded or after 10
  2151. seconds (to prevent stalls).
  2152. @method pollWebKit
  2153. @private
  2154. */
  2155. function pollWebKit() {
  2156. var css = pending.css, i;
  2157. if (css) {
  2158. i = styleSheets.length;
  2159. // Look for a stylesheet matching the pending URL.
  2160. while (--i >= 0) {
  2161. if (styleSheets[i].href === css.urls[0]) {
  2162. finish('css');
  2163. break;
  2164. }
  2165. }
  2166. pollCount += 1;
  2167. if (css) {
  2168. if (pollCount < 200) {
  2169. setTimeout(pollWebKit, 50);
  2170. } else {
  2171. // We've been polling for 10 seconds and nothing's happened, which may
  2172. // indicate that the stylesheet has been removed from the document
  2173. // before it had a chance to load. Stop polling and finish the pending
  2174. // request to prevent blocking further requests.
  2175. finish('css');
  2176. }
  2177. }
  2178. }
  2179. }
  2180. return {
  2181. /**
  2182. Requests the specified CSS URL or URLs and executes the specified
  2183. callback (if any) when they have finished loading. If an array of URLs is
  2184. specified, the stylesheets will be loaded in parallel and the callback
  2185. will be executed after all stylesheets have finished loading.
  2186. @method css
  2187. @param {String|Array} urls CSS URL or array of CSS URLs to load
  2188. @param {Function} callback (optional) callback function to execute when
  2189. the specified stylesheets are loaded
  2190. @param {Object} obj (optional) object to pass to the callback function
  2191. @param {Object} context (optional) if provided, the callback function
  2192. will be executed in this object's context
  2193. @static
  2194. */
  2195. css: function (urls, callback, obj, context) {
  2196. load('css', urls, callback, obj, context);
  2197. },
  2198. /**
  2199. Requests the specified JavaScript URL or URLs and executes the specified
  2200. callback (if any) when they have finished loading. If an array of URLs is
  2201. specified and the browser supports it, the scripts will be loaded in
  2202. parallel and the callback will be executed after all scripts have
  2203. finished loading.
  2204. Currently, only Firefox and Opera support parallel loading of scripts while
  2205. preserving execution order. In other browsers, scripts will be
  2206. queued and loaded one at a time to ensure correct execution order.
  2207. @method js
  2208. @param {String|Array} urls JS URL or array of JS URLs to load
  2209. @param {Function} callback (optional) callback function to execute when
  2210. the specified scripts are loaded
  2211. @param {Object} obj (optional) object to pass to the callback function
  2212. @param {Object} context (optional) if provided, the callback function
  2213. will be executed in this object's context
  2214. @static
  2215. */
  2216. js: function (urls, callback, obj, context) {
  2217. load('js', urls, callback, obj, context);
  2218. }
  2219. };
  2220. })(this.document);
  2221. /* **********************************************
  2222. Begin VMM.LoadLib.js
  2223. ********************************************** */
  2224. /*
  2225. LoadLib
  2226. Designed and built by Zach Wise digitalartwork.net
  2227. */
  2228. /* * CodeKit Import
  2229. * http://incident57.com/codekit/
  2230. ================================================== */
  2231. // @codekit-prepend "../Library/LazyLoad.js";
  2232. LoadLib = (function (doc) {
  2233. var loaded = [];
  2234. function isLoaded(url) {
  2235. var i = 0,
  2236. has_loaded = false;
  2237. for (i = 0; i < loaded.length; i++) {
  2238. if (loaded[i] == url) {
  2239. has_loaded = true;
  2240. }
  2241. }
  2242. if (has_loaded) {
  2243. return true;
  2244. } else {
  2245. loaded.push(url);
  2246. return false;
  2247. }
  2248. }
  2249. return {
  2250. css: function (urls, callback, obj, context) {
  2251. if (!isLoaded(urls)) {
  2252. LazyLoad.css(urls, callback, obj, context);
  2253. }
  2254. },
  2255. js: function (urls, callback, obj, context) {
  2256. if (!isLoaded(urls)) {
  2257. LazyLoad.js(urls, callback, obj, context);
  2258. }
  2259. }
  2260. };
  2261. })(this.document);
  2262. /* **********************************************
  2263. Begin VMM.Language.js
  2264. ********************************************** */
  2265. /* DEFAULT LANGUAGE
  2266. ================================================== */
  2267. if(typeof VMM!="undefined"){VMM.Language={lang:"fr",api:{wikipedia:"fr"},date:{month:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],month_abbr:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","dec."],day:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],day_abbr:["Dim.","Lu.","Ma.","Me.","Jeu.","Vend.","Sam."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_short:"HH:MM:SS",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d mmmm yyyy'</small>'",full_long:"dddd',' d mmm yyyy 'à' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d mmm yyyy'</small>'"},messages:{loading_timeline:"Chargement de la frise en cours... ",return_to_title:"Retour à la page d'accueil",expand_timeline:"Elargir la frise",contract_timeline:"Réduire la frise",wikipedia:"Extrait de Wikipedia, l'encyclopédie libre",loading_content:"Chargement",loading:"Chargement",swipe_nav:"Swipe to Navigate"}}}
  2268. if(typeof VMM != 'undefined' && typeof VMM.Language == 'undefined') {
  2269. VMM.Language = {
  2270. lang: "en",
  2271. api: {
  2272. wikipedia: "en"
  2273. },
  2274. date: {
  2275. month: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
  2276. month_abbr: ["Jan.", "Feb.", "March", "April", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec."],
  2277. day: ["Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
  2278. day_abbr: ["Sun.","Mon.", "Tues.", "Wed.", "Thurs.", "Fri.", "Sat."]
  2279. },
  2280. dateformats: {
  2281. year: "yyyy",
  2282. month_short: "mmm",
  2283. month: "mmmm yyyy",
  2284. full_short: "mmm d",
  2285. full: "mmmm d',' yyyy",
  2286. time_short: "h:MM:ss TT",
  2287. time_no_seconds_short: "h:MM TT",
  2288. time_no_seconds_small_date: "h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",
  2289. full_long: "mmm d',' yyyy 'at' h:MM TT",
  2290. full_long_small_date: "h:MM TT'<br/><small>mmm d',' yyyy'</small>'"
  2291. },
  2292. messages: {
  2293. loading_timeline: "Loading Timeline... ",
  2294. return_to_title: "Return to Title",
  2295. expand_timeline: "Expand Timeline",
  2296. contract_timeline: "Contract Timeline",
  2297. wikipedia: "From Wikipedia, the free encyclopedia",
  2298. loading_content: "Loading Content",
  2299. loading: "Loading",
  2300. swipe_nav: "Swipe to Navigate"
  2301. }
  2302. }
  2303. };
  2304. /* **********************************************
  2305. Begin VMM.Core.js
  2306. ********************************************** */
  2307. /* VeriteCo Core
  2308. ================================================== */
  2309. /* * CodeKit Import
  2310. * http://incident57.com/codekit/
  2311. ================================================== */
  2312. // @codekit-prepend "VMM.js";
  2313. // @codekit-prepend "VMM.Library.js";
  2314. // @codekit-prepend "VMM.Browser.js";
  2315. // @codekit-prepend "VMM.FileExtention.js";
  2316. // @codekit-prepend "VMM.Date.js";
  2317. // @codekit-prepend "VMM.Util.js";
  2318. // @codekit-prepend "VMM.LoadLib.js";
  2319. // @codekit-prepend "VMM.Language.js";
  2320. /* **********************************************
  2321. Begin VMM.ExternalAPI.js
  2322. ********************************************** */
  2323. /* External API
  2324. ================================================== */
  2325. if(typeof VMM != 'undefined' && typeof VMM.ExternalAPI == 'undefined') {
  2326. VMM.ExternalAPI = ({
  2327. keys: {
  2328. google: "",
  2329. flickr: "",
  2330. twitter: ""
  2331. },
  2332. keys_master: {
  2333. vp: "Pellentesque nibh felis, eleifend id, commodo in, interdum vitae, leo",
  2334. flickr: "RAIvxHY4hE/Elm5cieh4X5ptMyDpj7MYIxziGxi0WGCcy1s+yr7rKQ==",
  2335. google: "jwNGnYw4hE9lmAez4ll0QD+jo6SKBJFknkopLS4FrSAuGfIwyj57AusuR0s8dAo=",
  2336. twitter: ""
  2337. },
  2338. init: function() {
  2339. return this;
  2340. },
  2341. setKeys: function(d) {
  2342. VMM.ExternalAPI.keys = d;
  2343. },
  2344. pushQues: function() {
  2345. if (VMM.master_config.googlemaps.active) {
  2346. VMM.ExternalAPI.googlemaps.pushQue();
  2347. }
  2348. if (VMM.master_config.youtube.active) {
  2349. VMM.ExternalAPI.youtube.pushQue();
  2350. }
  2351. if (VMM.master_config.soundcloud.active) {
  2352. VMM.ExternalAPI.soundcloud.pushQue();
  2353. }
  2354. if (VMM.master_config.googledocs.active) {
  2355. VMM.ExternalAPI.googledocs.pushQue();
  2356. }
  2357. if (VMM.master_config.googleplus.active) {
  2358. VMM.ExternalAPI.googleplus.pushQue();
  2359. }
  2360. if (VMM.master_config.wikipedia.active) {
  2361. VMM.ExternalAPI.wikipedia.pushQue();
  2362. }
  2363. if (VMM.master_config.vimeo.active) {
  2364. VMM.ExternalAPI.vimeo.pushQue();
  2365. }
  2366. if (VMM.master_config.vine.active) {
  2367. VMM.ExternalAPI.vine.pushQue();
  2368. }
  2369. if (VMM.master_config.twitter.active) {
  2370. VMM.ExternalAPI.twitter.pushQue();
  2371. }
  2372. if (VMM.master_config.flickr.active) {
  2373. VMM.ExternalAPI.flickr.pushQue();
  2374. }
  2375. if (VMM.master_config.webthumb.active) {
  2376. VMM.ExternalAPI.webthumb.pushQue();
  2377. }
  2378. },
  2379. twitter: {
  2380. tweetArray: [],
  2381. get: function(m) {
  2382. var tweet = {mid: m.id, id: m.uid};
  2383. VMM.master_config.twitter.que.push(tweet);
  2384. VMM.master_config.twitter.active = true;
  2385. //VMM.master_config.api.pushques.push(VMM.ExternalAPI.twitter.pushQue);
  2386. },
  2387. create: function(tweet, callback) {
  2388. var id = tweet.mid.toString(),
  2389. error_obj = { twitterid: tweet.mid },
  2390. the_url = "//api.twitter.com/1/statuses/show.json?id=" + tweet.mid + "&include_entities=true&callback=?";
  2391. //twitter_timeout = setTimeout(VMM.ExternalAPI.twitter.errorTimeOut, VMM.master_config.timers.api, tweet),
  2392. //callback_timeout= setTimeout(callback, VMM.master_config.timers.api, tweet);
  2393. VMM.ExternalAPI.twitter.getOEmbed(tweet, callback);
  2394. /*
  2395. // Disabled thanks to twitter's new api
  2396. VMM.getJSON(the_url, function(d) {
  2397. var id = d.id_str,
  2398. twit = "<blockquote><p>",
  2399. td = VMM.Util.linkify_with_twitter(d.text, "_blank");
  2400. // TWEET CONTENT
  2401. twit += td;
  2402. twit += "</p></blockquote>";
  2403. // TWEET MEDIA
  2404. if (typeof d.entities.media != 'undefined') {
  2405. if (d.entities.media[0].type == "photo") {
  2406. //twit += "<img src=' " + d.entities.media[0].media_url + "' alt=''>"
  2407. }
  2408. }
  2409. // TWEET AUTHOR
  2410. twit += "<div class='vcard author'>";
  2411. twit += "<a class='screen-name url' href='https://twitter.com/" + d.user.screen_name + "' data-screen-name='" + d.user.screen_name + "' target='_blank'>";
  2412. twit += "<span class='avatar'><img src=' " + d.user.profile_image_url + "' alt=''></span>";
  2413. twit += "<span class='fn'>" + d.user.name + "</span>";
  2414. twit += "<span class='nickname'>@" + d.user.screen_name + "<span class='thumbnail-inline'></span></span>";
  2415. twit += "</a>";
  2416. twit += "</div>";
  2417. VMM.attachElement("#"+tweet.id.toString(), twit );
  2418. VMM.attachElement("#text_thumb_"+tweet.id.toString(), d.text );
  2419. VMM.attachElement("#marker_content_" + tweet.id.toString(), d.text );
  2420. })
  2421. .error(function(jqXHR, textStatus, errorThrown) {
  2422. trace("TWITTER error");
  2423. trace("TWITTER ERROR: " + textStatus + " " + jqXHR.responseText);
  2424. VMM.attachElement("#"+tweet.id, VMM.MediaElement.loadingmessage("ERROR LOADING TWEET " + tweet.mid) );
  2425. })
  2426. .success(function(d) {
  2427. clearTimeout(twitter_timeout);
  2428. clearTimeout(callback_timeout);
  2429. callback();
  2430. });
  2431. */
  2432. },
  2433. errorTimeOut: function(tweet) {
  2434. trace("TWITTER JSON ERROR TIMEOUT " + tweet.mid);
  2435. VMM.attachElement("#"+tweet.id.toString(), VMM.MediaElement.loadingmessage("Still waiting on Twitter: " + tweet.mid) );
  2436. // CHECK RATE STATUS
  2437. VMM.getJSON("//api.twitter.com/1/account/rate_limit_status.json", function(d) {
  2438. trace("REMAINING TWITTER API CALLS " + d.remaining_hits);
  2439. trace("TWITTER RATE LIMIT WILL RESET AT " + d.reset_time);
  2440. var mes = "";
  2441. if (d.remaining_hits == 0) {
  2442. mes = "<p>You've reached the maximum number of tweets you can load in an hour.</p>";
  2443. mes += "<p>You can view tweets again starting at: <br/>" + d.reset_time + "</p>";
  2444. } else {
  2445. mes = "<p>Still waiting on Twitter. " + tweet.mid + "</p>";
  2446. //mes = "<p>Tweet " + id + " was not found.</p>";
  2447. }
  2448. VMM.attachElement("#"+tweet.id.toString(), VMM.MediaElement.loadingmessage(mes) );
  2449. });
  2450. },
  2451. errorTimeOutOembed: function(tweet) {
  2452. trace("TWITTER JSON ERROR TIMEOUT " + tweet.mid);
  2453. VMM.attachElement("#"+tweet.id.toString(), VMM.MediaElement.loadingmessage("Still waiting on Twitter: " + tweet.mid) );
  2454. },
  2455. pushQue: function() {
  2456. if (VMM.master_config.twitter.que.length > 0) {
  2457. VMM.ExternalAPI.twitter.create(VMM.master_config.twitter.que[0], VMM.ExternalAPI.twitter.pushQue);
  2458. VMM.Util.removeRange(VMM.master_config.twitter.que,0);
  2459. }
  2460. },
  2461. getOEmbed: function(tweet, callback) {
  2462. var the_url = "//api.twitter.com/1/statuses/oembed.json?id=" + tweet.mid + "&omit_script=true&include_entities=true&callback=?",
  2463. twitter_timeout = setTimeout(VMM.ExternalAPI.twitter.errorTimeOutOembed, VMM.master_config.timers.api, tweet);
  2464. //callback_timeout= setTimeout(callback, VMM.master_config.timers.api, tweet);
  2465. VMM.getJSON(the_url, function(d) {
  2466. var twit = "",
  2467. tuser = "";
  2468. // TWEET CONTENT
  2469. twit += d.html.split("<\/p>\&mdash;")[0] + "</p></blockquote>";
  2470. tuser = d.author_url.split("twitter.com\/")[1];
  2471. // TWEET AUTHOR
  2472. twit += "<div class='vcard author'>";
  2473. twit += "<a class='screen-name url' href='" + d.author_url + "' target='_blank'>";
  2474. twit += "<span class='avatar'></span>";
  2475. twit += "<span class='fn'>" + d.author_name + "</span>";
  2476. twit += "<span class='nickname'>@" + tuser + "<span class='thumbnail-inline'></span></span>";
  2477. twit += "</a>";
  2478. twit += "</div>";
  2479. VMM.attachElement("#"+tweet.id.toString(), twit );
  2480. VMM.attachElement("#text_thumb_"+tweet.id.toString(), d.html );
  2481. VMM.attachElement("#marker_content_" + tweet.id.toString(), d.html );
  2482. })
  2483. .error(function(jqXHR, textStatus, errorThrown) {
  2484. trace("TWITTER error");
  2485. trace("TWITTER ERROR: " + textStatus + " " + jqXHR.responseText);
  2486. clearTimeout(twitter_timeout);
  2487. //clearTimeout(callback_timeout);
  2488. VMM.attachElement("#"+tweet.id, VMM.MediaElement.loadingmessage("ERROR LOADING TWEET " + tweet.mid) );
  2489. })
  2490. .success(function(d) {
  2491. clearTimeout(twitter_timeout);
  2492. // clearTimeout(callback_timeout);
  2493. callback();
  2494. });
  2495. },
  2496. getHTML: function(id) {
  2497. //var the_url = document.location.protocol + "//api.twitter.com/1/statuses/oembed.json?id=" + id+ "&callback=?";
  2498. var the_url = "//api.twitter.com/1/statuses/oembed.json?id=" + id+ "&omit_script=true&include_entities=true&callback=?";
  2499. VMM.getJSON(the_url, VMM.ExternalAPI.twitter.onJSONLoaded);
  2500. },
  2501. onJSONLoaded: function(d) {
  2502. trace("TWITTER JSON LOADED");
  2503. var id = d.id;
  2504. VMM.attachElement("#"+id, VMM.Util.linkify_with_twitter(d.html) );
  2505. },
  2506. parseTwitterDate: function(d) {
  2507. var date = new Date(Date.parse(d));
  2508. /*
  2509. var t = d.replace(/(\d{1,2}[:]\d{2}[:]\d{2}) (.*)/, '$2 $1');
  2510. t = t.replace(/(\+\S+) (.*)/, '$2 $1');
  2511. var date = new Date(Date.parse(t)).toLocaleDateString();
  2512. var time = new Date(Date.parse(t)).toLocaleTimeString();
  2513. */
  2514. return date;
  2515. },
  2516. prettyParseTwitterDate: function(d) {
  2517. var date = new Date(Date.parse(d));
  2518. return VMM.Date.prettyDate(date, true);
  2519. },
  2520. getTweets: function(tweets) {
  2521. var tweetArray = [];
  2522. var number_of_tweets = tweets.length;
  2523. for(var i = 0; i < tweets.length; i++) {
  2524. var twitter_id = "";
  2525. /* FIND THE TWITTER ID
  2526. ================================================== */
  2527. if (tweets[i].tweet.match("status\/")) {
  2528. twitter_id = tweets[i].tweet.split("status\/")[1];
  2529. } else if (tweets[i].tweet.match("statuses\/")) {
  2530. twitter_id = tweets[i].tweet.split("statuses\/")[1];
  2531. } else {
  2532. twitter_id = "";
  2533. }
  2534. /* FETCH THE DATA
  2535. ================================================== */
  2536. var the_url = "//api.twitter.com/1/statuses/show.json?id=" + twitter_id + "&include_entities=true&callback=?";
  2537. VMM.getJSON(the_url, function(d) {
  2538. var tweet = {}
  2539. /* FORMAT RESPONSE
  2540. ================================================== */
  2541. var twit = "<div class='twitter'><blockquote><p>";
  2542. var td = VMM.Util.linkify_with_twitter(d.text, "_blank");
  2543. twit += td;
  2544. twit += "</p>";
  2545. twit += "— " + d.user.name + " (<a href='https://twitter.com/" + d.user.screen_name + "'>@" + d.user.screen_name + "</a>) <a href='https://twitter.com/" + d.user.screen_name + "/status/" + d.id + "'>" + VMM.ExternalAPI.twitter.prettyParseTwitterDate(d.created_at) + " </a></blockquote></div>";
  2546. tweet.content = twit;
  2547. tweet.raw = d;
  2548. tweetArray.push(tweet);
  2549. /* CHECK IF THATS ALL OF THEM
  2550. ================================================== */
  2551. if (tweetArray.length == number_of_tweets) {
  2552. var the_tweets = {tweetdata: tweetArray}
  2553. VMM.fireEvent(global, "TWEETSLOADED", the_tweets);
  2554. }
  2555. })
  2556. .success(function() { trace("second success"); })
  2557. .error(function() { trace("error"); })
  2558. .complete(function() { trace("complete"); });
  2559. }
  2560. },
  2561. getTweetSearch: function(tweets, number_of_tweets) {
  2562. var _number_of_tweets = 40;
  2563. if (number_of_tweets != null && number_of_tweets != "") {
  2564. _number_of_tweets = number_of_tweets;
  2565. }
  2566. var the_url = "//search.twitter.com/search.json?q=" + tweets + "&rpp=" + _number_of_tweets + "&include_entities=true&result_type=mixed";
  2567. var tweetArray = [];
  2568. VMM.getJSON(the_url, function(d) {
  2569. /* FORMAT RESPONSE
  2570. ================================================== */
  2571. for(var i = 0; i < d.results.length; i++) {
  2572. var tweet = {}
  2573. var twit = "<div class='twitter'><blockquote><p>";
  2574. var td = VMM.Util.linkify_with_twitter(d.results[i].text, "_blank");
  2575. twit += td;
  2576. twit += "</p>";
  2577. twit += "— " + d.results[i].from_user_name + " (<a href='https://twitter.com/" + d.results[i].from_user + "'>@" + d.results[i].from_user + "</a>) <a href='https://twitter.com/" + d.results[i].from_user + "/status/" + d.id + "'>" + VMM.ExternalAPI.twitter.prettyParseTwitterDate(d.results[i].created_at) + " </a></blockquote></div>";
  2578. tweet.content = twit;
  2579. tweet.raw = d.results[i];
  2580. tweetArray.push(tweet);
  2581. }
  2582. var the_tweets = {tweetdata: tweetArray}
  2583. VMM.fireEvent(global, "TWEETSLOADED", the_tweets);
  2584. });
  2585. },
  2586. prettyHTML: function(id, secondary) {
  2587. var id = id.toString();
  2588. var error_obj = {
  2589. twitterid: id
  2590. };
  2591. var the_url = "//api.twitter.com/1/statuses/show.json?id=" + id + "&include_entities=true&callback=?";
  2592. var twitter_timeout = setTimeout(VMM.ExternalAPI.twitter.errorTimeOut, VMM.master_config.timers.api, id);
  2593. VMM.getJSON(the_url, VMM.ExternalAPI.twitter.formatJSON)
  2594. .error(function(jqXHR, textStatus, errorThrown) {
  2595. trace("TWITTER error");
  2596. trace("TWITTER ERROR: " + textStatus + " " + jqXHR.responseText);
  2597. VMM.attachElement("#twitter_"+id, "<p>ERROR LOADING TWEET " + id + "</p>" );
  2598. })
  2599. .success(function(d) {
  2600. clearTimeout(twitter_timeout);
  2601. if (secondary) {
  2602. VMM.ExternalAPI.twitter.secondaryMedia(d);
  2603. }
  2604. });
  2605. },
  2606. formatJSON: function(d) {
  2607. var id = d.id_str;
  2608. var twit = "<blockquote><p>";
  2609. var td = VMM.Util.linkify_with_twitter(d.text, "_blank");
  2610. //td = td.replace(/(@([\w]+))/g,"<a href='http://twitter.com/$2' target='_blank'>$1</a>");
  2611. //td = td.replace(/(#([\w]+))/g,"<a href='http://twitter.com/#search?q=%23$2' target='_blank'>$1</a>");
  2612. twit += td;
  2613. twit += "</p></blockquote>";
  2614. //twit += " <a href='https://twitter.com/" + d.user.screen_name + "/status/" + d.id_str + "' target='_blank' alt='link to original tweet' title='link to original tweet'>" + "<span class='created-at'></span>" + " </a>";
  2615. twit += "<div class='vcard author'>";
  2616. twit += "<a class='screen-name url' href='https://twitter.com/" + d.user.screen_name + "' data-screen-name='" + d.user.screen_name + "' target='_blank'>";
  2617. twit += "<span class='avatar'><img src=' " + d.user.profile_image_url + "' alt=''></span>";
  2618. twit += "<span class='fn'>" + d.user.name + "</span>";
  2619. twit += "<span class='nickname'>@" + d.user.screen_name + "<span class='thumbnail-inline'></span></span>";
  2620. twit += "</a>";
  2621. twit += "</div>";
  2622. if (typeof d.entities.media != 'undefined') {
  2623. if (d.entities.media[0].type == "photo") {
  2624. twit += "<img src=' " + d.entities.media[0].media_url + "' alt=''>"
  2625. }
  2626. }
  2627. VMM.attachElement("#twitter_"+id.toString(), twit );
  2628. VMM.attachElement("#text_thumb_"+id.toString(), d.text );
  2629. }
  2630. },
  2631. googlemaps: {
  2632. maptype: "TERRAIN", // see also below for default if this is a google type
  2633. setMapType: function(d) {
  2634. if (d != "") {
  2635. VMM.ExternalAPI.googlemaps.maptype = d;
  2636. }
  2637. },
  2638. get: function(m) {
  2639. var timer,
  2640. api_key,
  2641. map_url;
  2642. m.vars = VMM.Util.getUrlVars(m.id);
  2643. if (VMM.ExternalAPI.keys.google != "") {
  2644. api_key = VMM.ExternalAPI.keys.google;
  2645. } else {
  2646. api_key = Aes.Ctr.decrypt(VMM.ExternalAPI.keys_master.google, VMM.ExternalAPI.keys_master.vp, 256);
  2647. }
  2648. /*
  2649. Investigating a google map api change on the latest release that causes custom map types to stop working
  2650. http://stackoverflow.com/questions/13486271/google-map-markermanager-cannot-call-method-substr-of-undefined
  2651. soulution is to use api ver 3.9
  2652. */
  2653. map_url = "//maps.googleapis.com/maps/api/js?key=" + api_key + "&v=3.9&libraries=places&sensor=false&callback=VMM.ExternalAPI.googlemaps.onMapAPIReady";
  2654. if (VMM.master_config.googlemaps.active) {
  2655. VMM.master_config.googlemaps.que.push(m);
  2656. } else {
  2657. VMM.master_config.googlemaps.que.push(m);
  2658. if (VMM.master_config.googlemaps.api_loaded) {
  2659. } else {
  2660. LoadLib.js(map_url, function() {
  2661. trace("Google Maps API Library Loaded");
  2662. });
  2663. }
  2664. }
  2665. },
  2666. create: function(m) {
  2667. VMM.ExternalAPI.googlemaps.createAPIMap(m);
  2668. },
  2669. createiFrameMap: function(m) {
  2670. var embed_url = m.id + "&output=embed",
  2671. mc = "",
  2672. unique_map_id = m.uid.toString() + "_gmap";
  2673. mc += "<div class='google-map' id='" + unique_map_id + "' style='width=100%;height=100%;'>";
  2674. mc += "<iframe width='100%' height='100%' frameborder='0' scrolling='no' marginheight='0' marginwidth='0' src='" + embed_url + "'></iframe>";
  2675. mc += "</div>";
  2676. VMM.attachElement("#" + m.uid, mc);
  2677. },
  2678. createAPIMap: function(m) {
  2679. var map_attribution = "",
  2680. layer,
  2681. map,
  2682. map_options,
  2683. unique_map_id = m.uid.toString() + "_gmap",
  2684. map_attribution_html = "",
  2685. location = new google.maps.LatLng(41.875696,-87.624207),
  2686. latlong,
  2687. zoom = 11,
  2688. has_location = false,
  2689. has_zoom = false,
  2690. api_limit = false,
  2691. map_bounds;
  2692. function mapProvider(name) {
  2693. if (name in VMM.ExternalAPI.googlemaps.map_providers) {
  2694. map_attribution = VMM.ExternalAPI.googlemaps.map_attribution[VMM.ExternalAPI.googlemaps.map_providers[name].attribution];
  2695. return VMM.ExternalAPI.googlemaps.map_providers[name];
  2696. } else {
  2697. if (VMM.ExternalAPI.googlemaps.defaultType(name)) {
  2698. trace("GOOGLE MAP DEFAULT TYPE");
  2699. return google.maps.MapTypeId[name.toUpperCase()];
  2700. } else {
  2701. trace("Not a maptype: " + name );
  2702. }
  2703. }
  2704. }
  2705. google.maps.VeriteMapType = function(name) {
  2706. if (VMM.ExternalAPI.googlemaps.defaultType(name)) {
  2707. return google.maps.MapTypeId[name.toUpperCase()];
  2708. } else {
  2709. var provider = mapProvider(name);
  2710. return google.maps.ImageMapType.call(this, {
  2711. "getTileUrl": function(coord, zoom) {
  2712. var index = (zoom + coord.x + coord.y) % VMM.ExternalAPI.googlemaps.map_subdomains.length;
  2713. var retURL = provider.url
  2714. .replace("{S}", VMM.ExternalAPI.googlemaps.map_subdomains[index])
  2715. .replace("{Z}", zoom)
  2716. .replace("{X}", coord.x)
  2717. .replace("{Y}", coord.y)
  2718. .replace("{z}", zoom)
  2719. .replace("{x}", coord.x)
  2720. .replace("{y}", coord.y);
  2721. // trace(retURL);
  2722. return retURL;
  2723. },
  2724. "tileSize": new google.maps.Size(256, 256),
  2725. "name": name,
  2726. "minZoom": provider.minZoom,
  2727. "maxZoom": provider.maxZoom
  2728. });
  2729. }
  2730. };
  2731. google.maps.VeriteMapType.prototype = new google.maps.ImageMapType("_");
  2732. /* Make the Map
  2733. ================================================== */
  2734. if (VMM.ExternalAPI.googlemaps.maptype != "") {
  2735. if (VMM.ExternalAPI.googlemaps.defaultType(VMM.ExternalAPI.googlemaps.maptype)) {
  2736. layer = google.maps.MapTypeId[VMM.ExternalAPI.googlemaps.maptype.toUpperCase()];
  2737. } else {
  2738. layer = VMM.ExternalAPI.googlemaps.maptype;
  2739. }
  2740. } else {
  2741. layer = google.maps.MapTypeId['TERRAIN'];
  2742. }
  2743. var new_google_url_regex = new RegExp(/@([0-9\.\-]+),([0-9\.\-]+),(\d+)z/);
  2744. if (m.id.match(new_google_url_regex)) {
  2745. var match = m.id.match(new_google_url_regex)
  2746. lat = parseFloat(match[1]);
  2747. lng = parseFloat(match[2]);
  2748. location = new google.maps.LatLng(lat,lng);
  2749. zoom = parseFloat(match[3]);
  2750. has_location = has_zoom = true;
  2751. } else {
  2752. if (type.of(VMM.Util.getUrlVars(m.id)["ll"]) == "string") {
  2753. has_location = true;
  2754. latlong = VMM.Util.getUrlVars(m.id)["ll"].split(",");
  2755. location = new google.maps.LatLng(parseFloat(latlong[0]),parseFloat(latlong[1]));
  2756. } else if (type.of(VMM.Util.getUrlVars(m.id)["sll"]) == "string") {
  2757. latlong = VMM.Util.getUrlVars(m.id)["sll"].split(",");
  2758. location = new google.maps.LatLng(parseFloat(latlong[0]),parseFloat(latlong[1]));
  2759. }
  2760. if (type.of(VMM.Util.getUrlVars(m.id)["z"]) == "string") {
  2761. has_zoom = true;
  2762. zoom = parseFloat(VMM.Util.getUrlVars(m.id)["z"]);
  2763. }
  2764. }
  2765. map_options = {
  2766. zoom: zoom,
  2767. draggable: false,
  2768. disableDefaultUI: true,
  2769. mapTypeControl: false,
  2770. zoomControl: true,
  2771. zoomControlOptions: {
  2772. style: google.maps.ZoomControlStyle.SMALL,
  2773. position: google.maps.ControlPosition.TOP_RIGHT
  2774. },
  2775. center: location,
  2776. mapTypeId: layer,
  2777. mapTypeControlOptions: {
  2778. mapTypeIds: [layer]
  2779. }
  2780. }
  2781. VMM.attachElement("#" + m.uid, "<div class='google-map' id='" + unique_map_id + "' style='width=100%;height=100%;'></div>");
  2782. map = new google.maps.Map(document.getElementById(unique_map_id), map_options);
  2783. if (VMM.ExternalAPI.googlemaps.defaultType(VMM.ExternalAPI.googlemaps.maptype)) {
  2784. } else {
  2785. map.mapTypes.set(layer, new google.maps.VeriteMapType(layer));
  2786. // ATTRIBUTION
  2787. map_attribution_html = "<div class='map-attribution'><div class='attribution-text'>" + map_attribution + "</div></div>";
  2788. VMM.appendElement("#"+unique_map_id, map_attribution_html);
  2789. }
  2790. // DETERMINE IF KML IS POSSIBLE
  2791. if (type.of(VMM.Util.getUrlVars(m.id)["msid"]) == "string") {
  2792. loadKML();
  2793. } else {
  2794. //loadPlaces();
  2795. if (type.of(VMM.Util.getUrlVars(m.id)["q"]) == "string") {
  2796. geocodePlace();
  2797. }
  2798. }
  2799. // GEOCODE
  2800. function geocodePlace() {
  2801. var geocoder = new google.maps.Geocoder(),
  2802. address = VMM.Util.getUrlVars(m.id)["q"],
  2803. marker;
  2804. if (address.match("loc:")) {
  2805. var address_latlon = address.split(":")[1].split("+");
  2806. location = new google.maps.LatLng(parseFloat(address_latlon[0]),parseFloat(address_latlon[1]));
  2807. has_location = true;
  2808. }
  2809. geocoder.geocode( { 'address': address}, function(results, status) {
  2810. if (status == google.maps.GeocoderStatus.OK) {
  2811. marker = new google.maps.Marker({
  2812. map: map,
  2813. position: results[0].geometry.location
  2814. });
  2815. // POSITION MAP
  2816. //map.setCenter(results[0].geometry.location);
  2817. //map.panTo(location);
  2818. if (typeof results[0].geometry.viewport != 'undefined') {
  2819. map.fitBounds(results[0].geometry.viewport);
  2820. } else if (typeof results[0].geometry.bounds != 'undefined') {
  2821. map.fitBounds(results[0].geometry.bounds);
  2822. } else {
  2823. map.setCenter(results[0].geometry.location);
  2824. }
  2825. if (has_location) {
  2826. map.panTo(location);
  2827. }
  2828. if (has_zoom) {
  2829. map.setZoom(zoom);
  2830. }
  2831. } else {
  2832. trace("Geocode for " + address + " was not successful for the following reason: " + status);
  2833. trace("TRYING PLACES SEARCH");
  2834. if (has_location) {
  2835. map.panTo(location);
  2836. }
  2837. if (has_zoom) {
  2838. map.setZoom(zoom);
  2839. }
  2840. loadPlaces();
  2841. }
  2842. });
  2843. }
  2844. // PLACES
  2845. function loadPlaces() {
  2846. var place,
  2847. search_request,
  2848. infowindow,
  2849. search_bounds,
  2850. bounds_sw,
  2851. bounds_ne;
  2852. place_search = new google.maps.places.PlacesService(map);
  2853. infowindow = new google.maps.InfoWindow();
  2854. search_request = {
  2855. query: "",
  2856. types: ['country', 'neighborhood', 'political', 'locality', 'geocode']
  2857. };
  2858. if (type.of(VMM.Util.getUrlVars(m.id)["q"]) == "string") {
  2859. search_request.query = VMM.Util.getUrlVars(m.id)["q"];
  2860. }
  2861. if (has_location) {
  2862. search_request.location = location;
  2863. search_request.radius = "15000";
  2864. } else {
  2865. bounds_sw = new google.maps.LatLng(-89.999999,-179.999999);
  2866. bounds_ne = new google.maps.LatLng(89.999999,179.999999);
  2867. search_bounds = new google.maps.LatLngBounds(bounds_sw,bounds_ne);
  2868. //search_request.location = search_bounds;
  2869. }
  2870. place_search.textSearch(search_request, placeResults);
  2871. function placeResults(results, status) {
  2872. if (status == google.maps.places.PlacesServiceStatus.OK) {
  2873. for (var i = 0; i < results.length; i++) {
  2874. //createMarker(results[i]);
  2875. }
  2876. if (has_location) {
  2877. map.panTo(location);
  2878. } else {
  2879. if (results.length >= 1) {
  2880. map.panTo(results[0].geometry.location);
  2881. if (has_zoom) {
  2882. map.setZoom(zoom);
  2883. }
  2884. }
  2885. }
  2886. } else {
  2887. trace("Place search for " + search_request.query + " was not successful for the following reason: " + status);
  2888. // IF There's a problem loading the map, load a simple iFrame version instead
  2889. trace("YOU MAY NEED A GOOGLE MAPS API KEY IN ORDER TO USE THIS FEATURE OF TIMELINEJS");
  2890. trace("FIND OUT HOW TO GET YOUR KEY HERE: https://developers.google.com/places/documentation/#Authentication");
  2891. if (has_location) {
  2892. map.panTo(location);
  2893. if (has_zoom) {
  2894. map.setZoom(zoom);
  2895. }
  2896. } else {
  2897. trace("USING SIMPLE IFRAME MAP EMBED");
  2898. if (m.id[0].match("https")) {
  2899. m.id = m.url[0].replace("https", "http");
  2900. }
  2901. VMM.ExternalAPI.googlemaps.createiFrameMap(m);
  2902. }
  2903. }
  2904. }
  2905. function createMarker(place) {
  2906. var marker, placeLoc;
  2907. placeLoc = place.geometry.location;
  2908. marker = new google.maps.Marker({
  2909. map: map,
  2910. position: place.geometry.location
  2911. });
  2912. google.maps.event.addListener(marker, 'click', function() {
  2913. infowindow.setContent(place.name);
  2914. infowindow.open(map, this);
  2915. });
  2916. }
  2917. }
  2918. function loadPlacesAlt() {
  2919. var api_key,
  2920. places_url,
  2921. has_key = false;
  2922. trace("LOADING PLACES API FOR GOOGLE MAPS");
  2923. if (VMM.ExternalAPI.keys.google != "") {
  2924. api_key = VMM.ExternalAPI.keys.google;
  2925. has_key = true;
  2926. } else {
  2927. trace("YOU NEED A GOOGLE MAPS API KEY IN ORDER TO USE THIS FEATURE OF TIMELINEJS");
  2928. trace("FIND OUT HOW TO GET YOUR KEY HERE: https://developers.google.com/places/documentation/#Authentication");
  2929. }
  2930. places_url = "https://maps.googleapis.com/maps/api/place/textsearch/json?key=" + api_key + "&sensor=false&language=" + m.lang + "&";
  2931. if (type.of(VMM.Util.getUrlVars(m.id)["q"]) == "string") {
  2932. places_url += "query=" + VMM.Util.getUrlVars(m.id)["q"];
  2933. }
  2934. if (has_location) {
  2935. places_url += "&location=" + location;
  2936. }
  2937. if (has_key) {
  2938. VMM.getJSON(places_url, function(d) {
  2939. trace("PLACES JSON");
  2940. var places_location = "",
  2941. places_bounds = "",
  2942. places_bounds_ne = "",
  2943. places_bounds_sw = "";
  2944. trace(d);
  2945. if (d.status == "OVER_QUERY_LIMIT") {
  2946. trace("OVER_QUERY_LIMIT");
  2947. if (has_location) {
  2948. map.panTo(location);
  2949. if (has_zoom) {
  2950. map.setZoom(zoom);
  2951. }
  2952. } else {
  2953. trace("DOING TRADITIONAL MAP IFRAME EMBED UNTIL QUERY LIMIT RESTORED");
  2954. api_limit = true;
  2955. VMM.ExternalAPI.googlemaps.createiFrameMap(m);
  2956. }
  2957. } else {
  2958. if (d.results.length >= 1) {
  2959. //location = new google.maps.LatLng(parseFloat(d.results[0].geometry.location.lat),parseFloat(d.results[0].geometry.location.lng));
  2960. //map.panTo(location);
  2961. places_bounds_ne = new google.maps.LatLng(parseFloat(d.results[0].geometry.viewport.northeast.lat),parseFloat(d.results[0].geometry.viewport.northeast.lng));
  2962. places_bounds_sw = new google.maps.LatLng(parseFloat(d.results[0].geometry.viewport.southwest.lat),parseFloat(d.results[0].geometry.viewport.southwest.lng));
  2963. places_bounds = new google.maps.LatLngBounds(places_bounds_sw, places_bounds_ne)
  2964. map.fitBounds(places_bounds);
  2965. } else {
  2966. trace("NO RESULTS");
  2967. }
  2968. if (has_location) {
  2969. map.panTo(location);
  2970. }
  2971. if (has_zoom) {
  2972. map.setZoom(zoom);
  2973. }
  2974. }
  2975. })
  2976. .error(function(jqXHR, textStatus, errorThrown) {
  2977. trace("PLACES JSON ERROR");
  2978. trace("PLACES JSON ERROR: " + textStatus + " " + jqXHR.responseText);
  2979. })
  2980. .success(function(d) {
  2981. trace("PLACES JSON SUCCESS");
  2982. });
  2983. } else {
  2984. if (has_location) {
  2985. map.panTo(location);
  2986. if (has_zoom) {
  2987. map.setZoom(zoom);
  2988. }
  2989. } else {
  2990. trace("DOING TRADITIONAL MAP IFRAME EMBED BECAUSE NO GOOGLE MAP API KEY WAS PROVIDED");
  2991. VMM.ExternalAPI.googlemaps.createiFrameMap(m);
  2992. }
  2993. }
  2994. }
  2995. // KML
  2996. function loadKML() {
  2997. var kml_url, kml_layer, infowindow, text;
  2998. kml_url = m.id + "&output=kml";
  2999. kml_url = kml_url.replace("&output=embed", "");
  3000. kml_layer = new google.maps.KmlLayer(kml_url, {preserveViewport:true});
  3001. infowindow = new google.maps.InfoWindow();
  3002. kml_layer.setMap(map);
  3003. google.maps.event.addListenerOnce(kml_layer, "defaultviewport_changed", function() {
  3004. if (has_location) {
  3005. map.panTo(location);
  3006. } else {
  3007. map.fitBounds(kml_layer.getDefaultViewport() );
  3008. }
  3009. if (has_zoom) {
  3010. map.setZoom(zoom);
  3011. }
  3012. });
  3013. google.maps.event.addListener(kml_layer, 'click', function(kmlEvent) {
  3014. text = kmlEvent.featureData.description;
  3015. showInfoWindow(text);
  3016. function showInfoWindow(c) {
  3017. infowindow.setContent(c);
  3018. infowindow.open(map);
  3019. }
  3020. });
  3021. }
  3022. },
  3023. pushQue: function() {
  3024. for(var i = 0; i < VMM.master_config.googlemaps.que.length; i++) {
  3025. VMM.ExternalAPI.googlemaps.create(VMM.master_config.googlemaps.que[i]);
  3026. }
  3027. VMM.master_config.googlemaps.que = [];
  3028. },
  3029. onMapAPIReady: function() {
  3030. VMM.master_config.googlemaps.map_active = true;
  3031. VMM.master_config.googlemaps.places_active = true;
  3032. VMM.ExternalAPI.googlemaps.onAPIReady();
  3033. },
  3034. onPlacesAPIReady: function() {
  3035. VMM.master_config.googlemaps.places_active = true;
  3036. VMM.ExternalAPI.googlemaps.onAPIReady();
  3037. },
  3038. onAPIReady: function() {
  3039. if (!VMM.master_config.googlemaps.active) {
  3040. if (VMM.master_config.googlemaps.map_active && VMM.master_config.googlemaps.places_active) {
  3041. VMM.master_config.googlemaps.active = true;
  3042. VMM.ExternalAPI.googlemaps.pushQue();
  3043. }
  3044. }
  3045. },
  3046. defaultType: function(name) {
  3047. if (name.toLowerCase() == "satellite" || name.toLowerCase() == "hybrid" || name.toLowerCase() == "terrain" || name.toLowerCase() == "roadmap") {
  3048. return true;
  3049. } else {
  3050. return false;
  3051. }
  3052. },
  3053. map_subdomains: ["", "a.", "b.", "c.", "d."],
  3054. map_attribution: {
  3055. "stamen": "Map tiles by <a href='http://stamen.com'>Stamen Design</a>, under <a href='http://creativecommons.org/licenses/by/3.0'>CC BY 3.0</a>. Data by <a href='http://openstreetmap.org'>OpenStreetMap</a>, under <a href='http://creativecommons.org/licenses/by-sa/3.0'>CC BY SA</a>.",
  3056. "apple": "Map data &copy; 2012 Apple, Imagery &copy; 2012 Apple",
  3057. "osm": "&copy; <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
  3058. },
  3059. map_providers: {
  3060. "toner": {
  3061. "url": "//{S}tile.stamen.com/toner/{Z}/{X}/{Y}.png",
  3062. "minZoom": 0,
  3063. "maxZoom": 20,
  3064. "attribution": "stamen"
  3065. },
  3066. "toner-lines": {
  3067. "url": "//{S}tile.stamen.com/toner-lines/{Z}/{X}/{Y}.png",
  3068. "minZoom": 0,
  3069. "maxZoom": 20,
  3070. "attribution": "stamen"
  3071. },
  3072. "toner-labels": {
  3073. "url": "//{S}tile.stamen.com/toner-labels/{Z}/{X}/{Y}.png",
  3074. "minZoom": 0,
  3075. "maxZoom": 20,
  3076. "attribution": "stamen"
  3077. },
  3078. "sterrain": {
  3079. "url": "//{S}tile.stamen.com/terrain/{Z}/{X}/{Y}.jpg",
  3080. "minZoom": 4,
  3081. "maxZoom": 20,
  3082. "attribution": "stamen"
  3083. },
  3084. "apple": {
  3085. "url": "//gsp2.apple.com/tile?api=1&style=slideshow&layers=default&lang=en_US&z={z}&x={x}&y={y}&v=9",
  3086. "minZoom": 4,
  3087. "maxZoom": 14,
  3088. "attribution": "apple"
  3089. },
  3090. "watercolor": {
  3091. "url": "//{S}tile.stamen.com/watercolor/{Z}/{X}/{Y}.jpg",
  3092. "minZoom": 3,
  3093. "maxZoom": 16,
  3094. "attribution": "stamen"
  3095. },
  3096. "osm": {
  3097. "url": "//tile.openstreetmap.org/{z}/{x}/{y}.png",
  3098. "minZoom": 3,
  3099. "maxZoom": 18,
  3100. "attribution": "osm"
  3101. }
  3102. }
  3103. },
  3104. googleplus: {
  3105. get: function(m) {
  3106. var api_key;
  3107. var gplus = {user: m.user, activity: m.id, id: m.uid};
  3108. VMM.master_config.googleplus.que.push(gplus);
  3109. VMM.master_config.googleplus.active = true;
  3110. },
  3111. create: function(gplus, callback) {
  3112. var mediaElem = "",
  3113. api_key = "",
  3114. g_activity = "",
  3115. g_content = "",
  3116. g_attachments = "",
  3117. gperson_api_url,
  3118. gactivity_api_url;
  3119. googleplus_timeout = setTimeout(VMM.ExternalAPI.googleplus.errorTimeOut, VMM.master_config.timers.api, gplus),
  3120. callback_timeout = setTimeout(callback, VMM.master_config.timers.api, gplus);
  3121. if (VMM.master_config.Timeline.api_keys.google != "") {
  3122. api_key = VMM.master_config.Timeline.api_keys.google;
  3123. } else {
  3124. api_key = Aes.Ctr.decrypt(VMM.master_config.api_keys_master.google, VMM.master_config.vp, 256);
  3125. }
  3126. gperson_api_url = "https://www.googleapis.com/plus/v1/people/" + gplus.user + "/activities/public?alt=json&maxResults=100&fields=items(id,url)&key=" + api_key;
  3127. //mediaElem = "<iframe class='doc' frameborder='0' width='100%' height='100%' src='" + gplus.url + "&amp;embedded=true'></iframe>";
  3128. mediaElem = "GOOGLE PLUS API CALL";
  3129. VMM.getJSON(gperson_api_url, function(p_data) {
  3130. for(var i = 0; i < p_data.items.length; i++) {
  3131. trace("loop");
  3132. if (p_data.items[i].url.split("posts/")[1] == gplus.activity) {
  3133. trace("FOUND IT!!");
  3134. g_activity = p_data.items[i].id;
  3135. gactivity_api_url = "https://www.googleapis.com/plus/v1/activities/" + g_activity + "?alt=json&key=" + api_key;
  3136. VMM.getJSON(gactivity_api_url, function(a_data) {
  3137. trace(a_data);
  3138. //a_data.url
  3139. //a_data.image.url
  3140. //a_data.actor.displayName
  3141. //a_data.provider.title
  3142. //a_data.object.content
  3143. //g_content += "<h4>" + a_data.title + "</h4>";
  3144. if (typeof a_data.annotation != 'undefined') {
  3145. g_content += "<div class='googleplus-annotation'>'" + a_data.annotation + "</div>";
  3146. g_content += a_data.object.content;
  3147. } else {
  3148. g_content += a_data.object.content;
  3149. }
  3150. if (typeof a_data.object.attachments != 'undefined') {
  3151. //g_attachments += "<div class='googleplus-attachemnts'>";
  3152. for(var k = 0; k < a_data.object.attachments.length; k++) {
  3153. if (a_data.object.attachments[k].objectType == "photo") {
  3154. g_attachments = "<a href='" + a_data.object.url + "' target='_blank'>" + "<img src='" + a_data.object.attachments[k].image.url + "' class='article-thumb'></a>" + g_attachments;
  3155. } else if (a_data.object.attachments[k].objectType == "video") {
  3156. g_attachments = "<img src='" + a_data.object.attachments[k].image.url + "' class='article-thumb'>" + g_attachments;
  3157. g_attachments += "<div>";
  3158. g_attachments += "<a href='" + a_data.object.attachments[k].url + "' target='_blank'>"
  3159. g_attachments += "<h5>" + a_data.object.attachments[k].displayName + "</h5>";
  3160. //g_attachments += "<p>" + a_data.object.attachments[k].content + "</p>";
  3161. g_attachments += "</a>";
  3162. g_attachments += "</div>";
  3163. } else if (a_data.object.attachments[k].objectType == "article") {
  3164. g_attachments += "<div>";
  3165. g_attachments += "<a href='" + a_data.object.attachments[k].url + "' target='_blank'>"
  3166. g_attachments += "<h5>" + a_data.object.attachments[k].displayName + "</h5>";
  3167. g_attachments += "<p>" + a_data.object.attachments[k].content + "</p>";
  3168. g_attachments += "</a>";
  3169. g_attachments += "</div>";
  3170. }
  3171. trace(a_data.object.attachments[k]);
  3172. }
  3173. g_attachments = "<div class='googleplus-attachments'>" + g_attachments + "</div>";
  3174. }
  3175. //mediaElem = "<div class='googleplus'>";
  3176. mediaElem = "<div class='googleplus-content'>" + g_content + g_attachments + "</div>";
  3177. mediaElem += "<div class='vcard author'><a class='screen-name url' href='" + a_data.url + "' target='_blank'>";
  3178. mediaElem += "<span class='avatar'><img src='" + a_data.actor.image.url + "' style='max-width: 32px; max-height: 32px;'></span>"
  3179. mediaElem += "<span class='fn'>" + a_data.actor.displayName + "</span>";
  3180. mediaElem += "<span class='nickname'><span class='thumbnail-inline'></span></span>";
  3181. mediaElem += "</a></div>";
  3182. VMM.attachElement("#googleplus_" + gplus.activity, mediaElem);
  3183. });
  3184. break;
  3185. }
  3186. }
  3187. })
  3188. .error(function(jqXHR, textStatus, errorThrown) {
  3189. var error_obj = VMM.parseJSON(jqXHR.responseText);
  3190. trace(error_obj.error.message);
  3191. VMM.attachElement("#googleplus_" + gplus.activity, VMM.MediaElement.loadingmessage("<p>ERROR LOADING GOOGLE+ </p><p>" + error_obj.error.message + "</p>"));
  3192. })
  3193. .success(function(d) {
  3194. clearTimeout(googleplus_timeout);
  3195. clearTimeout(callback_timeout);
  3196. callback();
  3197. });
  3198. },
  3199. pushQue: function() {
  3200. if (VMM.master_config.googleplus.que.length > 0) {
  3201. VMM.ExternalAPI.googleplus.create(VMM.master_config.googleplus.que[0], VMM.ExternalAPI.googleplus.pushQue);
  3202. VMM.Util.removeRange(VMM.master_config.googleplus.que,0);
  3203. }
  3204. /*
  3205. for(var i = 0; i < VMM.master_config.googleplus.que.length; i++) {
  3206. VMM.ExternalAPI.googleplus.create(VMM.master_config.googleplus.que[i]);
  3207. }
  3208. VMM.master_config.googleplus.que = [];
  3209. */
  3210. },
  3211. errorTimeOut: function(gplus) {
  3212. trace("GOOGLE+ JSON ERROR TIMEOUT " + gplus.activity);
  3213. VMM.attachElement("#googleplus_" + gplus.activity, VMM.MediaElement.loadingmessage("<p>Still waiting on GOOGLE+ </p><p>" + gplus.activity + "</p>"));
  3214. }
  3215. },
  3216. googledocs: {
  3217. get: function(m) {
  3218. VMM.master_config.googledocs.que.push(m);
  3219. VMM.master_config.googledocs.active = true;
  3220. },
  3221. create: function(m) {
  3222. var mediaElem = "";
  3223. if (m.id.match(/docs.google.com/i)) {
  3224. mediaElem = "<iframe class='doc' frameborder='0' width='100%' height='100%' src='" + m.id + "&amp;embedded=true'></iframe>";
  3225. } else {
  3226. mediaElem = "<iframe class='doc' frameborder='0' width='100%' height='100%' src='" + "//docs.google.com/viewer?url=" + m.id + "&amp;embedded=true'></iframe>";
  3227. }
  3228. VMM.attachElement("#"+m.uid, mediaElem);
  3229. },
  3230. pushQue: function() {
  3231. for(var i = 0; i < VMM.master_config.googledocs.que.length; i++) {
  3232. VMM.ExternalAPI.googledocs.create(VMM.master_config.googledocs.que[i]);
  3233. }
  3234. VMM.master_config.googledocs.que = [];
  3235. }
  3236. },
  3237. flickr: {
  3238. get: function(m) {
  3239. VMM.master_config.flickr.que.push(m);
  3240. VMM.master_config.flickr.active = true;
  3241. },
  3242. create: function(m, callback) {
  3243. var api_key,
  3244. callback_timeout= setTimeout(callback, VMM.master_config.timers.api, m);
  3245. if (typeof VMM.master_config.Timeline != 'undefined' && VMM.master_config.Timeline.api_keys.flickr != "") {
  3246. api_key = VMM.master_config.Timeline.api_keys.flickr;
  3247. } else {
  3248. api_key = Aes.Ctr.decrypt(VMM.master_config.api_keys_master.flickr, VMM.master_config.vp, 256)
  3249. }
  3250. var the_url = "https://api.flickr.com/services/rest/?method=flickr.photos.getSizes&api_key=" + api_key + "&photo_id=" + m.id + "&format=json&jsoncallback=?";
  3251. VMM.getJSON(the_url, function(d) {
  3252. var flickr_id = VMM.ExternalAPI.flickr.getFlickrIdFromUrl(d.sizes.size[0].url);
  3253. var flickr_large_id = "#" + m.uid,
  3254. flickr_thumb_id = "#" + m.uid + "_thumb";
  3255. //flickr_thumb_id = "flickr_" + uid + "_thumb";
  3256. var flickr_img_size,
  3257. flickr_img_thumb,
  3258. flickr_size_found = false,
  3259. flickr_best_size = "Large";
  3260. flickr_best_size = VMM.ExternalAPI.flickr.sizes(VMM.master_config.sizes.api.height);
  3261. for(var i = 0; i < d.sizes.size.length; i++) {
  3262. if (d.sizes.size[i].label == flickr_best_size) {
  3263. flickr_size_found = true;
  3264. flickr_img_size = d.sizes.size[i].source;
  3265. }
  3266. }
  3267. if (!flickr_size_found) {
  3268. flickr_img_size = d.sizes.size[d.sizes.size.length - 2].source;
  3269. }
  3270. flickr_img_thumb = d.sizes.size[0].source;
  3271. VMM.Lib.attr(flickr_large_id, "src", flickr_img_size);
  3272. //VMM.attachElement(flickr_large_id, "<a href='" + flick.link + "' target='_blank'><img src='" + flickr_img_size + "'></a>");
  3273. VMM.attachElement(flickr_thumb_id, "<img src='" + flickr_img_thumb + "'>");
  3274. })
  3275. .error(function(jqXHR, textStatus, errorThrown) {
  3276. trace("FLICKR error");
  3277. trace("FLICKR ERROR: " + textStatus + " " + jqXHR.responseText);
  3278. })
  3279. .success(function(d) {
  3280. clearTimeout(callback_timeout);
  3281. callback();
  3282. });
  3283. },
  3284. pushQue: function() {
  3285. if (VMM.master_config.flickr.que.length > 0) {
  3286. VMM.ExternalAPI.flickr.create(VMM.master_config.flickr.que[0], VMM.ExternalAPI.flickr.pushQue);
  3287. VMM.Util.removeRange(VMM.master_config.flickr.que,0);
  3288. }
  3289. },
  3290. sizes: function(s) {
  3291. var _size = "";
  3292. if (s <= 75) {
  3293. _size = "Thumbnail";
  3294. } else if (s <= 180) {
  3295. _size = "Small";
  3296. } else if (s <= 240) {
  3297. _size = "Small 320";
  3298. } else if (s <= 375) {
  3299. _size = "Medium";
  3300. } else if (s <= 480) {
  3301. _size = "Medium 640";
  3302. } else if (s <= 600) {
  3303. _size = "Large";
  3304. } else {
  3305. _size = "Large";
  3306. }
  3307. return _size;
  3308. },
  3309. getFlickrIdFromUrl: function(url) {
  3310. var idx = url.indexOf("flickr.com/photos/");
  3311. if (idx == -1) return null;
  3312. var pos = idx + "flickr.com/photos/".length;
  3313. var photo_info = url.substr(pos)
  3314. if (photo_info.indexOf('/') == -1) return null;
  3315. if (photo_info.indexOf('/') == 0) photo_info = photo_info.substr(1);
  3316. return photo_info.split("/")[1];
  3317. }
  3318. },
  3319. instagram: {
  3320. get: function(m, thumb) {
  3321. if (thumb) {
  3322. return "//instagr.am/p/" + m.id + "/media/?size=t";
  3323. } else {
  3324. return "//instagr.am/p/" + m.id + "/media/?size=" + VMM.ExternalAPI.instagram.sizes(VMM.master_config.sizes.api.height);
  3325. }
  3326. },
  3327. sizes: function(s) {
  3328. var _size = "";
  3329. if (s <= 150) {
  3330. _size = "t";
  3331. } else if (s <= 306) {
  3332. _size = "m";
  3333. } else {
  3334. _size = "l";
  3335. }
  3336. return _size;
  3337. },
  3338. isInstagramUrl: function(url) {
  3339. return url.match("instagr.am/p/") || url.match("instagram.com/p/");
  3340. },
  3341. getInstagramIdFromUrl: function(url) {
  3342. try {
  3343. return url.split("\/p\/")[1].split("/")[0];
  3344. } catch(e) {
  3345. trace("Invalid Instagram url: " + url);
  3346. return null;
  3347. }
  3348. }
  3349. },
  3350. soundcloud: {
  3351. get: function(m) {
  3352. VMM.master_config.soundcloud.que.push(m);
  3353. VMM.master_config.soundcloud.active = true;
  3354. },
  3355. create: function(m, callback) {
  3356. var the_url = "//soundcloud.com/oembed?url=" + m.id + "&maxheight=168&format=js&callback=?";
  3357. VMM.getJSON(the_url, function(d) {
  3358. VMM.attachElement("#"+m.uid, d.html);
  3359. callback();
  3360. });
  3361. },
  3362. pushQue: function() {
  3363. if (VMM.master_config.soundcloud.que.length > 0) {
  3364. VMM.ExternalAPI.soundcloud.create(VMM.master_config.soundcloud.que[0], VMM.ExternalAPI.soundcloud.pushQue);
  3365. VMM.Util.removeRange(VMM.master_config.soundcloud.que,0);
  3366. }
  3367. }
  3368. },
  3369. wikipedia: {
  3370. get: function(m) {
  3371. VMM.master_config.wikipedia.que.push(m);
  3372. VMM.master_config.wikipedia.active = true;
  3373. },
  3374. create: function(m, callback) {
  3375. var the_url = "//" + m.lang + ".wikipedia.org/w/api.php?action=query&prop=extracts&redirects=&titles=" + m.id + "&exintro=1&format=json&callback=?";
  3376. callback_timeout= setTimeout(callback, VMM.master_config.timers.api, m);
  3377. if ( VMM.Browser.browser == "Explorer" && parseInt(VMM.Browser.version, 10) >= 7 && window.XDomainRequest) {
  3378. var temp_text = "<h4><a href='http://" + VMM.master_config.language.api.wikipedia + ".wikipedia.org/wiki/" + m.id + "' target='_blank'>" + m.url + "</a></h4>";
  3379. temp_text += "<span class='wiki-source'>" + VMM.master_config.language.messages.wikipedia + "</span>";
  3380. temp_text += "<p>Wikipedia entry unable to load using Internet Explorer 8 or below.</p>";
  3381. VMM.attachElement("#"+m.uid, temp_text );
  3382. }
  3383. VMM.getJSON(the_url, function(d) {
  3384. if (d.query) {
  3385. var wiki_extract,
  3386. wiki_title,
  3387. _wiki = "",
  3388. wiki_text = "",
  3389. wiki_number_of_paragraphs = 1,
  3390. wiki_text_array = [];
  3391. wiki_extract = VMM.Util.getObjectAttributeByIndex(d.query.pages, 0).extract;
  3392. wiki_title = VMM.Util.getObjectAttributeByIndex(d.query.pages, 0).title;
  3393. if (wiki_extract.match("<p>")) {
  3394. wiki_text_array = wiki_extract.split("<p>");
  3395. } else {
  3396. wiki_text_array.push(wiki_extract);
  3397. }
  3398. for(var i = 0; i < wiki_text_array.length; i++) {
  3399. if (i+1 <= wiki_number_of_paragraphs && i+1 < wiki_text_array.length) {
  3400. wiki_text += "<p>" + wiki_text_array[i+1];
  3401. }
  3402. }
  3403. _wiki = "<h4><a href='http://" + VMM.master_config.language.api.wikipedia + ".wikipedia.org/wiki/" + wiki_title + "' target='_blank'>" + wiki_title + "</a></h4>";
  3404. _wiki += "<span class='wiki-source'>" + VMM.master_config.language.messages.wikipedia + "</span>";
  3405. _wiki += VMM.Util.linkify_wikipedia(wiki_text);
  3406. if (wiki_extract.match("REDIRECT")) {
  3407. } else {
  3408. VMM.attachElement("#"+m.uid, _wiki );
  3409. }
  3410. }
  3411. //callback();
  3412. })
  3413. .error(function(jqXHR, textStatus, errorThrown) {
  3414. trace("WIKIPEDIA error");
  3415. trace("WIKIPEDIA ERROR: " + textStatus + " " + jqXHR.responseText);
  3416. trace(errorThrown);
  3417. VMM.attachElement("#"+m.uid, VMM.MediaElement.loadingmessage("<p>Wikipedia is not responding</p>"));
  3418. // TRY AGAIN?
  3419. clearTimeout(callback_timeout);
  3420. if (VMM.master_config.wikipedia.tries < 4) {
  3421. trace("WIKIPEDIA ATTEMPT " + VMM.master_config.wikipedia.tries);
  3422. trace(m);
  3423. VMM.master_config.wikipedia.tries++;
  3424. VMM.ExternalAPI.wikipedia.create(m, callback);
  3425. } else {
  3426. callback();
  3427. }
  3428. })
  3429. .success(function(d) {
  3430. VMM.master_config.wikipedia.tries = 0;
  3431. clearTimeout(callback_timeout);
  3432. callback();
  3433. });
  3434. },
  3435. pushQue: function() {
  3436. if (VMM.master_config.wikipedia.que.length > 0) {
  3437. trace("WIKIPEDIA PUSH QUE " + VMM.master_config.wikipedia.que.length);
  3438. VMM.ExternalAPI.wikipedia.create(VMM.master_config.wikipedia.que[0], VMM.ExternalAPI.wikipedia.pushQue);
  3439. VMM.Util.removeRange(VMM.master_config.wikipedia.que,0);
  3440. }
  3441. }
  3442. },
  3443. youtube: {
  3444. get: function(m) {
  3445. var the_url = "//gdata.youtube.com/feeds/api/videos/" + m.id + "?v=2&alt=jsonc&callback=?";
  3446. VMM.master_config.youtube.que.push(m);
  3447. if (!VMM.master_config.youtube.active) {
  3448. if (!VMM.master_config.youtube.api_loaded) {
  3449. LoadLib.js('//www.youtube.com/player_api', function() {
  3450. trace("YouTube API Library Loaded");
  3451. });
  3452. }
  3453. }
  3454. // THUMBNAIL
  3455. VMM.getJSON(the_url, function(d) {
  3456. VMM.ExternalAPI.youtube.createThumb(d, m)
  3457. });
  3458. },
  3459. create: function(m) {
  3460. if (typeof(m.start) != 'undefined') {
  3461. var vidstart = m.start.toString(),
  3462. vid_start_minutes = 0,
  3463. vid_start_seconds = 0;
  3464. if (vidstart.match('m')) {
  3465. vid_start_minutes = parseInt(vidstart.split("m")[0], 10);
  3466. vid_start_seconds = parseInt(vidstart.split("m")[1].split("s")[0], 10);
  3467. m.start = (vid_start_minutes * 60) + vid_start_seconds;
  3468. } else {
  3469. m.start = 0;
  3470. }
  3471. } else {
  3472. m.start = 0;
  3473. }
  3474. var p = {
  3475. active: false,
  3476. player: {},
  3477. name: m.uid,
  3478. playing: false,
  3479. hd: false
  3480. };
  3481. if (typeof(m.hd) != 'undefined') {
  3482. p.hd = true;
  3483. }
  3484. p.player[m.id] = new YT.Player(m.uid, {
  3485. height: '390',
  3486. width: '640',
  3487. playerVars: {
  3488. enablejsapi: 1,
  3489. color: ("dark" == VMM.master_config.Timeline.youtubeTheme) ? "red" : "white", // https://developers.google.com/youtube/player_parameters#color
  3490. showinfo: 0,
  3491. theme: ("undefined" !== VMM.master_config.Timeline.youtubeTheme) ? VMM.master_config.Timeline.youtubeTheme : "light", // https://developers.google.com/youtube/player_parameters#theme
  3492. start: m.start,
  3493. rel: 0
  3494. },
  3495. videoId: m.id,
  3496. events: {
  3497. 'onReady': VMM.ExternalAPI.youtube.onPlayerReady,
  3498. 'onStateChange': VMM.ExternalAPI.youtube.onStateChange
  3499. }
  3500. });
  3501. VMM.master_config.youtube.array.push(p);
  3502. },
  3503. createThumb: function(d, m) {
  3504. trace("CREATE THUMB");
  3505. trace(d);
  3506. trace(m);
  3507. if (typeof d.data != 'undefined') {
  3508. var thumb_id = "#" + m.uid + "_thumb";
  3509. VMM.attachElement(thumb_id, "<img src='" + d.data.thumbnail.sqDefault + "'>");
  3510. }
  3511. },
  3512. pushQue: function() {
  3513. for(var i = 0; i < VMM.master_config.youtube.que.length; i++) {
  3514. VMM.ExternalAPI.youtube.create(VMM.master_config.youtube.que[i]);
  3515. }
  3516. VMM.master_config.youtube.que = [];
  3517. },
  3518. onAPIReady: function() {
  3519. VMM.master_config.youtube.active = true;
  3520. VMM.ExternalAPI.youtube.pushQue();
  3521. },
  3522. stopPlayers: function() {
  3523. for(var i = 0; i < VMM.master_config.youtube.array.length; i++) {
  3524. if (VMM.master_config.youtube.array[i].playing) {
  3525. if (typeof VMM.master_config.youtube.array[i].player.the_name !== 'undefined') {
  3526. VMM.master_config.youtube.array[i].player.the_name.stopVideo();
  3527. }
  3528. }
  3529. }
  3530. },
  3531. onStateChange: function(e) {
  3532. for(var i = 0; i < VMM.master_config.youtube.array.length; i++) {
  3533. for (var z in VMM.master_config.youtube.array[i].player) {
  3534. if (VMM.master_config.youtube.array[i].player[z] == e.target) {
  3535. VMM.master_config.youtube.array[i].player.the_name = VMM.master_config.youtube.array[i].player[z];
  3536. }
  3537. }
  3538. if (VMM.master_config.youtube.array[i].player.the_name == e.target) {
  3539. if (e.data == YT.PlayerState.PLAYING) {
  3540. VMM.master_config.youtube.array[i].playing = true;
  3541. if (VMM.master_config.youtube.array[i].hd === false) {
  3542. VMM.master_config.youtube.array[i].hd = true;
  3543. VMM.master_config.youtube.array[i].player.the_name.setPlaybackQuality("hd720");
  3544. }
  3545. }
  3546. }
  3547. }
  3548. },
  3549. onPlayerReady: function(e) {
  3550. }
  3551. },
  3552. vimeo: {
  3553. get: function(m) {
  3554. VMM.master_config.vimeo.que.push(m);
  3555. VMM.master_config.vimeo.active = true;
  3556. },
  3557. create: function(m, callback) {
  3558. trace("VIMEO CREATE");
  3559. // THUMBNAIL
  3560. var thumb_url = "//vimeo.com/api/v2/video/" + m.id + ".json",
  3561. video_url = "//player.vimeo.com/video/" + m.id + "?title=0&amp;byline=0&amp;portrait=0&amp;color=ffffff";
  3562. VMM.getJSON(thumb_url, function(d) {
  3563. VMM.ExternalAPI.vimeo.createThumb(d, m);
  3564. callback();
  3565. });
  3566. // VIDEO
  3567. VMM.attachElement("#" + m.uid, "<iframe autostart='false' frameborder='0' width='100%' height='100%' src='" + video_url + "'></iframe>");
  3568. },
  3569. createThumb: function(d, m) {
  3570. trace("VIMEO CREATE THUMB");
  3571. var thumb_id = "#" + m.uid + "_thumb";
  3572. VMM.attachElement(thumb_id, "<img src='" + d[0].thumbnail_small + "'>");
  3573. },
  3574. pushQue: function() {
  3575. if (VMM.master_config.vimeo.que.length > 0) {
  3576. VMM.ExternalAPI.vimeo.create(VMM.master_config.vimeo.que[0], VMM.ExternalAPI.vimeo.pushQue);
  3577. VMM.Util.removeRange(VMM.master_config.vimeo.que,0);
  3578. }
  3579. }
  3580. },
  3581. vine: {
  3582. get: function(m) {
  3583. VMM.master_config.vine.que.push(m);
  3584. VMM.master_config.vine.active = true;
  3585. },
  3586. create: function(m, callback) {
  3587. trace("VINE CREATE");
  3588. var video_url = "https://vine.co/v/" + m.id + "/embed/simple";
  3589. // VIDEO
  3590. // TODO: NEED TO ADD ASYNC SCRIPT TO TIMELINE FLOW
  3591. VMM.attachElement("#" + m.uid, "<iframe frameborder='0' width='100%' height='100%' src='" + video_url + "'></iframe><script async src='http://platform.vine.co/static/scripts/embed.js' charset='utf-8'></script>");
  3592. },
  3593. pushQue: function() {
  3594. if (VMM.master_config.vine.que.length > 0) {
  3595. VMM.ExternalAPI.vine.create(VMM.master_config.vine.que[0], VMM.ExternalAPI.vine.pushQue);
  3596. VMM.Util.removeRange(VMM.master_config.vine.que,0);
  3597. }
  3598. }
  3599. },
  3600. webthumb: {
  3601. get: function(m, thumb) {
  3602. VMM.master_config.webthumb.que.push(m);
  3603. VMM.master_config.webthumb.active = true;
  3604. },
  3605. sizes: function(s) {
  3606. var _size = "";
  3607. if (s <= 150) {
  3608. _size = "t";
  3609. } else if (s <= 306) {
  3610. _size = "m";
  3611. } else {
  3612. _size = "l";
  3613. }
  3614. return _size;
  3615. },
  3616. create: function(m) {
  3617. trace("WEB THUMB CREATE");
  3618. var thumb_url = "//api.pagepeeker.com/v2/thumbs.php?";
  3619. url = m.id.replace("http://", "");//.split("/")[0];
  3620. // Main Image
  3621. VMM.attachElement("#" + m.uid, "<a href='" + m.id + "' target='_blank'><img src='" + thumb_url + "size=x&url=" + url + "'></a>");
  3622. // Thumb
  3623. VMM.attachElement("#" + m.uid + "_thumb", "<img src='" + thumb_url + "size=t&url=" + url + "'>");
  3624. },
  3625. pushQue: function() {
  3626. for(var i = 0; i < VMM.master_config.webthumb.que.length; i++) {
  3627. VMM.ExternalAPI.webthumb.create(VMM.master_config.webthumb.que[i]);
  3628. }
  3629. VMM.master_config.webthumb.que = [];
  3630. }
  3631. }
  3632. }).init();
  3633. }
  3634. /* YOUTUBE API READY
  3635. Can't find a way to customize this callback and keep it in the VMM namespace
  3636. Youtube wants it to be this function.
  3637. ================================================== */
  3638. function onYouTubePlayerAPIReady() {
  3639. trace("GLOBAL YOUTUBE API CALLED")
  3640. VMM.ExternalAPI.youtube.onAPIReady();
  3641. }
  3642. /* **********************************************
  3643. Begin VMM.MediaElement.js
  3644. ********************************************** */
  3645. /* MediaElement
  3646. ================================================== */
  3647. if(typeof VMM != 'undefined' && typeof VMM.MediaElement == 'undefined') {
  3648. VMM.MediaElement = ({
  3649. init: function() {
  3650. return this;
  3651. },
  3652. loadingmessage: function(m) {
  3653. return "<div class='vco-loading'><div class='vco-loading-container'><div class='vco-loading-icon'></div>" + "<div class='vco-message'><p>" + m + "</p></div></div></div>";
  3654. },
  3655. thumbnail: function(data, w, h, uid) {
  3656. var _w = 16,
  3657. _h = 24,
  3658. _uid = "";
  3659. if (w != null && w != "") {_w = w};
  3660. if (h != null && h != "") {_h = h};
  3661. if (uid != null && uid != "") {_uid = uid};
  3662. if (data.thumbnail != null && data.thumbnail != "") {
  3663. trace("CUSTOM THUMB");
  3664. mediaElem = "<div class='thumbnail thumb-custom' id='" + uid + "_custom_thumb'><img src='" + data.thumbnail + "'></div>";
  3665. return mediaElem;
  3666. } else if (data.media != null && data.media != "") {
  3667. var _valid = true,
  3668. mediaElem = "",
  3669. m = VMM.MediaType(data.media); //returns an object with .type and .id
  3670. // DETERMINE THUMBNAIL OR ICON
  3671. if (m.type == "image") {
  3672. mediaElem = "<div class='thumbnail thumb-photo'></div>";
  3673. return mediaElem;
  3674. } else if (m.type == "flickr") {
  3675. mediaElem = "<div class='thumbnail thumb-photo' id='" + uid + "_thumb'></div>";
  3676. return mediaElem;
  3677. } else if (m.type == "instagram") {
  3678. mediaElem = "<div class='thumbnail thumb-instagram' id='" + uid + "_thumb'><img src='" + VMM.ExternalAPI.instagram.get(m, true) + "'></div>";
  3679. return mediaElem;
  3680. } else if (m.type == "youtube") {
  3681. mediaElem = "<div class='thumbnail thumb-youtube' id='" + uid + "_thumb'></div>";
  3682. return mediaElem;
  3683. } else if (m.type == "googledoc") {
  3684. mediaElem = "<div class='thumbnail thumb-document'></div>";
  3685. return mediaElem;
  3686. } else if (m.type == "vimeo") {
  3687. mediaElem = "<div class='thumbnail thumb-vimeo' id='" + uid + "_thumb'></div>";
  3688. return mediaElem;
  3689. } else if (m.type == "vine") {
  3690. mediaElem = "<div class='thumbnail thumb-vine'></div>";
  3691. return mediaElem;
  3692. } else if (m.type == "dailymotion") {
  3693. mediaElem = "<div class='thumbnail thumb-video'></div>";
  3694. return mediaElem;
  3695. } else if (m.type == "twitter"){
  3696. mediaElem = "<div class='thumbnail thumb-twitter'></div>";
  3697. return mediaElem;
  3698. } else if (m.type == "twitter-ready") {
  3699. mediaElem = "<div class='thumbnail thumb-twitter'></div>";
  3700. return mediaElem;
  3701. } else if (m.type == "soundcloud") {
  3702. mediaElem = "<div class='thumbnail thumb-audio'></div>";
  3703. return mediaElem;
  3704. } else if (m.type == "google-map") {
  3705. mediaElem = "<div class='thumbnail thumb-map'></div>";
  3706. return mediaElem;
  3707. } else if (m.type == "googleplus") {
  3708. mediaElem = "<div class='thumbnail thumb-googleplus'></div>";
  3709. return mediaElem;
  3710. } else if (m.type == "wikipedia") {
  3711. mediaElem = "<div class='thumbnail thumb-wikipedia'></div>";
  3712. return mediaElem;
  3713. } else if (m.type == "storify") {
  3714. mediaElem = "<div class='thumbnail thumb-storify'></div>";
  3715. return mediaElem;
  3716. } else if (m.type == "quote") {
  3717. mediaElem = "<div class='thumbnail thumb-quote'></div>";
  3718. return mediaElem;
  3719. } else if (m.type == "iframe") {
  3720. mediaElem = "<div class='thumbnail thumb-video'></div>";
  3721. return mediaElem;
  3722. } else if (m.type == "unknown") {
  3723. if (m.id.match("blockquote")) {
  3724. mediaElem = "<div class='thumbnail thumb-quote'></div>";
  3725. } else {
  3726. mediaElem = "<div class='thumbnail thumb-plaintext'></div>";
  3727. }
  3728. return mediaElem;
  3729. } else if (m.type == "website") {
  3730. mediaElem = "<div class='thumbnail thumb-website' id='" + uid + "_thumb'></div>";
  3731. return mediaElem;
  3732. } else {
  3733. mediaElem = "<div class='thumbnail thumb-plaintext'></div>";
  3734. return mediaElem;
  3735. }
  3736. }
  3737. },
  3738. create: function(data, uid) {
  3739. var _valid = false,
  3740. //loading_messege = "<span class='messege'><p>" + VMM.master_config.language.messages.loading + "</p></span>";
  3741. loading_messege = VMM.MediaElement.loadingmessage(VMM.master_config.language.messages.loading + "...");
  3742. if (data.media != null && data.media != "") {
  3743. var mediaElem = "", captionElem = "", creditElem = "", _id = "", isTextMedia = false, m;
  3744. m = VMM.MediaType(data.media); //returns an object with .type and .id
  3745. m.uid = uid;
  3746. _valid = true;
  3747. // CREDIT
  3748. if (data.credit != null && data.credit != "") {
  3749. creditElem = "<div class='credit'>" + VMM.Util.linkify_with_twitter(data.credit, "_blank") + "</div>";
  3750. }
  3751. // CAPTION
  3752. if (data.caption != null && data.caption != "") {
  3753. captionElem = "<div class='caption'>" + VMM.Util.linkify_with_twitter(data.caption, "_blank") + "</div>";
  3754. }
  3755. // IMAGE
  3756. if (m.type == "image") {
  3757. mediaElem = "<div class='media-image media-shadow'><img src='" + m.id + "' class='media-image'></div>";
  3758. // FLICKR
  3759. } else if (m.type == "flickr") {
  3760. //mediaElem = "<div class='media-image media-shadow' id='" + uid + "'>" + loading_messege + "</div>";
  3761. mediaElem = "<div class='media-image media-shadow'><a href='" + m.link + "' target='_blank'><img id='" + uid + "'></a></div>";
  3762. VMM.ExternalAPI.flickr.get(m);
  3763. // INSTAGRAM
  3764. } else if (m.type == "instagram") {
  3765. mediaElem = "<div class='media-image media-shadow'><a href='" + m.link + "' target='_blank'><img src='" + VMM.ExternalAPI.instagram.get(m) + "'></a></div>";
  3766. // GOOGLE DOCS
  3767. } else if (m.type == "googledoc") {
  3768. mediaElem = "<div class='media-frame media-shadow doc' id='" + m.uid + "'>" + loading_messege + "</div>";
  3769. VMM.ExternalAPI.googledocs.get(m);
  3770. // YOUTUBE
  3771. } else if (m.type == "youtube") {
  3772. mediaElem = "<div class='media-shadow'><div class='media-frame video youtube' id='" + m.uid + "'>" + loading_messege + "</div></div>";
  3773. VMM.ExternalAPI.youtube.get(m);
  3774. // VIMEO
  3775. } else if (m.type == "vimeo") {
  3776. mediaElem = "<div class='media-shadow media-frame video vimeo' id='" + m.uid + "'>" + loading_messege + "</div>";
  3777. VMM.ExternalAPI.vimeo.get(m);
  3778. // DAILYMOTION
  3779. } else if (m.type == "dailymotion") {
  3780. mediaElem = "<div class='media-shadow'><iframe class='media-frame video dailymotion' autostart='false' frameborder='0' width='100%' height='100%' src='http://www.dailymotion.com/embed/video/" + m.id + "'></iframe></div>";
  3781. // VINE
  3782. } else if (m.type == "vine") {
  3783. mediaElem = "<div class='media-shadow media-frame video vine' id='" + m.uid + "'>" + loading_messege + "</div>";
  3784. VMM.ExternalAPI.vine.get(m);
  3785. // TWITTER
  3786. } else if (m.type == "twitter"){
  3787. mediaElem = "<div class='twitter' id='" + m.uid + "'>" + loading_messege + "</div>";
  3788. isTextMedia = true;
  3789. VMM.ExternalAPI.twitter.get(m);
  3790. // TWITTER
  3791. } else if (m.type == "twitter-ready") {
  3792. isTextMedia = true;
  3793. mediaElem = m.id;
  3794. // SOUNDCLOUD
  3795. } else if (m.type == "soundcloud") {
  3796. mediaElem = "<div class='media-frame media-shadow soundcloud' id='" + m.uid + "'>" + loading_messege + "</div>";
  3797. VMM.ExternalAPI.soundcloud.get(m);
  3798. // GOOGLE MAPS
  3799. } else if (m.type == "google-map") {
  3800. mediaElem = "<div class='media-frame media-shadow map' id='" + m.uid + "'>" + loading_messege + "</div>";
  3801. VMM.ExternalAPI.googlemaps.get(m);
  3802. // GOOGLE PLUS
  3803. } else if (m.type == "googleplus") {
  3804. _id = "googleplus_" + m.id;
  3805. mediaElem = "<div class='googleplus' id='" + _id + "'>" + loading_messege + "</div>";
  3806. isTextMedia = true;
  3807. VMM.ExternalAPI.googleplus.get(m);
  3808. // WIKIPEDIA
  3809. } else if (m.type == "wikipedia") {
  3810. mediaElem = "<div class='wikipedia' id='" + m.uid + "'>" + loading_messege + "</div>";
  3811. isTextMedia = true;
  3812. VMM.ExternalAPI.wikipedia.get(m);
  3813. // STORIFY
  3814. } else if (m.type == "storify") {
  3815. isTextMedia = true;
  3816. mediaElem = "<div class='plain-text-quote'>" + m.id + "</div>";
  3817. // IFRAME
  3818. } else if (m.type == "iframe") {
  3819. isTextMedia = true;
  3820. mediaElem = "<div class='media-shadow'><iframe class='media-frame video' autostart='false' frameborder='0' width='100%' height='100%' src='" + m.id + "'></iframe></div>";
  3821. // QUOTE
  3822. } else if (m.type == "quote") {
  3823. isTextMedia = true;
  3824. mediaElem = "<div class='plain-text-quote'>" + m.id + "</div>";
  3825. // UNKNOWN
  3826. } else if (m.type == "unknown") {
  3827. trace("NO KNOWN MEDIA TYPE FOUND TRYING TO JUST PLACE THE HTML");
  3828. isTextMedia = true;
  3829. mediaElem = "<div class='plain-text'><div class='container'>" + VMM.Util.properQuotes(m.id) + "</div></div>";
  3830. // WEBSITE
  3831. } else if (m.type == "website") {
  3832. mediaElem = "<div class='media-shadow website' id='" + m.uid + "'>" + loading_messege + "</div>";
  3833. VMM.ExternalAPI.webthumb.get(m);
  3834. //mediaElem = "<div class='media-shadow website'><a href='" + m.id + "' target='_blank'>" + "<img src='http://api1.thumbalizr.com/?url=" + m.id.replace(/[\./]$/g, "") + "&width=300' class='media-image'></a></div>";
  3835. // NO MATCH
  3836. } else {
  3837. trace("NO KNOWN MEDIA TYPE FOUND");
  3838. trace(m.type);
  3839. }
  3840. // WRAP THE MEDIA ELEMENT
  3841. mediaElem = "<div class='media-container' >" + mediaElem + creditElem + captionElem + "</div>";
  3842. // RETURN
  3843. if (isTextMedia) {
  3844. return "<div class='text-media'><div class='media-wrapper'>" + mediaElem + "</div></div>";
  3845. } else {
  3846. return "<div class='media-wrapper'>" + mediaElem + "</div>";
  3847. }
  3848. };
  3849. }
  3850. }).init();
  3851. }
  3852. /* **********************************************
  3853. Begin VMM.MediaType.js
  3854. ********************************************** */
  3855. /* MediaType
  3856. Determines the type of media the url string is.
  3857. returns an object with .type and .id
  3858. the id is a key piece of information needed to make
  3859. the request of the api.
  3860. ================================================== */
  3861. if(typeof VMM != 'undefined' && typeof VMM.MediaType == 'undefined') {
  3862. VMM.MediaType = function(_d) {
  3863. var d = _d.replace(/^\s\s*/, '').replace(/\s\s*$/, ''),
  3864. success = false,
  3865. media = {
  3866. type: "unknown",
  3867. id: "",
  3868. start: 0,
  3869. hd: false,
  3870. link: "",
  3871. lang: VMM.Language.lang,
  3872. uniqueid: VMM.Util.unique_ID(6)
  3873. };
  3874. if (d.match("div class='twitter'")) {
  3875. media.type = "twitter-ready";
  3876. media.id = d;
  3877. success = true;
  3878. } else if (d.match('<blockquote')) {
  3879. media.type = "quote";
  3880. media.id = d;
  3881. success = true;
  3882. } else if (d.match('<iframe')) {
  3883. media.type = "iframe";
  3884. trace("IFRAME")
  3885. regex = /src=['"](\S+?)['"]/;
  3886. group = d.match(regex);
  3887. if (group) {
  3888. media.id = group[1];
  3889. }
  3890. trace( "iframe url: " + media.id );
  3891. success = Boolean(media.id);
  3892. } else if (d.match('(www.)?youtube|youtu\.be')) {
  3893. if (d.match('v=')) {
  3894. media.id = VMM.Util.getUrlVars(d)["v"];
  3895. } else if (d.match('\/embed\/')) {
  3896. // TODO Issue #618 better splitting
  3897. media.id = d.split("embed\/")[1].split(/[?&]/)[0];
  3898. } else if (d.match(/v\/|v=|youtu\.be\//)){
  3899. media.id = d.split(/v\/|v=|youtu\.be\//)[1].split(/[?&]/)[0];
  3900. } else {
  3901. trace("YOUTUBE IN URL BUT NOT A VALID VIDEO");
  3902. }
  3903. media.start = VMM.Util.getUrlVars(d)["t"];
  3904. media.hd = VMM.Util.getUrlVars(d)["hd"];
  3905. media.type = "youtube";
  3906. success = true;
  3907. } else if (d.match('(player.)?vimeo\.com')) {
  3908. media.type = "vimeo";
  3909. media.id = d.split(/video\/|\/\/vimeo\.com\//)[1].split(/[?&]/)[0];;
  3910. success = true;
  3911. } else if (d.match('(www.)?dailymotion\.com')) {
  3912. media.id = d.split(/video\/|\/\/dailymotion\.com\//)[1];
  3913. media.type = "dailymotion";
  3914. success = true;
  3915. } else if (d.match('(www.)?vine\.co')) {
  3916. trace("VINE");
  3917. //https://vine.co/v/b55LOA1dgJU
  3918. if (d.match("vine.co/v/")) {
  3919. media.id = d.split("vine.co/v/")[1];
  3920. trace(media.id);
  3921. }
  3922. trace(d);
  3923. media.type = "vine";
  3924. success = true;
  3925. } else if (d.match('(player.)?soundcloud\.com')) {
  3926. media.type = "soundcloud";
  3927. media.id = d;
  3928. success = true;
  3929. } else if (d.match('(www.)?twitter\.com') && d.match('status') ) {
  3930. if (d.match("status\/")) {
  3931. media.id = d.split("status\/")[1];
  3932. } else if (d.match("statuses\/")) {
  3933. media.id = d.split("statuses\/")[1];
  3934. } else {
  3935. media.id = "";
  3936. }
  3937. media.type = "twitter";
  3938. success = true;
  3939. } else if (d.match("maps.google") && !d.match("staticmap") && !d.match('streetview')) {
  3940. media.type = "google-map";
  3941. media.id = d;
  3942. success = true;
  3943. } else if (d.match(/www.google.\w+\/maps/)) {
  3944. media.type = "google-map";
  3945. media.id = d;
  3946. success = true;
  3947. } else if (d.match("plus.google")) {
  3948. media.type = "googleplus";
  3949. media.id = d.split("/posts/")[1];
  3950. //https://plus.google.com/u/0/112374836634096795698/posts/bRJSvCb5mUU
  3951. //https://plus.google.com/107096716333816995401/posts/J5iMpEDHWNL
  3952. if (d.split("/posts/")[0].match("u/0/")) {
  3953. media.user = d.split("u/0/")[1].split("/posts")[0];
  3954. } else {
  3955. media.user = d.split("google.com/")[1].split("/posts/")[0];
  3956. }
  3957. success = true;
  3958. } else if (d.match("flickr.com/photos/")) {
  3959. media.type = "flickr";
  3960. media.id = VMM.ExternalAPI.flickr.getFlickrIdFromUrl(d)
  3961. media.link = d;
  3962. success = Boolean(media.id);
  3963. } else if (VMM.ExternalAPI.instagram.isInstagramUrl(d)) {
  3964. media.type = "instagram";
  3965. media.link = d;
  3966. media.id = VMM.ExternalAPI.instagram.getInstagramIdFromUrl(d)
  3967. success = Boolean(media.id);
  3968. } else if (d.match(/jpg|jpeg|png|gif|svg|bmp/i) ||
  3969. d.match("staticmap") ||
  3970. d.match("yfrog.com") ||
  3971. d.match("twitpic.com") ||
  3972. d.match('maps.googleapis.com/maps/api/streetview')) {
  3973. media.type = "image";
  3974. media.id = d;
  3975. success = true;
  3976. } else if (VMM.FileExtention.googleDocType(d)) {
  3977. media.type = "googledoc";
  3978. media.id = d;
  3979. success = true;
  3980. } else if (d.match('(www.)?wikipedia\.org')) {
  3981. media.type = "wikipedia";
  3982. //media.id = d.split("wiki\/")[1];
  3983. // TODO Issue #618 better splitting
  3984. var wiki_id = d.split("wiki\/")[1].split("#")[0].replace("_", " ");
  3985. media.id = wiki_id.replace(" ", "%20");
  3986. media.lang = d.split("//")[1].split(".wikipedia")[0];
  3987. success = true;
  3988. } else if (d.indexOf('http://') == 0) {
  3989. media.type = "website";
  3990. media.id = d;
  3991. success = true;
  3992. } else if (d.match('storify')) {
  3993. media.type = "storify";
  3994. media.id = d;
  3995. success = true;
  3996. } else {
  3997. trace("unknown media");
  3998. media.type = "unknown";
  3999. media.id = d;
  4000. success = true;
  4001. }
  4002. if (success) {
  4003. return media;
  4004. } else {
  4005. trace("No valid media id detected");
  4006. trace(d);
  4007. }
  4008. return false;
  4009. }
  4010. }
  4011. /* **********************************************
  4012. Begin VMM.TextElement.js
  4013. ********************************************** */
  4014. /* TextElement
  4015. ================================================== */
  4016. if(typeof VMM != 'undefined' && typeof VMM.TextElement == 'undefined') {
  4017. VMM.TextElement = ({
  4018. init: function() {
  4019. return this;
  4020. },
  4021. create: function(data) {
  4022. return data;
  4023. }
  4024. }).init();
  4025. }
  4026. /* **********************************************
  4027. Begin VMM.Media.js
  4028. ********************************************** */
  4029. /* Media
  4030. ================================================== */
  4031. /* * CodeKit Import
  4032. * http://incident57.com/codekit/
  4033. ================================================== */
  4034. // @codekit-prepend "VMM.ExternalAPI.js";
  4035. // @codekit-prepend "VMM.MediaElement.js";
  4036. // @codekit-prepend "VMM.MediaType.js";
  4037. // @codekit-prepend "VMM.TextElement.js";
  4038. /* **********************************************
  4039. Begin VMM.DragSlider.js
  4040. ********************************************** */
  4041. /* DRAG SLIDER
  4042. ================================================== */
  4043. if(typeof VMM != 'undefined' && typeof VMM.DragSlider == 'undefined') {
  4044. VMM.DragSlider = function() {
  4045. var drag = {
  4046. element: "",
  4047. element_move: "",
  4048. constraint: "",
  4049. sliding: false,
  4050. pagex: {
  4051. start: 0,
  4052. end: 0
  4053. },
  4054. pagey: {
  4055. start: 0,
  4056. end: 0
  4057. },
  4058. left: {
  4059. start: 0,
  4060. end: 0
  4061. },
  4062. time: {
  4063. start: 0,
  4064. end: 0
  4065. },
  4066. touch: false,
  4067. ease: "easeOutExpo"
  4068. },
  4069. dragevent = {
  4070. down: "mousedown",
  4071. up: "mouseup",
  4072. leave: "mouseleave",
  4073. move: "mousemove"
  4074. },
  4075. mousedrag = {
  4076. down: "mousedown",
  4077. up: "mouseup",
  4078. leave: "mouseleave",
  4079. move: "mousemove"
  4080. },
  4081. touchdrag = {
  4082. down: "touchstart",
  4083. up: "touchend",
  4084. leave: "mouseleave",
  4085. move: "touchmove"
  4086. },
  4087. dragslider = this,
  4088. is_sticky = false;
  4089. /* PUBLIC FUNCTIONS
  4090. ================================================== */
  4091. this.createPanel = function(drag_object, move_object, constraint, touch, sticky) {
  4092. drag.element = drag_object;
  4093. drag.element_move = move_object;
  4094. //dragslider = drag_object;
  4095. if ( sticky != null && sticky != "") {
  4096. is_sticky = sticky;
  4097. }
  4098. if ( constraint != null && constraint != "") {
  4099. drag.constraint = constraint;
  4100. } else {
  4101. drag.constraint = false;
  4102. }
  4103. if ( touch) {
  4104. drag.touch = touch;
  4105. } else {
  4106. drag.touch = false;
  4107. }
  4108. trace("TOUCH" + drag.touch);
  4109. if (drag.touch) {
  4110. dragevent = touchdrag;
  4111. } else {
  4112. dragevent = mousedrag;
  4113. }
  4114. makeDraggable(drag.element, drag.element_move);
  4115. }
  4116. this.updateConstraint = function(constraint) {
  4117. trace("updateConstraint");
  4118. drag.constraint = constraint;
  4119. }
  4120. this.cancelSlide = function(e) {
  4121. VMM.unbindEvent(drag.element, onDragMove, dragevent.move);
  4122. return true;
  4123. }
  4124. /* PRIVATE FUNCTIONS
  4125. ================================================== */
  4126. function makeDraggable(drag_object, move_object) {
  4127. VMM.bindEvent(drag_object, onDragStart, dragevent.down, {element: move_object, delement: drag_object});
  4128. VMM.bindEvent(drag_object, onDragEnd, dragevent.up, {element: move_object, delement: drag_object});
  4129. VMM.bindEvent(drag_object, onDragLeave, dragevent.leave, {element: move_object, delement: drag_object});
  4130. }
  4131. function onDragLeave(e) {
  4132. VMM.unbindEvent(e.data.delement, onDragMove, dragevent.move);
  4133. if (!drag.touch) {
  4134. e.preventDefault();
  4135. }
  4136. e.stopPropagation();
  4137. if (drag.sliding) {
  4138. drag.sliding = false;
  4139. dragEnd(e.data.element, e.data.delement, e);
  4140. return false;
  4141. } else {
  4142. return true;
  4143. }
  4144. }
  4145. function onDragStart(e) {
  4146. dragStart(e.data.element, e.data.delement, e);
  4147. if (!drag.touch) {
  4148. e.preventDefault();
  4149. }
  4150. //e.stopPropagation();
  4151. return true;
  4152. }
  4153. function onDragEnd(e) {
  4154. if (!drag.touch) {
  4155. e.preventDefault();
  4156. }
  4157. //e.stopPropagation();
  4158. if (drag.sliding) {
  4159. drag.sliding = false;
  4160. dragEnd(e.data.element, e.data.delement, e);
  4161. return false;
  4162. } else {
  4163. return true;
  4164. }
  4165. }
  4166. function onDragMove(e) {
  4167. dragMove(e.data.element, e);
  4168. }
  4169. function dragStart(elem, delem, e) {
  4170. if (drag.touch) {
  4171. trace("IS TOUCH")
  4172. VMM.Lib.css(elem, '-webkit-transition-duration', '0');
  4173. drag.pagex.start = e.originalEvent.touches[0].screenX;
  4174. drag.pagey.start = e.originalEvent.touches[0].screenY;
  4175. } else {
  4176. drag.pagex.start = e.pageX;
  4177. drag.pagey.start = e.pageY;
  4178. }
  4179. drag.left.start = getLeft(elem);
  4180. drag.time.start = new Date().getTime();
  4181. VMM.Lib.stop(elem);
  4182. VMM.bindEvent(delem, onDragMove, dragevent.move, {element: elem});
  4183. }
  4184. function dragEnd(elem, delem, e) {
  4185. VMM.unbindEvent(delem, onDragMove, dragevent.move);
  4186. dragMomentum(elem, e);
  4187. }
  4188. function dragMove(elem, e) {
  4189. var drag_to, drag_to_y;
  4190. drag.sliding = true;
  4191. if (drag.touch) {
  4192. drag.pagex.end = e.originalEvent.touches[0].screenX;
  4193. drag.pagey.end = e.originalEvent.touches[0].screenY;
  4194. } else {
  4195. drag.pagex.end = e.pageX;
  4196. drag.pagey.end = e.pageY;
  4197. }
  4198. drag.left.end = getLeft(elem);
  4199. drag_to = -(drag.pagex.start - drag.pagex.end - drag.left.start);
  4200. if (Math.abs(drag.pagey.start) - Math.abs(drag.pagey.end) > 10) {
  4201. trace("SCROLLING Y")
  4202. trace(Math.abs(drag.pagey.start) - Math.abs(drag.pagey.end));
  4203. }
  4204. if (Math.abs(drag_to - drag.left.start) > 10) {
  4205. VMM.Lib.css(elem, 'left', drag_to);
  4206. e.preventDefault();
  4207. e.stopPropagation();
  4208. }
  4209. }
  4210. function dragMomentum(elem, e) {
  4211. var drag_info = {
  4212. left: drag.left.end,
  4213. left_adjust: 0,
  4214. change: {
  4215. x: 0
  4216. },
  4217. time: (new Date().getTime() - drag.time.start) * 10,
  4218. time_adjust: (new Date().getTime() - drag.time.start) * 10
  4219. },
  4220. multiplier = 3000;
  4221. if (drag.touch) {
  4222. multiplier = 6000;
  4223. }
  4224. drag_info.change.x = multiplier * (Math.abs(drag.pagex.end) - Math.abs(drag.pagex.start));
  4225. drag_info.left_adjust = Math.round(drag_info.change.x / drag_info.time);
  4226. drag_info.left = Math.min(drag_info.left + drag_info.left_adjust);
  4227. if (drag.constraint) {
  4228. if (drag_info.left > drag.constraint.left) {
  4229. drag_info.left = drag.constraint.left;
  4230. if (drag_info.time > 5000) {
  4231. drag_info.time = 5000;
  4232. }
  4233. } else if (drag_info.left < drag.constraint.right) {
  4234. drag_info.left = drag.constraint.right;
  4235. if (drag_info.time > 5000) {
  4236. drag_info.time = 5000;
  4237. }
  4238. }
  4239. }
  4240. VMM.fireEvent(dragslider, "DRAGUPDATE", [drag_info]);
  4241. if (!is_sticky) {
  4242. if (drag_info.time > 0) {
  4243. if (drag.touch) {
  4244. VMM.Lib.animate(elem, drag_info.time, "easeOutCirc", {"left": drag_info.left});
  4245. } else {
  4246. VMM.Lib.animate(elem, drag_info.time, drag.ease, {"left": drag_info.left});
  4247. }
  4248. }
  4249. }
  4250. }
  4251. function getLeft(elem) {
  4252. return parseInt(VMM.Lib.css(elem, 'left').substring(0, VMM.Lib.css(elem, 'left').length - 2), 10);
  4253. }
  4254. }
  4255. }
  4256. /* **********************************************
  4257. Begin VMM.Slider.js
  4258. ********************************************** */
  4259. /* Slider
  4260. ================================================== */
  4261. /* * CodeKit Import
  4262. * http://incident57.com/codekit/
  4263. ================================================== */
  4264. // @codekit-append "VMM.Slider.Slide.js";
  4265. if(typeof VMM != 'undefined' && typeof VMM.Slider == 'undefined') {
  4266. VMM.Slider = function(parent, parent_config) {
  4267. var config,
  4268. timer,
  4269. $slider,
  4270. $slider_mask,
  4271. $slider_container,
  4272. $slides_items,
  4273. $dragslide,
  4274. $explainer,
  4275. events = {},
  4276. data = [],
  4277. slides = [],
  4278. slide_positions = [],
  4279. slides_content = "",
  4280. current_slide = 0,
  4281. current_width = 960,
  4282. touch = {
  4283. move: false,
  4284. x: 10,
  4285. y: 0,
  4286. off: 0,
  4287. dampen: 48
  4288. },
  4289. content = "",
  4290. _active = false,
  4291. layout = parent,
  4292. navigation = {
  4293. nextBtn: "",
  4294. prevBtn: "",
  4295. nextDate: "",
  4296. prevDate: "",
  4297. nextTitle: "",
  4298. prevTitle: ""
  4299. };
  4300. // CONFIG
  4301. if(typeof parent_config != 'undefined') {
  4302. config = parent_config;
  4303. } else {
  4304. config = {
  4305. preload: 4,
  4306. current_slide: 0,
  4307. interval: 10,
  4308. something: 0,
  4309. width: 720,
  4310. height: 400,
  4311. ease: "easeInOutExpo",
  4312. duration: 1000,
  4313. timeline: false,
  4314. spacing: 15,
  4315. slider: {
  4316. width: 720,
  4317. height: 400,
  4318. content: {
  4319. width: 720,
  4320. height: 400,
  4321. padding: 120,
  4322. padding_default: 120
  4323. },
  4324. nav: {
  4325. width: 100,
  4326. height: 200
  4327. }
  4328. }
  4329. };
  4330. }
  4331. /* PUBLIC VARS
  4332. ================================================== */
  4333. this.ver = "0.6";
  4334. config.slider.width = config.width;
  4335. config.slider.height = config.height;
  4336. /* PUBLIC FUNCTIONS
  4337. ================================================== */
  4338. this.init = function(d) {
  4339. slides = [];
  4340. slide_positions = [];
  4341. if(typeof d != 'undefined') {
  4342. this.setData(d);
  4343. } else {
  4344. trace("WAITING ON DATA");
  4345. }
  4346. };
  4347. this.width = function(w) {
  4348. if (w != null && w != "") {
  4349. config.slider.width = w;
  4350. reSize();
  4351. } else {
  4352. return config.slider.width;
  4353. }
  4354. }
  4355. this.height = function(h) {
  4356. if (h != null && h != "") {
  4357. config.slider.height = h;
  4358. reSize();
  4359. } else {
  4360. return config.slider.height;
  4361. }
  4362. }
  4363. /* GETTERS AND SETTERS
  4364. ================================================== */
  4365. this.setData = function(d) {
  4366. if(typeof d != 'undefined') {
  4367. data = d;
  4368. build();
  4369. } else{
  4370. trace("NO DATA");
  4371. }
  4372. };
  4373. this.getData = function() {
  4374. return data;
  4375. };
  4376. this.setConfig = function(d) {
  4377. if(typeof d != 'undefined') {
  4378. config = d;
  4379. } else{
  4380. trace("NO CONFIG DATA");
  4381. }
  4382. }
  4383. this.getConfig = function() {
  4384. return config;
  4385. };
  4386. this.setSize = function(w, h) {
  4387. if (w != null) {config.slider.width = w};
  4388. if (h != null) {config.slider.height = h};
  4389. if (_active) {
  4390. reSize();
  4391. }
  4392. }
  4393. this.active = function() {
  4394. return _active;
  4395. };
  4396. this.getCurrentNumber = function() {
  4397. return current_slide;
  4398. };
  4399. this.setSlide = function(n) {
  4400. goToSlide(n);
  4401. };
  4402. /* ON EVENT
  4403. ================================================== */
  4404. function onConfigSet() {
  4405. trace("onConfigSet");
  4406. };
  4407. function reSize(go_to_slide, from_start) {
  4408. var _go_to_slide = true,
  4409. _from_start = false;
  4410. if (go_to_slide != null) {_go_to_slide = go_to_slide};
  4411. if (from_start != null) {_from_start = from_start};
  4412. current_width = config.slider.width;
  4413. config.slider.nav.height = VMM.Lib.height(navigation.prevBtnContainer);
  4414. // Handle smaller sizes
  4415. if (VMM.Browser.device == "mobile" || current_width <= 640) {
  4416. config.slider.content.padding = 10;
  4417. } else {
  4418. config.slider.content.padding = config.slider.content.padding_default;
  4419. }
  4420. config.slider.content.width = current_width - (config.slider.content.padding *2);
  4421. VMM.Lib.width($slides_items, (slides.length * config.slider.content.width));
  4422. if (_from_start) {
  4423. VMM.Lib.css($slider_container, "left", slides[current_slide].leftpos());
  4424. }
  4425. // RESIZE SLIDES
  4426. sizeSlides();
  4427. // POSITION SLIDES
  4428. positionSlides();
  4429. // POSITION NAV
  4430. VMM.Lib.css(navigation.nextBtn, "left", (current_width - config.slider.nav.width));
  4431. VMM.Lib.height(navigation.prevBtn, config.slider.height);
  4432. VMM.Lib.height(navigation.nextBtn, config.slider.height);
  4433. VMM.Lib.css(navigation.nextBtnContainer, "top", ( (config.slider.height/2) - (config.slider.nav.height/2) ) + 10 );
  4434. VMM.Lib.css(navigation.prevBtnContainer, "top", ( (config.slider.height/2) - (config.slider.nav.height/2) ) + 10 );
  4435. // Animate Changes
  4436. VMM.Lib.height($slider_mask, config.slider.height);
  4437. VMM.Lib.width($slider_mask, current_width);
  4438. if (_go_to_slide) {
  4439. goToSlide(current_slide, "linear", 1);
  4440. };
  4441. if (current_slide == 0) {
  4442. VMM.Lib.visible(navigation.prevBtn, false);
  4443. }
  4444. }
  4445. function onDragFinish(e, d) {
  4446. trace("DRAG FINISH");
  4447. trace(d.left_adjust);
  4448. trace((config.slider.width / 2));
  4449. if (d.left_adjust < 0 ) {
  4450. if (Math.abs(d.left_adjust) > (config.slider.width / 2) ) {
  4451. //onNextClick(e);
  4452. if (current_slide == slides.length - 1) {
  4453. backToCurrentSlide();
  4454. } else {
  4455. goToSlide(current_slide+1, "easeOutExpo");
  4456. upDate();
  4457. }
  4458. } else {
  4459. backToCurrentSlide();
  4460. }
  4461. } else if (Math.abs(d.left_adjust) > (config.slider.width / 2) ) {
  4462. if (current_slide == 0) {
  4463. backToCurrentSlide();
  4464. } else {
  4465. goToSlide(current_slide-1, "easeOutExpo");
  4466. upDate();
  4467. }
  4468. } else {
  4469. backToCurrentSlide();
  4470. }
  4471. }
  4472. /* NAVIGATION
  4473. ================================================== */
  4474. function onNextClick(e) {
  4475. if (current_slide == slides.length - 1) {
  4476. backToCurrentSlide();
  4477. } else {
  4478. goToSlide(current_slide+1);
  4479. upDate();
  4480. }
  4481. }
  4482. function onPrevClick(e) {
  4483. if (current_slide == 0) {
  4484. backToCurrentSlide();
  4485. } else {
  4486. goToSlide(current_slide-1);
  4487. upDate();
  4488. }
  4489. }
  4490. function onKeypressNav(e) {
  4491. switch(e.keyCode) {
  4492. case 39:
  4493. // RIGHT ARROW
  4494. onNextClick(e);
  4495. break;
  4496. case 37:
  4497. // LEFT ARROW
  4498. onPrevClick(e);
  4499. break;
  4500. }
  4501. }
  4502. function onTouchUpdate(e, b) {
  4503. if (slide_positions.length == 0) {
  4504. for(var i = 0; i < slides.length; i++) {
  4505. slide_positions.push( slides[i].leftpos() );
  4506. }
  4507. }
  4508. if (typeof b.left == "number") {
  4509. var _pos = b.left;
  4510. var _slide_pos = -(slides[current_slide].leftpos());
  4511. if (_pos < _slide_pos - (config.slider_width/3)) {
  4512. onNextClick();
  4513. } else if (_pos > _slide_pos + (config.slider_width/3)) {
  4514. onPrevClick();
  4515. } else {
  4516. VMM.Lib.animate($slider_container, config.duration, config.ease, {"left": _slide_pos });
  4517. }
  4518. } else {
  4519. VMM.Lib.animate($slider_container, config.duration, config.ease, {"left": _slide_pos });
  4520. }
  4521. if (typeof b.top == "number") {
  4522. VMM.Lib.animate($slider_container, config.duration, config.ease, {"top": -b.top});
  4523. } else {
  4524. }
  4525. };
  4526. function onExplainerClick(e) {
  4527. detachMessege();
  4528. }
  4529. /* UPDATE
  4530. ================================================== */
  4531. function upDate() {
  4532. config.current_slide = current_slide;
  4533. VMM.fireEvent(layout, "UPDATE");
  4534. };
  4535. /* GET DATA
  4536. ================================================== */
  4537. function getData(d) {
  4538. data = d;
  4539. };
  4540. /* BUILD SLIDES
  4541. ================================================== */
  4542. function buildSlides(d) {
  4543. var i = 0;
  4544. VMM.attachElement($slides_items, "");
  4545. slides = [];
  4546. for(i = 0; i < d.length; i++) {
  4547. var _slide = new VMM.Slider.Slide(d[i], $slides_items);
  4548. //_slide.show();
  4549. slides.push(_slide);
  4550. }
  4551. }
  4552. function preloadSlides(skip) {
  4553. var i = 0;
  4554. if (skip) {
  4555. preloadTimeOutSlides();
  4556. } else {
  4557. for(i = 0; i < slides.length; i++) {
  4558. slides[i].clearTimers();
  4559. }
  4560. timer = setTimeout(preloadTimeOutSlides, config.duration);
  4561. }
  4562. }
  4563. function preloadTimeOutSlides() {
  4564. var i = 0;
  4565. for(i = 0; i < slides.length; i++) {
  4566. slides[i].enqueue = true;
  4567. }
  4568. for(i = 0; i < config.preload; i++) {
  4569. if ( !((current_slide + i) > slides.length - 1)) {
  4570. slides[current_slide + i].show();
  4571. slides[current_slide + i].enqueue = false;
  4572. }
  4573. if ( !( (current_slide - i) < 0 ) ) {
  4574. slides[current_slide - i].show();
  4575. slides[current_slide - i].enqueue = false;
  4576. }
  4577. }
  4578. if (slides.length > 50) {
  4579. for(i = 0; i < slides.length; i++) {
  4580. if (slides[i].enqueue) {
  4581. slides[i].hide();
  4582. }
  4583. }
  4584. }
  4585. sizeSlides();
  4586. }
  4587. function sizeSlide(slide_id) {
  4588. }
  4589. /* SIZE SLIDES
  4590. ================================================== */
  4591. function sizeSlides() {
  4592. var i = 0,
  4593. layout_text_media = ".slider-item .layout-text-media .media .media-container ",
  4594. layout_media = ".slider-item .layout-media .media .media-container ",
  4595. layout_both = ".slider-item .media .media-container",
  4596. layout_caption = ".slider-item .media .media-container .media-shadow .caption",
  4597. is_skinny = false,
  4598. mediasize = {
  4599. text_media: {
  4600. width: (config.slider.content.width/100) * 60,
  4601. height: config.slider.height - 60,
  4602. video: {
  4603. width: 0,
  4604. height: 0
  4605. },
  4606. text: {
  4607. width: ((config.slider.content.width/100) * 40) - 30,
  4608. height: config.slider.height
  4609. }
  4610. },
  4611. media: {
  4612. width: config.slider.content.width,
  4613. height: config.slider.height - 110,
  4614. video: {
  4615. width: 0,
  4616. height: 0
  4617. }
  4618. }
  4619. };
  4620. // Handle smaller sizes
  4621. if (VMM.Browser.device == "mobile" || current_width < 641) {
  4622. is_skinny = true;
  4623. }
  4624. VMM.master_config.sizes.api.width = mediasize.media.width;
  4625. VMM.master_config.sizes.api.height = mediasize.media.height;
  4626. mediasize.text_media.video = VMM.Util.ratio.fit(mediasize.text_media.width, mediasize.text_media.height, 16, 9);
  4627. mediasize.media.video = VMM.Util.ratio.fit(mediasize.media.width, mediasize.media.height, 16, 9);
  4628. VMM.Lib.css(".slider-item", "width", config.slider.content.width );
  4629. VMM.Lib.height(".slider-item", config.slider.height);
  4630. if (is_skinny) {
  4631. mediasize.text_media.width = config.slider.content.width - (config.slider.content.padding*2);
  4632. mediasize.media.width = config.slider.content.width - (config.slider.content.padding*2);
  4633. mediasize.text_media.height = ((config.slider.height/100) * 50 ) - 50;
  4634. mediasize.media.height = ((config.slider.height/100) * 70 ) - 40;
  4635. mediasize.text_media.video = VMM.Util.ratio.fit(mediasize.text_media.width, mediasize.text_media.height, 16, 9);
  4636. mediasize.media.video = VMM.Util.ratio.fit(mediasize.media.width, mediasize.media.height, 16, 9);
  4637. VMM.Lib.css(".slider-item .layout-text-media .text", "width", "100%" );
  4638. VMM.Lib.css(".slider-item .layout-text-media .text", "display", "block" );
  4639. VMM.Lib.css(".slider-item .layout-text-media .text .container", "display", "block" );
  4640. VMM.Lib.css(".slider-item .layout-text-media .text .container", "width", mediasize.media.width );
  4641. VMM.Lib.css(".slider-item .layout-text-media .text .container .start", "width", "auto" );
  4642. VMM.Lib.css(".slider-item .layout-text-media .media", "float", "none" );
  4643. VMM.Lib.addClass(".slider-item .content-container", "pad-top");
  4644. VMM.Lib.css(".slider-item .media blockquote p", "line-height", "18px" );
  4645. VMM.Lib.css(".slider-item .media blockquote p", "font-size", "16px" );
  4646. VMM.Lib.css(".slider-item", "overflow-y", "auto" );
  4647. } else {
  4648. VMM.Lib.css(".slider-item .layout-text-media .text", "width", "40%" );
  4649. VMM.Lib.css(".slider-item .layout-text-media .text", "display", "table-cell" );
  4650. VMM.Lib.css(".slider-item .layout-text-media .text .container", "display", "table-cell" );
  4651. VMM.Lib.css(".slider-item .layout-text-media .text .container", "width", "auto" );
  4652. VMM.Lib.css(".slider-item .layout-text-media .text .container .start", "width", mediasize.text_media.text.width );
  4653. //VMM.Lib.addClass(".slider-item .content-container", "pad-left");
  4654. VMM.Lib.removeClass(".slider-item .content-container", "pad-top");
  4655. VMM.Lib.css(".slider-item .layout-text-media .media", "float", "left" );
  4656. VMM.Lib.css(".slider-item .layout-text-media", "display", "table" );
  4657. VMM.Lib.css(".slider-item .media blockquote p", "line-height", "36px" );
  4658. VMM.Lib.css(".slider-item .media blockquote p", "font-size", "28px" );
  4659. VMM.Lib.css(".slider-item", "display", "table" );
  4660. VMM.Lib.css(".slider-item", "overflow-y", "auto" );
  4661. }
  4662. // MEDIA FRAME
  4663. VMM.Lib.css( layout_text_media + ".media-frame", "max-width", mediasize.text_media.width);
  4664. VMM.Lib.height( layout_text_media + ".media-frame", mediasize.text_media.height);
  4665. VMM.Lib.width( layout_text_media + ".media-frame", mediasize.text_media.width);
  4666. // WEBSITES
  4667. //VMM.Lib.css( layout_both + ".website", "max-width", 300 );
  4668. // IMAGES
  4669. VMM.Lib.css( layout_text_media + "img", "max-height", mediasize.text_media.height );
  4670. VMM.Lib.css( layout_media + "img", "max-height", mediasize.media.height );
  4671. // FIX FOR NON-WEBKIT BROWSERS
  4672. VMM.Lib.css( layout_text_media + "img", "max-width", mediasize.text_media.width );
  4673. VMM.Lib.css( layout_text_media + ".avatar img", "max-width", 32 );
  4674. VMM.Lib.css( layout_text_media + ".avatar img", "max-height", 32 );
  4675. VMM.Lib.css( layout_media + ".avatar img", "max-width", 32 );
  4676. VMM.Lib.css( layout_media + ".avatar img", "max-height", 32 );
  4677. VMM.Lib.css( layout_text_media + ".article-thumb", "max-width", "50%" );
  4678. //VMM.Lib.css( layout_text_media + ".article-thumb", "max-height", 100 );
  4679. VMM.Lib.css( layout_media + ".article-thumb", "max-width", 200 );
  4680. //VMM.Lib.css( layout_media + ".article-thumb", "max-height", 100 );
  4681. // IFRAME FULL SIZE VIDEO
  4682. VMM.Lib.width( layout_text_media + ".media-frame", mediasize.text_media.video.width);
  4683. VMM.Lib.height( layout_text_media + ".media-frame", mediasize.text_media.video.height);
  4684. VMM.Lib.width( layout_media + ".media-frame", mediasize.media.video.width);
  4685. VMM.Lib.height( layout_media + ".media-frame", mediasize.media.video.height);
  4686. VMM.Lib.css( layout_media + ".media-frame", "max-height", mediasize.media.video.height);
  4687. VMM.Lib.css( layout_media + ".media-frame", "max-width", mediasize.media.video.width);
  4688. // SOUNDCLOUD
  4689. VMM.Lib.height( layout_media + ".soundcloud", 168);
  4690. VMM.Lib.height( layout_text_media + ".soundcloud", 168);
  4691. VMM.Lib.width( layout_media + ".soundcloud", mediasize.media.width);
  4692. VMM.Lib.width( layout_text_media + ".soundcloud", mediasize.text_media.width);
  4693. VMM.Lib.css( layout_both + ".soundcloud", "max-height", 168 );
  4694. // MAPS
  4695. VMM.Lib.height( layout_text_media + ".map", mediasize.text_media.height);
  4696. VMM.Lib.width( layout_text_media + ".map", mediasize.text_media.width);
  4697. VMM.Lib.css( layout_media + ".map", "max-height", mediasize.media.height);
  4698. VMM.Lib.width( layout_media + ".map", mediasize.media.width);
  4699. // DOCS
  4700. VMM.Lib.height( layout_text_media + ".doc", mediasize.text_media.height);
  4701. VMM.Lib.width( layout_text_media + ".doc", mediasize.text_media.width);
  4702. VMM.Lib.height( layout_media + ".doc", mediasize.media.height);
  4703. VMM.Lib.width( layout_media + ".doc", mediasize.media.width);
  4704. // IE8 NEEDS THIS
  4705. VMM.Lib.width( layout_media + ".wikipedia", mediasize.media.width);
  4706. VMM.Lib.width( layout_media + ".twitter", mediasize.media.width);
  4707. VMM.Lib.width( layout_media + ".plain-text-quote", mediasize.media.width);
  4708. VMM.Lib.width( layout_media + ".plain-text", mediasize.media.width);
  4709. VMM.Lib.css( layout_both, "max-width", mediasize.media.width);
  4710. // CAPTION WIDTH
  4711. VMM.Lib.css( layout_text_media + ".caption", "max-width", mediasize.text_media.video.width);
  4712. VMM.Lib.css( layout_media + ".caption", "max-width", mediasize.media.video.width);
  4713. //VMM.Lib.css( layout_text_media + ".caption", "max-width", mediasize.text_media.width);
  4714. //VMM.Lib.css( layout_media + ".caption", "max-width", mediasize.media.width);
  4715. // MAINTAINS VERTICAL CENTER IF IT CAN
  4716. for(i = 0; i < slides.length; i++) {
  4717. slides[i].layout(is_skinny);
  4718. if (slides[i].content_height() > config.slider.height + 20) {
  4719. slides[i].css("display", "block");
  4720. } else {
  4721. slides[i].css("display", "table");
  4722. }
  4723. }
  4724. }
  4725. /* POSITION SLIDES
  4726. ================================================== */
  4727. function positionSlides() {
  4728. var pos = 0,
  4729. i = 0;
  4730. for(i = 0; i < slides.length; i++) {
  4731. pos = i * (config.slider.width+config.spacing);
  4732. slides[i].leftpos(pos);
  4733. }
  4734. }
  4735. /* OPACITY SLIDES
  4736. ================================================== */
  4737. function opacitySlides(n) {
  4738. var _ease = "linear",
  4739. i = 0;
  4740. for(i = 0; i < slides.length; i++) {
  4741. if (i == current_slide) {
  4742. slides[i].animate(config.duration, _ease, {"opacity": 1});
  4743. } else if (i == current_slide - 1 || i == current_slide + 1) {
  4744. slides[i].animate(config.duration, _ease, {"opacity": 0.1});
  4745. } else {
  4746. slides[i].opacity(n);
  4747. }
  4748. }
  4749. }
  4750. /* GO TO SLIDE
  4751. goToSlide(n, ease, duration);
  4752. ================================================== */
  4753. function goToSlide(n, ease, duration, fast, firstrun) {
  4754. var _ease = config.ease,
  4755. _duration = config.duration,
  4756. is_last = false,
  4757. is_first = false,
  4758. _title = "",
  4759. _pos;
  4760. /* STOP ANY VIDEO PLAYERS ACTIVE
  4761. ================================================== */
  4762. VMM.ExternalAPI.youtube.stopPlayers();
  4763. // Set current slide
  4764. current_slide = n;
  4765. _pos = slides[current_slide].leftpos();
  4766. if (current_slide == 0) {is_first = true};
  4767. if (current_slide +1 >= slides.length) {is_last = true};
  4768. if (ease != null && ease != "") {_ease = ease};
  4769. if (duration != null && duration != "") {_duration = duration};
  4770. /* NAVIGATION
  4771. set proper nav titles and dates etc.
  4772. ================================================== */
  4773. // Handle smaller sizes
  4774. if (VMM.Browser.device == "mobile") {
  4775. //if (VMM.Browser.device == "mobile" || current_width <= 640) {
  4776. VMM.Lib.visible(navigation.prevBtn, false);
  4777. VMM.Lib.visible(navigation.nextBtn, false);
  4778. } else {
  4779. if (is_first) {
  4780. VMM.Lib.visible(navigation.prevBtn, false);
  4781. } else {
  4782. VMM.Lib.visible(navigation.prevBtn, true);
  4783. _title = VMM.Util.unlinkify(data[current_slide - 1].title)
  4784. if (config.type == "timeline") {
  4785. if(typeof data[current_slide - 1].date === "undefined") {
  4786. VMM.attachElement(navigation.prevDate, _title);
  4787. VMM.attachElement(navigation.prevTitle, "");
  4788. } else {
  4789. VMM.attachElement(navigation.prevDate, VMM.Date.prettyDate(data[current_slide - 1].startdate, false, data[current_slide - 1].precisiondate));
  4790. VMM.attachElement(navigation.prevTitle, _title);
  4791. }
  4792. } else {
  4793. VMM.attachElement(navigation.prevTitle, _title);
  4794. }
  4795. }
  4796. if (is_last) {
  4797. VMM.Lib.visible(navigation.nextBtn, false);
  4798. } else {
  4799. VMM.Lib.visible(navigation.nextBtn, true);
  4800. _title = VMM.Util.unlinkify(data[current_slide + 1].title);
  4801. if (config.type == "timeline") {
  4802. if(typeof data[current_slide + 1].date === "undefined") {
  4803. VMM.attachElement(navigation.nextDate, _title);
  4804. VMM.attachElement(navigation.nextTitle, "");
  4805. } else {
  4806. VMM.attachElement(navigation.nextDate, VMM.Date.prettyDate(data[current_slide + 1].startdate, false, data[current_slide + 1].precisiondate) );
  4807. VMM.attachElement(navigation.nextTitle, _title);
  4808. }
  4809. } else {
  4810. VMM.attachElement(navigation.nextTitle, _title);
  4811. }
  4812. }
  4813. }
  4814. /* ANIMATE SLIDE
  4815. ================================================== */
  4816. if (fast) {
  4817. VMM.Lib.css($slider_container, "left", -(_pos - config.slider.content.padding));
  4818. } else{
  4819. VMM.Lib.stop($slider_container);
  4820. VMM.Lib.animate($slider_container, _duration, _ease, {"left": -(_pos - config.slider.content.padding)});
  4821. }
  4822. if (firstrun) {
  4823. VMM.fireEvent(layout, "LOADED");
  4824. }
  4825. /* SET Vertical Scoll
  4826. ================================================== */
  4827. if (slides[current_slide].height() > config.slider_height) {
  4828. VMM.Lib.css(".slider", "overflow-y", "scroll" );
  4829. } else {
  4830. VMM.Lib.css(layout, "overflow-y", "hidden" );
  4831. var scroll_height = 0;
  4832. try {
  4833. scroll_height = VMM.Lib.prop(layout, "scrollHeight");
  4834. VMM.Lib.animate(layout, _duration, _ease, {scrollTop: scroll_height - VMM.Lib.height(layout) });
  4835. }
  4836. catch(err) {
  4837. scroll_height = VMM.Lib.height(layout);
  4838. }
  4839. }
  4840. preloadSlides();
  4841. VMM.fireEvent($slider, "MESSAGE", "TEST");
  4842. }
  4843. function backToCurrentSlide() {
  4844. VMM.Lib.stop($slider_container);
  4845. VMM.Lib.animate($slider_container, config.duration, "easeOutExpo", {"left": -(slides[current_slide].leftpos()) + config.slider.content.padding} );
  4846. }
  4847. /* MESSEGES
  4848. ================================================== */
  4849. function showMessege(e, msg, other) {
  4850. trace("showMessege " + msg);
  4851. //VMM.attachElement($timeline, $feedback);
  4852. VMM.attachElement($explainer, "<div class='vco-explainer'><div class='vco-explainer-container'><div class='vco-bezel'><div class='vco-gesture-icon'></div>" + "<div class='vco-message'><p>" + msg + "</p></div></div></div></div>");
  4853. };
  4854. function hideMessege() {
  4855. VMM.Lib.animate($explainer, config.duration, config.ease, {"opacity": 0}, detachMessege);
  4856. };
  4857. function detachMessege() {
  4858. VMM.Lib.detach($explainer);
  4859. }
  4860. /* BUILD NAVIGATION
  4861. ================================================== */
  4862. function buildNavigation() {
  4863. var temp_icon = "<div class='icon'>&nbsp;</div>";
  4864. navigation.nextBtn = VMM.appendAndGetElement($slider, "<div>", "nav-next");
  4865. navigation.prevBtn = VMM.appendAndGetElement($slider, "<div>", "nav-previous");
  4866. navigation.nextBtnContainer = VMM.appendAndGetElement(navigation.nextBtn, "<div>", "nav-container", temp_icon);
  4867. navigation.prevBtnContainer = VMM.appendAndGetElement(navigation.prevBtn, "<div>", "nav-container", temp_icon);
  4868. if (config.type == "timeline") {
  4869. navigation.nextDate = VMM.appendAndGetElement(navigation.nextBtnContainer, "<div>", "date", "");
  4870. navigation.prevDate = VMM.appendAndGetElement(navigation.prevBtnContainer, "<div>", "date", "");
  4871. }
  4872. navigation.nextTitle = VMM.appendAndGetElement(navigation.nextBtnContainer, "<div>", "title", "");
  4873. navigation.prevTitle = VMM.appendAndGetElement(navigation.prevBtnContainer, "<div>", "title", "");
  4874. VMM.bindEvent(".nav-next", onNextClick);
  4875. VMM.bindEvent(".nav-previous", onPrevClick);
  4876. VMM.bindEvent(window, onKeypressNav, 'keydown');
  4877. }
  4878. /* BUILD
  4879. ================================================== */
  4880. function build() {
  4881. var __duration = 3000;
  4882. // Clear out existing content
  4883. VMM.attachElement(layout, "");
  4884. // Get DOM Objects to local objects
  4885. $slider = VMM.getElement(layout);
  4886. $slider_mask = VMM.appendAndGetElement($slider, "<div>", "slider-container-mask");
  4887. $slider_container = VMM.appendAndGetElement($slider_mask, "<div>", "slider-container");
  4888. $slides_items = VMM.appendAndGetElement($slider_container, "<div>", "slider-item-container");
  4889. // BUILD NAVIGATION
  4890. buildNavigation();
  4891. // ATTACH SLIDES
  4892. buildSlides(data);
  4893. /* MAKE SLIDER DRAGGABLE/TOUCHABLE
  4894. ================================================== */
  4895. if (VMM.Browser.device == "tablet" || VMM.Browser.device == "mobile") {
  4896. // Different Animation duration for touch
  4897. config.duration = 500;
  4898. __duration = 1000;
  4899. // Make touchable
  4900. $dragslide = new VMM.DragSlider();
  4901. $dragslide.createPanel($slider, $slider_container, "", config.touch, true);
  4902. VMM.bindEvent($dragslide, onDragFinish, 'DRAGUPDATE');
  4903. // EXPLAINER
  4904. $explainer = VMM.appendAndGetElement($slider_mask, "<div>", "vco-feedback", "");
  4905. showMessege(null, VMM.master_config.language.messages.swipe_nav);
  4906. VMM.Lib.height($explainer, config.slider.height);
  4907. VMM.bindEvent($explainer, onExplainerClick);
  4908. VMM.bindEvent($explainer, onExplainerClick, 'touchend');
  4909. }
  4910. reSize(false, true);
  4911. VMM.Lib.visible(navigation.prevBtn, false);
  4912. goToSlide(config.current_slide, "easeOutExpo", __duration, true, true);
  4913. _active = true;
  4914. };
  4915. };
  4916. }
  4917. /* **********************************************
  4918. Begin VMM.Slider.Slide.js
  4919. ********************************************** */
  4920. /* Slider Slide
  4921. ================================================== */
  4922. if (typeof VMM.Slider != 'undefined') {
  4923. VMM.Slider.Slide = function(d, _parent) {
  4924. var $media, $text, $slide, $wrap, element, c,
  4925. data = d,
  4926. slide = {},
  4927. element = "",
  4928. media = "",
  4929. loaded = false,
  4930. preloaded = false,
  4931. is_skinny = false,
  4932. _enqueue = true,
  4933. _removeque = false,
  4934. _id = "slide_",
  4935. _class = 0,
  4936. timer = {pushque:"", render:"", relayout:"", remove:"", skinny:false},
  4937. times = {pushque:500, render:100, relayout:100, remove:30000};
  4938. _id = _id + data.uniqueid;
  4939. this.enqueue = _enqueue;
  4940. this.id = _id;
  4941. element = VMM.appendAndGetElement(_parent, "<div>", "slider-item");
  4942. if (typeof data.classname != 'undefined') {
  4943. trace("HAS CLASSNAME");
  4944. VMM.Lib.addClass(element, data.classname);
  4945. } else {
  4946. trace("NO CLASSNAME");
  4947. trace(data);
  4948. }
  4949. c = {slide:"", text: "", media: "", media_element: "", layout: "content-container layout", has: { headline: false, text: false, media: false }};
  4950. /* PUBLIC
  4951. ================================================== */
  4952. this.show = function(skinny) {
  4953. _enqueue = false;
  4954. timer.skinny = skinny;
  4955. _removeque = false;
  4956. clearTimeout(timer.remove);
  4957. if (!loaded) {
  4958. if (preloaded) {
  4959. clearTimeout(timer.relayout);
  4960. timer.relayout = setTimeout(reloadLayout, times.relayout);
  4961. } else {
  4962. render(skinny);
  4963. }
  4964. }
  4965. };
  4966. this.hide = function() {
  4967. if (loaded && !_removeque) {
  4968. _removeque = true;
  4969. clearTimeout(timer.remove);
  4970. timer.remove = setTimeout(removeSlide, times.remove);
  4971. }
  4972. };
  4973. this.clearTimers = function() {
  4974. //clearTimeout(timer.remove);
  4975. clearTimeout(timer.relayout);
  4976. clearTimeout(timer.pushque);
  4977. clearTimeout(timer.render);
  4978. };
  4979. this.layout = function(skinny) {
  4980. if (loaded && preloaded) {
  4981. reLayout(skinny);
  4982. }
  4983. };
  4984. this.elem = function() {
  4985. return element;
  4986. };
  4987. this.position = function() {
  4988. return VMM.Lib.position(element);
  4989. };
  4990. this.leftpos = function(p) {
  4991. if(typeof p != 'undefined') {
  4992. VMM.Lib.css(element, "left", p);
  4993. } else {
  4994. return VMM.Lib.position(element).left
  4995. }
  4996. };
  4997. this.animate = function(d, e, p) {
  4998. VMM.Lib.animate(element, d, e, p);
  4999. };
  5000. this.css = function(p, v) {
  5001. VMM.Lib.css(element, p, v );
  5002. }
  5003. this.opacity = function(p) {
  5004. VMM.Lib.css(element, "opacity", p);
  5005. }
  5006. this.width = function() {
  5007. return VMM.Lib.width(element);
  5008. };
  5009. this.height = function() {
  5010. return VMM.Lib.height(element);
  5011. };
  5012. this.content_height = function () {
  5013. var ch = VMM.Lib.find( element, ".content")[0];
  5014. if (ch != 'undefined' && ch != null) {
  5015. return VMM.Lib.height(ch);
  5016. } else {
  5017. return 0;
  5018. }
  5019. }
  5020. /* PRIVATE
  5021. ================================================== */
  5022. var render = function(skinny) {
  5023. trace("RENDER " + _id);
  5024. loaded = true;
  5025. preloaded = true;
  5026. timer.skinny = skinny;
  5027. buildSlide();
  5028. clearTimeout(timer.pushque);
  5029. clearTimeout(timer.render);
  5030. timer.pushque = setTimeout(VMM.ExternalAPI.pushQues, times.pushque);
  5031. };
  5032. var removeSlide = function() {
  5033. //VMM.attachElement(element, "");
  5034. trace("REMOVE SLIDE TIMER FINISHED");
  5035. loaded = false;
  5036. VMM.Lib.detach($text);
  5037. VMM.Lib.detach($media);
  5038. };
  5039. var reloadLayout = function() {
  5040. loaded = true;
  5041. reLayout(timer.skinny, true);
  5042. };
  5043. var reLayout = function(skinny, reload) {
  5044. if (c.has.text) {
  5045. if (skinny) {
  5046. if (!is_skinny || reload) {
  5047. VMM.Lib.removeClass($slide, "pad-left");
  5048. VMM.Lib.detach($text);
  5049. VMM.Lib.detach($media);
  5050. VMM.Lib.append($slide, $text);
  5051. VMM.Lib.append($slide, $media);
  5052. is_skinny = true;
  5053. }
  5054. } else {
  5055. if (is_skinny || reload) {
  5056. VMM.Lib.addClass($slide, "pad-left");
  5057. VMM.Lib.detach($text);
  5058. VMM.Lib.detach($media);
  5059. VMM.Lib.append($slide, $media);
  5060. VMM.Lib.append($slide, $text);
  5061. is_skinny = false;
  5062. }
  5063. }
  5064. } else if (reload) {
  5065. if (c.has.headline) {
  5066. VMM.Lib.detach($text);
  5067. VMM.Lib.append($slide, $text);
  5068. }
  5069. VMM.Lib.detach($media);
  5070. VMM.Lib.append($slide, $media);
  5071. }
  5072. }
  5073. var buildSlide = function() {
  5074. trace("BUILDSLIDE");
  5075. $wrap = VMM.appendAndGetElement(element, "<div>", "content");
  5076. $slide = VMM.appendAndGetElement($wrap, "<div>");
  5077. /* DATE
  5078. ================================================== */
  5079. if (data.startdate != null && data.startdate != "") {
  5080. if (type.of(data.startdate) == "date") {
  5081. if (data.type != "start") {
  5082. var st = VMM.Date.prettyDate(data.startdate, false, data.precisiondate);
  5083. var en = VMM.Date.prettyDate(data.enddate, false, data.precisiondate);
  5084. var tag = "";
  5085. /* TAG / CATEGORY
  5086. ================================================== */
  5087. if (data.tag != null && data.tag != "") {
  5088. tag = VMM.createElement("span", data.tag, "slide-tag");
  5089. }
  5090. if (st != en) {
  5091. c.text += VMM.createElement("h2", st + " &mdash; " + en + tag, "date");
  5092. } else {
  5093. c.text += VMM.createElement("h2", st + tag, "date");
  5094. }
  5095. }
  5096. }
  5097. }
  5098. /* HEADLINE
  5099. ================================================== */
  5100. if (data.headline != null && data.headline != "") {
  5101. c.has.headline = true;
  5102. if (data.type == "start") {
  5103. c.text += VMM.createElement("h2", VMM.Util.linkify_with_twitter(data.headline, "_blank"), "start");
  5104. } else {
  5105. c.text += VMM.createElement("h3", VMM.Util.linkify_with_twitter(data.headline, "_blank"));
  5106. }
  5107. }
  5108. /* TEXT
  5109. ================================================== */
  5110. if (data.text != null && data.text != "") {
  5111. c.has.text = true;
  5112. c.text += VMM.createElement("p", VMM.Util.linkify_with_twitter(data.text, "_blank"));
  5113. }
  5114. if (c.has.text || c.has.headline) {
  5115. c.text = VMM.createElement("div", c.text, "container");
  5116. //$text = VMM.appendAndGetElement($slide, "<div>", "text", c.text);
  5117. $text = VMM.appendAndGetElement($slide, "<div>", "text", VMM.TextElement.create(c.text));
  5118. }
  5119. /* SLUG
  5120. ================================================== */
  5121. if (data.needs_slug) {
  5122. }
  5123. /* MEDIA
  5124. ================================================== */
  5125. if (data.asset != null && data.asset != "") {
  5126. if (data.asset.media != null && data.asset.media != "") {
  5127. c.has.media = true;
  5128. $media = VMM.appendAndGetElement($slide, "<div>", "media", VMM.MediaElement.create(data.asset, data.uniqueid));
  5129. }
  5130. }
  5131. /* COMBINE
  5132. ================================================== */
  5133. if (c.has.text) { c.layout += "-text" };
  5134. if (c.has.media){ c.layout += "-media" };
  5135. if (c.has.text) {
  5136. if (timer.skinny) {
  5137. VMM.Lib.addClass($slide, c.layout);
  5138. is_skinny = true;
  5139. } else {
  5140. VMM.Lib.addClass($slide, c.layout);
  5141. VMM.Lib.addClass($slide, "pad-left");
  5142. VMM.Lib.detach($text);
  5143. VMM.Lib.append($slide, $text);
  5144. }
  5145. } else {
  5146. VMM.Lib.addClass($slide, c.layout);
  5147. }
  5148. };
  5149. }
  5150. };
  5151. /* **********************************************
  5152. Begin AES.js
  5153. ********************************************** */
  5154. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  5155. /* AES implementation in JavaScript (c) Chris Veness 2005-2011 */
  5156. /* - see http://csrc.nist.gov/publications/PubsFIPS.html#197 */
  5157. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  5158. var Aes = {}; // Aes namespace
  5159. /**
  5160. * AES Cipher function: encrypt 'input' state with Rijndael algorithm
  5161. * applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage
  5162. *
  5163. * @param {Number[]} input 16-byte (128-bit) input state array
  5164. * @param {Number[][]} w Key schedule as 2D byte-array (Nr+1 x Nb bytes)
  5165. * @returns {Number[]} Encrypted output state array
  5166. */
  5167. Aes.cipher = function(input, w) { // main Cipher function [§5.1]
  5168. var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
  5169. var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
  5170. var state = [[],[],[],[]]; // initialise 4xNb byte-array 'state' with input [§3.4]
  5171. for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i];
  5172. state = Aes.addRoundKey(state, w, 0, Nb);
  5173. for (var round=1; round<Nr; round++) {
  5174. state = Aes.subBytes(state, Nb);
  5175. state = Aes.shiftRows(state, Nb);
  5176. state = Aes.mixColumns(state, Nb);
  5177. state = Aes.addRoundKey(state, w, round, Nb);
  5178. }
  5179. state = Aes.subBytes(state, Nb);
  5180. state = Aes.shiftRows(state, Nb);
  5181. state = Aes.addRoundKey(state, w, Nr, Nb);
  5182. var output = new Array(4*Nb); // convert state to 1-d array before returning [§3.4]
  5183. for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)];
  5184. return output;
  5185. }
  5186. /**
  5187. * Perform Key Expansion to generate a Key Schedule
  5188. *
  5189. * @param {Number[]} key Key as 16/24/32-byte array
  5190. * @returns {Number[][]} Expanded key schedule as 2D byte-array (Nr+1 x Nb bytes)
  5191. */
  5192. Aes.keyExpansion = function(key) { // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2]
  5193. var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
  5194. var Nk = key.length/4 // key length (in words): 4/6/8 for 128/192/256-bit keys
  5195. var Nr = Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys
  5196. var w = new Array(Nb*(Nr+1));
  5197. var temp = new Array(4);
  5198. for (var i=0; i<Nk; i++) {
  5199. var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];
  5200. w[i] = r;
  5201. }
  5202. for (var i=Nk; i<(Nb*(Nr+1)); i++) {
  5203. w[i] = new Array(4);
  5204. for (var t=0; t<4; t++) temp[t] = w[i-1][t];
  5205. if (i % Nk == 0) {
  5206. temp = Aes.subWord(Aes.rotWord(temp));
  5207. for (var t=0; t<4; t++) temp[t] ^= Aes.rCon[i/Nk][t];
  5208. } else if (Nk > 6 && i%Nk == 4) {
  5209. temp = Aes.subWord(temp);
  5210. }
  5211. for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t];
  5212. }
  5213. return w;
  5214. }
  5215. /*
  5216. * ---- remaining routines are private, not called externally ----
  5217. */
  5218. Aes.subBytes = function(s, Nb) { // apply SBox to state S [§5.1.1]
  5219. for (var r=0; r<4; r++) {
  5220. for (var c=0; c<Nb; c++) s[r][c] = Aes.sBox[s[r][c]];
  5221. }
  5222. return s;
  5223. }
  5224. Aes.shiftRows = function(s, Nb) { // shift row r of state S left by r bytes [§5.1.2]
  5225. var t = new Array(4);
  5226. for (var r=1; r<4; r++) {
  5227. for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb]; // shift into temp copy
  5228. for (var c=0; c<4; c++) s[r][c] = t[c]; // and copy back
  5229. } // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
  5230. return s; // see asmaes.sourceforge.net/rijndael/rijndaelImplementation.pdf
  5231. }
  5232. Aes.mixColumns = function(s, Nb) { // combine bytes of each col of state S [§5.1.3]
  5233. for (var c=0; c<4; c++) {
  5234. var a = new Array(4); // 'a' is a copy of the current column from 's'
  5235. var b = new Array(4); // 'b' is a•{02} in GF(2^8)
  5236. for (var i=0; i<4; i++) {
  5237. a[i] = s[i][c];
  5238. b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1;
  5239. }
  5240. // a[n] ^ b[n] is a•{03} in GF(2^8)
  5241. s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3
  5242. s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3
  5243. s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3
  5244. s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3
  5245. }
  5246. return s;
  5247. }
  5248. Aes.addRoundKey = function(state, w, rnd, Nb) { // xor Round Key into state S [§5.1.4]
  5249. for (var r=0; r<4; r++) {
  5250. for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r];
  5251. }
  5252. return state;
  5253. }
  5254. Aes.subWord = function(w) { // apply SBox to 4-byte word w
  5255. for (var i=0; i<4; i++) w[i] = Aes.sBox[w[i]];
  5256. return w;
  5257. }
  5258. Aes.rotWord = function(w) { // rotate 4-byte word w left by one byte
  5259. var tmp = w[0];
  5260. for (var i=0; i<3; i++) w[i] = w[i+1];
  5261. w[3] = tmp;
  5262. return w;
  5263. }
  5264. // sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [§5.1.1]
  5265. Aes.sBox = [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
  5266. 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
  5267. 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
  5268. 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
  5269. 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
  5270. 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
  5271. 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
  5272. 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
  5273. 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
  5274. 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
  5275. 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
  5276. 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
  5277. 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
  5278. 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
  5279. 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
  5280. 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16];
  5281. // rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2]
  5282. Aes.rCon = [ [0x00, 0x00, 0x00, 0x00],
  5283. [0x01, 0x00, 0x00, 0x00],
  5284. [0x02, 0x00, 0x00, 0x00],
  5285. [0x04, 0x00, 0x00, 0x00],
  5286. [0x08, 0x00, 0x00, 0x00],
  5287. [0x10, 0x00, 0x00, 0x00],
  5288. [0x20, 0x00, 0x00, 0x00],
  5289. [0x40, 0x00, 0x00, 0x00],
  5290. [0x80, 0x00, 0x00, 0x00],
  5291. [0x1b, 0x00, 0x00, 0x00],
  5292. [0x36, 0x00, 0x00, 0x00] ];
  5293. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  5294. /* AES Counter-mode implementation in JavaScript (c) Chris Veness 2005-2011 */
  5295. /* - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */
  5296. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  5297. Aes.Ctr = {}; // Aes.Ctr namespace: a subclass or extension of Aes
  5298. /**
  5299. * Encrypt a text using AES encryption in Counter mode of operation
  5300. *
  5301. * Unicode multi-byte character safe
  5302. *
  5303. * @param {String} plaintext Source text to be encrypted
  5304. * @param {String} password The password to use to generate a key
  5305. * @param {Number} nBits Number of bits to be used in the key (128, 192, or 256)
  5306. * @returns {string} Encrypted text
  5307. */
  5308. Aes.Ctr.encrypt = function(plaintext, password, nBits) {
  5309. var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
  5310. if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys
  5311. plaintext = Utf8.encode(plaintext);
  5312. password = Utf8.encode(password);
  5313. //var t = new Date(); // timer
  5314. // use AES itself to encrypt password to get cipher key (using plain password as source for key
  5315. // expansion) - gives us well encrypted key (though hashed key might be preferred for prod'n use)
  5316. var nBytes = nBits/8; // no bytes in key (16/24/32)
  5317. var pwBytes = new Array(nBytes);
  5318. for (var i=0; i<nBytes; i++) { // use 1st 16/24/32 chars of password for key
  5319. pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i);
  5320. }
  5321. var key = Aes.cipher(pwBytes, Aes.keyExpansion(pwBytes)); // gives us 16-byte key
  5322. key = key.concat(key.slice(0, nBytes-16)); // expand key to 16/24/32 bytes long
  5323. // initialise 1st 8 bytes of counter block with nonce (NIST SP800-38A §B.2): [0-1] = millisec,
  5324. // [2-3] = random, [4-7] = seconds, together giving full sub-millisec uniqueness up to Feb 2106
  5325. var counterBlock = new Array(blockSize);
  5326. var nonce = (new Date()).getTime(); // timestamp: milliseconds since 1-Jan-1970
  5327. var nonceMs = nonce%1000;
  5328. var nonceSec = Math.floor(nonce/1000);
  5329. var nonceRnd = Math.floor(Math.random()*0xffff);
  5330. for (var i=0; i<2; i++) counterBlock[i] = (nonceMs >>> i*8) & 0xff;
  5331. for (var i=0; i<2; i++) counterBlock[i+2] = (nonceRnd >>> i*8) & 0xff;
  5332. for (var i=0; i<4; i++) counterBlock[i+4] = (nonceSec >>> i*8) & 0xff;
  5333. // and convert it to a string to go on the front of the ciphertext
  5334. var ctrTxt = '';
  5335. for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]);
  5336. // generate key schedule - an expansion of the key into distinct Key Rounds for each round
  5337. var keySchedule = Aes.keyExpansion(key);
  5338. var blockCount = Math.ceil(plaintext.length/blockSize);
  5339. var ciphertxt = new Array(blockCount); // ciphertext as array of strings
  5340. for (var b=0; b<blockCount; b++) {
  5341. // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
  5342. // done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
  5343. for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;
  5344. for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8)
  5345. var cipherCntr = Aes.cipher(counterBlock, keySchedule); // -- encrypt counter block --
  5346. // block size is reduced on final block
  5347. var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1;
  5348. var cipherChar = new Array(blockLength);
  5349. for (var i=0; i<blockLength; i++) { // -- xor plaintext with ciphered counter char-by-char --
  5350. cipherChar[i] = cipherCntr[i] ^ plaintext.charCodeAt(b*blockSize+i);
  5351. cipherChar[i] = String.fromCharCode(cipherChar[i]);
  5352. }
  5353. ciphertxt[b] = cipherChar.join('');
  5354. }
  5355. // Array.join is more efficient than repeated string concatenation in IE
  5356. var ciphertext = ctrTxt + ciphertxt.join('');
  5357. ciphertext = Base64.encode(ciphertext); // encode in base64
  5358. //alert((new Date()) - t);
  5359. return ciphertext;
  5360. }
  5361. /**
  5362. * Decrypt a text encrypted by AES in counter mode of operation
  5363. *
  5364. * @param {String} ciphertext Source text to be encrypted
  5365. * @param {String} password The password to use to generate a key
  5366. * @param {Number} nBits Number of bits to be used in the key (128, 192, or 256)
  5367. * @returns {String} Decrypted text
  5368. */
  5369. Aes.Ctr.decrypt = function(ciphertext, password, nBits) {
  5370. var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
  5371. if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys
  5372. ciphertext = Base64.decode(ciphertext);
  5373. password = Utf8.encode(password);
  5374. //var t = new Date(); // timer
  5375. // use AES to encrypt password (mirroring encrypt routine)
  5376. var nBytes = nBits/8; // no bytes in key
  5377. var pwBytes = new Array(nBytes);
  5378. for (var i=0; i<nBytes; i++) {
  5379. pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i);
  5380. }
  5381. var key = Aes.cipher(pwBytes, Aes.keyExpansion(pwBytes));
  5382. key = key.concat(key.slice(0, nBytes-16)); // expand key to 16/24/32 bytes long
  5383. // recover nonce from 1st 8 bytes of ciphertext
  5384. var counterBlock = new Array(8);
  5385. ctrTxt = ciphertext.slice(0, 8);
  5386. for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i);
  5387. // generate key schedule
  5388. var keySchedule = Aes.keyExpansion(key);
  5389. // separate ciphertext into blocks (skipping past initial 8 bytes)
  5390. var nBlocks = Math.ceil((ciphertext.length-8) / blockSize);
  5391. var ct = new Array(nBlocks);
  5392. for (var b=0; b<nBlocks; b++) ct[b] = ciphertext.slice(8+b*blockSize, 8+b*blockSize+blockSize);
  5393. ciphertext = ct; // ciphertext is now array of block-length strings
  5394. // plaintext will get generated block-by-block into array of block-length strings
  5395. var plaintxt = new Array(ciphertext.length);
  5396. for (var b=0; b<nBlocks; b++) {
  5397. // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
  5398. for (var c=0; c<4; c++) counterBlock[15-c] = ((b) >>> c*8) & 0xff;
  5399. for (var c=0; c<4; c++) counterBlock[15-c-4] = (((b+1)/0x100000000-1) >>> c*8) & 0xff;
  5400. var cipherCntr = Aes.cipher(counterBlock, keySchedule); // encrypt counter block
  5401. var plaintxtByte = new Array(ciphertext[b].length);
  5402. for (var i=0; i<ciphertext[b].length; i++) {
  5403. // -- xor plaintxt with ciphered counter byte-by-byte --
  5404. plaintxtByte[i] = cipherCntr[i] ^ ciphertext[b].charCodeAt(i);
  5405. plaintxtByte[i] = String.fromCharCode(plaintxtByte[i]);
  5406. }
  5407. plaintxt[b] = plaintxtByte.join('');
  5408. }
  5409. // join array of blocks into single plaintext string
  5410. var plaintext = plaintxt.join('');
  5411. plaintext = Utf8.decode(plaintext); // decode from UTF8 back to Unicode multi-byte chars
  5412. //alert((new Date()) - t);
  5413. return plaintext;
  5414. }
  5415. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  5416. /* Base64 class: Base 64 encoding / decoding (c) Chris Veness 2002-2011 */
  5417. /* note: depends on Utf8 class */
  5418. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  5419. var Base64 = {}; // Base64 namespace
  5420. Base64.code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  5421. /**
  5422. * Encode string into Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648]
  5423. * (instance method extending String object). As per RFC 4648, no newlines are added.
  5424. *
  5425. * @param {String} str The string to be encoded as base-64
  5426. * @param {Boolean} [utf8encode=false] Flag to indicate whether str is Unicode string to be encoded
  5427. * to UTF8 before conversion to base64; otherwise string is assumed to be 8-bit characters
  5428. * @returns {String} Base64-encoded string
  5429. */
  5430. Base64.encode = function(str, utf8encode) { // http://tools.ietf.org/html/rfc4648
  5431. utf8encode = (typeof utf8encode == 'undefined') ? false : utf8encode;
  5432. var o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = '', c, plain, coded;
  5433. var b64 = Base64.code;
  5434. plain = utf8encode ? str.encodeUTF8() : str;
  5435. c = plain.length % 3; // pad string to length of multiple of 3
  5436. if (c > 0) { while (c++ < 3) { pad += '='; plain += '\0'; } }
  5437. // note: doing padding here saves us doing special-case packing for trailing 1 or 2 chars
  5438. for (c=0; c<plain.length; c+=3) { // pack three octets into four hexets
  5439. o1 = plain.charCodeAt(c);
  5440. o2 = plain.charCodeAt(c+1);
  5441. o3 = plain.charCodeAt(c+2);
  5442. bits = o1<<16 | o2<<8 | o3;
  5443. h1 = bits>>18 & 0x3f;
  5444. h2 = bits>>12 & 0x3f;
  5445. h3 = bits>>6 & 0x3f;
  5446. h4 = bits & 0x3f;
  5447. // use hextets to index into code string
  5448. e[c/3] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
  5449. }
  5450. coded = e.join(''); // join() is far faster than repeated string concatenation in IE
  5451. // replace 'A's from padded nulls with '='s
  5452. coded = coded.slice(0, coded.length-pad.length) + pad;
  5453. return coded;
  5454. }
  5455. /**
  5456. * Decode string from Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648]
  5457. * (instance method extending String object). As per RFC 4648, newlines are not catered for.
  5458. *
  5459. * @param {String} str The string to be decoded from base-64
  5460. * @param {Boolean} [utf8decode=false] Flag to indicate whether str is Unicode string to be decoded
  5461. * from UTF8 after conversion from base64
  5462. * @returns {String} decoded string
  5463. */
  5464. Base64.decode = function(str, utf8decode) {
  5465. utf8decode = (typeof utf8decode == 'undefined') ? false : utf8decode;
  5466. var o1, o2, o3, h1, h2, h3, h4, bits, d=[], plain, coded;
  5467. var b64 = Base64.code;
  5468. coded = utf8decode ? str.decodeUTF8() : str;
  5469. for (var c=0; c<coded.length; c+=4) { // unpack four hexets into three octets
  5470. h1 = b64.indexOf(coded.charAt(c));
  5471. h2 = b64.indexOf(coded.charAt(c+1));
  5472. h3 = b64.indexOf(coded.charAt(c+2));
  5473. h4 = b64.indexOf(coded.charAt(c+3));
  5474. bits = h1<<18 | h2<<12 | h3<<6 | h4;
  5475. o1 = bits>>>16 & 0xff;
  5476. o2 = bits>>>8 & 0xff;
  5477. o3 = bits & 0xff;
  5478. d[c/4] = String.fromCharCode(o1, o2, o3);
  5479. // check for padding
  5480. if (h4 == 0x40) d[c/4] = String.fromCharCode(o1, o2);
  5481. if (h3 == 0x40) d[c/4] = String.fromCharCode(o1);
  5482. }
  5483. plain = d.join(''); // join() is far faster than repeated string concatenation in IE
  5484. return utf8decode ? plain.decodeUTF8() : plain;
  5485. }
  5486. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  5487. /* Utf8 class: encode / decode between multi-byte Unicode characters and UTF-8 multiple */
  5488. /* single-byte character encoding (c) Chris Veness 2002-2011 */
  5489. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  5490. var Utf8 = {}; // Utf8 namespace
  5491. /**
  5492. * Encode multi-byte Unicode string into utf-8 multiple single-byte characters
  5493. * (BMP / basic multilingual plane only)
  5494. *
  5495. * Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars
  5496. *
  5497. * @param {String} strUni Unicode string to be encoded as UTF-8
  5498. * @returns {String} encoded string
  5499. */
  5500. Utf8.encode = function(strUni) {
  5501. // use regular expressions & String.replace callback function for better efficiency
  5502. // than procedural approaches
  5503. var strUtf = strUni.replace(
  5504. /[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz
  5505. function(c) {
  5506. var cc = c.charCodeAt(0);
  5507. return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); }
  5508. );
  5509. strUtf = strUtf.replace(
  5510. /[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz
  5511. function(c) {
  5512. var cc = c.charCodeAt(0);
  5513. return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); }
  5514. );
  5515. return strUtf;
  5516. }
  5517. /**
  5518. * Decode utf-8 encoded string back into multi-byte Unicode characters
  5519. *
  5520. * @param {String} strUtf UTF-8 string to be decoded back to Unicode
  5521. * @returns {String} decoded string
  5522. */
  5523. Utf8.decode = function(strUtf) {
  5524. // note: decode 3-byte chars first as decoded 2-byte strings could appear to be 3-byte char!
  5525. var strUni = strUtf.replace(
  5526. /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars
  5527. function(c) { // (note parentheses for precence)
  5528. var cc = ((c.charCodeAt(0)&0x0f)<<12) | ((c.charCodeAt(1)&0x3f)<<6) | ( c.charCodeAt(2)&0x3f);
  5529. return String.fromCharCode(cc); }
  5530. );
  5531. strUni = strUni.replace(
  5532. /[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars
  5533. function(c) { // (note parentheses for precence)
  5534. var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f;
  5535. return String.fromCharCode(cc); }
  5536. );
  5537. return strUni;
  5538. }
  5539. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  5540. /* **********************************************
  5541. Begin bootstrap-tooltip.js
  5542. ********************************************** */
  5543. /* ===========================================================
  5544. * bootstrap-tooltip.js v2.0.1
  5545. * http://twitter.github.com/bootstrap/javascript.html#tooltips
  5546. * Inspired by the original jQuery.tipsy by Jason Frame
  5547. * ===========================================================
  5548. * Copyright 2012 Twitter, Inc.
  5549. *
  5550. * Licensed under the Apache License, Version 2.0 (the "License");
  5551. * you may not use this file except in compliance with the License.
  5552. * You may obtain a copy of the License at
  5553. *
  5554. * http://www.apache.org/licenses/LICENSE-2.0
  5555. *
  5556. * Unless required by applicable law or agreed to in writing, software
  5557. * distributed under the License is distributed on an "AS IS" BASIS,
  5558. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  5559. * See the License for the specific language governing permissions and
  5560. * limitations under the License.
  5561. * ========================================================== */
  5562. !function( $ ) {
  5563. "use strict"
  5564. /* TOOLTIP PUBLIC CLASS DEFINITION
  5565. * =============================== */
  5566. var Tooltip = function ( element, options ) {
  5567. this.init('tooltip', element, options)
  5568. }
  5569. Tooltip.prototype = {
  5570. constructor: Tooltip
  5571. , init: function ( type, element, options ) {
  5572. var eventIn
  5573. , eventOut
  5574. this.type = type
  5575. this.$element = $(element)
  5576. this.options = this.getOptions(options)
  5577. this.enabled = true
  5578. if (this.options.trigger != 'manual') {
  5579. eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
  5580. eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
  5581. this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
  5582. this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
  5583. }
  5584. this.options.selector ?
  5585. (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
  5586. this.fixTitle()
  5587. }
  5588. , getOptions: function ( options ) {
  5589. options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
  5590. if (options.delay && typeof options.delay == 'number') {
  5591. options.delay = {
  5592. show: options.delay
  5593. , hide: options.delay
  5594. }
  5595. }
  5596. return options
  5597. }
  5598. , enter: function ( e ) {
  5599. var self = $(e.currentTarget)[this.type](this._options).data(this.type)
  5600. if (!self.options.delay || !self.options.delay.show) {
  5601. self.show()
  5602. } else {
  5603. self.hoverState = 'in'
  5604. setTimeout(function() {
  5605. if (self.hoverState == 'in') {
  5606. self.show()
  5607. }
  5608. }, self.options.delay.show)
  5609. }
  5610. }
  5611. , leave: function ( e ) {
  5612. var self = $(e.currentTarget)[this.type](this._options).data(this.type)
  5613. if (!self.options.delay || !self.options.delay.hide) {
  5614. self.hide()
  5615. } else {
  5616. self.hoverState = 'out'
  5617. setTimeout(function() {
  5618. if (self.hoverState == 'out') {
  5619. self.hide()
  5620. }
  5621. }, self.options.delay.hide)
  5622. }
  5623. }
  5624. , show: function () {
  5625. var $tip
  5626. , inside
  5627. , pos
  5628. , actualWidth
  5629. , actualHeight
  5630. , placement
  5631. , tp
  5632. if (this.hasContent() && this.enabled) {
  5633. $tip = this.tip()
  5634. this.setContent()
  5635. if (this.options.animation) {
  5636. $tip.addClass('fade')
  5637. }
  5638. placement = typeof this.options.placement == 'function' ?
  5639. this.options.placement.call(this, $tip[0], this.$element[0]) :
  5640. this.options.placement
  5641. inside = /in/.test(placement)
  5642. $tip
  5643. .remove()
  5644. .css({ top: 0, left: 0, display: 'block' })
  5645. .appendTo(inside ? this.$element : document.body)
  5646. pos = this.getPosition(inside)
  5647. actualWidth = $tip[0].offsetWidth
  5648. actualHeight = $tip[0].offsetHeight
  5649. switch (inside ? placement.split(' ')[1] : placement) {
  5650. case 'bottom':
  5651. tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
  5652. break
  5653. case 'top':
  5654. tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
  5655. break
  5656. case 'left':
  5657. tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
  5658. break
  5659. case 'right':
  5660. tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
  5661. break
  5662. }
  5663. $tip
  5664. .css(tp)
  5665. .addClass(placement)
  5666. .addClass('in')
  5667. }
  5668. }
  5669. , setContent: function () {
  5670. var $tip = this.tip()
  5671. $tip.find('.timeline-tooltip-inner').html(this.getTitle())
  5672. $tip.removeClass('fade in top bottom left right')
  5673. }
  5674. , hide: function () {
  5675. var that = this
  5676. , $tip = this.tip()
  5677. $tip.removeClass('in')
  5678. function removeWithAnimation() {
  5679. var timeout = setTimeout(function () {
  5680. $tip.off($.support.transition.end).remove()
  5681. }, 500)
  5682. $tip.one($.support.transition.end, function () {
  5683. clearTimeout(timeout)
  5684. $tip.remove()
  5685. })
  5686. }
  5687. $.support.transition && this.$tip.hasClass('fade') ?
  5688. removeWithAnimation() :
  5689. $tip.remove()
  5690. }
  5691. , fixTitle: function () {
  5692. var $e = this.$element
  5693. if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
  5694. $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
  5695. }
  5696. }
  5697. , hasContent: function () {
  5698. return this.getTitle()
  5699. }
  5700. , getPosition: function (inside) {
  5701. return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
  5702. width: this.$element[0].offsetWidth
  5703. , height: this.$element[0].offsetHeight
  5704. })
  5705. }
  5706. , getTitle: function () {
  5707. var title
  5708. , $e = this.$element
  5709. , o = this.options
  5710. title = $e.attr('data-original-title')
  5711. || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
  5712. title = title.toString().replace(/(^\s*|\s*$)/, "")
  5713. return title
  5714. }
  5715. , tip: function () {
  5716. return this.$tip = this.$tip || $(this.options.template)
  5717. }
  5718. , validate: function () {
  5719. if (!this.$element[0].parentNode) {
  5720. this.hide()
  5721. this.$element = null
  5722. this.options = null
  5723. }
  5724. }
  5725. , enable: function () {
  5726. this.enabled = true
  5727. }
  5728. , disable: function () {
  5729. this.enabled = false
  5730. }
  5731. , toggleEnabled: function () {
  5732. this.enabled = !this.enabled
  5733. }
  5734. , toggle: function () {
  5735. this[this.tip().hasClass('in') ? 'hide' : 'show']()
  5736. }
  5737. }
  5738. /* TOOLTIP PLUGIN DEFINITION
  5739. * ========================= */
  5740. $.fn.tooltip = function ( option ) {
  5741. return this.each(function () {
  5742. var $this = $(this)
  5743. , data = $this.data('tooltip')
  5744. , options = typeof option == 'object' && option
  5745. if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
  5746. if (typeof option == 'string') data[option]()
  5747. })
  5748. }
  5749. $.fn.tooltip.Constructor = Tooltip
  5750. $.fn.tooltip.defaults = {
  5751. animation: true
  5752. , delay: 0
  5753. , selector: false
  5754. , placement: 'top'
  5755. , trigger: 'hover'
  5756. , title: ''
  5757. , template: '<div class="timeline-tooltip"><div class="timeline-tooltip-arrow"></div><div class="timeline-tooltip-inner"></div></div>'
  5758. }
  5759. }( window.jQuery );
  5760. /* **********************************************
  5761. Begin VMM.StoryJS.js
  5762. ********************************************** */
  5763. /* VeriteCo StoryJS
  5764. ================================================== */
  5765. /* * CodeKit Import
  5766. * http://incident57.com/codekit/
  5767. ================================================== */
  5768. // @codekit-prepend "Core/VMM.Core.js";
  5769. // @codekit-prepend "Language/VMM.Language.js";
  5770. // @codekit-prepend "Media/VMM.Media.js";
  5771. // @codekit-prepend "Slider/VMM.DragSlider.js";
  5772. // @codekit-prepend "Slider/VMM.Slider.js";
  5773. // @codekit-prepend "Library/AES.js";
  5774. // @codekit-prepend "Library/bootstrap-tooltip.js";
  5775. if(typeof VMM != 'undefined' && typeof VMM.StoryJS == 'undefined') {
  5776. VMM.StoryJS = function() {
  5777. /* PRIVATE VARS
  5778. ================================================== */
  5779. /* PUBLIC FUNCTIONS
  5780. ================================================== */
  5781. this.init = function(d) {
  5782. };
  5783. }
  5784. }
  5785. /* **********************************************
  5786. Begin VMM.Timeline.js
  5787. ********************************************** */
  5788. // VMM.Timeline.js
  5789. /* * CodeKit Import
  5790. * http://incident57.com/codekit/
  5791. ================================================== */
  5792. // @codekit-prepend "Core/VMM.StoryJS.js";
  5793. // @codekit-append "VMM.Timeline.TimeNav.js";
  5794. // @codekit-append "VMM.Timeline.DataObj.js";
  5795. /* Timeline
  5796. ================================================== */
  5797. if(typeof VMM != 'undefined' && typeof VMM.Timeline == 'undefined') {
  5798. VMM.Timeline = function(_timeline_id, w, h) {
  5799. var $timeline,
  5800. $container,
  5801. $feature,
  5802. $feedback,
  5803. $slider,
  5804. $navigation,
  5805. slider,
  5806. timenav,
  5807. version = "2.x",
  5808. timeline_id = "#timelinejs",
  5809. events = {},
  5810. data = {},
  5811. _dates = [],
  5812. config = {},
  5813. has_width = false,
  5814. has_height = false,
  5815. ie7 = false,
  5816. is_moving = false;
  5817. if (type.of(_timeline_id) == "string") {
  5818. if (_timeline_id.match("#")) {
  5819. timeline_id = _timeline_id;
  5820. } else {
  5821. timeline_id = "#" + _timeline_id;
  5822. }
  5823. } else {
  5824. timeline_id = "#timelinejs";
  5825. }
  5826. /* CONFIG
  5827. ================================================== */
  5828. config = {
  5829. embed: false,
  5830. events: {
  5831. data_ready: "DATAREADY",
  5832. messege: "MESSEGE",
  5833. headline: "HEADLINE",
  5834. slide_change: "SLIDE_CHANGE",
  5835. resize: "resize"
  5836. },
  5837. id: timeline_id,
  5838. source: "nothing",
  5839. type: "timeline",
  5840. touch: false,
  5841. orientation: "normal",
  5842. maptype: "",
  5843. version: "2.x",
  5844. preload: 4,
  5845. current_slide: 0,
  5846. hash_bookmark: false,
  5847. start_at_end: false,
  5848. start_at_slide: 0,
  5849. start_zoom_adjust: 0,
  5850. start_page: false,
  5851. api_keys: {
  5852. google: "",
  5853. flickr: "",
  5854. twitter: ""
  5855. },
  5856. interval: 10,
  5857. something: 0,
  5858. width: 960,
  5859. height: 540,
  5860. spacing: 15,
  5861. loaded: {
  5862. slider: false,
  5863. timenav: false,
  5864. percentloaded: 0
  5865. },
  5866. nav: {
  5867. start_page: false,
  5868. interval_width: 200,
  5869. density: 4,
  5870. minor_width: 0,
  5871. minor_left: 0,
  5872. constraint: {
  5873. left: 0,
  5874. right: 0,
  5875. right_min: 0,
  5876. right_max: 0
  5877. },
  5878. zoom: {
  5879. adjust: 0
  5880. },
  5881. multiplier: {
  5882. current: 6,
  5883. min: .1,
  5884. max: 50
  5885. },
  5886. rows: [1, 1, 1],
  5887. width: 960,
  5888. height: 200,
  5889. marker: {
  5890. width: 150,
  5891. height: 50
  5892. }
  5893. },
  5894. feature: {
  5895. width: 960,
  5896. height: 540
  5897. },
  5898. slider: {
  5899. width: 720,
  5900. height: 400,
  5901. content: {
  5902. width: 720,
  5903. height: 400,
  5904. padding: 130,
  5905. padding_default:130
  5906. },
  5907. nav: {
  5908. width: 100,
  5909. height: 200
  5910. }
  5911. },
  5912. ease: "easeInOutExpo",
  5913. duration: 1000,
  5914. gmap_key: "",
  5915. language: VMM.Language
  5916. };
  5917. if ( w != null && w != "") {
  5918. config.width = w;
  5919. has_width = true;
  5920. }
  5921. if ( h != null && h != "") {
  5922. config.height = h;
  5923. has_height = true;
  5924. }
  5925. if(window.location.hash) {
  5926. var hash = window.location.hash.substring(1);
  5927. if (!isNaN(hash)) {
  5928. config.current_slide = parseInt(hash);
  5929. }
  5930. }
  5931. window.onhashchange = function () {
  5932. var hash = window.location.hash.substring(1);
  5933. if (config.hash_bookmark) {
  5934. if (is_moving) {
  5935. goToEvent(parseInt(hash));
  5936. } else {
  5937. is_moving = false;
  5938. }
  5939. } else {
  5940. goToEvent(parseInt(hash));
  5941. }
  5942. }
  5943. /* CREATE CONFIG
  5944. ================================================== */
  5945. function createConfig(conf) {
  5946. // APPLY SUPPLIED CONFIG TO TIMELINE CONFIG
  5947. if (typeof embed_config == 'object') {
  5948. timeline_config = embed_config;
  5949. }
  5950. if (typeof timeline_config == 'object') {
  5951. trace("HAS TIMELINE CONFIG");
  5952. config = VMM.Util.mergeConfig(config, timeline_config);
  5953. } else if (typeof conf == 'object') {
  5954. config = VMM.Util.mergeConfig(config, conf);
  5955. }
  5956. if (VMM.Browser.device == "mobile" || VMM.Browser.device == "tablet") {
  5957. config.touch = true;
  5958. }
  5959. config.nav.width = config.width;
  5960. config.nav.height = 200;
  5961. config.feature.width = config.width;
  5962. config.feature.height = config.height - config.nav.height;
  5963. config.nav.zoom.adjust = parseInt(config.start_zoom_adjust, 10);
  5964. VMM.Timeline.Config = config;
  5965. VMM.master_config.Timeline = VMM.Timeline.Config;
  5966. this.events = config.events;
  5967. if (config.gmap_key != "") {
  5968. config.api_keys.google = config.gmap_key;
  5969. }
  5970. trace("VERSION " + config.version);
  5971. version = config.version;
  5972. }
  5973. /* CREATE TIMELINE STRUCTURE
  5974. ================================================== */
  5975. function createStructure() {
  5976. // CREATE DOM STRUCTURE
  5977. $timeline = VMM.getElement(timeline_id);
  5978. VMM.Lib.addClass($timeline, "vco-timeline");
  5979. VMM.Lib.addClass($timeline, "vco-storyjs");
  5980. $container = VMM.appendAndGetElement($timeline, "<div>", "vco-container vco-main");
  5981. $feature = VMM.appendAndGetElement($container, "<div>", "vco-feature");
  5982. $slider = VMM.appendAndGetElement($feature, "<div>", "vco-slider");
  5983. $navigation = VMM.appendAndGetElement($container, "<div>", "vco-navigation");
  5984. $feedback = VMM.appendAndGetElement($timeline, "<div>", "vco-feedback", "");
  5985. if (typeof config.language.right_to_left != 'undefined') {
  5986. VMM.Lib.addClass($timeline, "vco-right-to-left");
  5987. }
  5988. slider = new VMM.Slider($slider, config);
  5989. timenav = new VMM.Timeline.TimeNav($navigation);
  5990. if (!has_width) {
  5991. config.width = VMM.Lib.width($timeline);
  5992. } else {
  5993. VMM.Lib.width($timeline, config.width);
  5994. }
  5995. if (!has_height) {
  5996. config.height = VMM.Lib.height($timeline);
  5997. } else {
  5998. VMM.Lib.height($timeline, config.height);
  5999. }
  6000. if (config.touch) {
  6001. VMM.Lib.addClass($timeline, "vco-touch");
  6002. } else {
  6003. VMM.Lib.addClass($timeline, "vco-notouch");
  6004. }
  6005. }
  6006. /* ON EVENT
  6007. ================================================== */
  6008. function onDataReady(e, d) {
  6009. trace("onDataReady");
  6010. data = d.timeline;
  6011. if (type.of(data.era) != "array") {
  6012. data.era = [];
  6013. }
  6014. buildDates();
  6015. };
  6016. function onDatesProcessed() {
  6017. build();
  6018. }
  6019. function reSize() {
  6020. updateSize();
  6021. slider.setSize(config.feature.width, config.feature.height);
  6022. timenav.setSize(config.width, config.height);
  6023. if (orientationChange()) {
  6024. setViewport();
  6025. }
  6026. };
  6027. function onSliderLoaded(e) {
  6028. config.loaded.slider = true;
  6029. onComponentLoaded();
  6030. };
  6031. function onComponentLoaded(e) {
  6032. config.loaded.percentloaded = config.loaded.percentloaded + 25;
  6033. if (config.loaded.slider && config.loaded.timenav) {
  6034. hideMessege();
  6035. }
  6036. }
  6037. function onTimeNavLoaded(e) {
  6038. config.loaded.timenav = true;
  6039. onComponentLoaded();
  6040. }
  6041. function onSlideUpdate(e) {
  6042. is_moving = true;
  6043. config.current_slide = slider.getCurrentNumber();
  6044. setHash(config.current_slide);
  6045. timenav.setMarker(config.current_slide, config.ease,config.duration);
  6046. };
  6047. function onMarkerUpdate(e) {
  6048. is_moving = true;
  6049. config.current_slide = timenav.getCurrentNumber();
  6050. setHash(config.current_slide);
  6051. slider.setSlide(config.current_slide);
  6052. };
  6053. function goToEvent(n) {
  6054. if (n <= _dates.length - 1 && n >= 0) {
  6055. config.current_slide = n;
  6056. slider.setSlide(config.current_slide);
  6057. timenav.setMarker(config.current_slide, config.ease,config.duration);
  6058. }
  6059. }
  6060. function setHash(n) {
  6061. if (config.hash_bookmark) {
  6062. window.location.hash = "#" + n.toString();
  6063. }
  6064. }
  6065. function getViewport() {
  6066. }
  6067. function setViewport() {
  6068. var viewport_content = "",
  6069. viewport_orientation = searchOrientation(window.orientation);
  6070. if (VMM.Browser.device == "mobile") {
  6071. if (viewport_orientation == "portrait") {
  6072. //viewport_content = "width=device-width; initial-scale=0.75, maximum-scale=0.75";
  6073. viewport_content = "width=device-width; initial-scale=0.5, maximum-scale=0.5";
  6074. } else if (viewport_orientation == "landscape") {
  6075. viewport_content = "width=device-width; initial-scale=0.5, maximum-scale=0.5";
  6076. } else {
  6077. viewport_content = "width=device-width, initial-scale=1, maximum-scale=1.0";
  6078. }
  6079. } else if (VMM.Browser.device == "tablet") {
  6080. //viewport_content = "width=device-width, initial-scale=1, maximum-scale=1.0";
  6081. }
  6082. if (document.getElementById("viewport")) {
  6083. //VMM.Lib.attr("#viewport", "content", viewport_content);
  6084. } else {
  6085. //VMM.appendElement("head", "<meta id='viewport' name='viewport' content=" + viewport_content + "/>");
  6086. }
  6087. }
  6088. /* ORIENTATION
  6089. ================================================== */
  6090. function searchOrientation(orientation) {
  6091. var orient = "";
  6092. if ( orientation == 0 || orientation == 180) {
  6093. orient = "portrait";
  6094. } else if ( orientation == 90 || orientation == -90) {
  6095. orient = "landscape";
  6096. } else {
  6097. orient = "normal";
  6098. }
  6099. return orient;
  6100. }
  6101. function orientationChange() {
  6102. var orientation = searchOrientation(window.orientation);
  6103. if (orientation == config.orientation) {
  6104. return false;
  6105. } else {
  6106. config.orientation = orientation;
  6107. return true;
  6108. }
  6109. }
  6110. /* PUBLIC FUNCTIONS
  6111. ================================================== */
  6112. this.init = function(c, _data) {
  6113. trace('INIT');
  6114. setViewport();
  6115. createConfig(c);
  6116. createStructure();
  6117. if (type.of(_data) == "string") {
  6118. config.source = _data;
  6119. }
  6120. // LANGUAGE
  6121. VMM.Date.setLanguage(config.language);
  6122. VMM.master_config.language = config.language;
  6123. // EXTERNAL API
  6124. VMM.ExternalAPI.setKeys(config.api_keys);
  6125. VMM.ExternalAPI.googlemaps.setMapType(config.maptype);
  6126. // EVENTS
  6127. VMM.bindEvent(global, onDataReady, config.events.data_ready);
  6128. VMM.bindEvent(global, showMessege, config.events.messege);
  6129. VMM.fireEvent(global, config.events.messege, config.language.messages.loading_timeline);
  6130. /* GET DATA
  6131. ================================================== */
  6132. if (VMM.Browser.browser == "Explorer" || VMM.Browser.browser == "MSIE") {
  6133. if (parseInt(VMM.Browser.version, 10) <= 7 && (VMM.Browser.tridentVersion == null || VMM.Browser.tridentVersion < 4)) {
  6134. ie7 = true;
  6135. }
  6136. }
  6137. if (type.of(config.source) == "string" || type.of(config.source) == "object") {
  6138. VMM.Timeline.DataObj.getData(config.source);
  6139. } else {
  6140. VMM.fireEvent(global, config.events.messege, "No data source provided");
  6141. //VMM.Timeline.DataObj.getData(VMM.getElement(timeline_id));
  6142. }
  6143. };
  6144. this.iframeLoaded = function() {
  6145. trace("iframeLoaded");
  6146. };
  6147. this.reload = function(_d) {
  6148. trace("Load new timeline data" + _d);
  6149. VMM.fireEvent(global, config.events.messege, config.language.messages.loading_timeline);
  6150. data = {};
  6151. VMM.Timeline.DataObj.getData(_d);
  6152. config.current_slide = 0;
  6153. slider.setSlide(0);
  6154. timenav.setMarker(0, config.ease,config.duration);
  6155. };
  6156. /* DATA
  6157. ================================================== */
  6158. function getData(url) {
  6159. VMM.getJSON(url, function(d) {
  6160. data = VMM.Timeline.DataObj.getData(d);
  6161. VMM.fireEvent(global, config.events.data_ready);
  6162. });
  6163. };
  6164. /* MESSEGES
  6165. ================================================== */
  6166. function showMessege(e, msg, other) {
  6167. trace("showMessege " + msg);
  6168. //VMM.attachElement($timeline, $feedback);
  6169. if (other) {
  6170. VMM.attachElement($feedback, msg);
  6171. } else{
  6172. VMM.attachElement($feedback, VMM.MediaElement.loadingmessage(msg));
  6173. }
  6174. };
  6175. function hideMessege() {
  6176. VMM.Lib.animate($feedback, config.duration, config.ease*4, {"opacity": 0}, detachMessege);
  6177. };
  6178. function detachMessege() {
  6179. VMM.Lib.detach($feedback);
  6180. }
  6181. /* BUILD DISPLAY
  6182. ================================================== */
  6183. function build() {
  6184. // START AT SLIDE
  6185. if (parseInt(config.start_at_slide) > 0 && config.current_slide == 0) {
  6186. config.current_slide = parseInt(config.start_at_slide);
  6187. }
  6188. // START AT END
  6189. if (config.start_at_end && config.current_slide == 0) {
  6190. config.current_slide = _dates.length - 1;
  6191. }
  6192. // IE7
  6193. if (ie7) {
  6194. ie7 = true;
  6195. 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.");
  6196. } else {
  6197. detachMessege();
  6198. reSize();
  6199. // EVENT LISTENERS
  6200. VMM.bindEvent($slider, onSliderLoaded, "LOADED");
  6201. VMM.bindEvent($navigation, onTimeNavLoaded, "LOADED");
  6202. VMM.bindEvent($slider, onSlideUpdate, "UPDATE");
  6203. VMM.bindEvent($navigation, onMarkerUpdate, "UPDATE");
  6204. // INITIALIZE COMPONENTS
  6205. slider.init(_dates);
  6206. timenav.init(_dates, data.era);
  6207. // RESIZE EVENT LISTENERS
  6208. VMM.bindEvent(global, reSize, config.events.resize);
  6209. }
  6210. };
  6211. function updateSize() {
  6212. trace("UPDATE SIZE");
  6213. config.width = VMM.Lib.width($timeline);
  6214. config.height = VMM.Lib.height($timeline);
  6215. config.nav.width = config.width;
  6216. config.feature.width = config.width;
  6217. config.feature.height = config.height - config.nav.height - 3;
  6218. if (VMM.Browser.device == "mobile") {
  6219. /*
  6220. if (VMM.Browser.orientation == "portrait") {
  6221. config.feature.height = 480;
  6222. config.height = 480 + config.nav.height;
  6223. } else if(VMM.Browser.orientation == "landscape") {
  6224. config.feature.height = 320;
  6225. config.height = 320 + config.nav.height;
  6226. } else {
  6227. config.feature.height = config.height - config.nav.height - 3;
  6228. }
  6229. */
  6230. }
  6231. if (config.width < 641) {
  6232. VMM.Lib.addClass($timeline, "vco-skinny");
  6233. } else {
  6234. VMM.Lib.removeClass($timeline, "vco-skinny");
  6235. }
  6236. };
  6237. // BUILD DATE OBJECTS
  6238. function buildDates() {
  6239. _dates = [];
  6240. VMM.fireEvent(global, config.events.messege, "Building Dates");
  6241. updateSize();
  6242. for(var i = 0; i < data.date.length; i++) {
  6243. if (data.date[i].startDate != null && data.date[i].startDate != "") {
  6244. var _date = {},
  6245. do_start = VMM.Date.parse(data.date[i].startDate, true),
  6246. do_end;
  6247. _date.startdate = do_start.date;
  6248. _date.precisiondate = do_start.precision;
  6249. if (!isNaN(_date.startdate)) {
  6250. // END DATE
  6251. if (data.date[i].endDate != null && data.date[i].endDate != "") {
  6252. _date.enddate = VMM.Date.parse(data.date[i].endDate);
  6253. } else {
  6254. _date.enddate = _date.startdate;
  6255. }
  6256. _date.needs_slug = false;
  6257. if (data.date[i].headline == "") {
  6258. if (data.date[i].slug != null && data.date[i].slug != "") {
  6259. _date.needs_slug = true;
  6260. }
  6261. }
  6262. _date.title = data.date[i].headline;
  6263. _date.headline = data.date[i].headline;
  6264. _date.type = data.date[i].type;
  6265. _date.date = VMM.Date.prettyDate(_date.startdate, false, _date.precisiondate);
  6266. _date.asset = data.date[i].asset;
  6267. _date.fulldate = _date.startdate.getTime();
  6268. _date.text = data.date[i].text;
  6269. _date.content = "";
  6270. _date.tag = data.date[i].tag;
  6271. _date.slug = data.date[i].slug;
  6272. _date.uniqueid = VMM.Util.unique_ID(7);
  6273. _date.classname = data.date[i].classname;
  6274. _dates.push(_date);
  6275. }
  6276. }
  6277. };
  6278. /* CUSTOM SORT
  6279. ================================================== */
  6280. if (data.type != "storify") {
  6281. _dates.sort(function(a, b){
  6282. return a.fulldate - b.fulldate
  6283. });
  6284. }
  6285. /* CREATE START PAGE IF AVAILABLE
  6286. ================================================== */
  6287. if (data.headline != null && data.headline != "" && data.text != null && data.text != "") {
  6288. var startpage_date,
  6289. do_start,
  6290. _date = {},
  6291. td_num = 0,
  6292. td;
  6293. if (typeof data.startDate != 'undefined') {
  6294. do_start = VMM.Date.parse(data.startDate, true);
  6295. startpage_date = do_start.date;
  6296. } else {
  6297. startpage_date = false;
  6298. }
  6299. trace("HAS STARTPAGE");
  6300. trace(startpage_date);
  6301. if (startpage_date && startpage_date < _dates[0].startdate) {
  6302. _date.startdate = new Date(startpage_date);
  6303. } else {
  6304. td = _dates[0].startdate;
  6305. _date.startdate = new Date(_dates[0].startdate);
  6306. if (td.getMonth() === 0 && td.getDate() == 1 && td.getHours() === 0 && td.getMinutes() === 0 ) {
  6307. // trace("YEAR ONLY");
  6308. _date.startdate.setFullYear(td.getFullYear() - 1);
  6309. } else if (td.getDate() <= 1 && td.getHours() === 0 && td.getMinutes() === 0) {
  6310. // trace("YEAR MONTH");
  6311. _date.startdate.setMonth(td.getMonth() - 1);
  6312. } else if (td.getHours() === 0 && td.getMinutes() === 0) {
  6313. // trace("YEAR MONTH DAY");
  6314. _date.startdate.setDate(td.getDate() - 1);
  6315. } else if (td.getMinutes() === 0) {
  6316. // trace("YEAR MONTH DAY HOUR");
  6317. _date.startdate.setHours(td.getHours() - 1);
  6318. } else {
  6319. // trace("YEAR MONTH DAY HOUR MINUTE");
  6320. _date.startdate.setMinutes(td.getMinutes() - 1);
  6321. }
  6322. }
  6323. _date.uniqueid = VMM.Util.unique_ID(7);
  6324. _date.enddate = _date.startdate;
  6325. _date.precisiondate = do_start.precision;
  6326. _date.title = data.headline;
  6327. _date.headline = data.headline;
  6328. _date.text = data.text;
  6329. _date.type = "start";
  6330. _date.date = VMM.Date.prettyDate(data.startDate, false, _date.precisiondate);
  6331. _date.asset = data.asset;
  6332. _date.slug = false;
  6333. _date.needs_slug = false;
  6334. _date.fulldate = _date.startdate.getTime();
  6335. if (config.embed) {
  6336. VMM.fireEvent(global, config.events.headline, _date.headline);
  6337. }
  6338. _dates.unshift(_date);
  6339. }
  6340. /* CUSTOM SORT
  6341. ================================================== */
  6342. if (data.type != "storify") {
  6343. _dates.sort(function(a, b){
  6344. return a.fulldate - b.fulldate
  6345. });
  6346. }
  6347. onDatesProcessed();
  6348. }
  6349. };
  6350. VMM.Timeline.Config = {};
  6351. };
  6352. /* **********************************************
  6353. Begin VMM.Timeline.TimeNav.js
  6354. ********************************************** */
  6355. /* VMM.Timeline.TimeNav.js
  6356. TimeNav
  6357. This class handles the bottom timeline navigation.
  6358. It requires the VMM.Util class and VMM.Date class
  6359. ================================================== */
  6360. if(typeof VMM.Timeline != 'undefined' && typeof VMM.Timeline.TimeNav == 'undefined') {
  6361. VMM.Timeline.TimeNav = function(parent, content_width, content_height) {
  6362. trace("VMM.Timeline.TimeNav");
  6363. var $timenav, $content, $time, $timeintervalminor, $timeinterval, $timeintervalmajor, $timebackground,
  6364. $timeintervalbackground, $timenavline, $timenavindicator, $timeintervalminor_minor, $toolbar, $zoomin, $zoomout, $dragslide,
  6365. config = VMM.Timeline.Config,
  6366. row_height,
  6367. events = {},
  6368. timespan = {},
  6369. layout = parent,
  6370. data = [],
  6371. era_markers = [],
  6372. markers = [],
  6373. interval_array = [],
  6374. interval_major_array = [],
  6375. tags = [],
  6376. current_marker = 0,
  6377. _active = false,
  6378. eras,
  6379. content,
  6380. timeouts = {
  6381. interval_position: ""
  6382. },
  6383. timenav_pos = {
  6384. left: "",
  6385. visible: {
  6386. left: "",
  6387. right: ""
  6388. }
  6389. },
  6390. timelookup = {
  6391. day: 24,
  6392. month: 12,
  6393. year: 10,
  6394. hour: 60,
  6395. minute: 60,
  6396. second: 1000,
  6397. decade: 10,
  6398. century: 100,
  6399. millenium: 1000,
  6400. age: 1000000,
  6401. epoch: 10000000,
  6402. era: 100000000,
  6403. eon: 500000000,
  6404. week: 4.34812141,
  6405. days_in_month: 30.4368499,
  6406. days_in_week: 7,
  6407. weeks_in_month: 4.34812141,
  6408. weeks_in_year: 52.177457,
  6409. days_in_year: 365.242199,
  6410. hours_in_day: 24
  6411. },
  6412. dateFractionBrowser = {
  6413. day: 86400000,
  6414. week: 7,
  6415. month: 30.4166666667,
  6416. year: 12,
  6417. hour: 24,
  6418. minute: 1440,
  6419. second: 86400,
  6420. decade: 10,
  6421. century: 100,
  6422. millenium: 1000,
  6423. age: 1000000,
  6424. epoch: 10000000,
  6425. era: 100000000,
  6426. eon: 500000000
  6427. },
  6428. interval = {
  6429. type: "year",
  6430. number: 10,
  6431. first: 1970,
  6432. last: 2011,
  6433. multiplier: 100,
  6434. classname: "_idd",
  6435. interval_type: "interval"
  6436. },
  6437. interval_major = {
  6438. type: "year",
  6439. number: 10,
  6440. first: 1970,
  6441. last: 2011,
  6442. multiplier: 100,
  6443. classname: "major",
  6444. interval_type: "interval major"
  6445. },
  6446. interval_macro = {
  6447. type: "year",
  6448. number: 10,
  6449. first: 1970,
  6450. last: 2011,
  6451. multiplier: 100,
  6452. classname: "_dd_minor",
  6453. interval_type: "interval minor"
  6454. },
  6455. interval_calc = {
  6456. day: {},
  6457. month: {},
  6458. year: {},
  6459. hour: {},
  6460. minute: {},
  6461. second: {},
  6462. decade: {},
  6463. century: {},
  6464. millenium: {},
  6465. week: {},
  6466. age: {},
  6467. epoch: {},
  6468. era: {},
  6469. eon: {}
  6470. };
  6471. /* ADD to Config
  6472. ================================================== */
  6473. row_height = config.nav.marker.height/2;
  6474. config.nav.rows = {
  6475. full: [1, row_height*2, row_height*4],
  6476. half: [1, row_height, row_height*2, row_height*3, row_height*4, row_height*5],
  6477. current: []
  6478. }
  6479. if (content_width != null && content_width != "") {
  6480. config.nav.width = content_width;
  6481. }
  6482. if (content_height != null && content_height != "") {
  6483. config.nav.height = content_height;
  6484. }
  6485. /* INIT
  6486. ================================================== */
  6487. this.init = function(d,e) {
  6488. trace('VMM.Timeline.TimeNav init');
  6489. // need to evaluate d
  6490. // some function to determine type of data and prepare it
  6491. if(typeof d != 'undefined') {
  6492. this.setData(d, e);
  6493. } else {
  6494. trace("WAITING ON DATA");
  6495. }
  6496. };
  6497. /* GETTERS AND SETTERS
  6498. ================================================== */
  6499. this.setData = function(d,e) {
  6500. if(typeof d != 'undefined') {
  6501. data = {};
  6502. data = d;
  6503. eras = e;
  6504. build();
  6505. } else{
  6506. trace("NO DATA");
  6507. }
  6508. };
  6509. this.setSize = function(w, h) {
  6510. if (w != null) {config.width = w};
  6511. if (h != null) {config.height = h};
  6512. if (_active) {
  6513. reSize();
  6514. }
  6515. }
  6516. this.setMarker = function(n, ease, duration, fast) {
  6517. goToMarker(n, ease, duration);
  6518. }
  6519. this.getCurrentNumber = function() {
  6520. return current_marker;
  6521. }
  6522. /* ON EVENT
  6523. ================================================== */
  6524. function onConfigSet() {
  6525. trace("onConfigSet");
  6526. };
  6527. function reSize(firstrun) {
  6528. config.nav.constraint.left = (config.width/2);
  6529. config.nav.constraint.right = config.nav.constraint.right_min - (config.width/2);
  6530. $dragslide.updateConstraint(config.nav.constraint);
  6531. VMM.Lib.css($timenavline, "left", Math.round(config.width/2)+2);
  6532. VMM.Lib.css($timenavindicator, "left", Math.round(config.width/2)-8);
  6533. goToMarker(config.current_slide, config.ease, config.duration, true, firstrun);
  6534. };
  6535. function upDate() {
  6536. VMM.fireEvent(layout, "UPDATE");
  6537. }
  6538. function onZoomIn() {
  6539. $dragslide.cancelSlide();
  6540. if (config.nav.multiplier.current > config.nav.multiplier.min) {
  6541. if (config.nav.multiplier.current <= 1) {
  6542. config.nav.multiplier.current = config.nav.multiplier.current - .25;
  6543. } else {
  6544. if (config.nav.multiplier.current > 5) {
  6545. if (config.nav.multiplier.current > 16) {
  6546. config.nav.multiplier.current = Math.round(config.nav.multiplier.current - 10);
  6547. } else {
  6548. config.nav.multiplier.current = Math.round(config.nav.multiplier.current - 4);
  6549. }
  6550. } else {
  6551. config.nav.multiplier.current = Math.round(config.nav.multiplier.current - 1);
  6552. }
  6553. }
  6554. if (config.nav.multiplier.current <= 0) {
  6555. config.nav.multiplier.current = config.nav.multiplier.min;
  6556. }
  6557. refreshTimeline();
  6558. }
  6559. }
  6560. function onZoomOut() {
  6561. $dragslide.cancelSlide();
  6562. if (config.nav.multiplier.current < config.nav.multiplier.max) {
  6563. if (config.nav.multiplier.current > 4) {
  6564. if (config.nav.multiplier.current > 16) {
  6565. config.nav.multiplier.current = Math.round(config.nav.multiplier.current + 10);
  6566. } else {
  6567. config.nav.multiplier.current = Math.round(config.nav.multiplier.current + 4);
  6568. }
  6569. } else {
  6570. config.nav.multiplier.current = Math.round(config.nav.multiplier.current + 1);
  6571. }
  6572. if (config.nav.multiplier.current >= config.nav.multiplier.max) {
  6573. config.nav.multiplier.current = config.nav.multiplier.max;
  6574. }
  6575. refreshTimeline();
  6576. }
  6577. }
  6578. function onBackHome(e) {
  6579. $dragslide.cancelSlide();
  6580. goToMarker(0);
  6581. upDate();
  6582. }
  6583. function onMouseScroll(e) {
  6584. var delta = 0,
  6585. scroll_to = 0;
  6586. if (!e) {
  6587. e = window.event;
  6588. }
  6589. if (e.originalEvent) {
  6590. e = e.originalEvent;
  6591. }
  6592. // Browsers unable to differntiate between up/down and left/right scrolling
  6593. /*
  6594. if (e.wheelDelta) {
  6595. delta = e.wheelDelta/6;
  6596. } else if (e.detail) {
  6597. delta = -e.detail*12;
  6598. }
  6599. */
  6600. // Webkit and browsers able to differntiate between up/down and left/right scrolling
  6601. if (typeof e.wheelDeltaX != 'undefined' ) {
  6602. delta = e.wheelDeltaY/6;
  6603. if (Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY)) {
  6604. delta = e.wheelDeltaX/6;
  6605. } else {
  6606. //delta = e.wheelDeltaY/6;
  6607. delta = 0;
  6608. }
  6609. }
  6610. if (delta) {
  6611. if (e.preventDefault) {
  6612. e.preventDefault();
  6613. }
  6614. e.returnValue = false;
  6615. }
  6616. // Stop from scrolling too far
  6617. scroll_to = VMM.Lib.position($timenav).left + delta;
  6618. if (scroll_to > config.nav.constraint.left) {
  6619. scroll_to = config.width/2;
  6620. } else if (scroll_to < config.nav.constraint.right) {
  6621. scroll_to = config.nav.constraint.right;
  6622. }
  6623. //VMM.Lib.stop($timenav);
  6624. //VMM.Lib.animate($timenav, config.duration/2, "linear", {"left": scroll_to});
  6625. VMM.Lib.css($timenav, "left", scroll_to);
  6626. }
  6627. function refreshTimeline() {
  6628. trace("config.nav.multiplier " + config.nav.multiplier.current);
  6629. positionMarkers(true);
  6630. positionEras(true);
  6631. positionInterval($timeinterval, interval_array, true, true);
  6632. positionInterval($timeintervalmajor, interval_major_array, true);
  6633. config.nav.constraint.left = (config.width/2);
  6634. config.nav.constraint.right = config.nav.constraint.right_min - (config.width/2);
  6635. $dragslide.updateConstraint(config.nav.constraint);
  6636. };
  6637. /* MARKER EVENTS
  6638. ================================================== */
  6639. function onMarkerClick(e) {
  6640. $dragslide.cancelSlide();
  6641. goToMarker(e.data.number);
  6642. upDate();
  6643. };
  6644. function onMarkerHover(e) {
  6645. VMM.Lib.toggleClass(e.data.elem, "zFront");
  6646. };
  6647. function goToMarker(n, ease, duration, fast, firstrun) {
  6648. trace("GO TO MARKER");
  6649. var _ease = config.ease,
  6650. _duration = config.duration,
  6651. is_last = false,
  6652. is_first = false;
  6653. current_marker = n;
  6654. timenav_pos.left = (config.width/2) - markers[current_marker].pos_left
  6655. timenav_pos.visible.left = Math.abs(timenav_pos.left) - 100;
  6656. timenav_pos.visible.right = Math.abs(timenav_pos.left) + config.width + 100;
  6657. if (current_marker == 0) {
  6658. is_first = true;
  6659. }
  6660. if (current_marker +1 == markers.length) {
  6661. is_last = true
  6662. }
  6663. if (ease != null && ease != "") {_ease = ease};
  6664. if (duration != null && duration != "") {_duration = duration};
  6665. // set marker style
  6666. for(var i = 0; i < markers.length; i++) {
  6667. VMM.Lib.removeClass(markers[i].marker, "active");
  6668. }
  6669. if (config.start_page && markers[0].type == "start") {
  6670. VMM.Lib.visible(markers[0].marker, false);
  6671. VMM.Lib.addClass(markers[0].marker, "start");
  6672. }
  6673. VMM.Lib.addClass(markers[current_marker].marker, "active");
  6674. // ANIMATE MARKER
  6675. VMM.Lib.stop($timenav);
  6676. VMM.Lib.animate($timenav, _duration, _ease, {"left": timenav_pos.left});
  6677. }
  6678. /* TOUCH EVENTS
  6679. ================================================== */
  6680. function onTouchUpdate(e, b) {
  6681. VMM.Lib.animate($timenav, b.time/2, config.ease, {"left": b.left});
  6682. };
  6683. /* CALCULATIONS
  6684. ================================================== */
  6685. function averageMarkerPositionDistance() {
  6686. var last_pos = 0,
  6687. pos = 0,
  6688. pos_dif = 0,
  6689. mp_diff = [],
  6690. i = 0;
  6691. for(i = 0; i < markers.length; i++) {
  6692. if (data[i].type == "start") {
  6693. } else {
  6694. var _pos = positionOnTimeline(interval, markers[i].relative_pos),
  6695. last_pos = pos;
  6696. pos = _pos.begin;
  6697. pos_dif = pos - last_pos;
  6698. mp_diff.push(pos_dif);
  6699. }
  6700. }
  6701. return VMM.Util.average(mp_diff).mean;
  6702. }
  6703. function averageDateDistance() {
  6704. var last_dd = 0,
  6705. dd = 0,
  6706. _dd = "",
  6707. date_dif = 0,
  6708. date_diffs = [],
  6709. is_first_date = true,
  6710. i = 0;
  6711. for(i = 0; i < data.length; i++) {
  6712. if (data[i].type == "start") {
  6713. trace("DATA DATE IS START")
  6714. } else {
  6715. _dd = data[i].startdate;
  6716. last_dd = dd;
  6717. dd = _dd;
  6718. date_dif = dd - last_dd;
  6719. date_diffs.push(date_dif);
  6720. }
  6721. }
  6722. return VMM.Util.average(date_diffs);
  6723. }
  6724. function calculateMultiplier() {
  6725. var temp_multiplier = config.nav.multiplier.current,
  6726. i = 0;
  6727. for(i = 0; i < temp_multiplier; i++) {
  6728. if (averageMarkerPositionDistance() < 75) {
  6729. if (config.nav.multiplier.current > 1) {
  6730. config.nav.multiplier.current = (config.nav.multiplier.current - 1);
  6731. }
  6732. }
  6733. }
  6734. }
  6735. function calculateInterval() {
  6736. // NEED TO REWRITE ALL OF THIS
  6737. var _first = getDateFractions(data[0].startdate),
  6738. _last = getDateFractions(data[data.length - 1].enddate);
  6739. // EON
  6740. interval_calc.eon.type = "eon";
  6741. interval_calc.eon.first = _first.eons;
  6742. interval_calc.eon.base = Math.floor(_first.eons);
  6743. interval_calc.eon.last = _last.eons;
  6744. interval_calc.eon.number = timespan.eons;
  6745. interval_calc.eon.multiplier = timelookup.eons;
  6746. interval_calc.eon.minor = timelookup.eons;
  6747. // ERA
  6748. interval_calc.era.type = "era";
  6749. interval_calc.era.first = _first.eras;
  6750. interval_calc.era.base = Math.floor(_first.eras);
  6751. interval_calc.era.last = _last.eras;
  6752. interval_calc.era.number = timespan.eras;
  6753. interval_calc.era.multiplier = timelookup.eras;
  6754. interval_calc.era.minor = timelookup.eras;
  6755. // EPOCH
  6756. interval_calc.epoch.type = "epoch";
  6757. interval_calc.epoch.first = _first.epochs;
  6758. interval_calc.epoch.base = Math.floor(_first.epochs);
  6759. interval_calc.epoch.last = _last.epochs;
  6760. interval_calc.epoch.number = timespan.epochs;
  6761. interval_calc.epoch.multiplier = timelookup.epochs;
  6762. interval_calc.epoch.minor = timelookup.epochs;
  6763. // AGE
  6764. interval_calc.age.type = "age";
  6765. interval_calc.age.first = _first.ages;
  6766. interval_calc.age.base = Math.floor(_first.ages);
  6767. interval_calc.age.last = _last.ages;
  6768. interval_calc.age.number = timespan.ages;
  6769. interval_calc.age.multiplier = timelookup.ages;
  6770. interval_calc.age.minor = timelookup.ages;
  6771. // MILLENIUM
  6772. interval_calc.millenium.type = "millenium";
  6773. interval_calc.millenium.first = _first.milleniums;
  6774. interval_calc.millenium.base = Math.floor(_first.milleniums);
  6775. interval_calc.millenium.last = _last.milleniums;
  6776. interval_calc.millenium.number = timespan.milleniums;
  6777. interval_calc.millenium.multiplier = timelookup.millenium;
  6778. interval_calc.millenium.minor = timelookup.millenium;
  6779. // CENTURY
  6780. interval_calc.century.type = "century";
  6781. interval_calc.century.first = _first.centuries;
  6782. interval_calc.century.base = Math.floor(_first.centuries);
  6783. interval_calc.century.last = _last.centuries;
  6784. interval_calc.century.number = timespan.centuries;
  6785. interval_calc.century.multiplier = timelookup.century;
  6786. interval_calc.century.minor = timelookup.century;
  6787. // DECADE
  6788. interval_calc.decade.type = "decade";
  6789. interval_calc.decade.first = _first.decades;
  6790. interval_calc.decade.base = Math.floor(_first.decades);
  6791. interval_calc.decade.last = _last.decades;
  6792. interval_calc.decade.number = timespan.decades;
  6793. interval_calc.decade.multiplier = timelookup.decade;
  6794. interval_calc.decade.minor = timelookup.decade;
  6795. // YEAR
  6796. interval_calc.year.type = "year";
  6797. interval_calc.year.first = _first.years;
  6798. interval_calc.year.base = Math.floor(_first.years);
  6799. interval_calc.year.last = _last.years;
  6800. interval_calc.year.number = timespan.years;
  6801. interval_calc.year.multiplier = 1;
  6802. interval_calc.year.minor = timelookup.month;
  6803. // MONTH
  6804. interval_calc.month.type = "month";
  6805. interval_calc.month.first = _first.months;
  6806. interval_calc.month.base = Math.floor(_first.months);
  6807. interval_calc.month.last = _last.months;
  6808. interval_calc.month.number = timespan.months;
  6809. interval_calc.month.multiplier = 1;
  6810. interval_calc.month.minor = Math.round(timelookup.week);
  6811. // WEEK
  6812. // NOT DONE
  6813. interval_calc.week.type = "week";
  6814. interval_calc.week.first = _first.weeks;
  6815. interval_calc.week.base = Math.floor(_first.weeks);
  6816. interval_calc.week.last = _last.weeks;
  6817. interval_calc.week.number = timespan.weeks;
  6818. interval_calc.week.multiplier = 1;
  6819. interval_calc.week.minor = 7;
  6820. // DAY
  6821. interval_calc.day.type = "day";
  6822. interval_calc.day.first = _first.days;
  6823. interval_calc.day.base = Math.floor(_first.days);
  6824. interval_calc.day.last = _last.days;
  6825. interval_calc.day.number = timespan.days;
  6826. interval_calc.day.multiplier = 1;
  6827. interval_calc.day.minor = 24;
  6828. // HOUR
  6829. interval_calc.hour.type = "hour";
  6830. interval_calc.hour.first = _first.hours;
  6831. interval_calc.hour.base = Math.floor(_first.hours);
  6832. interval_calc.hour.last = _last.hours;
  6833. interval_calc.hour.number = timespan.hours;
  6834. interval_calc.hour.multiplier = 1;
  6835. interval_calc.hour.minor = 60;
  6836. // MINUTE
  6837. interval_calc.minute.type = "minute";
  6838. interval_calc.minute.first = _first.minutes;
  6839. interval_calc.minute.base = Math.floor(_first.minutes);
  6840. interval_calc.minute.last = _last.minutes;
  6841. interval_calc.minute.number = timespan.minutes;
  6842. interval_calc.minute.multiplier = 1;
  6843. interval_calc.minute.minor = 60;
  6844. // SECOND
  6845. interval_calc.second.type = "decade";
  6846. interval_calc.second.first = _first.seconds;
  6847. interval_calc.second.base = Math.floor(_first.seconds);
  6848. interval_calc.second.last = _last.seconds;
  6849. interval_calc.second.number = timespan.seconds;
  6850. interval_calc.second.multiplier = 1;
  6851. interval_calc.second.minor = 10;
  6852. }
  6853. function getDateFractions(the_date, is_utc) {
  6854. var _time = {};
  6855. _time.days = the_date / dateFractionBrowser.day;
  6856. _time.weeks = _time.days / dateFractionBrowser.week;
  6857. _time.months = _time.days / dateFractionBrowser.month;
  6858. _time.years = _time.months / dateFractionBrowser.year;
  6859. _time.hours = _time.days * dateFractionBrowser.hour;
  6860. _time.minutes = _time.days * dateFractionBrowser.minute;
  6861. _time.seconds = _time.days * dateFractionBrowser.second;
  6862. _time.decades = _time.years / dateFractionBrowser.decade;
  6863. _time.centuries = _time.years / dateFractionBrowser.century;
  6864. _time.milleniums = _time.years / dateFractionBrowser.millenium;
  6865. _time.ages = _time.years / dateFractionBrowser.age;
  6866. _time.epochs = _time.years / dateFractionBrowser.epoch;
  6867. _time.eras = _time.years / dateFractionBrowser.era;
  6868. _time.eons = _time.years / dateFractionBrowser.eon;
  6869. /*
  6870. trace("AGES " + _time.ages);
  6871. trace("EPOCHS " + _time.epochs);
  6872. trace("MILLENIUMS " + _time.milleniums);
  6873. trace("CENTURIES " + _time.centuries);
  6874. trace("DECADES " + _time.decades);
  6875. trace("YEARS " + _time.years);
  6876. trace("MONTHS " + _time.months);
  6877. trace("WEEKS " + _time.weeks);
  6878. trace("DAYS " + _time.days);
  6879. trace("HOURS " + _time.hours);
  6880. trace("MINUTES " + _time.minutes);
  6881. trace("SECONDS " + _time.seconds);
  6882. */
  6883. return _time;
  6884. }
  6885. /* POSITION
  6886. Positions elements on the timeline based on date
  6887. relative to the calculated interval
  6888. ================================================== */
  6889. function positionRelative(_interval, first, last) {
  6890. var _first,
  6891. _last,
  6892. _type = _interval.type,
  6893. timerelative = {
  6894. start: "",
  6895. end: "",
  6896. type: _type
  6897. };
  6898. /* FIRST
  6899. ================================================== */
  6900. _first = getDateFractions(first);
  6901. timerelative.start = first.months;
  6902. if (_type == "eon") {
  6903. timerelative.start = _first.eons;
  6904. } else if (_type == "era") {
  6905. timerelative.start = _first.eras;
  6906. } else if (_type == "epoch") {
  6907. timerelative.start = _first.epochs;
  6908. } else if (_type == "age") {
  6909. timerelative.start = _first.ages;
  6910. } else if (_type == "millenium") {
  6911. timerelative.start = first.milleniums;
  6912. } else if (_type == "century") {
  6913. timerelative.start = _first.centuries;
  6914. } else if (_type == "decade") {
  6915. timerelative.start = _first.decades;
  6916. } else if (_type == "year") {
  6917. timerelative.start = _first.years;
  6918. } else if (_type == "month") {
  6919. timerelative.start = _first.months;
  6920. } else if (_type == "week") {
  6921. timerelative.start = _first.weeks;
  6922. } else if (_type == "day") {
  6923. timerelative.start = _first.days;
  6924. } else if (_type == "hour") {
  6925. timerelative.start = _first.hours;
  6926. } else if (_type == "minute") {
  6927. timerelative.start = _first.minutes;
  6928. }
  6929. /* LAST
  6930. ================================================== */
  6931. if (type.of(last) == "date") {
  6932. _last = getDateFractions(last);
  6933. timerelative.end = last.months;
  6934. if (_type == "eon") {
  6935. timerelative.end = _last.eons;
  6936. } else if (_type == "era") {
  6937. timerelative.end = _last.eras;
  6938. } else if (_type == "epoch") {
  6939. timerelative.end = _last.epochs;
  6940. } else if (_type == "age") {
  6941. timerelative.end = _last.ages;
  6942. } else if (_type == "millenium") {
  6943. timerelative.end = last.milleniums;
  6944. } else if (_type == "century") {
  6945. timerelative.end = _last.centuries;
  6946. } else if (_type == "decade") {
  6947. timerelative.end = _last.decades;
  6948. } else if (_type == "year") {
  6949. timerelative.end = _last.years;
  6950. } else if (_type == "month") {
  6951. timerelative.end = _last.months;
  6952. } else if (_type == "week") {
  6953. timerelative.end = _last.weeks;
  6954. } else if (_type == "day") {
  6955. timerelative.end = _last.days;
  6956. } else if (_type == "hour") {
  6957. timerelative.end = _last.hours;
  6958. } else if (_type == "minute") {
  6959. timerelative.end = _last.minutes;
  6960. }
  6961. } else {
  6962. timerelative.end = timerelative.start;
  6963. }
  6964. return timerelative
  6965. }
  6966. function positionOnTimeline(the_interval, timerelative) {
  6967. return {
  6968. begin: (timerelative.start - interval.base) * (config.nav.interval_width / config.nav.multiplier.current),
  6969. end: (timerelative.end - interval.base) * (config.nav.interval_width / config.nav.multiplier.current)
  6970. };
  6971. }
  6972. function positionMarkers(is_animated) {
  6973. var row = 2,
  6974. previous_pos = 0,
  6975. pos_offset = -2,
  6976. row_depth = 0,
  6977. row_depth_sub = 0,
  6978. line_last_height_pos = 150,
  6979. line_height = 6,
  6980. cur_mark = 0,
  6981. in_view_margin = config.width,
  6982. pos_cache_array = [],
  6983. pos_cache_max = 6,
  6984. in_view = {
  6985. left: timenav_pos.visible.left - in_view_margin,
  6986. right: timenav_pos.visible.right + in_view_margin
  6987. },
  6988. i = 0,
  6989. k = 0;
  6990. config.nav.minor_width = config.width;
  6991. VMM.Lib.removeClass(".flag", "row1");
  6992. VMM.Lib.removeClass(".flag", "row2");
  6993. VMM.Lib.removeClass(".flag", "row3");
  6994. for(i = 0; i < markers.length; i++) {
  6995. var line,
  6996. marker = markers[i],
  6997. pos = positionOnTimeline(interval, markers[i].relative_pos),
  6998. row_pos = 0,
  6999. is_in_view = false,
  7000. pos_cache_obj = {id: i, pos: 0, row: 0},
  7001. pos_cache_close = 0;
  7002. // COMPENSATE FOR DATES BEING POITIONED IN THE MIDDLE
  7003. pos.begin = Math.round(pos.begin + pos_offset);
  7004. pos.end = Math.round(pos.end + pos_offset);
  7005. line = Math.round(pos.end - pos.begin);
  7006. marker.pos_left = pos.begin;
  7007. if (current_marker == i) {
  7008. timenav_pos.left = (config.width/2) - pos;
  7009. timenav_pos.visible.left = Math.abs(timenav_pos.left);
  7010. timenav_pos.visible.right = Math.abs(timenav_pos.left) + config.width;
  7011. in_view.left = timenav_pos.visible.left - in_view_margin;
  7012. in_view.right = timenav_pos.visible.right + in_view_margin;
  7013. }
  7014. if (Math.abs(pos.begin) >= in_view.left && Math.abs(pos.begin) <= in_view.right ) {
  7015. is_in_view = true;
  7016. }
  7017. // APPLY POSITION TO MARKER
  7018. if (is_animated) {
  7019. VMM.Lib.stop(marker.marker);
  7020. VMM.Lib.animate(marker.marker, config.duration/2, config.ease, {"left": pos.begin});
  7021. } else {
  7022. VMM.Lib.stop(marker.marker);
  7023. VMM.Lib.css(marker.marker, "left", pos.begin);
  7024. }
  7025. if (i == current_marker) {
  7026. cur_mark = pos.begin;
  7027. }
  7028. // EVENT LENGTH LINE
  7029. if (line > 5) {
  7030. VMM.Lib.css(marker.lineevent, "height", line_height);
  7031. VMM.Lib.css(marker.lineevent, "top", line_last_height_pos);
  7032. if (is_animated) {
  7033. VMM.Lib.animate(marker.lineevent, config.duration/2, config.ease, {"width": line});
  7034. } else {
  7035. VMM.Lib.css(marker.lineevent, "width", line);
  7036. }
  7037. }
  7038. // CONTROL ROW POSITION
  7039. if (tags.length > 0) {
  7040. for (k = 0; k < tags.length; k++) {
  7041. if (k < config.nav.rows.current.length) {
  7042. if (marker.tag == tags[k]) {
  7043. row = k;
  7044. if (k == config.nav.rows.current.length - 1) {
  7045. trace("ON LAST ROW");
  7046. VMM.Lib.addClass(marker.flag, "flag-small-last");
  7047. }
  7048. }
  7049. }
  7050. }
  7051. row_pos = config.nav.rows.current[row];
  7052. } else {
  7053. if (pos.begin - previous_pos.begin < (config.nav.marker.width + config.spacing)) {
  7054. if (row < config.nav.rows.current.length - 1) {
  7055. row ++;
  7056. } else {
  7057. row = 0;
  7058. row_depth ++;
  7059. }
  7060. } else {
  7061. row_depth = 1;
  7062. row = 1;
  7063. }
  7064. row_pos = config.nav.rows.current[row];
  7065. }
  7066. // SET LAST MARKER POSITION
  7067. previous_pos = pos;
  7068. // POSITION CACHE
  7069. pos_cache_obj.pos = pos;
  7070. pos_cache_obj.row = row;
  7071. pos_cache_array.push(pos_cache_obj);
  7072. if (pos_cache_array.length > pos_cache_max) {
  7073. VMM.Util.removeRange(pos_cache_array,0);
  7074. }
  7075. //if (is_animated && is_in_view) {
  7076. if (is_animated) {
  7077. VMM.Lib.stop(marker.flag);
  7078. VMM.Lib.animate(marker.flag, config.duration, config.ease, {"top": row_pos});
  7079. } else {
  7080. VMM.Lib.stop(marker.flag);
  7081. VMM.Lib.css(marker.flag, "top", row_pos);
  7082. }
  7083. // IS THE MARKER A REPRESENTATION OF A START SCREEN?
  7084. if (config.start_page && markers[i].type == "start") {
  7085. VMM.Lib.visible(marker.marker, false);
  7086. }
  7087. if (pos > config.nav.minor_width) {
  7088. config.nav.minor_width = pos;
  7089. }
  7090. if (pos < config.nav.minor_left) {
  7091. config.nav.minor_left = pos;
  7092. }
  7093. }
  7094. // ANIMATE THE TIMELINE TO ADJUST TO CHANGES
  7095. if (is_animated) {
  7096. VMM.Lib.stop($timenav);
  7097. VMM.Lib.animate($timenav, config.duration/2, config.ease, {"left": (config.width/2) - (cur_mark)});
  7098. } else {
  7099. }
  7100. //VMM.Lib.delay_animate(config.duration, $timenav, config.duration/2, config.ease, {"left": (config.width/2) - (cur_mark)});
  7101. }
  7102. function positionEras(is_animated) {
  7103. var i = 0,
  7104. p = 0;
  7105. for(i = 0; i < era_markers.length; i++) {
  7106. var era = era_markers[i],
  7107. pos = positionOnTimeline(interval, era.relative_pos),
  7108. row_pos = 0,
  7109. row = 0,
  7110. era_height = config.nav.marker.height * config.nav.rows.full.length,
  7111. era_length = pos.end - pos.begin;
  7112. // CONTROL ROW POSITION
  7113. if (era.tag != "") {
  7114. era_height = (config.nav.marker.height * config.nav.rows.full.length) / config.nav.rows.current.length;
  7115. for (p = 0; p < tags.length; p++) {
  7116. if (p < config.nav.rows.current.length) {
  7117. if (era.tag == tags[p]) {
  7118. row = p;
  7119. }
  7120. }
  7121. }
  7122. row_pos = config.nav.rows.current[row];
  7123. } else {
  7124. row_pos = -1;
  7125. }
  7126. // APPLY POSITION TO MARKER
  7127. if (is_animated) {
  7128. VMM.Lib.stop(era.content);
  7129. VMM.Lib.stop(era.text_content);
  7130. VMM.Lib.animate(era.content, config.duration/2, config.ease, {"top": row_pos, "left": pos.begin, "width": era_length, "height":era_height});
  7131. VMM.Lib.animate(era.text_content, config.duration/2, config.ease, {"left": pos.begin});
  7132. } else {
  7133. VMM.Lib.stop(era.content);
  7134. VMM.Lib.stop(era.text_content);
  7135. VMM.Lib.css(era.content, "left", pos.begin);
  7136. VMM.Lib.css(era.content, "width", era_length);
  7137. VMM.Lib.css(era.content, "height", era_height);
  7138. VMM.Lib.css(era.content, "top", row_pos);
  7139. VMM.Lib.css(era.text_content, "left", pos.begin);
  7140. }
  7141. }
  7142. }
  7143. function positionInterval(the_main_element, the_intervals, is_animated, is_minor) {
  7144. var last_position = 0,
  7145. last_position_major = 0,
  7146. //in_view_margin = (config.nav.minor_width/config.nav.multiplier.current)/2,
  7147. in_view_margin = config.width,
  7148. in_view = {
  7149. left: timenav_pos.visible.left - in_view_margin,
  7150. right: timenav_pos.visible.right + in_view_margin
  7151. }
  7152. not_too_many = true,
  7153. i = 0;
  7154. config.nav.minor_left = 0;
  7155. if (the_intervals.length > 100) {
  7156. not_too_many = false;
  7157. trace("TOO MANY " + the_intervals.length);
  7158. }
  7159. for(i = 0; i < the_intervals.length; i++) {
  7160. var _interval = the_intervals[i].element,
  7161. _interval_date = the_intervals[i].date,
  7162. _interval_visible = the_intervals[i].visible,
  7163. _pos = positionOnTimeline(interval, the_intervals[i].relative_pos),
  7164. pos = _pos.begin,
  7165. _animation = the_intervals[i].animation,
  7166. is_visible = true,
  7167. is_in_view = false,
  7168. pos_offset = 50;
  7169. _animation.pos = pos;
  7170. _animation.animate = false;
  7171. if (Math.abs(pos) >= in_view.left && Math.abs(pos) <= in_view.right ) {
  7172. is_in_view = true;
  7173. }
  7174. if (true) {
  7175. // CONDENSE WHAT IS DISPLAYED
  7176. if (config.nav.multiplier.current > 16 && is_minor) {
  7177. is_visible = false;
  7178. } else {
  7179. if ((pos - last_position) < 65 ) {
  7180. if ((pos - last_position) < 35 ) {
  7181. if (i%4 == 0) {
  7182. if (pos == 0) {
  7183. is_visible = false;
  7184. }
  7185. } else {
  7186. is_visible = false;
  7187. }
  7188. } else {
  7189. if (!VMM.Util.isEven(i)) {
  7190. is_visible = false;
  7191. }
  7192. }
  7193. }
  7194. }
  7195. if (is_visible) {
  7196. if (the_intervals[i].is_detached) {
  7197. VMM.Lib.append(the_main_element, _interval);
  7198. the_intervals[i].is_detached = false;
  7199. }
  7200. } else {
  7201. the_intervals[i].is_detached = true;
  7202. VMM.Lib.detach(_interval);
  7203. }
  7204. if (_interval_visible) {
  7205. if (!is_visible) {
  7206. _animation.opacity = "0";
  7207. if (is_animated && not_too_many) {
  7208. _animation.animate = true;
  7209. }
  7210. the_intervals[i].interval_visible = false;
  7211. } else {
  7212. _animation.opacity = "100";
  7213. if (is_animated && is_in_view) {
  7214. _animation.animate = true;
  7215. }
  7216. }
  7217. } else {
  7218. _animation.opacity = "100";
  7219. if (is_visible) {
  7220. if (is_animated && not_too_many) {
  7221. _animation.animate = true;
  7222. } else {
  7223. if (is_animated && is_in_view) {
  7224. _animation.animate = true;
  7225. }
  7226. }
  7227. the_intervals[i].interval_visible = true;
  7228. } else {
  7229. if (is_animated && not_too_many) {
  7230. _animation.animate = true;
  7231. }
  7232. }
  7233. }
  7234. last_position = pos;
  7235. if (pos > config.nav.minor_width) {
  7236. config.nav.minor_width = pos;
  7237. }
  7238. if (pos < config.nav.minor_left) {
  7239. config.nav.minor_left = pos;
  7240. }
  7241. }
  7242. if (_animation.animate) {
  7243. VMM.Lib.animate(_interval, config.duration/2, config.ease, {opacity: _animation.opacity, left: _animation.pos});
  7244. } else {
  7245. VMM.Lib.css(_interval, "opacity", _animation.opacity);
  7246. VMM.Lib.css(_interval, "left", pos);
  7247. }
  7248. }
  7249. config.nav.constraint.right_min = -(config.nav.minor_width)+(config.width);
  7250. config.nav.constraint.right = config.nav.constraint.right_min + (config.width/2);
  7251. VMM.Lib.css($timeintervalminor_minor, "left", config.nav.minor_left - (config.width)/2);
  7252. VMM.Lib.width($timeintervalminor_minor, (config.nav.minor_width)+(config.width) + Math.abs(config.nav.minor_left) );
  7253. }
  7254. /* Interval Elements
  7255. ================================================== */
  7256. function createIntervalElements(_interval, _array, _element_parent) {
  7257. var inc_time = 0,
  7258. _first_run = true,
  7259. _last_pos = 0,
  7260. _largest_pos = 0,
  7261. _timezone_offset,
  7262. _first_date,
  7263. _last_date,
  7264. int_number = Math.ceil(_interval.number) + 2,
  7265. firefox = {
  7266. flag: false,
  7267. offset: 0
  7268. },
  7269. i = 0;
  7270. VMM.attachElement(_element_parent, "");
  7271. _interval.date = new Date(data[0].startdate.getFullYear(), 0, 1, 0,0,0);
  7272. _timezone_offset = _interval.date.getTimezoneOffset();
  7273. for(i = 0; i < int_number; i++) {
  7274. trace(_interval.type);
  7275. var _is_year = false,
  7276. int_obj = {
  7277. element: VMM.appendAndGetElement(_element_parent, "<div>", _interval.classname),
  7278. date: new Date(data[0].startdate.getFullYear(), 0, 1, 0,0,0),
  7279. visible: false,
  7280. date_string: "",
  7281. type: _interval.interval_type,
  7282. relative_pos: 0,
  7283. is_detached: false,
  7284. animation: {
  7285. animate: false,
  7286. pos: "",
  7287. opacity: "100"
  7288. }
  7289. };
  7290. if (_interval.type == "eon") {
  7291. if (_first_run) {
  7292. _first_date = Math.floor(data[0].startdate.getFullYear() / 500000000) * 500000000;
  7293. }
  7294. int_obj.date.setFullYear(_first_date + (inc_time * 500000000));
  7295. _is_year = true;
  7296. } else if (_interval.type == "era") {
  7297. if (_first_run) {
  7298. _first_date = Math.floor(data[0].startdate.getFullYear() / 100000000) * 100000000;
  7299. }
  7300. int_obj.date.setFullYear(_first_date + (inc_time * 100000000));
  7301. _is_year = true;
  7302. } else if (_interval.type == "epoch") {
  7303. if (_first_run) {
  7304. _first_date = Math.floor(data[0].startdate.getFullYear() / 10000000) * 10000000
  7305. }
  7306. int_obj.date.setFullYear(_first_date + (inc_time * 10000000));
  7307. _is_year = true;
  7308. } else if (_interval.type == "age") {
  7309. if (_first_run) {
  7310. _first_date = Math.floor(data[0].startdate.getFullYear() / 1000000) * 1000000
  7311. }
  7312. int_obj.date.setFullYear(_first_date + (inc_time * 1000000));
  7313. _is_year = true;
  7314. } else if (_interval.type == "millenium") {
  7315. if (_first_run) {
  7316. _first_date = Math.floor(data[0].startdate.getFullYear() / 1000) * 1000;
  7317. }
  7318. int_obj.date.setFullYear(_first_date + (inc_time * 1000));
  7319. _is_year = true;
  7320. } else if (_interval.type == "century") {
  7321. if (_first_run) {
  7322. _first_date = Math.floor(data[0].startdate.getFullYear() / 100) * 100
  7323. }
  7324. int_obj.date.setFullYear(_first_date + (inc_time * 100));
  7325. _is_year = true;
  7326. } else if (_interval.type == "decade") {
  7327. if (_first_run) {
  7328. _first_date = Math.floor(data[0].startdate.getFullYear() / 10) * 10;
  7329. }
  7330. int_obj.date.setFullYear(_first_date + (inc_time * 10));
  7331. _is_year = true;
  7332. } else if (_interval.type == "year") {
  7333. if (_first_run) {
  7334. _first_date = data[0].startdate.getFullYear();
  7335. }
  7336. int_obj.date.setFullYear(_first_date + inc_time);
  7337. _is_year = true;
  7338. } else if (_interval.type == "month") {
  7339. if (_first_run) {
  7340. _first_date = data[0].startdate.getMonth();
  7341. }
  7342. int_obj.date.setMonth(_first_date + inc_time);
  7343. } else if (_interval.type == "week") {
  7344. if (_first_run) {
  7345. _first_date = data[0].startdate.getMonth();
  7346. }
  7347. int_obj.date.setMonth(data[0].startdate.getMonth());
  7348. int_obj.date.setDate(_first_date + (inc_time * 7) );
  7349. } else if (_interval.type == "day") {
  7350. if (_first_run) {
  7351. _first_date = data[0].startdate.getDate();
  7352. }
  7353. int_obj.date.setMonth(data[0].startdate.getMonth());
  7354. int_obj.date.setDate(_first_date + inc_time);
  7355. } else if (_interval.type == "hour") {
  7356. if (_first_run) {
  7357. _first_date = data[0].startdate.getHours();
  7358. }
  7359. int_obj.date.setMonth(data[0].startdate.getMonth());
  7360. int_obj.date.setDate(data[0].startdate.getDate());
  7361. int_obj.date.setHours(_first_date + inc_time);
  7362. } else if (_interval.type == "minute") {
  7363. if (_first_run) {
  7364. _first_date = data[0].startdate.getMinutes();
  7365. }
  7366. int_obj.date.setMonth(data[0].startdate.getMonth());
  7367. int_obj.date.setDate(data[0].startdate.getDate());
  7368. int_obj.date.setHours(data[0].startdate.getHours());
  7369. int_obj.date.setMinutes(_first_date + inc_time);
  7370. } else if (_interval.type == "second") {
  7371. if (_first_run) {
  7372. _first_date = data[0].startdate.getSeconds();
  7373. }
  7374. int_obj.date.setMonth(data[0].startdate.getMonth());
  7375. int_obj.date.setDate(data[0].startdate.getDate());
  7376. int_obj.date.setHours(data[0].startdate.getHours());
  7377. int_obj.date.setMinutes(data[0].startdate.getMinutes());
  7378. int_obj.date.setSeconds(_first_date + inc_time);
  7379. } else if (_interval.type == "millisecond") {
  7380. if (_first_run) {
  7381. _first_date = data[0].startdate.getMilliseconds();
  7382. }
  7383. int_obj.date.setMonth(data[0].startdate.getMonth());
  7384. int_obj.date.setDate(data[0].startdate.getDate());
  7385. int_obj.date.setHours(data[0].startdate.getHours());
  7386. int_obj.date.setMinutes(data[0].startdate.getMinutes());
  7387. int_obj.date.setSeconds(data[0].startdate.getSeconds());
  7388. int_obj.date.setMilliseconds(_first_date + inc_time);
  7389. }
  7390. // FIX WEIRD FIREFOX BUG FOR GMT TIME FORMATTING
  7391. if (VMM.Browser.browser == "Firefox") {
  7392. if (int_obj.date.getFullYear() == "1970" && int_obj.date.getTimezoneOffset() != _timezone_offset) {
  7393. trace("FIREFOX 1970 TIMEZONE OFFSET " + int_obj.date.getTimezoneOffset() + " SHOULD BE " + _timezone_offset);
  7394. trace(_interval.type + " " + _interval.date);
  7395. // try and fix firefox bug, if not the flag will catch it
  7396. firefox.offset = (int_obj.date.getTimezoneOffset()/60);
  7397. firefox.flag = true;
  7398. int_obj.date.setHours(int_obj.date.getHours() + firefox.offset );
  7399. } else if (firefox.flag) {
  7400. // catch the bug the second time around
  7401. firefox.flag = false;
  7402. int_obj.date.setHours(int_obj.date.getHours() + firefox.offset );
  7403. if (_is_year) {
  7404. firefox.flag = true;
  7405. }
  7406. }
  7407. }
  7408. if (_is_year) {
  7409. if ( int_obj.date.getFullYear() < 0 ) {
  7410. int_obj.date_string = Math.abs( int_obj.date.getFullYear() ).toString() + " B.C.";
  7411. } else {
  7412. int_obj.date_string = int_obj.date.getFullYear();
  7413. }
  7414. } else {
  7415. int_obj.date_string = VMM.Date.prettyDate(int_obj.date, true);
  7416. }
  7417. // Increment Time
  7418. inc_time = inc_time + 1;
  7419. // No longer first run
  7420. _first_run = false;
  7421. int_obj.relative_pos = positionRelative(interval, int_obj.date);
  7422. _last_pos = int_obj.relative_pos.begin;
  7423. if (int_obj.relative_pos.begin > _largest_pos) {
  7424. _largest_pos = int_obj.relative_pos.begin;
  7425. }
  7426. // Add the time string to the element and position it.
  7427. VMM.appendElement(int_obj.element, int_obj.date_string);
  7428. VMM.Lib.css(int_obj.element, "text-indent", -(VMM.Lib.width(int_obj.element)/2));
  7429. VMM.Lib.css(int_obj.element, "opacity", "0");
  7430. // add the interval element to the array
  7431. _array.push(int_obj);
  7432. }
  7433. VMM.Lib.width($timeintervalminor_minor, _largest_pos);
  7434. positionInterval(_element_parent, _array);
  7435. }
  7436. /* BUILD
  7437. ================================================== */
  7438. function build() {
  7439. var i = 0,
  7440. j = 0;
  7441. VMM.attachElement(layout, "");
  7442. $timenav = VMM.appendAndGetElement(layout, "<div>", "timenav");
  7443. $content = VMM.appendAndGetElement($timenav, "<div>", "content");
  7444. $time = VMM.appendAndGetElement($timenav, "<div>", "time");
  7445. $timeintervalminor = VMM.appendAndGetElement($time, "<div>", "time-interval-minor");
  7446. $timeintervalminor_minor = VMM.appendAndGetElement($timeintervalminor, "<div>", "minor");
  7447. $timeintervalmajor = VMM.appendAndGetElement($time, "<div>", "time-interval-major");
  7448. $timeinterval = VMM.appendAndGetElement($time, "<div>", "time-interval");
  7449. $timebackground = VMM.appendAndGetElement(layout, "<div>", "timenav-background");
  7450. $timenavline = VMM.appendAndGetElement($timebackground, "<div>", "timenav-line");
  7451. $timenavindicator = VMM.appendAndGetElement($timebackground, "<div>", "timenav-indicator");
  7452. $timeintervalbackground = VMM.appendAndGetElement($timebackground, "<div>", "timenav-interval-background", "<div class='top-highlight'></div>");
  7453. $toolbar = VMM.appendAndGetElement(layout, "<div>", "vco-toolbar");
  7454. buildInterval();
  7455. buildMarkers();
  7456. buildEras();
  7457. calculateMultiplier();
  7458. positionMarkers(false);
  7459. positionEras();
  7460. positionInterval($timeinterval, interval_array, false, true);
  7461. positionInterval($timeintervalmajor, interval_major_array);
  7462. if (config.start_page) {
  7463. $backhome = VMM.appendAndGetElement($toolbar, "<div>", "back-home", "<div class='icon'></div>");
  7464. VMM.bindEvent(".back-home", onBackHome, "click");
  7465. VMM.Lib.attribute($backhome, "title", VMM.master_config.language.messages.return_to_title);
  7466. VMM.Lib.attribute($backhome, "rel", "timeline-tooltip");
  7467. }
  7468. // MAKE TIMELINE DRAGGABLE/TOUCHABLE
  7469. $dragslide = new VMM.DragSlider;
  7470. $dragslide.createPanel(layout, $timenav, config.nav.constraint, config.touch);
  7471. if (config.touch && config.start_page) {
  7472. VMM.Lib.addClass($toolbar, "touch");
  7473. VMM.Lib.css($toolbar, "top", 55);
  7474. VMM.Lib.css($toolbar, "left", 10);
  7475. } else {
  7476. if (config.start_page) {
  7477. VMM.Lib.css($toolbar, "top", 27);
  7478. }
  7479. $zoomin = VMM.appendAndGetElement($toolbar, "<div>", "zoom-in", "<div class='icon'></div>");
  7480. $zoomout = VMM.appendAndGetElement($toolbar, "<div>", "zoom-out", "<div class='icon'></div>");
  7481. // ZOOM EVENTS
  7482. VMM.bindEvent($zoomin, onZoomIn, "click");
  7483. VMM.bindEvent($zoomout, onZoomOut, "click");
  7484. // TOOLTIP
  7485. VMM.Lib.attribute($zoomin, "title", VMM.master_config.language.messages.expand_timeline);
  7486. VMM.Lib.attribute($zoomin, "rel", "timeline-tooltip");
  7487. VMM.Lib.attribute($zoomout, "title", VMM.master_config.language.messages.contract_timeline);
  7488. VMM.Lib.attribute($zoomout, "rel", "timeline-tooltip");
  7489. $toolbar.tooltip({selector: "div[rel=timeline-tooltip]", placement: "right"});
  7490. // MOUSE EVENTS
  7491. VMM.bindEvent(layout, onMouseScroll, 'DOMMouseScroll');
  7492. VMM.bindEvent(layout, onMouseScroll, 'mousewheel');
  7493. }
  7494. // USER CONFIGURABLE ADJUSTMENT TO DEFAULT ZOOM
  7495. if (config.nav.zoom.adjust != 0) {
  7496. if (config.nav.zoom.adjust < 0) {
  7497. for(i = 0; i < Math.abs(config.nav.zoom.adjust); i++) {
  7498. onZoomOut();
  7499. }
  7500. } else {
  7501. for(j = 0; j < config.nav.zoom.adjust; j++) {
  7502. onZoomIn();
  7503. }
  7504. }
  7505. }
  7506. //VMM.fireEvent(layout, "LOADED");
  7507. _active = true;
  7508. reSize(true);
  7509. VMM.fireEvent(layout, "LOADED");
  7510. };
  7511. function buildInterval() {
  7512. var i = 0,
  7513. j = 0;
  7514. // CALCULATE INTERVAL
  7515. timespan = getDateFractions((data[data.length - 1].enddate) - (data[0].startdate), true);
  7516. trace(timespan);
  7517. calculateInterval();
  7518. /* DETERMINE DEFAULT INTERVAL TYPE
  7519. millenium, ages, epoch, era and eon are not optimized yet. They may never be.
  7520. ================================================== */
  7521. /*
  7522. if (timespan.eons > data.length / config.nav.density) {
  7523. interval = interval_calc.eon;
  7524. interval_major = interval_calc.eon;
  7525. interval_macro = interval_calc.era;
  7526. } else if (timespan.eras > data.length / config.nav.density) {
  7527. interval = interval_calc.era;
  7528. interval_major = interval_calc.eon;
  7529. interval_macro = interval_calc.epoch;
  7530. } else if (timespan.epochs > data.length / config.nav.density) {
  7531. interval = interval_calc.epoch;
  7532. interval_major = interval_calc.era;
  7533. interval_macro = interval_calc.age;
  7534. } else if (timespan.ages > data.length / config.nav.density) {
  7535. interval = interval_calc.ages;
  7536. interval_major = interval_calc.epoch;
  7537. interval_macro = interval_calc.millenium;
  7538. } else if (timespan.milleniums > data.length / config.nav.density) {
  7539. interval = interval_calc.millenium;
  7540. interval_major = interval_calc.age;
  7541. interval_macro = interval_calc.century;
  7542. } else
  7543. */
  7544. if (timespan.centuries > data.length / config.nav.density) {
  7545. interval = interval_calc.century;
  7546. interval_major = interval_calc.millenium;
  7547. interval_macro = interval_calc.decade;
  7548. } else if (timespan.decades > data.length / config.nav.density) {
  7549. interval = interval_calc.decade;
  7550. interval_major = interval_calc.century;
  7551. interval_macro = interval_calc.year;
  7552. } else if (timespan.years > data.length / config.nav.density) {
  7553. interval = interval_calc.year;
  7554. interval_major = interval_calc.decade;
  7555. interval_macro = interval_calc.month;
  7556. } else if (timespan.months > data.length / config.nav.density) {
  7557. interval = interval_calc.month;
  7558. interval_major = interval_calc.year;
  7559. interval_macro = interval_calc.day;
  7560. } else if (timespan.days > data.length / config.nav.density) {
  7561. interval = interval_calc.day;
  7562. interval_major = interval_calc.month;
  7563. interval_macro = interval_calc.hour;
  7564. } else if (timespan.hours > data.length / config.nav.density) {
  7565. interval = interval_calc.hour;
  7566. interval_major = interval_calc.day;
  7567. interval_macro = interval_calc.minute;
  7568. } else if (timespan.minutes > data.length / config.nav.density) {
  7569. interval = interval_calc.minute;
  7570. interval_major = interval_calc.hour;
  7571. interval_macro = interval_calc.second;
  7572. } else if (timespan.seconds > data.length / config.nav.density) {
  7573. interval = interval_calc.second;
  7574. interval_major = interval_calc.minute;
  7575. interval_macro = interval_calc.second;
  7576. } else {
  7577. trace("NO IDEA WHAT THE TYPE SHOULD BE");
  7578. interval = interval_calc.day;
  7579. interval_major = interval_calc.month;
  7580. interval_macro = interval_calc.hour;
  7581. }
  7582. trace("INTERVAL TYPE: " + interval.type);
  7583. trace("INTERVAL MAJOR TYPE: " + interval_major.type);
  7584. createIntervalElements(interval, interval_array, $timeinterval);
  7585. createIntervalElements(interval_major, interval_major_array, $timeintervalmajor);
  7586. // Cleanup duplicate interval elements between normal and major
  7587. for(i = 0; i < interval_array.length; i++) {
  7588. for(j = 0; j < interval_major_array.length; j++) {
  7589. if (interval_array[i].date_string == interval_major_array[j].date_string) {
  7590. VMM.attachElement(interval_array[i].element, "");
  7591. }
  7592. }
  7593. }
  7594. }
  7595. function buildMarkers() {
  7596. var row = 2,
  7597. lpos = 0,
  7598. row_depth = 0,
  7599. i = 0,
  7600. k = 0,
  7601. l = 0;
  7602. markers = [];
  7603. era_markers = [];
  7604. for(i = 0; i < data.length; i++) {
  7605. var _marker,
  7606. _marker_flag,
  7607. _marker_content,
  7608. _marker_dot,
  7609. _marker_line,
  7610. _marker_line_event,
  7611. _marker_obj,
  7612. _marker_title = "",
  7613. has_title = false;
  7614. _marker = VMM.appendAndGetElement($content, "<div>", "marker");
  7615. _marker_flag = VMM.appendAndGetElement(_marker, "<div>", "flag");
  7616. _marker_content = VMM.appendAndGetElement(_marker_flag, "<div>", "flag-content");
  7617. _marker_dot = VMM.appendAndGetElement(_marker, "<div>", "dot");
  7618. _marker_line = VMM.appendAndGetElement(_marker, "<div>", "line");
  7619. _marker_line_event = VMM.appendAndGetElement(_marker_line, "<div>", "event-line");
  7620. _marker_relative_pos = positionRelative(interval, data[i].startdate, data[i].enddate);
  7621. _marker_thumb = "";
  7622. // THUMBNAIL
  7623. if (data[i].asset != null && data[i].asset != "") {
  7624. VMM.appendElement(_marker_content, VMM.MediaElement.thumbnail(data[i].asset, 24, 24, data[i].uniqueid));
  7625. } else {
  7626. VMM.appendElement(_marker_content, "<div style='margin-right:7px;height:50px;width:2px;float:left;'></div>");
  7627. }
  7628. // ADD DATE AND TITLE
  7629. if (data[i].title == "" || data[i].title == " " ) {
  7630. trace("TITLE NOTHING")
  7631. if (typeof data[i].slug != 'undefined' && data[i].slug != "") {
  7632. trace("SLUG")
  7633. _marker_title = VMM.Util.untagify(data[i].slug);
  7634. has_title = true;
  7635. } else {
  7636. var m = VMM.MediaType(data[i].asset.media);
  7637. if (m.type == "quote" || m.type == "unknown") {
  7638. _marker_title = VMM.Util.untagify(m.id);
  7639. has_title = true;
  7640. } else {
  7641. has_title = false;
  7642. }
  7643. }
  7644. } else if (data[i].title != "" || data[i].title != " ") {
  7645. trace(data[i].title)
  7646. _marker_title = VMM.Util.untagify(data[i].title);
  7647. has_title = true;
  7648. } else {
  7649. trace("TITLE SLUG NOT FOUND " + data[i].slug)
  7650. }
  7651. if (has_title) {
  7652. VMM.appendElement(_marker_content, "<h3>" + _marker_title + "</h3>");
  7653. } else {
  7654. VMM.appendElement(_marker_content, "<h3>" + _marker_title + "</h3>");
  7655. VMM.appendElement(_marker_content, "<h3 id='marker_content_" + data[i].uniqueid + "'>" + _marker_title + "</h3>");
  7656. }
  7657. // ADD ID
  7658. VMM.Lib.attr(_marker, "id", ( "marker_" + data[i].uniqueid).toString() );
  7659. // MARKER CLICK
  7660. VMM.bindEvent(_marker_flag, onMarkerClick, "", {number: i});
  7661. VMM.bindEvent(_marker_flag, onMarkerHover, "mouseenter mouseleave", {number: i, elem:_marker_flag});
  7662. _marker_obj = {
  7663. marker: _marker,
  7664. flag: _marker_flag,
  7665. lineevent: _marker_line_event,
  7666. type: "marker",
  7667. full: true,
  7668. relative_pos: _marker_relative_pos,
  7669. tag: data[i].tag,
  7670. pos_left: 0
  7671. };
  7672. if (data[i].type == "start") {
  7673. trace("BUILD MARKER HAS START PAGE");
  7674. config.start_page = true;
  7675. _marker_obj.type = "start";
  7676. }
  7677. if (data[i].type == "storify") {
  7678. _marker_obj.type = "storify";
  7679. }
  7680. if (data[i].tag) {
  7681. tags.push(data[i].tag);
  7682. }
  7683. markers.push(_marker_obj);
  7684. }
  7685. // CREATE TAGS
  7686. tags = VMM.Util.deDupeArray(tags);
  7687. if (tags.length > 3) {
  7688. config.nav.rows.current = config.nav.rows.half;
  7689. } else {
  7690. config.nav.rows.current = config.nav.rows.full;
  7691. }
  7692. for(k = 0; k < tags.length; k++) {
  7693. if (k < config.nav.rows.current.length) {
  7694. var tag_element = VMM.appendAndGetElement($timebackground, "<div>", "timenav-tag");
  7695. VMM.Lib.addClass(tag_element, "timenav-tag-row-" + (k+1));
  7696. if (tags.length > 3) {
  7697. VMM.Lib.addClass(tag_element, "timenav-tag-size-half");
  7698. } else {
  7699. VMM.Lib.addClass(tag_element, "timenav-tag-size-full");
  7700. }
  7701. VMM.appendElement(tag_element, "<div><h3>" + tags[k] + "</h3></div>");
  7702. }
  7703. }
  7704. // RESIZE FLAGS IF NEEDED
  7705. if (tags.length > 3) {
  7706. for(l = 0; l < markers.length; l++) {
  7707. VMM.Lib.addClass(markers[l].flag, "flag-small");
  7708. markers[l].full = false;
  7709. }
  7710. }
  7711. }
  7712. function buildEras() {
  7713. var number_of_colors = 6,
  7714. current_color = 0,
  7715. j = 0;
  7716. // CREATE ERAS
  7717. for(j = 0; j < eras.length; j++) {
  7718. var era = {
  7719. content: VMM.appendAndGetElement($content, "<div>", "era"),
  7720. text_content: VMM.appendAndGetElement($timeinterval, "<div>", "era"),
  7721. startdate: VMM.Date.parse(eras[j].startDate),
  7722. enddate: VMM.Date.parse(eras[j].endDate),
  7723. title: eras[j].headline,
  7724. uniqueid: VMM.Util.unique_ID(6),
  7725. tag: "",
  7726. relative_pos: ""
  7727. },
  7728. st = VMM.Date.prettyDate(era.startdate),
  7729. en = VMM.Date.prettyDate(era.enddate),
  7730. era_text = "<div>&nbsp;</div>";
  7731. if (typeof eras[j].tag != "undefined") {
  7732. era.tag = eras[j].tag;
  7733. }
  7734. era.relative_pos = positionRelative(interval, era.startdate, era.enddate);
  7735. VMM.Lib.attr(era.content, "id", era.uniqueid);
  7736. VMM.Lib.attr(era.text_content, "id", era.uniqueid + "_text");
  7737. // Background Color
  7738. VMM.Lib.addClass(era.content, "era"+(current_color+1));
  7739. VMM.Lib.addClass(era.text_content, "era"+(current_color+1));
  7740. if (current_color < number_of_colors) {
  7741. current_color++;
  7742. } else {
  7743. current_color = 0;
  7744. }
  7745. VMM.appendElement(era.content, era_text);
  7746. VMM.appendElement(era.text_content, VMM.Util.unlinkify(era.title));
  7747. era_markers.push(era);
  7748. }
  7749. }
  7750. };
  7751. }
  7752. /* **********************************************
  7753. Begin VMM.Timeline.DataObj.js
  7754. ********************************************** */
  7755. /* VMM.Timeline.DataObj.js
  7756. TIMELINE SOURCE DATA PROCESSOR
  7757. ================================================== */
  7758. if (typeof VMM.Timeline !== 'undefined' && typeof VMM.Timeline.DataObj == 'undefined') {
  7759. VMM.Timeline.DataObj = {
  7760. data_obj: {},
  7761. model_array: [],
  7762. getData: function (raw_data) {
  7763. VMM.Timeline.DataObj.data_obj = {};
  7764. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, VMM.Timeline.Config.language.messages.loading_timeline);
  7765. if (type.of(raw_data) == "object") {
  7766. trace("DATA SOURCE: JSON OBJECT");
  7767. VMM.Timeline.DataObj.parseJSON(raw_data);
  7768. } else if (type.of(raw_data) == "string") {
  7769. if (raw_data.match("%23")) {
  7770. trace("DATA SOURCE: TWITTER SEARCH");
  7771. VMM.Timeline.DataObj.model.tweets.getData("%23medill");
  7772. } else if ( raw_data.match("spreadsheet") ) {
  7773. trace("DATA SOURCE: GOOGLE SPREADSHEET");
  7774. VMM.Timeline.DataObj.model.googlespreadsheet.getData(raw_data);
  7775. } else if (raw_data.match("storify.com")) {
  7776. trace("DATA SOURCE: STORIFY");
  7777. VMM.Timeline.DataObj.model.storify.getData(raw_data);
  7778. //http://api.storify.com/v1/stories/number10gov/g8-and-nato-chicago-summit
  7779. } else if (raw_data.match("\.jsonp")) {
  7780. trace("DATA SOURCE: JSONP");
  7781. LoadLib.js(raw_data, VMM.Timeline.DataObj.onJSONPLoaded);
  7782. } else {
  7783. trace("DATA SOURCE: JSON");
  7784. var req = "";
  7785. if (raw_data.indexOf("?") > -1) {
  7786. req = raw_data + "&callback=onJSONP_Data";
  7787. } else {
  7788. req = raw_data + "?callback=onJSONP_Data";
  7789. }
  7790. VMM.getJSON(req, VMM.Timeline.DataObj.parseJSON);
  7791. }
  7792. } else if (type.of(raw_data) == "html") {
  7793. trace("DATA SOURCE: HTML");
  7794. VMM.Timeline.DataObj.parseHTML(raw_data);
  7795. } else {
  7796. trace("DATA SOURCE: UNKNOWN");
  7797. }
  7798. },
  7799. onJSONPLoaded: function() {
  7800. trace("JSONP IS LOADED");
  7801. VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, storyjs_jsonp_data);
  7802. },
  7803. parseHTML: function (d) {
  7804. trace("parseHTML");
  7805. trace("WARNING: THIS IS STILL ALPHA AND WILL NOT WORK WITH ID's other than #timeline");
  7806. var _data_obj = VMM.Timeline.DataObj.data_template_obj;
  7807. /* Timeline start slide
  7808. ================================================== */
  7809. if (VMM.Lib.find("#timeline section", "time")[0]) {
  7810. _data_obj.timeline.startDate = VMM.Lib.html(VMM.Lib.find("#timeline section", "time")[0]);
  7811. _data_obj.timeline.headline = VMM.Lib.html(VMM.Lib.find("#timeline section", "h2"));
  7812. _data_obj.timeline.text = VMM.Lib.html(VMM.Lib.find("#timeline section", "article"));
  7813. var found_main_media = false;
  7814. if (VMM.Lib.find("#timeline section", "figure img").length != 0) {
  7815. found_main_media = true;
  7816. _data_obj.timeline.asset.media = VMM.Lib.attr(VMM.Lib.find("#timeline section", "figure img"), "src");
  7817. } else if (VMM.Lib.find("#timeline section", "figure a").length != 0) {
  7818. found_main_media = true;
  7819. _data_obj.timeline.asset.media = VMM.Lib.attr(VMM.Lib.find("#timeline section", "figure a"), "href");
  7820. } else {
  7821. //trace("NOT FOUND");
  7822. }
  7823. if (found_main_media) {
  7824. if (VMM.Lib.find("#timeline section", "cite").length != 0) {
  7825. _data_obj.timeline.asset.credit = VMM.Lib.html(VMM.Lib.find("#timeline section", "cite"));
  7826. }
  7827. if (VMM.Lib.find(this, "figcaption").length != 0) {
  7828. _data_obj.timeline.asset.caption = VMM.Lib.html(VMM.Lib.find("#timeline section", "figcaption"));
  7829. }
  7830. }
  7831. }
  7832. /* Timeline Date Slides
  7833. ================================================== */
  7834. VMM.Lib.each("#timeline li", function(i, elem){
  7835. var valid_date = false;
  7836. var _date = {
  7837. "type":"default",
  7838. "startDate":"",
  7839. "headline":"",
  7840. "text":"",
  7841. "asset":
  7842. {
  7843. "media":"",
  7844. "credit":"",
  7845. "caption":""
  7846. },
  7847. "tags":"Optional"
  7848. };
  7849. if (VMM.Lib.find(this, "time") != 0) {
  7850. valid_date = true;
  7851. _date.startDate = VMM.Lib.html(VMM.Lib.find(this, "time")[0]);
  7852. if (VMM.Lib.find(this, "time")[1]) {
  7853. _date.endDate = VMM.Lib.html(VMM.Lib.find(this, "time")[1]);
  7854. }
  7855. _date.headline = VMM.Lib.html(VMM.Lib.find(this, "h3"));
  7856. _date.text = VMM.Lib.html(VMM.Lib.find(this, "article"));
  7857. var found_media = false;
  7858. if (VMM.Lib.find(this, "figure img").length != 0) {
  7859. found_media = true;
  7860. _date.asset.media = VMM.Lib.attr(VMM.Lib.find(this, "figure img"), "src");
  7861. } else if (VMM.Lib.find(this, "figure a").length != 0) {
  7862. found_media = true;
  7863. _date.asset.media = VMM.Lib.attr(VMM.Lib.find(this, "figure a"), "href");
  7864. } else {
  7865. //trace("NOT FOUND");
  7866. }
  7867. if (found_media) {
  7868. if (VMM.Lib.find(this, "cite").length != 0) {
  7869. _date.asset.credit = VMM.Lib.html(VMM.Lib.find(this, "cite"));
  7870. }
  7871. if (VMM.Lib.find(this, "figcaption").length != 0) {
  7872. _date.asset.caption = VMM.Lib.html(VMM.Lib.find(this, "figcaption"));
  7873. }
  7874. }
  7875. trace(_date);
  7876. _data_obj.timeline.date.push(_date);
  7877. }
  7878. });
  7879. VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, _data_obj);
  7880. },
  7881. parseJSON: function(d) {
  7882. trace("parseJSON");
  7883. if (d.timeline.type == "default") {
  7884. trace("DATA SOURCE: JSON STANDARD TIMELINE");
  7885. VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, d);
  7886. } else if (d.timeline.type == "twitter") {
  7887. trace("DATA SOURCE: JSON TWEETS");
  7888. VMM.Timeline.DataObj.model_Tweets.buildData(d);
  7889. } else {
  7890. trace("DATA SOURCE: UNKNOWN JSON");
  7891. trace(type.of(d.timeline));
  7892. };
  7893. },
  7894. /* MODEL OBJECTS
  7895. New Types of Data can be formatted for the timeline here
  7896. ================================================== */
  7897. model: {
  7898. googlespreadsheet: {
  7899. extractSpreadsheetKey: function(url) {
  7900. var key = VMM.Util.getUrlVars(url)["key"];
  7901. if (!key) {
  7902. if (url.match("docs.google.com/spreadsheets/d/")) {
  7903. var pos = url.indexOf("docs.google.com/spreadsheets/d/") + "docs.google.com/spreadsheets/d/".length;
  7904. var tail = url.substr(pos);
  7905. key = tail.split('/')[0]
  7906. }
  7907. }
  7908. if (!key) { key = url}
  7909. return key;
  7910. },
  7911. getData: function(raw) {
  7912. var getjsondata, key, worksheet, url, timeout, tries = 0;
  7913. // new Google Docs URLs can specify 'key' differently.
  7914. // that format doesn't seem to have a way to specify a worksheet.
  7915. key = VMM.Timeline.DataObj.model.googlespreadsheet.extractSpreadsheetKey(raw);
  7916. worksheet = VMM.Util.getUrlVars(raw)["worksheet"];
  7917. if (typeof worksheet == "undefined") worksheet = "1";
  7918. url = "https://spreadsheets.google.com/feeds/list/" + key + "/" + worksheet + "/public/values?alt=json";
  7919. timeout = setTimeout(function() {
  7920. trace("Google Docs timeout " + url);
  7921. trace(url);
  7922. if (tries < 3) {
  7923. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Still waiting on Google Docs, trying again " + tries);
  7924. tries ++;
  7925. getjsondata.abort()
  7926. requestJsonData();
  7927. } else {
  7928. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Google Docs is not responding");
  7929. }
  7930. }, 16000);
  7931. function requestJsonData() {
  7932. getjsondata = VMM.getJSON(url, function(d) {
  7933. clearTimeout(timeout);
  7934. VMM.Timeline.DataObj.model.googlespreadsheet.buildData(d);
  7935. })
  7936. .error(function(jqXHR, textStatus, errorThrown) {
  7937. if (jqXHR.status == 400) {
  7938. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Error reading Google spreadsheet. Check the URL and make sure it's published to the web.");
  7939. clearTimeout(timeout);
  7940. return;
  7941. }
  7942. trace("Google Docs ERROR");
  7943. trace("Google Docs ERROR: " + textStatus + " " + jqXHR.responseText);
  7944. })
  7945. .success(function(d) {
  7946. clearTimeout(timeout);
  7947. });
  7948. }
  7949. requestJsonData();
  7950. },
  7951. buildData: function(d) {
  7952. var data_obj = VMM.Timeline.DataObj.data_template_obj,
  7953. is_valid = false;
  7954. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Parsing Google Doc Data");
  7955. function getGVar(v) {
  7956. if (typeof v != 'undefined') {
  7957. return v.$t;
  7958. } else {
  7959. return "";
  7960. }
  7961. }
  7962. if (typeof d.feed.entry == 'undefined') {
  7963. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Error parsing spreadsheet. Make sure you have no blank rows and that the headers have not been changed.");
  7964. } else {
  7965. is_valid = true;
  7966. for(var i = 0; i < d.feed.entry.length; i++) {
  7967. var dd = d.feed.entry[i],
  7968. dd_type = "";
  7969. if (typeof(dd.gsx$startdate) == 'undefined') {
  7970. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Missing start date. Make sure the headers of your Google Spreadsheet have not been changed.");
  7971. return;
  7972. }
  7973. if (typeof dd.gsx$type != 'undefined') {
  7974. dd_type = dd.gsx$type.$t;
  7975. } else if (typeof dd.gsx$titleslide != 'undefined') {
  7976. dd_type = dd.gsx$titleslide.$t;
  7977. }
  7978. if (dd_type.match("start") || dd_type.match("title") ) {
  7979. data_obj.timeline.startDate = getGVar(dd.gsx$startdate);
  7980. data_obj.timeline.headline = getGVar(dd.gsx$headline);
  7981. data_obj.timeline.asset.media = getGVar(dd.gsx$media);
  7982. data_obj.timeline.asset.caption = getGVar(dd.gsx$mediacaption);
  7983. data_obj.timeline.asset.credit = getGVar(dd.gsx$mediacredit);
  7984. data_obj.timeline.text = getGVar(dd.gsx$text);
  7985. data_obj.timeline.type = "google spreadsheet";
  7986. } else if (dd_type.match("era")) {
  7987. var era = {
  7988. startDate: getGVar(dd.gsx$startdate),
  7989. endDate: getGVar(dd.gsx$enddate),
  7990. headline: getGVar(dd.gsx$headline),
  7991. text: getGVar(dd.gsx$text),
  7992. tag: getGVar(dd.gsx$tag)
  7993. }
  7994. data_obj.timeline.era.push(era);
  7995. } else {
  7996. var date = {
  7997. type: "google spreadsheet",
  7998. startDate: getGVar(dd.gsx$startdate),
  7999. endDate: getGVar(dd.gsx$enddate),
  8000. headline: getGVar(dd.gsx$headline),
  8001. text: getGVar(dd.gsx$text),
  8002. tag: getGVar(dd.gsx$tag),
  8003. asset: {
  8004. media: getGVar(dd.gsx$media),
  8005. credit: getGVar(dd.gsx$mediacredit),
  8006. caption: getGVar(dd.gsx$mediacaption),
  8007. thumbnail: getGVar(dd.gsx$mediathumbnail)
  8008. }
  8009. };
  8010. data_obj.timeline.date.push(date);
  8011. }
  8012. };
  8013. }
  8014. if (is_valid) {
  8015. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Finished Parsing Data");
  8016. VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, data_obj);
  8017. } else {
  8018. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, VMM.Language.messages.loading + " Google Doc Data (cells)");
  8019. trace("There may be too many entries. Still trying to load data. Now trying to load cells to avoid Googles limitation on cells");
  8020. VMM.Timeline.DataObj.model.googlespreadsheet.getDataCells(d.feed.link[0].href);
  8021. }
  8022. },
  8023. getDataCells: function(raw) {
  8024. var getjsondata, key, url, timeout, tries = 0;
  8025. key = VMM.Timeline.DataObj.model.googlespreadsheet.extractSpreadsheetKey(raw);
  8026. url = "https://spreadsheets.google.com/feeds/cells/" + key + "/od6/public/values?alt=json";
  8027. timeout = setTimeout(function() {
  8028. trace("Google Docs timeout " + url);
  8029. trace(url);
  8030. if (tries < 3) {
  8031. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Still waiting on Google Docs, trying again " + tries);
  8032. tries ++;
  8033. getjsondata.abort()
  8034. requestJsonData();
  8035. } else {
  8036. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Google Docs is not responding");
  8037. }
  8038. }, 16000);
  8039. function requestJsonData() {
  8040. getjsondata = VMM.getJSON(url, function(d) {
  8041. clearTimeout(timeout);
  8042. VMM.Timeline.DataObj.model.googlespreadsheet.buildDataCells(d);
  8043. })
  8044. .error(function(jqXHR, textStatus, errorThrown) {
  8045. trace("Google Docs ERROR");
  8046. trace("Google Docs ERROR: " + textStatus + " " + jqXHR.responseText);
  8047. })
  8048. .success(function(d) {
  8049. clearTimeout(timeout);
  8050. });
  8051. }
  8052. requestJsonData();
  8053. },
  8054. buildDataCells: function(d) {
  8055. var data_obj = VMM.Timeline.DataObj.data_template_obj,
  8056. is_valid = false,
  8057. cellnames = ["timeline"],
  8058. list = [],
  8059. max_row = 0,
  8060. i = 0,
  8061. k = 0;
  8062. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, VMM.Language.messages.loading_timeline + " Parsing Google Doc Data (cells)");
  8063. function getGVar(v) {
  8064. if (typeof v != 'undefined') {
  8065. return v.$t;
  8066. } else {
  8067. return "";
  8068. }
  8069. }
  8070. if (typeof d.feed.entry != 'undefined') {
  8071. is_valid = true;
  8072. // DETERMINE NUMBER OF ROWS
  8073. for(i = 0; i < d.feed.entry.length; i++) {
  8074. var dd = d.feed.entry[i];
  8075. if (parseInt(dd.gs$cell.row) > max_row) {
  8076. max_row = parseInt(dd.gs$cell.row);
  8077. }
  8078. }
  8079. // CREATE OBJECT FOR EACH ROW
  8080. for(var i = 0; i < max_row + 1; i++) {
  8081. var date = {
  8082. type: "",
  8083. startDate: "",
  8084. endDate: "",
  8085. headline: "",
  8086. text: "",
  8087. tag: "",
  8088. asset: {
  8089. media: "",
  8090. credit: "",
  8091. caption: "",
  8092. thumbnail: ""
  8093. }
  8094. };
  8095. list.push(date);
  8096. }
  8097. // PREP GOOGLE DOC CELL DATA TO EVALUATE
  8098. for(i = 0; i < d.feed.entry.length; i++) {
  8099. var dd = d.feed.entry[i],
  8100. dd_type = "",
  8101. column_name = "",
  8102. cell = {
  8103. content: getGVar(dd.gs$cell),
  8104. col: dd.gs$cell.col,
  8105. row: dd.gs$cell.row,
  8106. name: ""
  8107. };
  8108. //trace(cell);
  8109. if (cell.row == 1) {
  8110. if (cell.content == "Start Date") {
  8111. column_name = "startDate";
  8112. } else if (cell.content == "End Date") {
  8113. column_name = "endDate";
  8114. } else if (cell.content == "Headline") {
  8115. column_name = "headline";
  8116. } else if (cell.content == "Text") {
  8117. column_name = "text";
  8118. } else if (cell.content == "Media") {
  8119. column_name = "media";
  8120. } else if (cell.content == "Media Credit") {
  8121. column_name = "credit";
  8122. } else if (cell.content == "Media Caption") {
  8123. column_name = "caption";
  8124. } else if (cell.content == "Media Thumbnail") {
  8125. column_name = "thumbnail";
  8126. } else if (cell.content == "Type") {
  8127. column_name = "type";
  8128. } else if (cell.content == "Tag") {
  8129. column_name = "tag";
  8130. }
  8131. cellnames.push(column_name);
  8132. } else {
  8133. cell.name = cellnames[cell.col];
  8134. list[cell.row][cell.name] = cell.content;
  8135. }
  8136. };
  8137. for(i = 0; i < list.length; i++) {
  8138. var date = list[i];
  8139. if (date.type.match("start") || date.type.match("title") ) {
  8140. data_obj.timeline.startDate = date.startDate;
  8141. data_obj.timeline.headline = date.headline;
  8142. data_obj.timeline.asset.media = date.media;
  8143. data_obj.timeline.asset.caption = date.caption;
  8144. data_obj.timeline.asset.credit = date.credit;
  8145. data_obj.timeline.text = date.text;
  8146. data_obj.timeline.type = "google spreadsheet";
  8147. } else if (date.type.match("era")) {
  8148. var era = {
  8149. startDate: date.startDate,
  8150. endDate: date.endDate,
  8151. headline: date.headline,
  8152. text: date.text,
  8153. tag: date.tag
  8154. }
  8155. data_obj.timeline.era.push(era);
  8156. } else {
  8157. if (date.startDate) {
  8158. var date = {
  8159. type: "google spreadsheet",
  8160. startDate: date.startDate,
  8161. endDate: date.endDate,
  8162. headline: date.headline,
  8163. text: date.text,
  8164. tag: date.tag,
  8165. asset: {
  8166. media: date.media,
  8167. credit: date.credit,
  8168. caption: date.caption,
  8169. thumbnail: date.thumbnail
  8170. }
  8171. };
  8172. data_obj.timeline.date.push(date);
  8173. } else {
  8174. trace("Skipping item " + i + " in list: no start date.")
  8175. }
  8176. }
  8177. }
  8178. }
  8179. is_valid = data_obj.timeline.date.length > 0;
  8180. if (is_valid) {
  8181. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Finished Parsing Data");
  8182. VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, data_obj);
  8183. } else {
  8184. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Unable to load Google Doc data source. Make sure you have no blank rows and that the headers have not been changed.");
  8185. }
  8186. }
  8187. },
  8188. storify: {
  8189. getData: function(raw) {
  8190. var key, url, storify_timeout;
  8191. //http://storify.com/number10gov/g8-and-nato-chicago-summit
  8192. //http://api.storify.com/v1/stories/number10gov/g8-and-nato-chicago-summit
  8193. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Loading Storify...");
  8194. key = raw.split("storify.com\/")[1];
  8195. url = "//api.storify.com/v1/stories/" + key + "?per_page=300&callback=?";
  8196. storify_timeout = setTimeout(function() {
  8197. trace("STORIFY timeout");
  8198. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Storify is not responding");
  8199. }, 6000);
  8200. VMM.getJSON(url, VMM.Timeline.DataObj.model.storify.buildData)
  8201. .error(function(jqXHR, textStatus, errorThrown) {
  8202. trace("STORIFY error");
  8203. trace("STORIFY ERROR: " + textStatus + " " + jqXHR.responseText);
  8204. })
  8205. .success(function(d) {
  8206. clearTimeout(storify_timeout);
  8207. });
  8208. },
  8209. buildData: function(d) {
  8210. VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Parsing Data");
  8211. var _data_obj = VMM.Timeline.DataObj.data_template_obj;
  8212. _data_obj.timeline.startDate = new Date(d.content.date.created);;
  8213. _data_obj.timeline.headline = d.content.title;
  8214. trace(d);
  8215. //d.permalink
  8216. var tt = "";
  8217. var t_name = d.content.author.username;
  8218. var t_nickname = "";
  8219. if (typeof d.content.author.name != 'undefined') {
  8220. t_name = d.content.author.name;
  8221. t_nickname = d.content.author.username + "&nbsp;";
  8222. }
  8223. if (typeof d.content.description != 'undefined' && d.content.description != null) {
  8224. tt += d.content.description;
  8225. }
  8226. tt += "<div class='storify'>"
  8227. //tt += " <a href='" + d.content.permalink + "' target='_blank' alt='link to original story' title='link to original story'>" + "<span class='created-at'></span>" + " </a>";
  8228. tt += "<div class='vcard author'><a class='screen-name url' href='" + d.content.author.permalink + "' target='_blank'>";
  8229. tt += "<span class='avatar'><img src='" + d.content.author.avatar + "' style='max-width: 32px; max-height: 32px;'></span>"
  8230. tt += "<span class='fn'>" + t_name + "</span>";
  8231. tt += "<span class='nickname'>" + t_nickname + "<span class='thumbnail-inline'></span></span>";
  8232. tt += "</a>";
  8233. //tt += "<span class='nickname'>" + d.content.author.stats.stories + " Stories</span>";
  8234. //tt += "<span class='nickname'>" + d.content.author.stats.subscribers + " Subscribers</span>";
  8235. tt += "</div>"
  8236. tt += "</div>";
  8237. _data_obj.timeline.text = tt;
  8238. _data_obj.timeline.asset.media = d.content.thumbnail;
  8239. //_data_obj.timeline.asset.media = dd.gsx$media.$t;
  8240. //_data_obj.timeline.asset.caption = dd.gsx$mediacaption.$t;
  8241. //_data_obj.timeline.asset.credit = dd.gsx$mediacredit.$t;
  8242. _data_obj.timeline.type = "storify";
  8243. for(var i = 0; i < d.content.elements.length; i++) {
  8244. var dd = d.content.elements[i];
  8245. var is_text = false;
  8246. var d_date = new Date(dd.posted_at);
  8247. //trace(tempdat);
  8248. trace(dd.type);
  8249. //trace(dd);
  8250. var _date = {
  8251. "type": "storify",
  8252. "startDate": dd.posted_at,
  8253. "endDate": dd.posted_at,
  8254. "headline": " ",
  8255. "slug": "",
  8256. "text": "",
  8257. "asset": {
  8258. "media": "",
  8259. "credit": "",
  8260. "caption": ""
  8261. }
  8262. };
  8263. /* MEDIA
  8264. ================================================== */
  8265. if (dd.type == "image") {
  8266. if (typeof dd.source.name != 'undefined') {
  8267. if (dd.source.name == "flickr") {
  8268. _date.asset.media = "//flickr.com/photos/" + dd.meta.pathalias + "/" + dd.meta.id + "/";
  8269. _date.asset.credit = "<a href='" + _date.asset.media + "'>" + dd.attribution.name + "</a>";
  8270. _date.asset.credit += " on <a href='" + dd.source.href + "'>" + dd.source.name + "</a>";
  8271. } else if (dd.source.name == "instagram") {
  8272. _date.asset.media = dd.permalink;
  8273. _date.asset.credit = "<a href='" + dd.permalink + "'>" + dd.attribution.name + "</a>";
  8274. _date.asset.credit += " on <a href='" + dd.source.href + "'>" + dd.source.name + "</a>";
  8275. } else {
  8276. _date.asset.credit = "<a href='" + dd.permalink + "'>" + dd.attribution.name + "</a>";
  8277. if (typeof dd.source.href != 'undefined') {
  8278. _date.asset.credit += " on <a href='" + dd.source.href + "'>" + dd.source.name + "</a>";
  8279. }
  8280. _date.asset.media = dd.data.image.src;
  8281. }
  8282. } else {
  8283. _date.asset.credit = "<a href='" + dd.permalink + "'>" + dd.attribution.name + "</a>";
  8284. _date.asset.media = dd.data.image.src;
  8285. }
  8286. _date.slug = dd.attribution.name;
  8287. if (typeof dd.data.image.caption != 'undefined') {
  8288. if (dd.data.image.caption != 'undefined') {
  8289. _date.asset.caption = dd.data.image.caption;
  8290. _date.slug = dd.data.image.caption;
  8291. }
  8292. }
  8293. } else if (dd.type == "quote") {
  8294. if (dd.permalink.match("twitter")) {
  8295. _date.asset.media = dd.permalink;
  8296. _date.slug = VMM.Util.untagify(dd.data.quote.text);
  8297. } else if (dd.permalink.match("storify")) {
  8298. is_text = true;
  8299. _date.asset.media = "<blockquote>" + dd.data.quote.text.replace(/<\s*\/?\s*b\s*.*?>/g,"") + "</blockquote>";
  8300. }
  8301. } else if (dd.type == "link") {
  8302. _date.headline = dd.data.link.title;
  8303. _date.text = dd.data.link.description;
  8304. if (dd.data.link.thumbnail != 'undefined' && dd.data.link.thumbnail != '') {
  8305. _date.asset.media = dd.data.link.thumbnail;
  8306. } else {
  8307. _date.asset.media = dd.permalink;
  8308. }
  8309. //_date.asset.media = dd.permalink;
  8310. _date.asset.caption = "<a href='" + dd.permalink + "' target='_blank'>" + dd.data.link.title + "</a>"
  8311. _date.slug = dd.data.link.title;
  8312. } else if (dd.type == "text") {
  8313. if (dd.permalink.match("storify")) {
  8314. is_text = true;
  8315. var d_name = d.content.author.username;
  8316. var d_nickname = "";
  8317. if (typeof dd.attribution.name != 'undefined') {
  8318. t_name = dd.attribution.name;
  8319. t_nickname = dd.attribution.username + "&nbsp;";
  8320. }
  8321. var asset_text = "<div class='storify'>"
  8322. asset_text += "<blockquote><p>" + dd.data.text.replace(/<\s*\/?\s*b\s*.*?>/g,"") + "</p></blockquote>";
  8323. //asset_text += " <a href='" + dd.attribution.href + "' target='_blank' alt='link to author' title='link to author'>" + "<span class='created-at'></span>" + " </a>";
  8324. asset_text += "<div class='vcard author'><a class='screen-name url' href='" + dd.attribution.href + "' target='_blank'>";
  8325. asset_text += "<span class='avatar'><img src='" + dd.attribution.thumbnail + "' style='max-width: 32px; max-height: 32px;'></span>"
  8326. asset_text += "<span class='fn'>" + t_name + "</span>";
  8327. asset_text += "<span class='nickname'>" + t_nickname + "<span class='thumbnail-inline'></span></span>";
  8328. asset_text += "</a></div></div>";
  8329. _date.text = asset_text;
  8330. // Try and put it before the element where it is expected on storify
  8331. if ( (i+1) >= d.content.elements.length ) {
  8332. _date.startDate = d.content.elements[i-1].posted_at;
  8333. } else {
  8334. if (d.content.elements[i+1].type == "text" && d.content.elements[i+1].permalink.match("storify")) {
  8335. if ( (i+2) >= d.content.elements.length ) {
  8336. _date.startDate = d.content.elements[i-1].posted_at;
  8337. } else {
  8338. if (d.content.elements[i+2].type == "text" && d.content.elements[i+2].permalink.match("storify")) {
  8339. if ( (i+3) >= d.content.elements.length ) {
  8340. _date.startDate = d.content.elements[i-1].posted_at;
  8341. } else {
  8342. if (d.content.elements[i+3].type == "text" && d.content.elements[i+3].permalink.match("storify")) {
  8343. _date.startDate = d.content.elements[i-1].posted_at;
  8344. } else {
  8345. trace("LEVEL 3");
  8346. _date.startDate = d.content.elements[i+3].posted_at;
  8347. }
  8348. }
  8349. } else {
  8350. trace("LEVEL 2");
  8351. _date.startDate = d.content.elements[i+2].posted_at;
  8352. }
  8353. }
  8354. } else {
  8355. trace("LEVEL 1");
  8356. _date.startDate = d.content.elements[i+1].posted_at;
  8357. }
  8358. }
  8359. _date.endDate = _date.startDate
  8360. }
  8361. } else if (dd.type == "video") {
  8362. _date.headline = dd.data.video.title;
  8363. _date.asset.caption = dd.data.video.description;
  8364. _date.asset.caption = dd.source.username;
  8365. _date.asset.media = dd.data.video.src;
  8366. } else {
  8367. trace("NO MATCH ");
  8368. trace(dd);
  8369. }
  8370. if (is_text) {
  8371. _date.slug = VMM.Util.untagify(dd.data.text);
  8372. }
  8373. _data_obj.timeline.date.push(_date);
  8374. };
  8375. VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, _data_obj);
  8376. }
  8377. },
  8378. tweets: {
  8379. type: "twitter",
  8380. buildData: function(raw_data) {
  8381. VMM.bindEvent(global, VMM.Timeline.DataObj.model.tweets.onTwitterDataReady, "TWEETSLOADED");
  8382. VMM.ExternalAPI.twitter.getTweets(raw_data.timeline.tweets);
  8383. },
  8384. getData: function(raw_data) {
  8385. VMM.bindEvent(global, VMM.Timeline.DataObj.model.tweets.onTwitterDataReady, "TWEETSLOADED");
  8386. VMM.ExternalAPI.twitter.getTweetSearch(raw_data);
  8387. },
  8388. onTwitterDataReady: function(e, d) {
  8389. var _data_obj = VMM.Timeline.DataObj.data_template_obj;
  8390. for(var i = 0; i < d.tweetdata.length; i++) {
  8391. var _date = {
  8392. "type":"tweets",
  8393. "startDate":"",
  8394. "headline":"",
  8395. "text":"",
  8396. "asset":
  8397. {
  8398. "media":"",
  8399. "credit":"",
  8400. "caption":""
  8401. },
  8402. "tags":"Optional"
  8403. };
  8404. // pass in the 'created_at' string returned from twitter //
  8405. // stamp arrives formatted as Tue Apr 07 22:52:51 +0000 2009 //
  8406. //var twit_date = VMM.ExternalAPI.twitter.parseTwitterDate(d.tweetdata[i].raw.created_at);
  8407. //trace(twit_date);
  8408. _date.startDate = d.tweetdata[i].raw.created_at;
  8409. if (type.of(d.tweetdata[i].raw.from_user_name)) {
  8410. _date.headline = d.tweetdata[i].raw.from_user_name + " (<a href='https://twitter.com/" + d.tweetdata[i].raw.from_user + "'>" + "@" + d.tweetdata[i].raw.from_user + "</a>)" ;
  8411. } else {
  8412. _date.headline = d.tweetdata[i].raw.user.name + " (<a href='https://twitter.com/" + d.tweetdata[i].raw.user.screen_name + "'>" + "@" + d.tweetdata[i].raw.user.screen_name + "</a>)" ;
  8413. }
  8414. _date.asset.media = d.tweetdata[i].content;
  8415. _data_obj.timeline.date.push(_date);
  8416. };
  8417. VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, _data_obj);
  8418. }
  8419. }
  8420. },
  8421. /* TEMPLATE OBJECTS
  8422. ================================================== */
  8423. data_template_obj: { "timeline": { "headline":"", "description":"", "asset": { "media":"", "credit":"", "caption":"" }, "date": [], "era":[] } },
  8424. date_obj: {"startDate":"2012,2,2,11,30", "headline":"", "text":"", "asset": {"media":"http://youtu.be/vjVfu8-Wp6s", "credit":"", "caption":"" }, "tags":"Optional"}
  8425. };
  8426. }