Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

1039 wiersze
34 KiB

  1. // Custom page actions
  2. ;(function($){
  3. 'use strict';
  4. window.sandboxTheme = function(){
  5. var $body = $('body'),
  6. eventNames = ['resize', 'scroll', 'ready', 'load', 'sticky'],
  7. readyStates = ['interactive', 'complete'],
  8. trigger_event = function(){
  9. var feature,
  10. featureName,
  11. eventName = typeof arguments[0] !== 'undefined' ? arguments[0] : null;
  12. if ( eventName && $.inArray(eventName, eventNames) !== -1 ) {
  13. // Trigger all features
  14. for ( featureName in sandboxTheme.features ) {
  15. if ( sandboxTheme.features.hasOwnProperty(featureName) ) {
  16. if ( sandboxTheme.info['feature-' + featureName] ) {
  17. feature = sandboxTheme.features[featureName];
  18. if ( feature.hasOwnProperty(eventName) ) {
  19. feature[eventName]();
  20. }
  21. }
  22. }
  23. }
  24. }
  25. },
  26. ready_events_register = function(){
  27. trigger_event('ready');
  28. $(window).on('scroll', function(){
  29. trigger_event('scroll');
  30. });
  31. $(window).on('debouncedresize', function(){
  32. trigger_event('resize');
  33. });
  34. },
  35. setup = function setup(){
  36. var featureName,
  37. feature,
  38. featureOptions,
  39. dataName,
  40. dataValue,
  41. data = arguments[0];
  42. sandboxTheme.info = {};
  43. sandboxTheme.page = {};
  44. if ( $.isPlainObject(data) ) {
  45. for ( dataName in data ) {
  46. if ( data.hasOwnProperty(dataName) ) {
  47. dataValue = dataName === 'id' ? parseInt(data[dataName]) : data[dataName];
  48. if ( dataName !== 'info') {
  49. sandboxTheme.page[dataName] = dataValue;
  50. }
  51. }
  52. }
  53. if ( data.hasOwnProperty('info') ) {
  54. for ( dataName in data.info ) {
  55. if ( data.info.hasOwnProperty(dataName) ) {
  56. sandboxTheme.info[dataName] = data.info[dataName];
  57. }
  58. }
  59. }
  60. }
  61. $.log(data);
  62. // Loop through all features to set all neccessary data
  63. for ( featureName in sandboxTheme.features ) {
  64. if ( sandboxTheme.features.hasOwnProperty(featureName) ) {
  65. feature = sandboxTheme.features[featureName];
  66. // Make a copy of merged page feature options and feature options
  67. // jQuery.extend() will take care for a boolean value of options.page.features[featureName]
  68. featureOptions = $.extend(true, {}, feature.options || {});
  69. // Merge the feature with common feature functions, options and info
  70. $.extend(true, feature, {
  71. options: featureOptions,
  72. info: {
  73. name: featureName,
  74. /**
  75. * Lookup for a hash fragment that starts with the features name
  76. * false if no match is found
  77. */
  78. hash: window.location.hash.length > 0 && window.location.hash.match('^#' + featureName) ? window.location.hash.replace('#' + featureName + '-', '') : false,
  79. }
  80. });
  81. sandboxTheme.info['feature-' + featureName] = Boolean(feature.setup());
  82. }
  83. }
  84. // Execute events
  85. if ( $.inArray(document.readyState, readyStates) !== -1 ) {
  86. ready_events_register();
  87. } else {
  88. $(document).on('DOMContentLoaded readyStates', function(){
  89. ready_events_register();
  90. });
  91. }
  92. $(window).on('load', function(){
  93. trigger_event('load');
  94. });
  95. };
  96. return {
  97. init: function init(){
  98. setup(arguments[0] || null);
  99. },
  100. $body: $body,
  101. is_page: function is_page(){
  102. var id = typeof arguments[0] !== 'undefined' ? parseInt(arguments[0]) : null;
  103. if ( id ) {
  104. return id === sandboxTheme.page.id;
  105. } else {
  106. return sandboxTheme.info.is_page;
  107. }
  108. },
  109. get_page: function get_page(){
  110. var property = typeof arguments[0] === 'string' ? arguments[0] : null;
  111. if ( property ) {
  112. if ( sandboxTheme.page.hasOwnProperty(property) ) {
  113. return sandboxTheme.page[property];
  114. } else {
  115. return 'ERROR: no page property called "' + property + '"';
  116. }
  117. } else {
  118. return sandboxTheme.page;
  119. }
  120. },
  121. trigger: function trigger(eventName){
  122. var eventName = typeof arguments[0] !== 'undefined' ? arguments[0] : null;
  123. if ( eventName && $.inArray(eventName, eventNames) !== -1 ) {
  124. trigger_event(eventName);
  125. }
  126. }
  127. };
  128. }();
  129. sandboxTheme.features = {
  130. /**
  131. * Scrolled
  132. * ========
  133. * Controlls a className to be set, when the page has been scrolled
  134. * Any layout based on this behaviour is at style.css
  135. */
  136. scrolled: {
  137. info: {
  138. isScrolled: false
  139. },
  140. scroll: function scroll(){
  141. if (this.$window.scrollTop() > 100){
  142. if ( !this.info.isScrolled ) {
  143. this.info.isScrolled = true;
  144. sandboxTheme.$body.addClass(this.info.name);
  145. }
  146. } else {
  147. if ( this.info.isScrolled ) {
  148. this.info.isScrolled = false;
  149. sandboxTheme.$body.removeClass(this.info.name);
  150. }
  151. }
  152. },
  153. ready: function ready(){
  154. var scrollTop = 0;
  155. this.$window = $(window);
  156. this.$target = window.location.hash.length > 0 ? $(window.location.hash) : false;
  157. if ( this.$target && this.$target.length > 0 ) {
  158. scrollTop = this.$target.offset().top;
  159. }
  160. $('html, body').scrollTop(scrollTop);
  161. this.scroll();
  162. },
  163. setup: function setup(){
  164. var isSetup = true; //sandboxTheme.info.is_front_page || sandboxTheme.info.is_home || sandboxTheme.info.is_archive;
  165. return isSetup;
  166. }
  167. },
  168. /**
  169. * Forms support
  170. * =============
  171. */
  172. forms: {
  173. options: {
  174. selectors: {
  175. form: '.wpcf7-form',
  176. form_container: '.content, .textwidget',
  177. inputs: '.inputs, .textarea',
  178. input_container: 'p',
  179. label: 'label',
  180. input: 'input'
  181. },
  182. classNames: {
  183. focus: 'focus',
  184. valued: 'valued',
  185. },
  186. },
  187. events: function events(){
  188. var selectors = this.options.selectors,
  189. classNames = this.options.classNames;
  190. this.$forms.each(function(index){
  191. var $form = $(this),
  192. $inputs = $form.find(selectors.input);
  193. $inputs.on('focusin', function(){
  194. $(this).parents(selectors.input_container).addClass(classNames.focus);
  195. });
  196. $inputs.on('focusout', function(){
  197. var $input = $(this),
  198. $input_container = $input.parents(selectors.input_container).first();
  199. $input_container.removeClass(classNames.focus);
  200. if ( $input.val() === '' ) {
  201. if ( $input_container.is('.' + classNames.valued) ) {
  202. $input_container.removeClass(classNames.valued);
  203. }
  204. } else if ( !$input_container.is('.' + classNames.valued) ) {
  205. $input_container.addClass(classNames.valued);
  206. }
  207. });
  208. $form.on('submit', function(){
  209. $inputs.each(function(index){
  210. $(this).parents(selectors.input_container).first().removeClass(classNames.valued);
  211. });
  212. });
  213. });
  214. },
  215. ready: function ready(){
  216. var selectors = this.options.selectors;
  217. this.$forms = $(selectors.form);
  218. this.events();
  219. },
  220. setup: function setup(){
  221. return true;
  222. }
  223. },
  224. /**
  225. * Back to top
  226. * ===========
  227. */
  228. toTop: {
  229. options: {
  230. selectors: {
  231. toTop: '.to-top'
  232. }
  233. },
  234. events: function events(){
  235. $(this.options.selectors.toTop).on('click', function(event){
  236. $.mPageScroll2id('scrollTo', this.hash);
  237. event.preventDefault();
  238. });
  239. },
  240. ready: function ready(){
  241. this.events();
  242. },
  243. setup: function setup(){
  244. return true;
  245. }
  246. },
  247. /**
  248. * Offpage side menu with toggle button
  249. * ====================================
  250. * controls the behaviour of the mobile menu
  251. * Visible on: Viewport lower then 987px
  252. * Look at CSS for Layout
  253. */
  254. sideMenu: {
  255. options: {
  256. outsideOff: true,
  257. selectors: {
  258. container:'#site-actions',
  259. site_menu: '#site-menu > .inner',
  260. source: '#site-menu .menu > li',
  261. blackout: 'body > .blackout',
  262. additional_content: '.header-bar',
  263. logo: '#site-logo',
  264. additional_items: '.add-to-sideMenu',
  265. has_sub_menu: '.menu-item-has-children',
  266. current_item: '.current-menu-item',
  267. current_item_parent: '.current-menu-parent',
  268. current_item_parents: '.current-menu-ancestor',
  269. main: '#main'
  270. },
  271. classNames: {
  272. toggler: 'toggle',
  273. active: 'active',
  274. visible: 'visible',
  275. menu: 'menu',
  276. sub_menu: 'sub-menu',
  277. searcher: 'search',
  278. additional: 'additional',
  279. parentLink: 'sub-menu-parent-link'
  280. }
  281. },
  282. templates:{
  283. toggler: '<a />',
  284. // Animated CSS Bars like svg rect elements
  285. icon: '<div><span></span><span></span><span></span><span></span></div>',
  286. },
  287. info: {},
  288. toggle_sub_menu: function toggle_sub_menu($item){
  289. var active_class = this.options.classNames.toggler + '-' + this.options.classNames.active,
  290. $sub_menu_parent = $item.parent(),
  291. $active_sub_menu_parent = this.$has_sub_menu.filter('.' + active_class);
  292. if ( $active_sub_menu_parent.length > 0 ) {
  293. $active_sub_menu_parent.removeClass(active_class);
  294. $active_sub_menu_parent.children('ul').slideUp(250);
  295. }
  296. if ( !$sub_menu_parent.is($active_sub_menu_parent) ) {
  297. $sub_menu_parent.addClass(active_class);
  298. $sub_menu_parent.children('ul').slideDown(250)
  299. }
  300. },
  301. events: function events(){
  302. var info = this.info,
  303. classNames = this.options.classNames,
  304. selectors = this.options.selectors,
  305. $toggler = this.$toggler,
  306. $sideMenu = this.$sideMenu,
  307. sideMenu = this;
  308. // Toggle menu Off/On Page with toggler
  309. this.$toggler.on('click', function(event){
  310. if ( info.isVisible ) {
  311. $toggler.removeClass(classNames.active);
  312. $sideMenu.removeClass(classNames.visible);
  313. sandboxTheme.$body.removeClass(info.name + '-' + classNames.visible);
  314. info.isVisible = false;
  315. } else {
  316. $toggler.addClass(classNames.active);
  317. $sideMenu.addClass(classNames.visible).find('a').eq(0).trigger('focus');
  318. sandboxTheme.$body.addClass(info.name + '-' + classNames.visible);
  319. info.isVisible = true;
  320. }
  321. event.preventDefault();
  322. });
  323. // Toggle sub_menu Display
  324. this.$has_sub_menu.children('a').on('click', function click(event){
  325. sideMenu.toggle_sub_menu($(this));
  326. event.preventDefault();
  327. });
  328. // Toggle menu Off/On Page with Outside Click
  329. if ( this.options.outsideOff === true ) {
  330. this.$blackout.on('click', function(){
  331. $toggler.trigger('click').trigger('focus');
  332. });
  333. }
  334. },
  335. ready: function ready(){
  336. var options = this.options,
  337. info = this.info,
  338. templates = this.templates,
  339. classNames = options.classNames,
  340. selectors = options.selectors,
  341. sideMenu = this;
  342. this.$container = $(selectors.container);
  343. this.$site_menu = $(selectors.site_menu);
  344. // Get sources
  345. this.$logo = $(selectors.logo).clone().removeAttr('id');
  346. this.$additional_content = $(selectors.additional_content).clone().addClass(classNames.additional).removeAttr('id');
  347. this.$source = $(selectors.source).clone();
  348. // include sources to $sideMenu
  349. this.$source.appendTo(this.$container).wrapAll('<nav class="' + info.name + '" id="' + info.name + '" />').wrapAll('<ul class="' + classNames.menu + '" />');
  350. // Menus
  351. this.$sideMenu = this.$source.parents('#' + info.name);
  352. this.$has_sub_menu = this.$sideMenu.find(selectors.has_sub_menu);
  353. this.$has_sub_menu.each(function(index){
  354. var $sub_menu_parent = $(this),
  355. $sub_menu = $sub_menu_parent.children('ul');
  356. if ( $sub_menu_parent.is(selectors.current_item_parents) ) {
  357. $sub_menu_parent.addClass(classNames.toggler + '-' + classNames.active)
  358. sideMenu.$active_sub_menu_parent = $sub_menu_parent;
  359. } else {
  360. $sub_menu.hide();
  361. }
  362. $sub_menu.prepend($('<li class="' + classNames.parentLink + '" />').prepend($sub_menu.prev('a').clone()))
  363. });
  364. this.$logo.appendTo(this.$sideMenu);
  365. this.$additional_content.appendTo(this.$sideMenu);
  366. // Interactions
  367. this.$toggler = $(templates.toggler).attr('href', '#' + info.name).attr('id', info.name + '-' + classNames.toggler).addClass(info.name + ' ' + classNames.toggler);
  368. this.$toggler.html(templates.icon);
  369. this.$toggler.appendTo(this.$site_menu);
  370. this.$blackout = $(selectors.blackout);
  371. this.events();
  372. //
  373. sandboxTheme.$body.addClass(info.name + '-' + classNames.active);
  374. },
  375. setup: function setup(){
  376. this.info.isVisible = false;
  377. return true;
  378. }
  379. },
  380. /**
  381. * Nicer comments form
  382. * ===================
  383. */
  384. comments: {
  385. options: {
  386. offset: 70,
  387. selectors: {
  388. comments: '#comments',
  389. respond: '#respond',
  390. commentForm: '#commentform',
  391. comment_field: '#comment',
  392. trigger: '.comment-reply-title',
  393. replytocom: '.comment-form-replytocom',
  394. need_login: '.need-login',
  395. }
  396. },
  397. info: {
  398. isTriggered: false
  399. },
  400. events: function events(){
  401. var $trigger = this.$trigger,
  402. $commentForm = this.$commentForm,
  403. $comment_field = this.$comment_field,
  404. $respond = this.$respond,
  405. offset = this.options.offset,
  406. info = this.info;
  407. $trigger.on('click.' + info.name, function(event){
  408. if ( !info.isTriggered ) {
  409. $('body').addClass(info.name + '-visible');
  410. $commentForm.trigger('focusin.' + info.name).slideDown(600, 'swing');
  411. info.isTriggered = true;
  412. } else {
  413. $('body').removeClass(info.name + '-visible');
  414. $commentForm.trigger('blur.' + info.name).slideUp(600, 'swing');
  415. info.isTriggered = false;
  416. }
  417. event.preventDefault();
  418. });
  419. if ( !this.$comments.is(this.options.selectors.replytocom) ){
  420. $commentForm.on('submit', function(){
  421. if ( $comment_field.val() === '' ) {
  422. $comment_field.val('Ohne Begründung');
  423. }
  424. });
  425. }
  426. },
  427. resize: function resize(){},
  428. ready: function ready(){
  429. var selectors = this.options.selectors;
  430. this.$comments = $(selectors.comments);
  431. this.$respond = $(selectors.respond);
  432. this.$commentForm = $(selectors.commentForm).hide();
  433. this.$comment_field = $(selectors.comment_field);
  434. this.$trigger = this.$respond.find(selectors.trigger).not(selectors.need_login);
  435. this.events();
  436. if ( window.location.hash === selectors.respond ) {
  437. this.$trigger.trigger('click');
  438. }
  439. },
  440. setup: function setup(){
  441. return sandboxTheme.info.comments_open && sandboxTheme.info.is_user_logged_in;
  442. }
  443. },
  444. /**
  445. * accordeon
  446. * =========
  447. */
  448. accordeon: {
  449. options: {
  450. speed: 300, // {number} Speed of the slideUp/Down animation
  451. initOpen: 1, // {number} initial accordion to show on page load, 0 = all accordions are closed!
  452. scrollToInitOpen: true, // {boolean} scroll to the open item on init? Only works when initShow is set or a hash opens an item.
  453. scrollToInitOpenOffset: 60, // {number} calulate an extra offset when jumpToInitOpen is true (eg. use with fixed header)
  454. selectors: { // select DOM elements
  455. container: '#content > *', // where to look at accordions
  456. title: '.title',
  457. },
  458. classNames: { // Class names will be mixed with the name space "accordion"
  459. heading: 'heading', // {string} Accordion heading class
  460. trigger: 'trigger', // {string} Accordion open/close trigger class
  461. content: 'content', // {string} Accordion content class
  462. no: 'no', // {string} Accordion leave out class
  463. opened: 'opened', // {string} Accordion is opened
  464. closed: 'closed', // {string} Accordion is closed
  465. enabled: 'enabled',
  466. },
  467. },
  468. templates: {
  469. div: '<div />',
  470. link: '<a href="" />'
  471. },
  472. /**
  473. * Store any dynamic information about your feature here.
  474. *
  475. * @usage
  476. * Use it like the Modernizr object:
  477. *
  478. * if ( this.info.myInfo ) {
  479. * // do stuff
  480. * }
  481. *
  482. * var myInfo = this.info.myInfo
  483. */
  484. info: {
  485. /**
  486. * Index/Count of the accordion items
  487. *
  488. * We increase to 1 before the first accordion is markuped for good readabilty.
  489. * Always remeber that the first element of an array has an index of 0!
  490. */
  491. index: 1
  492. },
  493. events: function events(){
  494. var options = this.options,
  495. selectors = options.selectors,
  496. classNames = options.classNames,
  497. info = this.info,
  498. accordeon = this;
  499. this.$headings.each(function(){
  500. var $heading = $(this),
  501. $accordeon = $heading.parent(), // not guaranteed
  502. $accordeon_content = $heading.next('.' + info.name),
  503. accordeon_id = $heading.is(selectors.title) ? $accordeon.attr('id') : false,
  504. accordeon_content_id = $accordeon_content.attr('id');
  505. $heading.children('a').on('click', function(event){
  506. var scrollTop = $(window).scrollTop();
  507. if ( $heading.is('.' + classNames.opened) ) {
  508. $heading.removeClass(classNames.opened);
  509. $accordeon_content.stop().slideUp(options.speed, function(){
  510. $heading.addClass(classNames.closed);
  511. if ( window.location.hash === '#' + accordeon_id || window.location.hash === '#' + accordeon_content_id ) {
  512. window.location.hash = '';
  513. $(window).scrollTop(scrollTop);
  514. }
  515. });
  516. } else {
  517. $heading.addClass(classNames.opened);
  518. $accordeon_content.stop().slideDown(options.speed, function(){
  519. $heading.removeClass(classNames.closed);
  520. if ( accordeon_id ) {
  521. $accordeon.removeAttr('id');
  522. window.location.hash = accordeon_id;
  523. $accordeon.attr('id', accordeon_id);
  524. } else {
  525. $accordeon_content.removeAttr('id');
  526. window.location.hash = accordeon_content_id;
  527. $accordeon_content.attr('id', accordeon_content_id);
  528. }
  529. });
  530. }
  531. event.preventDefault();
  532. });
  533. });
  534. },
  535. ready: function ready(){
  536. var options = this.options,
  537. selectors = this.options.selectors,
  538. classNames = this.options.classNames,
  539. info = this.info,
  540. templates = this.templates,
  541. $accordeons = $(),
  542. accordeon_ids = [],
  543. open_index = options.initOpen,
  544. location_id = window.location.hash.replace('#', '');
  545. this.$container = $(selectors.container);
  546. this.$headings = this.$container.find('.' + info.name).not('.' + classNames.no + '-' + info.name);
  547. /**
  548. * collect accordeon data
  549. */
  550. this.$headings.each(function(){
  551. var $heading = $(this),
  552. $accordeon = $heading.parent();
  553. if ( $heading.is(selectors.title) ) { // then has no ".inner" div next
  554. $accordeons = $accordeons.add($accordeon);
  555. accordeon_ids.push($accordeon.attr('id'));
  556. }
  557. });
  558. /**
  559. * Set the index of the initial opened accordeon
  560. */
  561. if ( accordeon_ids.indexOf(location_id) >= 0 ) {
  562. open_index = accordeon_ids.indexOf(location_id)+1;
  563. } else if ( info.hash ) {
  564. open_index = info.hash;
  565. if ( accordeon_ids.length > 0 ) {
  566. window.location.hash = accordeon_ids[open_index-1];
  567. }
  568. }
  569. /**
  570. * Generate the accordion items and open the one to show initial or selected by location.hash
  571. *
  572. * Only headings that dont have the 'no-accordion' class and
  573. * have content until the next heading are valid accordion item selectors
  574. */
  575. this.$headings.each(function(){
  576. var $heading = $(this),
  577. $accordeon_content = $heading.nextUntil('.' + info.name);
  578. if ( $accordeon_content.length > 0 ) {
  579. $heading.removeClass(info.name).addClass(info.name + '-' + classNames.heading);
  580. if ( !$heading.is(selectors.title) ) { // then has no ".inner" div next
  581. $heading.wrapInner(templates.link).children('a').attr('href', '#' + info.name + '-' + info.index)
  582. $accordeon_content = $accordeon_content.wrapAll(templates.div);
  583. $accordeon_content.attr('id', info.name + '-' + info.index);
  584. }
  585. $accordeon_content.addClass(info.name);
  586. /**
  587. * the one to open initial
  588. */
  589. if ( open_index === info.index ) {
  590. $heading.addClass(classNames.opened);
  591. /**
  592. * scroll to the opened item?
  593. */
  594. if ( options.initOpen !== open_index && options.scrollToInitOpen ) {
  595. $(window).scrollTop($heading.offset().top-parseInt(options.scrollToInitOpenOffset));
  596. }
  597. } else {
  598. $heading.addClass(classNames.closed);
  599. $accordeon_content.hide();
  600. }
  601. /**
  602. * Count valid accordions
  603. */
  604. info.index++;
  605. }
  606. });
  607. this.$accordeons = $accordeons.length > 0 ? $accordeons : false;
  608. this.info.accordeon_ids = accordeon_ids.length > 0 ? accordeon_ids : false;
  609. this.events();
  610. document.body.classList.add(info.name + '-' + classNames.enabled);
  611. },
  612. setup: function setup(){
  613. if ( this.info.hash ) {
  614. // use hash as initOpen index
  615. this.info.hash = parseInt(this.info.hash);
  616. }
  617. return true; // sandboxTheme.is_page(8); // true on Kurssuche;
  618. }
  619. },
  620. /**
  621. * FAQ navigation
  622. */
  623. content_tabs: {
  624. options: {
  625. selectors: {
  626. tabs: '.tabs'
  627. },
  628. classNames: {
  629. active: 'active'
  630. },
  631. scroll_offset: 45,
  632. scroll_speed: 300,
  633. scrollIntoView: {
  634. behavior: 'auto',
  635. block: 'center',
  636. inline: 'nearest'
  637. }
  638. },
  639. scroll: function(){
  640. var classNames = this.options.classNames,
  641. scroll_top = $(document).scrollTop()+this.options.scroll_offset+20,
  642. $tab_items = this.$tab_items;
  643. $tab_items.each(function(index){
  644. var $tab_item = $(this),
  645. $content = $(this.hash);
  646. if ( $content.position().top <= scroll_top && $content.position().top + $content.height() > scroll_top) {
  647. $tab_items.removeClass(classNames.active);
  648. $tab_item.addClass(classNames.active);
  649. } else {
  650. $tab_item.removeClass(classNames.active);
  651. }
  652. });
  653. },
  654. events: function(){
  655. var options = this.options,
  656. selectors = options.selectors;
  657. this.$tab_items.on('click', function(event){
  658. var $tab_item = $(this);
  659. $('html, body').stop().animate({
  660. scrollTop: $(this.hash).offset().top-parseInt(options.scroll_offset),
  661. }, options.scroll_speed, 'swing');
  662. event.preventDefault();
  663. });
  664. },
  665. ready: function(){
  666. this.$tabs = $(this.options.selectors.tabs);
  667. this.$tab_items = this.$tabs.find('a');
  668. this.events();
  669. },
  670. setup: function(){
  671. return sandboxTheme.info.post_type === 'aktivitaet';
  672. }
  673. },
  674. /**
  675. * FAQ navigation
  676. */
  677. faq_nav: {
  678. options: {
  679. page_slug: 'faqs', // FAQ page slug/permalink
  680. scrollOffset: 60, // {number} calulate an extra offset when scrolling to accordeon
  681. speed: 300,
  682. selectors: {
  683. nav: '.faq-navigation',
  684. menu: '.menu',
  685. sub_menu: '.sub-menu',
  686. has_children: '.menu-item-has-children',
  687. articles: '.articles',
  688. faq_heading: '.title'
  689. },
  690. classNames: {
  691. active: 'active',
  692. closed: 'closed',
  693. opened: 'opened',
  694. },
  695. },
  696. events: function events(){
  697. var options = this.options,
  698. selectors = options.selectors,
  699. classNames = options.classNames;
  700. // submenu open/close
  701. this.$menu.children('li').children('a').on('click', function(event){
  702. var $menu_item = $(this).parent(),
  703. $sub_menu = $(this).next(selectors.sub_menu);
  704. if ( $menu_item.is('.' + classNames.opened) ) {
  705. $menu_item.removeClass(classNames.opened);
  706. $sub_menu.stop().slideUp(options.speed, function(){
  707. $menu_item.addClass(classNames.closed);
  708. });
  709. } else {
  710. $menu_item.addClass(classNames.opened);
  711. $sub_menu.stop().slideDown(options.speed, function(){
  712. $menu_item.removeClass(classNames.closed);
  713. });
  714. }
  715. event.preventDefault();
  716. });
  717. // direct to faq accordions and open on demand
  718. this.$menu.find(selectors.sub_menu).find('a').on('click', function(event){
  719. var $heading = $(this.hash).children(selectors.title),
  720. trigger_index = 0;
  721. $('html, body').stop().animate({
  722. scrollTop: $heading.offset().top-parseInt(options.scrollOffset),
  723. }, options.speed, 'swing', function(){
  724. if ( trigger_index === 0 && !$heading.is('.' + classNames.opened) ) { // gets called twice for html and body
  725. $heading.children('a').trigger('click');
  726. }
  727. trigger_index++;
  728. });
  729. event.preventDefault();
  730. });
  731. },
  732. ready: function ready(){
  733. var selectors = this.options.selectors,
  734. classNames = this.options.classNames,
  735. location_id = window.location.hash.replace('#', ''),
  736. $active_menu_item,
  737. $opend_menu_item,
  738. accordeon = sandboxTheme.features.accordeon;
  739. // sections selection
  740. this.$nav = $(selectors.nav);
  741. this.$menu = this.$nav.find(selectors.menu);
  742. /**
  743. * Set the index of the initial opened accordeon
  744. */
  745. if ( accordeon.info.accordeon_ids && accordeon.info.accordeon_ids.length > 0 && accordeon.info.accordeon_ids.indexOf(location_id) >= 0 ) {
  746. $active_menu_item = this.$menu.find('a[href="' + window.location.hash + '"]');
  747. $opend_menu_item = $active_menu_item.parents('li').last();
  748. } else {
  749. $opend_menu_item = this.$menu.children('li').first();
  750. }
  751. this.$menu.find(selectors.sub_menu).hide().parent('li').addClass(classNames.closed);
  752. // event handling
  753. this.events();
  754. // initiate
  755. $opend_menu_item.children('a').trigger('click');
  756. },
  757. setup: function setup(){
  758. var is_setup = sandboxTheme.get_page('slug') === this.options.page_slug; // only on FAQ page
  759. return is_setup;
  760. }
  761. },
  762. /**
  763. * social widget support
  764. * =====================
  765. */
  766. social: {
  767. options: {
  768. selectors: {
  769. widget: '#social-2',
  770. title: '.title',
  771. list: 'ul',
  772. list_item: 'li'
  773. },
  774. classNames: {
  775. open: 'open',
  776. }
  777. },
  778. info: {
  779. },
  780. events: function events(){
  781. var selectors = this.options.selectors,
  782. classNames = this.options.classNames,
  783. info = this.info,
  784. $list = this.$list,
  785. $body = sandboxTheme.$body;
  786. this.$social.find(selectors.title).on('click', function(event){
  787. // $.log($body.is('.' + info.name + '-' + classNames.open));
  788. if ( $body.is('.' + info.name + '-' + classNames.open) ) {
  789. $body.removeClass(info.name + '-' + classNames.open);
  790. } else {
  791. $body.addClass(info.name + '-' + classNames.open);
  792. }
  793. event.preventDefault();
  794. });
  795. },
  796. ready: function ready(){
  797. this.$social = $(this.options.selectors.widget);
  798. if ( this.$social.length > 0 ) {
  799. this.$list = this.$social.find(this.options.selectors.list);
  800. this.events();
  801. }
  802. },
  803. setup: function setup(){
  804. return sandboxTheme.info.is_single && sandboxTheme.info.post_type === 'alpha_download'; // true on Lernmaterial;
  805. }
  806. },
  807. /**
  808. * Carousel
  809. * ========
  810. */
  811. carousel: {
  812. options: {
  813. classNames:{
  814. prev: 'prev',
  815. next: 'next'
  816. },
  817. selectors: {
  818. container: 'section.slider',
  819. carousel: '.slides',
  820. slides: '.slide',
  821. navigation: '.prev-next'
  822. },
  823. carouFredSel: {
  824. direction: 'up',
  825. height: 'variable',
  826. items: {
  827. visible: 1,
  828. },
  829. scroll: {
  830. easing: 'swing',
  831. fx: 'scroll',
  832. duration: 1000,
  833. pauseOnHover: true,
  834. },
  835. auto: {
  836. play: true,
  837. duration: 2000,
  838. timoutDuration: 5
  839. }
  840. },
  841. texts: {
  842. prev: 'Zur&uuml;ck',
  843. next: 'Vor',
  844. }
  845. },
  846. resize: function resize(){},
  847. get_size: function get_size(){
  848. return {
  849. height: this.$container.parent().height(),
  850. width: this.$container.parent().width()
  851. };
  852. },
  853. set_size: function set_size(){
  854. var scrollDuration = this.options.carouFredSel.scroll.duration,
  855. size = this.get_size();
  856. this.$container.animate({
  857. width: size.width,
  858. height: size.height,
  859. }, {
  860. duration: scrollDuration
  861. });
  862. this.$slides.animate({
  863. width: size.width,
  864. height: size.height,
  865. }, {
  866. duration: scrollDuration
  867. });
  868. },
  869. ready: function ready(){
  870. var selectors = this.options.selectors,
  871. classNames = this.options.classNames,
  872. carousel = this;
  873. this.$container = $('.slider');
  874. this.info.active = this.$container.length > 0;
  875. if ( this.info.active ) {
  876. this.$navigation = $('<div class="' + classNames.prev + '-' + classNames.next + '"></div>');
  877. this.$carousel = this.$container.find(selectors.carousel);
  878. this.$slides = this.$carousel.find(selectors.slides);
  879. $.extend(this.options.carouFredSel, {
  880. pagination: {
  881. container: '.slider-nav',
  882. keys: true,
  883. anchorBuilder: function anchorBuilder(index){
  884. return '<li><a href="#"><span>' + index + '</span></a></li>';
  885. }
  886. },
  887. prev: {
  888. button: function(){
  889. var $prev = $('<a class="' + classNames.prev + '">Zur&uuml;ck</a>');
  890. $prev.appendTo(carousel.$navigation);
  891. return $prev;
  892. }
  893. },
  894. next: {
  895. button: function(){
  896. var $next = $('<a class="' + classNames.next + '">Vor</a>');
  897. $next.appendTo(carousel.$navigation);
  898. return $next;
  899. }
  900. }
  901. });
  902. // Slider Javascript Powered
  903. this.$navigation.appendTo(this.$container);
  904. this.$carousel.carouFredSel(this.options.carouFredSel, {
  905. debug: true
  906. });
  907. }
  908. },
  909. setup: function setup(){
  910. var isSetup = sandboxTheme.info.is_front_page; // || sandboxTheme.info.is_home;
  911. this.info.active = false;
  912. return isSetup;
  913. }
  914. }
  915. };
  916. /**
  917. * Initiate theme actions
  918. *
  919. * merges WP REST API results with theme_data
  920. *
  921. * @object sandboxTheme_data data handed over with wp_localize_script
  922. * @object pageData WP REST API result
  923. *
  924. * @uses sandboxTheme.init() initiates the page theme actions
  925. */
  926. var siteData = $.getJSON(sandboxTheme_data.urls.rest);
  927. siteData.done(function(pageData){
  928. if ( $.isPlainObject(pageData) ) {
  929. sandboxTheme.init($.extend(sandboxTheme_data, pageData));
  930. } else {
  931. sandboxTheme.init(sandboxTheme_data);
  932. }
  933. });
  934. })(jQuery);