PageRenderTime 66ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/ElmcityAdmin/elmcity-1.17.js

https://github.com/judell/elmcity
JavaScript | 1211 lines | 1104 code | 96 blank | 11 comment | 50 complexity | 9478f1ffd803bb7a6efbf9b840c62f52 MD5 | raw file
  1. var host = 'http://elmcity.cloudapp.net/';
  2. var blobhost = 'http://elmcity.blob.core.windows.net/';
  3. var anchor_names = [];
  4. var today = new Date();
  5. var last_day;
  6. var datepicker = false;
  7. //var is_mobile = false;
  8. //var is_mobile_declared = false;
  9. //var is_mobile_detected = false;
  10. var is_eventsonly = false;
  11. var is_bare_events = false;
  12. var is_theme = false;
  13. var is_view = false;
  14. var is_sidebar = true;
  15. var show_images = true;
  16. var hide_maps = true;
  17. var top_method = 0; // for use in position_sidebar
  18. var default_args = {};
  19. var last_available_day = null;
  20. var can_load_events;
  21. var metadata;
  22. var $j = jQuery.noConflict();
  23. var redirected_hubs = [ 'AnnArborChronicle'];
  24. var redirected_hubs_dict = { 'AnnArborChronicle':'events.annarborchronicle.com' };
  25. var category_images = {};
  26. var source_images = {};
  27. function get_top_elt_top() {
  28. try
  29. {
  30. var top_elt_top = $j('#' + top_element)[0].getClientRects()[0].top;
  31. }
  32. catch (e)
  33. {
  34. console.log(e.message);
  35. top_elt_top = 0;
  36. }
  37. return top_elt_top;
  38. }
  39. function position_sidebar(top_element)
  40. {
  41. if ( is_eventsonly )
  42. return;
  43. var top_elt_top = get_top_elt_top();
  44. var top = top_elt_top < 0 ? 0 : top_elt_top;
  45. $j('#sidebar').css('position','fixed').css('top',top);
  46. var date_str = find_current_name().replace('d','');
  47. var parsed = parse_yyyy_mm_dd(date_str)
  48. $j('#datepicker').datepicker('setDate', new Date(parsed['year'], parsed['month']-1, parsed['day']));
  49. apply_datepicker_styles();
  50. }
  51. function on_load()
  52. {
  53. }
  54. function get_elmcity_id()
  55. {
  56. return $j('#elmcity_id').text().trim();
  57. }
  58. function get_view()
  59. {
  60. return $j('#view').text().trim();
  61. }
  62. function get_selected_hub()
  63. {
  64. return $j('#hub_select option:selected').val();
  65. }
  66. function get_generated_hub()
  67. {
  68. return $j('#hub').text().trim();
  69. }
  70. function gup( name )
  71. {
  72. var value = default_args[name];
  73. if ( value == null ) value = '';
  74. name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  75. var regexS = "[\\?&]"+name+"=([^&#]*)";
  76. var regex = new RegExp( regexS );
  77. var results = regex.exec( window.location.href );
  78. if( results != null )
  79. value = results[1].replace(/%20/,' ');
  80. return value;
  81. }
  82. function parse_yyyy_mm_dd(date_str)
  83. {
  84. var match = /(\d{4,4})(\d{2,2})(\d{2,2})/.exec(date_str);
  85. return { year: match[1], month: match[2], day: match[3] }
  86. }
  87. function parse_mm_dd_yyyy(date_str)
  88. {
  89. var match = /(\d{2,2})\/(\d{2,2})\/(\d{4,4})/.exec(date_str);
  90. return { month: match[1], day: match[2], year: match[3] }
  91. }
  92. function parse_yyyy_mm_dd_T_hh_mm(date_str)
  93. {
  94. var match = /(\d{4,4})-(\d+)-(\d+)T(\d+):(\d+)/.exec(date_str);
  95. return { year: match[1], month: match[2], day: match[3], hour: match[4], minute: match[5] }
  96. }
  97. function scroll(event) {
  98. if ( is_eventsonly )
  99. return;
  100. position_sidebar(top_element);
  101. }
  102. function resize(event) {
  103. position_sidebar(top_element);
  104. }
  105. function style_current_date() {
  106. }
  107. function find_last_day()
  108. {
  109. try
  110. {
  111. var last_anchor = anchor_names[anchor_names.length - 1];
  112. var parsed = parse_yyyy_mm_dd(last_anchor.replace('d',''));
  113. return new Date(parsed['year'], parsed['month'] - 1, parsed['day']);
  114. }
  115. catch (e)
  116. {
  117. return new Date();
  118. }
  119. }
  120. function get_anchor_names(anchors)
  121. {
  122. var anchor_names = [];
  123. for (var i = 0; i < anchors.length; i++)
  124. {
  125. anchor_names.push(anchors[i].name);
  126. }
  127. return anchor_names;
  128. }
  129. function day_anchors()
  130. {
  131. return $j('a[name^="d"]');
  132. }
  133. function find_current_name()
  134. {
  135. if ( is_eventsonly )
  136. return;
  137. // console.log("find_current_name");
  138. try
  139. {
  140. var before = [];
  141. var datepicker_top = $j("#datepicker")[0].getClientRects()[0].top;
  142. var datepicker_bottom = $j("#datepicker")[0].getClientRects()[0].bottom;
  143. var datepicker_height = datepicker_bottom - datepicker_top;
  144. var datepicker_center = datepicker_top + ( datepicker_height / 2 );
  145. var anchors = day_anchors();
  146. for (var i = 0; i < anchors.length; i++)
  147. {
  148. var anchor = anchors[i];
  149. var anchor_top = anchor.getClientRects()[0].top;
  150. if ( anchor_top < datepicker_center )
  151. before.push(anchor.name);
  152. else
  153. break;
  154. }
  155. var ret = before[before.length-1];
  156. if ( typeof ret == 'undefined' )
  157. ret = anchors[0].name;
  158. }
  159. catch (e)
  160. {
  161. console.log("find_current_name: " + e.message);
  162. }
  163. return ret;
  164. }
  165. $j(window).scroll(function(event) {
  166. scroll(event);
  167. });
  168. $j(window).resize(function(event) {
  169. console.log('resize');
  170. resize(event);
  171. });
  172. function prep_day_anchors_and_last_day()
  173. {
  174. var anchors = day_anchors();
  175. anchor_names = get_anchor_names(anchors);
  176. last_day = find_last_day();
  177. }
  178. function setup_datepicker()
  179. {
  180. if ( is_eventsonly && ! is_bare_events )
  181. return;
  182. // console.log("setup_datepicker");
  183. prep_day_anchors_and_last_day();
  184. $j('#datepicker').datepicker({
  185. onSelect: function(dateText, inst) { goDay(dateText); },
  186. onChangeMonthYear: function(year, month, inst) { goMonth(year, month); },
  187. minDate: today,
  188. maxDate: last_available_day,
  189. hideIfNoPrevNext: true,
  190. beforeShowDay: maybeShowDay
  191. });
  192. apply_datepicker_styles();
  193. $j('#sidebar').css('visibility','visible');
  194. $j('#datepicker').css('visibility','visible');
  195. $j('#tags').css('visibility','visible');
  196. }
  197. function ready()
  198. {
  199. var elmcity_id = get_elmcity_id();
  200. load_category_images(elmcity_id);
  201. load_source_images(elmcity_id);
  202. is_theme = gup('theme') != '';
  203. var view = gup('view');
  204. is_view = view != '';
  205. is_eventsonly = gup('eventsonly').startsWith('y');
  206. is_bare_events = gup('bare_events').startsWith('y');
  207. if ( is_eventsonly ) {
  208. show_images = false; // default to no images for eventsonly views
  209. }
  210. else {
  211. show_images = true; // default to show images for full views
  212. }
  213. if ( gup('show_images').startsWith('n') ) // optionally override to false
  214. show_images = false;
  215. if ( gup('show_images').startsWith('y') ) // optionally override to true
  216. show_images = true;
  217. if ( gup('hide_maps').startsWith('n') ) // optionally override to false
  218. hide_maps = false;
  219. // is_mobile_declared = gup('mobile').startsWith('y');
  220. // is_mobile_detected = $j('#mobile_detected').text().trim() == "__MOBILE_DETECTED__";
  221. // is_mobile = is_mobile_declared || is_mobile_detected;
  222. if ( is_eventsonly )
  223. $j('.bl').css('margin-right','3%'); // could overwrite theme-defined?
  224. is_sidebar = ! is_eventsonly;
  225. if ( gup('hubtitle').startsWith('n') )
  226. $j('.hubtitle').remove();
  227. if ( gup('tags').startsWith('n') )
  228. $j('.cat').remove();
  229. if ( gup('tags').startsWith('hide') ) // keep them invisibly for use with image display
  230. $j('.cat').css('display','none');
  231. if ( is_view && is_sidebar )
  232. try {
  233. var href = $j('#subscribe').attr('href');
  234. href = href.replace('__VIEW__', gup('view'));
  235. $j('#subscribe').attr('href',href);
  236. $j('#subscribe').text('subscribe');
  237. }
  238. catch (e) {
  239. console.log('cannot activate subscribe link');
  240. }
  241. if ( gup('timeofday') == 'no' )
  242. $j('.timeofday').remove();
  243. if ( gup('datestyle') != '' )
  244. apply_json_css('.ed', 'datestyle');
  245. if ( gup('itemstyle') != '' )
  246. apply_json_css('.bl', 'itemstyle');
  247. if ( gup('titlestyle') != '' )
  248. apply_json_css('.ttl', 'titlestyle');
  249. if ( gup('linkstyle') != '' )
  250. apply_json_css('.ttl a', 'linkstyle');
  251. if ( gup('dtstartstyle') != '' )
  252. apply_json_css('.st', 'dtstartstyle');
  253. if ( gup('sd') != '' )
  254. apply_json_css('.sd', 'sd');
  255. if ( gup('atc') != '' )
  256. apply_json_css('.atc', 'atc');
  257. if ( gup('cat') != '' )
  258. apply_json_css('.cat', 'cat');
  259. if ( gup('sourcestyle') != '' )
  260. apply_json_css('.src', 'sourcestyle');
  261. // remember_or_forget_days();
  262. // adjust_openers();
  263. show_category_image_under_picker();
  264. try {
  265. metadata = JSON.parse($j('#elmcity_metadata').text());
  266. last_available_day = new Date (metadata["last_available_day"]);
  267. last_available_day.addDays(1);
  268. can_load_events = metadata["days"].filter( function(x) { return anchor_names.indexOf(x) == -1 } )
  269. }
  270. catch (e) {
  271. console.log('cannot process metadata');
  272. }
  273. if ( is_sidebar )
  274. setup_datepicker();
  275. position_sidebar();
  276. // $j('a[title="see details"]').removeAttr('target');
  277. }
  278. $j(document).ready(function()
  279. {
  280. ready();
  281. });
  282. function apply_json_css(element,style)
  283. {
  284. try
  285. {
  286. var style = decodeURIComponent(gup(style));
  287. style = style.replace(/'/g,'"');
  288. $j(element).css(JSON.parse(style));
  289. }
  290. catch (e)
  291. {
  292. console.log(e.message);
  293. }
  294. }
  295. function scrollToElement(id)
  296. {
  297. if ( $j('#'+ id).length )
  298. window.scrollTo(0, $j('#' + id).offset().top);
  299. }
  300. function getDateStr(date) {
  301. var year = date.getFullYear();
  302. var month = maybeZeroPad(date.getMonth() + 1);
  303. var day = maybeZeroPad(date.getDate());
  304. return "d" + year + month + day;
  305. }
  306. function hasLoadedEvents(date_str) {
  307. return $j.inArray(date_str, anchor_names) == -1 ? false : true;
  308. }
  309. function canLoadEvents(date_str) {
  310. return $j.inArray(date_str, can_load_events) == -1 ? false : true;
  311. }
  312. function maybeShowDay(date) {
  313. var date_str = getDateStr(date);
  314. var style;
  315. var d = new Date();
  316. var today = new Date(d.getFullYear(), d.getMonth(), d.getDate());
  317. var has_loaded_events = hasLoadedEvents(date_str);
  318. var can_load_events = canLoadEvents(date_str);
  319. var tooltip = '';
  320. if (
  321. date < today ||
  322. ( last_available_day != null && date > last_available_day ) ||
  323. ( ! hasLoadedEvents(date_str) && ! canLoadEvents(date_str) )
  324. )
  325. style = "ui-state-disabled";
  326. else if ( has_loaded_events && is_today(date) ) {
  327. style = 'cal_day is_today has_loaded_events';
  328. }
  329. else {
  330. var tooltip_date_str = date.toDateString();
  331. if ( has_loaded_events ) {
  332. style = 'cal_day has_loaded_events';
  333. tooltip = "go to " + tooltip_date_str
  334. }
  335. else if ( can_load_events) {
  336. style = 'cal_day can_load_events';
  337. tooltip = "load events for " + tooltip_date_str;
  338. }
  339. }
  340. return [true, style, tooltip];
  341. }
  342. function apply_datepicker_styles() {
  343. // $j('#datepicker').datepicker('refresh');
  344. $j('.cal_day a').css('font-weight','bold').css('color','darkgreen');
  345. $j('.is_today a').css('text-decoration','underline');
  346. $j('.has_loaded_events a').css('color','darkgreen').css('font-weight:bold');
  347. $j('.can_load_events a').css('font-style','italic').css('color','black').css('font-weight','normal');
  348. $j('.ui-datepicker-current-day a').css('border-color','darkgreen').css('border-width','thin');
  349. $j('td .cal_day a').removeClass('ui-state-default');
  350. $j('td .cal_day a').removeClass('ui-state-active');
  351. $j('td.ui-state-disabled').removeAttr('onclick');
  352. $j('td.ui-state-disabled a').removeAttr('href');
  353. }
  354. function is_today(date) {
  355. var now = new Date();
  356. return ( now.getYear() == date.getYear() && now.getMonth() == date.getMonth() && now.getDate() == date.getDate() );
  357. }
  358. function goDay(date_text)
  359. {
  360. var parsed = parse_mm_dd_yyyy(date_text)
  361. var year = parsed['year'];
  362. var month = parsed['month'];
  363. var day = parsed['day'];
  364. var date_str = 'd' + year + month + day;
  365. var has_loaded_events = hasLoadedEvents(date_str);
  366. if (!has_loaded_events)
  367. load_events_for_date(year, month, day);
  368. else
  369. scrollToElement(date_str);
  370. setTimeout('apply_datepicker_styles()',100);
  371. }
  372. function goMonth(year, month)
  373. {
  374. month = maybeZeroPad(month.toString());
  375. var id = $j('h1[id^="d' + year + month + '"]').attr('id')
  376. // scrollToElement(id);
  377. setTimeout('apply_datepicker_styles()',100);
  378. }
  379. function maybeZeroPad(str)
  380. {
  381. str = str.toString();
  382. if ( str.length == 1 ) str = '0' + str;
  383. return str;
  384. }
  385. function remove(array, str)
  386. {
  387. for(var i=0; i<array.length; i++)
  388. {
  389. if ( array[i] == str || array[i].startsWith(str) )
  390. {
  391. array.splice(i, 1);
  392. break;
  393. }
  394. }
  395. }
  396. Date.prototype.addDays = function(days) {
  397. this.setDate(this.getDate()+days);
  398. }
  399. String.prototype.replaceAt=function(index, char) {
  400. return this.substr(0, index) + char + this.substr(index+char.length);
  401. }
  402. String.prototype.startsWith = function (str){
  403. return this.indexOf(str) == 0;
  404. };
  405. String.prototype.contains = function (str){
  406. return this.indexOf(str) != -1;
  407. };
  408. String.prototype.endsWith = function (str){
  409. return this.indexOf(str) == this.length - str.length - 1;
  410. };
  411. if(!String.prototype.trim) {
  412. String.prototype.trim = function () {
  413. return this.replace(/^\s+|\s+$/g,'');
  414. };
  415. }
  416. function case_insensitive_sort(a, b)
  417. {
  418. var x = a.toLowerCase();
  419. var y = b.toLowerCase();
  420. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  421. }
  422. function make_path(view)
  423. {
  424. var path;
  425. var elmcity_id = get_elmcity_id();
  426. if ( view == undefined )
  427. {
  428. var selected = $j('#tag_select option:selected').val();
  429. view = selected.replace(/\s*\((\d+)\)/,'');
  430. path = make_view_path_from_picklist(view, elmcity_id);
  431. }
  432. else
  433. {
  434. path = make_view_path_from_view(view, elmcity_id);
  435. }
  436. if ( gup('tags') != '')
  437. path = add_href_arg(path,'tags',gup('tags') );
  438. if ( gup('test') != '')
  439. path = add_href_arg(path,'test',gup('test') );
  440. if ( gup('theme') != '')
  441. path = add_href_arg(path,'theme',gup('theme') );
  442. if ( gup('count') != '')
  443. path = add_href_arg(path,'count',gup('count') );
  444. if ( gup('hubtitle') != '')
  445. path = add_href_arg(path,'hubtitle',gup('hubtitle') );
  446. if ( gup('eventsonly') != '')
  447. path = add_href_arg(path,'eventsonly',gup('eventsonly') );
  448. if ( gup('template') != '')
  449. path = add_href_arg(path,'template',gup('template') );
  450. if ( gup('jsurl') != '')
  451. path = add_href_arg(path,'jsurl',gup('jsurl') );
  452. if ( gup('hub') != '')
  453. path = add_href_arg(path,'hub', get_selected_hub() );
  454. return path;
  455. }
  456. function show_view(view)
  457. {
  458. var elmcity_id = get_elmcity_id();
  459. var path = make_path(view);
  460. location.href = path;
  461. }
  462. function make_view_path_from_view(view, elmcity_id)
  463. {
  464. var path;
  465. if ( redirected_hubs.indexOf(elmcity_id) == -1 )
  466. path = '/' + elmcity_id + '/?view=' + encodeURIComponent(view);
  467. else
  468. path = '/html?view=' + encodeURIComponent(view);
  469. return path;
  470. }
  471. function make_view_path_from_picklist(view, elmcity_id)
  472. {
  473. var path;
  474. if ( redirected_hubs.indexOf(elmcity_id) == -1 )
  475. {
  476. if ( view == 'all' )
  477. path = '/' + elmcity_id + '/';
  478. else
  479. path = '/' + elmcity_id + '/?view=' + encodeURIComponent(view);
  480. }
  481. else
  482. {
  483. if ( view == 'all' )
  484. path = '/html' + '/';
  485. else
  486. path = '/html?view=' + encodeURIComponent(view);
  487. }
  488. return path;
  489. }
  490. function remove_href_arg(href, name)
  491. {
  492. var pat = eval('/[\?&]*' + name + '=[^&]*/');
  493. href = href.replace(pat,'');
  494. if ( (! href.contains('?')) && href.contains('&') )
  495. href = href.replaceAt(href.indexOf('&'),'?');
  496. return href;
  497. }
  498. function add_href_arg(href, name, value)
  499. {
  500. href = remove_href_arg(href,name);
  501. if ( href.contains('?') )
  502. href = href + '&' + name + '=' + value;
  503. else
  504. {
  505. href = href + '?' + name + '=' + value;
  506. }
  507. return href;
  508. }
  509. function dismiss_menu(id)
  510. {
  511. var elt = $j('#' + id);
  512. elt.find('.menu').remove();
  513. }
  514. function get_add_to_cal_url(id,flavor)
  515. {
  516. var elt = $j('#' + id);
  517. var start = elt.find('.st').attr('content');
  518. var end = ''; // for now
  519. var url = elt.find('.ttl').find('a').attr('href');
  520. var summary = get_summary(id);
  521. var description = elt.find('.src').text();
  522. var location = ''; // for now
  523. var elmcity_id = get_elmcity_id();
  524. var service_url = host + 'add_to_cal?elmcity_id=' + elmcity_id +
  525. '&flavor=' + flavor +
  526. '&start=' + encodeURIComponent(start) +
  527. '&end=' + end +
  528. '&summary=' + encodeURIComponent(summary) +
  529. '&url=' + encodeURIComponent(url) +
  530. '&description=' + encodeURIComponent(description) +
  531. '&location=' + location;
  532. return service_url;
  533. }
  534. function add_to_google(id)
  535. {
  536. try
  537. {
  538. var service_url = get_add_to_cal_url(id, 'google');
  539. $j('.menu').remove();
  540. // console.log('redirecting to ' + service_url);
  541. // location.href = service_url;
  542. window.open(service_url, "add to google");
  543. }
  544. catch (e)
  545. {
  546. console.log(e.message);
  547. }
  548. }
  549. function add_to_hotmail(id)
  550. {
  551. var service_url = get_add_to_cal_url(id, 'hotmail');
  552. $j('.menu').remove();
  553. location.href = service_url;
  554. }
  555. function add_to_ical(id)
  556. {
  557. var service_url = get_add_to_cal_url(id, 'ical');
  558. $j('.menu').remove();
  559. location.href = service_url;
  560. }
  561. function add_to_facebook(id)
  562. {
  563. var service_url = get_add_to_cal_url(id, 'facebook');
  564. $j('.menu').remove();
  565. location.href = service_url;
  566. }
  567. function add_to_cal(id)
  568. {
  569. elt = $j('#' + id);
  570. quoted_id = '\'' + id + '\'';
  571. elt.find('.menu').remove();
  572. elt.append(
  573. '<ul class="menu">' +
  574. '<li><a title="add this event to your Google calendar" href="javascript:add_to_google(' + quoted_id + ')">add to Google Calendar</a></li>' +
  575. '<li><a title="add this event to your Hotmail calendar" href="javascript:add_to_hotmail(' + quoted_id + ')">add to Hotmail Calendar</a></li>' +
  576. '<li><a title="add to your Outlook, Apple iCal, or other iCalendar-aware desktop calendar" href="javascript:add_to_ical(' + quoted_id + ')">add to iCal</a></li>' +
  577. '<li><a title="add to Facebook (remind yourself and invite friends with 1 click!)" href="javascript:add_to_facebook(' + quoted_id + ')">add to Facebook</a></li>' +
  578. '<li><a title="dismiss this menu" href="javascript:dismiss_menu(' + quoted_id + ')">cancel</a></li>' +
  579. '</ul>'
  580. );
  581. }
  582. var current_id;
  583. var current_source;
  584. function active_description(description) {
  585. var template = '<div id="__ID___desc" style="overflow:hidden;text-indent:0;border-style:solid;border-width:thin;padding:8px;margin:8px">__CLOSER__ __IMAGES__ <div style="clear:both"><hr width="100%"><span class="desc">__LOCATION_AND_DESCRIPTION__</span>__MAP__<div>__UPCOMING__</div>__SOURCE__</div></div>';
  586. if ( $j('#' + current_id + '_desc').length > 0 )
  587. return;
  588. template = template.replace('__ID__', current_id);
  589. var orig_length = description.length;
  590. description = description.replace(/<br>\s+/g, '<br>')
  591. description = description.replace(/(<br>)\1+/g, '<br><br>')
  592. template = template.replace('__LOCATION_AND_DESCRIPTION__',description);
  593. quoted_id = '\'' + current_id + '\'';
  594. var cat_images = "";
  595. var source_image = "";
  596. var all_images = new Array();
  597. // build html for source image
  598. try {
  599. var img_url = source_images[current_source];
  600. if ( typeof (img_url) != 'undefined' && img_url.contains('NoCurrentImage') == false )
  601. source_image += '<a title="source: ' + current_source + '"><img alt="' + current_source + '" style="float:left;margin:8px;width:100px" src="' + img_url + '"></a>'
  602. }
  603. catch (e) {
  604. console.log(e.message);
  605. }
  606. // build html for catgory images
  607. try {
  608. var cats = $j('#' + current_id + ' .cat a').slice(0,2);
  609. for ( i = 0; i < cats.length; i++ )
  610. {
  611. var cat = cats[i].firstChild.textContent;
  612. if ( cat == 'facebook' )
  613. continue;
  614. var img_url = category_images[cat];
  615. if ( typeof (img_url) != 'undefined' && img_url.contains('NoCurrentImage') == false )
  616. {
  617. var href = location.href;
  618. href = add_href_arg(href, 'view', cat);
  619. href = remove_href_arg(href, 'show_desc');
  620. var message;
  621. var href_html;
  622. if ( gup('view') != cat )
  623. {
  624. message = 'switch to the ' + cat + ' category';
  625. href_html = 'href="' + href + '" ';
  626. }
  627. else
  628. {
  629. message = 'current category: ' + cat;
  630. href_html = ' ';
  631. }
  632. cat_images += '<a title="' + message + '"' + href_html + '><img alt="' + cat + '" style="float:left;margin:8px;width:100px;border-style:solid;border-width:thin;border-color:slategray" src="' + img_url + '"></a>';
  633. }
  634. }
  635. }
  636. catch (e) {
  637. console.log(e.message);
  638. }
  639. if ( show_images && ( source_image != '' || category_images != '' ) ) {
  640. template = template.replace('__IMAGES__', source_image + cat_images);
  641. }
  642. else {
  643. template = template.replace('__IMAGES__','');
  644. }
  645. //s.match( /(\d+-\d+-)(\d+)(T\d+:\d+)/ )
  646. //["2013-10-07T19:00", "2013-10-", "07", "T19:00"]
  647. try {
  648. var lat = $j('#' + current_id + ' span[property="v:latitude"]').attr('content');
  649. var lon = $j('#' + current_id + ' span[property="v:longitude"]').attr('content');
  650. if ( typeof (lat) != 'undefined' && typeof(lon) != 'undefined' ) {
  651. var date = get_md(current_id) + ' ' + get_st2(current_id);
  652. var title = get_summary(current_id);
  653. var map_url = host + 'get_blob?id=admin&path=map_detail.html?lat=' + lat + '&lon=' + lon + '&title=' + encodeURIComponent(title) + '&date=' + encodeURIComponent(date);
  654. var map_display = 'none';
  655. if ( ! hide_maps )
  656. map_display = "block";
  657. var iframe = '<iframe style="display:__DISPLAY__;margin-top:20px" src="' + map_url + '" width="100%" height="400" scrolling="no" seamless="seamless"></iframe>';
  658. iframe = iframe.replace('__DISPLAY__', map_display);
  659. var map_opener = '<p class="elmcity_info_para"><b>Map:</b></p><p class="elmcity_info_para" id="' + current_id + '_map_opener' + '"><a href="javascript:reveal_map(current_id)"><img style="border-style:solid;border-width:thin" title="click to enlarge map" src="' + blobhost + 'admin/map_icon.jpg' + '"></a></p>';
  660. if ( ! hide_maps )
  661. map_opener = '';
  662. template = template.replace('__MAP__', map_opener + iframe);
  663. }
  664. else
  665. template = template.replace('__MAP__', '');
  666. }
  667. catch (e) {
  668. console.log(e.message);
  669. }
  670. // build the closer
  671. var x = '<span style="font-size:larger;float:right;"><a title="hide description" href="javascript:hide_desc(' + quoted_id + ')"> [X] </a> </span>';
  672. template = template.replace('__CLOSER__', x);
  673. // acquire upcoming events from source
  674. var elmcity_id = get_elmcity_id();
  675. var from_dt = get_dtstart(current_id);
  676. var to_dt = '3000-01-01T00:00'; // just a date far in future, the count arg will trim the results
  677. if ( $j('#' + current_id + ' .src').text() != '' ) { // skip if coalesced
  678. template = template.replace('__UPCOMING__', '<p style="display:none" id="' + current_id + '_upcoming"></p>');
  679. var redirected_host = get_redirected_host();
  680. var url= redirected_host + '/json?source=' + current_source + '&from=' + from_dt + '&to=' + to_dt + '&count=4';
  681. try {
  682. $j.ajax({
  683. url: url,
  684. cache: false,
  685. complete: function(xhr, status) {
  686. try {
  687. var upcoming = JSON.parse(xhr.responseText);
  688. if ( $j.keys(upcoming).length > 0 ) {
  689. var fn = 'show_upcoming_html("' + current_id + '",' + xhr.responseText + ')';
  690. window.setTimeout(fn, 0);
  691. }
  692. }
  693. catch (e) {
  694. console.log('cannot process upcoming events' + e.message);
  695. }
  696. }
  697. });
  698. }
  699. catch (e) {
  700. console.log('cannot get upcoming events' + e.message);
  701. }
  702. }
  703. else
  704. template = template.replace('__UPCOMING__','');
  705. // build link to source calendar
  706. var url = $j('#' + current_id + ' span[rel="v:url"]').attr('href');
  707. var src = $j('#' + current_id + ' span[property="v:description"]').text()
  708. var link = '<p style="font-size:larger"><a target="origin" title="visit the source calendar in a new window or tab" href="' + url + '">click for event details</a></p>';
  709. template = template.replace('__SOURCE__',link);
  710. elt = $j('#' + current_id);
  711. elt.append(template);
  712. }
  713. function get_redirected_host() {
  714. var elmcity_id = get_elmcity_id();
  715. var redirected_host = host;
  716. if ( redirected_hubs.indexOf(elmcity_id) != -1 )
  717. redirected_host = 'http://' + redirected_hubs_dict[elmcity_id] + '/';
  718. else
  719. redirected_host = host + elmcity_id;
  720. return redirected_host;
  721. }
  722. function reveal_map(id) {
  723. $j('#' + id + ' iframe').css('display','block');
  724. $j('#' + id + '_map_opener').remove();
  725. }
  726. function show_upcoming_html(id, obj) {
  727. if ( $j.keys(obj).length == 1 ) // only the current event
  728. return;
  729. obj = obj.splice(1); // the query matches the current event so exclude it
  730. var upcoming = $j('#' + id + '_upcoming');
  731. // var upcoming_html = '<p class="elmcity_info_para"><b>Next on the </b>' + '<span class="src">' + current_source + '</span>' + ' <b>calendar</b>:</b></p>';
  732. var upcoming_html = '<p class="elmcity_info_para"><b>Next on the <u>' + current_source + '</u>' + ' calendar:</b></p>';
  733. upcoming_html += '<div style="margin-left:5%">';
  734. for ( i in obj ) {
  735. var dtstart = new Date(obj[i]['dtstart']).toLocaleString();
  736. upcoming_html += '<p class="elmcity_info_para">' + '<i>' + obj[i]['title'] + '</i>' + ', ' + '<b>' + dtstart + '</b>';
  737. var upcoming_location = obj[i]['location'];
  738. if ( upcoming_location != '' ) {
  739. upcoming_html += ', ' + upcoming_location;
  740. }
  741. upcoming_html += '</p>';
  742. }
  743. upcoming_html += '</div>';
  744. upcoming.html(upcoming_html);
  745. upcoming.css('display','block');
  746. }
  747. function hide_desc(id)
  748. {
  749. quoted_id = '\'' + id + '\'';
  750. $j('#' + id + '_desc').remove();
  751. $j('#' + id + ' .sd').css('display','inline');
  752. $j('#' + id + ' .atc').css('display','inline');
  753. }
  754. function show_more(id)
  755. {
  756. $j('div.' + id).show();
  757. $j('span.' + id).remove();
  758. }
  759. function show_desc(id)
  760. {
  761. quoted_id = '\'' + id + '\'';
  762. $j('#' + id + ' .sd').css('display','none');
  763. $j('#' + id + ' .atc').css('display','none');
  764. var elmcity_id = get_elmcity_id();
  765. var uid = get_uid(id);
  766. var hash = get_hash(id);
  767. var url;
  768. if ( hash == '' )
  769. url = host + elmcity_id + '/description_from_uid?uid=' + uid + '&jsonp=active_description';
  770. else
  771. url = host + elmcity_id + '/description_from_hash?hash=' + hash + '&jsonp=active_description';
  772. current_id = id;
  773. current_source = get_source(id);
  774. $j.getScript(url);
  775. if ( ! gup('open_at_top').startsWith('n') )
  776. scrollToElement(id);
  777. }
  778. function find_id_of_last_event()
  779. {
  780. var events = $j('.bl');
  781. var last = events[events.length-1];
  782. return last.attributes['id'].value;
  783. }
  784. function get_summary(id)
  785. {
  786. var elt = $j('#' + id);
  787. var summary = $j('#' + id + ' .ttl span').text();
  788. if ( summary == '')
  789. summary = $j('#' + id + ' .ttl a').text();
  790. return summary;
  791. }
  792. function get_uid(id)
  793. {
  794. return $j('#' + id + ' .uid').text();
  795. }
  796. function get_hash(id)
  797. {
  798. return $j('#' + id + ' .hash').text();
  799. }
  800. function get_dtstart(id)
  801. {
  802. return $j('#' + id + ' .st').attr('content');
  803. }
  804. function get_md(id)
  805. {
  806. return $j('#' + id + ' .md').text();
  807. }
  808. function get_st(id)
  809. {
  810. return $j('#' + id + ' .st').attr('content');
  811. }
  812. function get_st2(id)
  813. {
  814. return $j('#' + id + ' .st').text();
  815. }
  816. function get_source(id)
  817. {
  818. return $j('#' + id + ' .src').text();
  819. }
  820. $j.extend({
  821. keys: function(obj){
  822. var a = [];
  823. $j.each(obj, function(k){ a.push(k) });
  824. return a;
  825. }
  826. });
  827. function load_category_images(id)
  828. {
  829. if ( $j.keys(category_images).length > 0 )
  830. return;
  831. $j.ajax({
  832. url: host + 'get_blob?id=' + id + '&path=category_images.json',
  833. cache: false,
  834. complete: function(xhr, status) {
  835. try {
  836. category_images = JSON.parse(xhr.responseText);
  837. }
  838. catch (e) {
  839. console.log('no category images' + e.message);
  840. }
  841. }
  842. });
  843. }
  844. function load_source_images(id)
  845. {
  846. if ( $j.keys(source_images).length > 0 )
  847. return;
  848. $j.ajax({
  849. url: host + 'get_blob?id=' + id + '&path=source_images.json',
  850. cache: false,
  851. complete: function(xhr, status) {
  852. try {
  853. source_images = JSON.parse(xhr.responseText);
  854. }
  855. catch (e) {
  856. console.log('no source images' + e.message);
  857. }
  858. }
  859. });
  860. }
  861. function load_events_for_date (year, month, day) {
  862. var per_date_events_url = location.href;
  863. per_date_events_url = add_href_arg(per_date_events_url, 'from', year + '-' + month + '-' + day + 'T00:00');
  864. var next_date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day), 0, 0);
  865. next_date.setDate(next_date.getDate() + 1);
  866. var next_date_year = maybeZeroPad(next_date.getFullYear().toString(), 2);
  867. var next_date_month = maybeZeroPad((next_date.getMonth() + 1).toString(), 2);
  868. var next_date_day = maybeZeroPad(next_date.getDate().toString(), 2);
  869. per_date_events_url = add_href_arg(per_date_events_url, 'to', next_date_year + '-' + next_date_month + '-' + next_date_day + 'T00:00');
  870. per_date_events_url = add_href_arg(per_date_events_url, 'bare_events', 'y');
  871. per_date_events_url = add_href_arg(per_date_events_url, 'tags', 'hide');
  872. per_date_events_url = remove_href_arg(per_date_events_url, 'days');
  873. $j('#datepicker').append('<p style="font-size:larger" id="loading-date">loading...</p>')
  874. $j.ajax({
  875. url: per_date_events_url,
  876. cache: false
  877. }).done(function (html) {
  878. console.log('load_events_for_date ' + html.length + ' characters of html');
  879. var insertion_anchor = find_insertion_anchor(year, month, day);
  880. if ( insertion_anchor != '' )
  881. $j('#' + insertion_anchor).before(html);
  882. else
  883. $j('div .events').append(html);
  884. prep_day_anchors_and_last_day();
  885. setTimeout('apply_datepicker_styles()',100);
  886. // adjust_openers();
  887. scrollToElement('d' + year + month + day);
  888. $j('#loading-date').remove();
  889. if ( gup('tags').startsWith('hide') ) // keep them invisibly for use with image display
  890. $j('.cat').css('display','none');
  891. });
  892. }
  893. function find_insertion_anchor (year, month, day) {
  894. var return_anchor = '';
  895. for (var i in anchor_names) {
  896. var anchor = anchor_names[i];
  897. if (anchor > 'd' + year + month + day)
  898. return_anchor = anchor;
  899. }
  900. return return_anchor;
  901. }
  902. function adjust_openers() {
  903. if ( is_eventsonly )
  904. return;
  905. $j('.ttl a').removeAttr('target');
  906. // find noncoalesced ttls, adjust tooltips
  907. var noncoalesced = $j('.ttl a[property="v:summary"]');
  908. noncoalesced.attr('title','see details')
  909. // and hrefs
  910. for ( var i = 0; i < noncoalesced.length; i++ )
  911. {
  912. var id = noncoalesced[i].parentNode.parentNode.getAttribute('id');
  913. $j('#' + id + ' .ttl a').attr('href','javascript:show_desc("' + id + '")');
  914. }
  915. // find coalesced ttls
  916. var coalesced = $j('.ttl span[property="v:summary"]');
  917. // activate their opener links
  918. for ( var i = 0; i < coalesced.length; i++ )
  919. {
  920. var ttl_span_summary = $j('.ttl span[property="v:summary"]')[i];
  921. var id = ttl_span_summary.parentNode.parentNode.getAttribute('id');
  922. var text = $j('.ttl span[property="v:summary"]')[i].innerHTML;
  923. var html = '<a href="javascript:show_desc(\'' + id + '\')">' + text + '</a>';
  924. $j(ttl_span_summary).html(html);
  925. }
  926. $j('.sd').remove();
  927. }
  928. function show_category_image_under_picker() {
  929. if ( $j.keys(category_images).length == 0 )
  930. return;
  931. if ( ! show_images )
  932. return;
  933. var view = gup('view');
  934. if ( typeof(category_images[view]) != 'undefined' && category_images[view] != blobhost + 'admin/NoCurrentImage.jpg' )
  935. {
  936. var href = location.href;
  937. $j('#category_image')[0].innerHTML = '<img style="width:140px;border-width:thin;border-style:solid" src="' + category_images[view] + '">';
  938. }
  939. else
  940. $j('#category_image')[0].innerHTML = '';
  941. }
  942. /*
  943. function find_sb_left_pct() {
  944. sb_left = $j('#sidebar')[0].getClientRects()[0].left
  945. body_width = $j(window).width();
  946. sb_left_pct = (sb_left / body_width).toString();
  947. var regex = new RegExp( '\\.\\d{2,2}' );
  948. sb_left_pct = regex.exec(sb_left_pct)[0].replace('.','') + '%';
  949. return sb_left_pct;
  950. }
  951. */