1jQuery(document).on('ymapsReady', function () { 2 3 4 ymaps.option.presetStorage.add('custom#museumV', { 5 iconLayout: 'default#image', 6 iconImageHref: 'https://www.lenoblmus.ru/themes/custom/proto/maps/images/voennie.svg', 7 iconImageSize: [30, 34], 8 iconImageOffset: [-3, -42] 9 }); 10 11 ymaps.option.presetStorage.add('custom#museumK', { 12 iconLayout: 'default#image', 13 iconImageHref: 'https://www.lenoblmus.ru/themes/custom/proto/maps/images/kraevedcheskie.svg', 14 iconImageSize: [30, 34], 15 iconImageOffset: [-3, -42] 16 }); 17 ymaps.option.presetStorage.add('custom#museumKRE', { 18 iconLayout: 'default#image', 19 iconImageHref: 'https://www.lenoblmus.ru/themes/custom/proto/maps/images/krepostnie.svg', 20 iconImageSize: [30, 34], 21 iconImageOffset: [-3, -42] 22 }); 23 ymaps.option.presetStorage.add('custom#museumL', { 24 iconLayout: 'default#image', 25 iconImageHref: 'https://www.lenoblmus.ru/themes/custom/proto/maps/images/literaturnie.svg', 26 iconImageSize: [30, 34], 27 iconImageOffset: [-3, -42] 28 }); 29 ymaps.option.presetStorage.add('custom#museumU', { 30 iconLayout: 'default#image', 31 iconImageHref: 'https://www.lenoblmus.ru/themes/custom/proto/maps/images/usadbi.svg', 32 iconImageSize: [30, 34], 33 iconImageOffset: [-3, -42] 34 }); 35 ymaps.option.presetStorage.add('custom#museumH', { 36 iconLayout: 'default#image', 37 iconImageHref: 'https://www.lenoblmus.ru/themes/custom/proto/maps/images/hudozh.png', 38 iconImageSize: [38, 42], 39 iconImageOffset: [-3, -42] 40 }); 41}); 42; 43(function ($, Drupal) { 44 Drupal.behaviors.yandexMaps = { 45 attach: function (context, settings) { 46 if (window.ymaps) { 47 // Fix bug at dynamic load library in ajax request 48 if (!(context instanceof HTMLElement)) { 49 context = document; 50 } 51 52 // Trigger DOM event after ymaps ready. 53 $(document).once('ymapsready').each(function () { 54 ymaps.ready(function () { 55 $(document).trigger('ymapsReady'); 56 }); 57 }); 58 59 var $maps = $('div.yandex-map', context).once('yandex-map'); 60 if ($maps.length) { 61 ymaps.ready(function () { 62 $maps.each(function () { 63 if (!this.id) {
64 this.id = Drupal.yandexMaps.generateMapId(); 65 } 66 Drupal.yandexMaps.mapInit(this.id); 67 }); 68 }); 69 } 70 } 71 } 72 }; 73 74 Drupal.yandexMaps = Drupal.yandexMaps || { 75 data: {}, 76 77 defaultSettings: { 78 center: [0, 0], 79 zoom: 0 80 }, 81 82 /** 83 * Initialize map. 84 */ 85 mapInit: function (mapId, mapSettings) { 86 var dataSettings = Drupal.yandexMaps.getDataSettings(mapId); 87 mapSettings = $.extend({}, Drupal.yandexMaps.defaultSettings, dataSettings, mapSettings); 88 89 if (!drupalSettings.yandexMaps) { 90 drupalSettings.yandexMaps = {}; 91 } 92 93 // Create map 94 var map = Drupal.yandexMaps.createMap(mapId, mapSettings); 95 96 // Set geo objects default options 97 var defaultObjectsOptions = {strokeWidth: 4}; 98 if (drupalSettings.yandexMaps.objectsDefaultPreset) { 99 defaultObjectsOptions.preset = drupalSettings.yandexMaps.objectsDefaultPreset; 100 } 101 if (mapSettings.objectPreset) { 102 defaultObjectsOptions.preset = mapSettings.objectPreset; 103 } 104 map.geoObjects.options.set(defaultObjectsOptions); 105 106 // Add geo objects 107 if (!mapSettings.withoutObjects) { 108 if (mapSettings.objects) { 109 Drupal.yandexMaps.addObject(map, mapSettings.objects, mapSettings.editable, mapSettings.clusterize); 110 } 111 else if (mapSettings.editable) { 112 var objects = $('#' + mapId + ' ~ input[name$="[objects]"]').val(); 113 Drupal.yandexMaps.addObject(map, objects, mapSettings.editable); 114 } 115 } 116 117 // Restore map state from cookie 118 if (mapSettings.saveState && Drupal.yandexMaps.getMapStateFromCookie(mapId)) { 119 var mapState = Drupal.yandexMaps.getMapStateFromCookie(mapId); 120 map.setCenter(mapState.center); 121 map.setZoom(mapState.zoom); 122 } 123 // Auto centering and zooming 124 else { 125 // Auto centering 126 if (mapSettings.autoCentering || !mapSettings.center || (mapSettings.center[0] == 0 && mapSettings.center[1] == 0)) { 127 Drupal.yandexMaps.autoCentering(map); 128 } 129 130 // Auto zooming 131 if (mapSettings.autoZooming || !mapSettings.zoom) { 132 Drupal.yandexMaps.autoZooming(map); 133 } 134 } 135 136 // Editing features 137 if (mapSettings.editable) { 138 Drupal.yandexMaps.addEditButtons(map, mapSettings.objectTypes); 139 map.geoObjects.events.add('remove', Drupal.yandexMaps.objectsChangeHandler); 140 map.events.add('click', Drupal.yandexMaps.mapClickHandler); 141 142 // Select default edit button 143 if (mapSettings.selectedControl) { 144 var edutButton = Drupal.yandexMaps.getEditButton(map, mapSettings.selectedControl); 145 edutButton.events.fire('click'); 146 edutButton.select(); 147 } 148 } 149 150 if (mapSettings.editable || mapSettings.saveState) { 151 map.events.add('boundschange', Drupal.yandexMaps.mapBoundschangeHandler); 152 } 153 154 Drupal.yandexMaps.tweakSearchControl(map); 155 156 $('#' + mapId).trigger('ymapsCreated', [map]); 157 158 return map; 159 }, 160 161 /** 162 * Create map. 163 */ 164 createMap: function (mapId, settings) { 165 var mapState = Drupal.yandexMaps.getMapStateFromSettings(settings); 166 var map = new ymaps.Map(mapId, mapState, settings.options); 167 map.mapId = mapId; 168 169 Drupal.yandexMaps.data[mapId] = { 170 map: map, 171 settings: settings, 172 cursor: null, 173 drawingMode: false 174 }; 175 176 return map; 177 }, 178 179 /** 180 * Return map data-* settings. 181 */ 182 getDataSettings: function (mapId) { 183 var $map = $('#' + mapId); 184 var settings = {}; 185 var arrayTypeSettings = ['center', 'controls', 'behaviors', 'objectTypes']; 186 187 $.each($map.data(), function (attributeKey, attributeValue) { 188 var matches = attributeKey.match(/map(.+)/); 189 if (matches) { 190 var settingKey = matches[1].substring(0, 1).toLowerCase() + matches[1].substring(1); 191 192 if ($.inArray(settingKey, arrayTypeSettings) != -1 && $.type(attributeValue) != 'array') { 193 attributeValue = (attributeValue == '<none>') ? [] : attributeValue.split(','); 194 attributeValue = $.map(attributeValue, $.trim); 195 } 196 // Boolean setting without value, example <div data-map-clusterize> 197 else if (attributeValue === '') { 198 attributeValue = true; 199 } 200 201 settings[settingKey] = attributeValue; 202 } 203 }); 204 205 return settings; 206 }, 207 208 /** 209 * Return default map state from settings. 210 */ 211 getMapStateFromSettings: function (settings) { 212 var state = {}; 213 $.each(['behaviors', 'bounds', 'center', 'controls', 'type', 'zoom'], function (index, stateKey) { 214 if (stateKey in settings) { 215 state[stateKey] = settings[stateKey]; 216 } 217 }); 218 return state; 219 }, 220 221 /** 222 * Return map state from cookie. 223 */ 224 getMapStateFromCookie: function (mapId) { 225 if (!$.cookie) { 226 return; 227 } 228 229 var mapsState = $.cookie('Drupal.visitor.mapsState'); 230 mapsState = mapsState ? JSON.parse(mapsState) : {}; 231 232 if (!mapId) { 233 return mapsState; 234 } 235 else if (mapsState[mapId]) { 236 return mapsState[mapId]; 237 } 238 return; 239 }, 240 241 /** 242 * Save map state to cookie. 243 */ 244 saveMapStateToCookie: function (mapId, mapState) { 245 if (!$.cookie) { 246 return; 247 } 248 249 var mapsState = Drupal.yandexMaps.getMapStateFromCookie(); 250 mapsState[mapId] = mapState;
251 $.cookie('Drupal.visitor.mapsState', JSON.stringify(mapsState), { 252 path: drupalSettings.path.baseUrl, 253 expires: 365 254 }); 255 }, 256 257 /** 258 * Add edit buttons. 259 */ 260 addEditButtons: function (map, buttonTypes) { 261 if (!buttonTypes) return; 262 263 var buttonTitles = { 264 point: Drupal.t('Add point', {}, {context: 'Geometry'}), 265 line: Drupal.t('Add line', {}, {context: 'Geometry'}), 266 polygon: Drupal.t('Add polygone', {}, {context: 'Geometry'}), 267 }; 268 269 var i = 0; 270 $.each(buttonTypes, function (index, buttonType) { 271 var button = new ymaps.control.Button({ 272 data: { 273 image: Drupal.url(drupalSettings.yandexMaps.modulePath) + '/img/icon-' + buttonType + '.svg', 274 title: buttonTitles[buttonType], 275 editButtonType: buttonType // Custom data property 276 } 277 }); 278 button.events.add('click', Drupal.yandexMaps.editButtonClickHandler); 279 map.controls.add(button, {floatIndex: i--}); 280 }); 281 }, 282 283 /** 284 * Return selected edit button. 285 */ 286 getSelectedEditButton: function (map) { 287 var button = null; 288 map.controls.each(function (control) { 289 if (control.data.get('editButtonType') && control.state.get('selected')) { 290 button = control; 291 } 292 }); 293 return button; 294 }, 295 296 /** 297 * Return edit button by type. 298 */ 299 getEditButton: function (map, editButtonType) { 300 var editButton; 301 map.controls.each(function (control) { 302 if (control.data.get('editButtonType') == editButtonType) { 303 editButton = control; 304 } 305 }); 306 return editButton; 307 }, 308 309 /** 310 * Deselect controls. 311 */ 312 deselectControls: function (map) { 313 // Deselect edit buttons 314 map.controls.each(function (control) { 315 if (control.data.get('editButtonType')) { 316 control.deselect(); 317 } 318 }); 319 320 // Deselect ruler 321 var rulerControl = map.controls.get('rulerControl'); 322 if (rulerControl) { 323 rulerControl.deselect(); 324 } 325 }, 326 327 /** 328 * Add geo object. 329 */ 330 addObject: function (map, object, editMode, clusterize) { 331 if (!object) return; 332 333 if ($.type(object) === 'string') { 334 object = JSON.parse(object); 335 } 336 337 var geoQueryResult = ymaps.geoQuery(object); 338 339 // Clusterize placemarks 340 if (clusterize) { 341 var points = geoQueryResult.search('geometry.type = "Point"'); 342 var notPoints = geoQueryResult.search('geometry.type != "Point"'); 343 var clusterer = points.clusterize({ 344 hasHint: false, 345 margin: 15, 346 zoomMargin: 20 347 }); 348 map.geoObjects.add(clusterer); 349 notPoints.addToMap(map); 350 } 351 else { 352 geoQueryResult.addToMap(map); 353 } 354 355 // Enable edit mode 356 if (editMode) { 357 geoQueryResult.addEvents(['mapchange', 'editorstatechange', 'dragend', 'geometrychange'], Drupal.yandexMaps.objectsChangeHandler); 358 geoQueryResult.addEvents('editorstatechange', Drupal.yandexMaps.objectEditorStateChangeHandler); 359 geoQueryResult.addEvents('dblclick', Drupal.yandexMaps.objectsDblclickHandler); 360 geoQueryResult.setOptions({draggable: true}); 361 geoQueryResult.each(function (object) { 362 object.editor.startEditing(); 363 }); 364 } 365 }, 366 367 /** 368 * Add geo object by type. 369 */ 370 addObjectByType: function (map, objectType, geometry, editMode, startDrawing) { 371 var object; 372 373 if (objectType == 'point') { 374 object = new ymaps.Placemark(geometry); 375 } 376 else if (objectType == 'line') { 377 object = new ymaps.Polyline(geometry); 378 } 379 else if (objectType == 'polygon') { 380 object = new ymaps.Polygon(geometry); 381 } 382 383 Drupal.yandexMaps.addObject(map, object, editMode); 384 385 if (startDrawing) { 386 object.editor.startDrawing(); 387 } 388 }, 389 390 /** 391 * Return map.geoObjects in GeoJSON format. 392 */ 393 getObjectsInGeoJson: function (map) { 394 var objects = { 395 type: 'FeatureCollection', 396 features: [] 397 }; 398 map.geoObjects.each(function (object) { 399 var feature = { 400 type: 'Feature', 401 geometry: { 402 type: object.geometry.getType(), 403 coordinates: object.geometry.getCoordinates() 404 } 405 }; 406 objects.features.push(feature); 407 }); 408 return JSON.stringify(objects); 409 }, 410 411 /** 412 * Auto centering map. 413 */ 414 autoCentering: function (map) { 415 if (map.geoObjects.getLength() == 0) { 416 return; 417 } 418 419 var centerAndZoom = ymaps.util.bounds.getCenterAndZoom(map.geoObjects.getBounds(), map.container.getSize()); 420 map.setCenter(centerAndZoom.center); 421 }, 422 423 /** 424 * Auto zooming map. 425 */ 426 autoZooming: function (map) { 427 if (map.geoObjects.getLength() == 0) { 428 return; 429 } 430 431 var mapSize = map.container.getSize(); 432 var centerAndZoom = ymaps.util.bounds.getCenterAndZoom( 433 map.geoObjects.getBounds(), 434 mapSize, 435 ymaps.projection.wgs84Mercator, 436 {margin: 40} 437 ); 438 map.setZoom(centerAndZoom.zoom <= 16 ? centerAndZoom.zoom : 16); 439 }, 440 441 /** 442 * Return new map id. 443 */
444 generateMapId: function (number) { 445 if (!number) number = 1; 446 var mapId = 'yandex-map-' + number; 447 448 if ($('#' + mapId).length > 0) { 449 return Drupal.yandexMaps.generateMapId(number + 1); 450 } 451 452 return mapId; 453 }, 454 455 /** 456 * Return total bounds by bounds collection. 457 */ 458 getTotalBounds: function (boundsCollection) { 459 var totalBounds; 460 461 $.each(boundsCollection, function (index, bounds) { 462 if (!bounds) { 463 return; 464 } 465 if (!totalBounds) { 466 totalBounds = bounds; 467 return; 468 } 469 470 // Min 471 if (totalBounds[0][0] > bounds[0][0]) totalBounds[0][0] = bounds[0][0]; 472 if (totalBounds[0][1] > bounds[0][1]) totalBounds[0][1] = bounds[0][1]; 473 // Max 474 if (totalBounds[1][0] < bounds[1][0]) totalBounds[1][0] = bounds[1][0]; 475 if (totalBounds[1][1] < bounds[1][1]) totalBounds[1][1] = bounds[1][1]; 476 }); 477 478 return totalBounds; 479 }, 480 481 /** 482 * Tweak search control. 483 */ 484 tweakSearchControl: function (map) { 485 var searchControl = map.controls.get('searchControl'); 486 if (searchControl) { 487 // Remove search result placemark after close balloon 488 searchControl.events.add('resultshow', function (event) { 489 var resultIndex = event.get('index'); 490 var result = searchControl.getResultsArray()[resultIndex]; 491 result.balloon.events.add('close', function (event) { 492 searchControl.hideResult(); 493 }); 494 }); 495 } 496 }, 497 498 /** 499 * Change map cursor. 500 */ 501 changeCursor: function (map, cursor) { 502 var cursorAccessor = Drupal.yandexMaps.data[map.mapId].cursor; 503 if (!cursorAccessor || !cursorAccessor.getKey(cursor)) { 504 cursorAccessor = map.cursors.push(cursor); 505 } 506 else { 507 cursorAccessor.setKey(cursor); 508 } 509 }, 510 511 /** 512 * Edit button click handler. 513 */ 514 editButtonClickHandler: function (event) { 515 var button = event.get('target'); 516 var map = button.getMap(); 517 518 if (!button.state.get('selected')) { 519 Drupal.yandexMaps.deselectControls(map); 520 Drupal.yandexMaps.changeCursor(map, 'arrow'); 521 } 522 else { 523 Drupal.yandexMaps.changeCursor(map, 'grab'); 524 } 525 }, 526 527 /** 528 * Object editorstatechange handler. 529 */ 530 objectEditorStateChangeHandler: function (event) { 531 var geoObject = event.get('target'); 532 var map = geoObject.getMap(); 533 if (map) { 534 Drupal.yandexMaps.data[map.mapId].drawingMode = geoObject.editor.state.get('drawing'); 535 } 536 }, 537 538 /** 539 * Objects change handler. 540 */ 541 objectsChangeHandler: function (event) { 542 var geoObject = event.get('target'); 543 var map = geoObject.getMap(); 544 if (map) { 545 var $objectsInput = $('#' + map.mapId + ' ~ input[name$="[objects]"]'); 546 $objectsInput.val(Drupal.yandexMaps.getObjectsInGeoJson(map)); 547 } 548 }, 549 550 /** 551 * Object dblclick handler. 552 */ 553 objectsDblclickHandler: function (event) { 554 var geoObject = event.get('target'); 555 var map = geoObject.getMap(); 556 map.geoObjects.remove(geoObject); 557 event.stopPropagation(); 558 }, 559 560 /** 561 * Map click handler. 562 */ 563 mapClickHandler: function (event) { 564 var map = event.get('target'); 565 var settings = Drupal.yandexMaps.data[map.mapId].settings; 566 var selectedButton = Drupal.yandexMaps.getSelectedEditButton(map); 567 568 if (selectedButton && !Drupal.yandexMaps.data[map.mapId].drawingMode) { 569 if (!settings.multiple) { 570 map.geoObjects.removeAll(); 571 } 572 573 var selectedButtonType = selectedButton.data.get('editButtonType'); 574 var geometry = event.get('coords'); 575 var startDrawing = false; 576 577 if (selectedButtonType == 'line') { 578 geometry = [geometry]; 579 startDrawing = true; 580 } 581 else if (selectedButtonType == 'polygon') { 582 geometry = [[geometry]]; 583 startDrawing = true; 584 } 585 586 Drupal.yandexMaps.addObjectByType(map, selectedButtonType, geometry, true, startDrawing); 587 } 588 }, 589 590 /** 591 * Map boundschange handler. 592 */
593 mapBoundschangeHandler: function (event) { 594 var map = event.get('target'); 595 if (map) { 596 var settings = Drupal.yandexMaps.data[map.mapId].settings; 597 598 if (settings.editable) { 599 $('#' + map.mapId + ' ~ input[name$="[center]"]').val(map.getCenter().join(',')); 600 $('#' + map.mapId + ' ~ input[name$="[zoom]"]').val(map.getZoom()); 601 } 602 603 if (settings.saveState) { 604 Drupal.yandexMaps.saveMapStateToCookie(map.mapId, { 605 center: map.getCenter(), 606 zoom: map.getZoom(), 607 }); 608 } 609 } 610 } 611 }; 612})(jQuery, Drupal); 613; 614/* 615 * Superfish v1.4.8 - jQuery menu widget 616 * Copyright (c) 2008 Joel Birch 617 * 618 * Dual licensed under the MIT and GPL licenses: 619 * http://www.opensource.org/licenses/mit-license.php 620 * http://www.gnu.org/licenses/gpl.html 621 * 622 * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt 623 */ 624/* 625 * This is not the original jQuery Superfish plugin. 626 * Please refer to the README for more information. 627 */ 628 629(function($){ 630 $.fn.superfish = function(op){ 631 var sf = $.fn.superfish, 632 c = sf.c, 633 $arrow = $(['<span class="',c.arrowClass,'"> »</span>'].join('')), 634 over = function(){ 635 var $$ = $(this), menu = getMenu($$); 636 clearTimeout(menu.sfTimer); 637 $$.showSuperfishUl().siblings().hideSuperfishUl(); 638 }, 639 out = function(){ 640 var $$ = $(this), menu = getMenu($$), o = sf.op; 641 clearTimeout(menu.sfTimer); 642 menu.sfTimer=setTimeout(function(){ 643 if ($$.children('.sf-clicked').length == 0){ 644 o.retainPath=($.inArray($$[0],o.$path)>-1); 645 $$.hideSuperfishUl(); 646 if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);} 647 } 648 },o.delay); 649 }, 650 getMenu = function($menu){ 651 var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0]; 652 sf.op = sf.o[menu.serial]; 653 return menu; 654 }, 655 addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); }; 656 657 return this.each(function() { 658 var s = this.serial = sf.o.length; 659 var o = $.extend({},sf.defaults,op); 660 o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels), 661 p = o.$path; 662 for (var l = 0; l < p.length; l++){ 663 p.eq(l).addClass([o.hoverClass,c.bcClass].join(' ')).filter('li:has(ul)').removeClass(o.pathClass); 664 } 665 sf.o[s] = sf.op = o; 666 667 $('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() { 668 if (o.autoArrows) addArrow( $(this).children('a:first-child, span.nolink:first-child') ); 669 }) 670 .not('.'+c.bcClass) 671 .hideSuperfishUl(); 672 673 var $a = $('a, span.nolink',this); 674 $a.each(function(i){ 675 var $li = $a.eq(i).parents('li'); 676 $a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);}); 677 }); 678 o.onInit.call(this); 679 680 }).each(function() { 681 var menuClasses = [c.menuClass]; 682 if (sf.op.dropShadows){ 683 menuClasses.push(c.shadowClass); 684 } 685 $(this).addClass(menuClasses.join(' ')); 686 }); 687 }; 688 689 var sf = $.fn.superfish; 690 sf.o = []; 691 sf.op = {}; 692 693 sf.c = { 694 bcClass: 'sf-breadcrumb', 695 menuClass: 'sf-js-enabled', 696 anchorClass: 'sf-with-ul', 697 arrowClass: 'sf-sub-indicator', 698 shadowClass: 'sf-shadow' 699 }; 700 sf.defaults = { 701 hoverClass: 'sfHover', 702 pathClass: 'overideThisToUse', 703 pathLevels: 1, 704 delay: 800, 705 animation: {opacity:'show'}, 706 speed: 'fast', 707 autoArrows: true, 708 dropShadows: true, 709 disableHI: false, // true disables hoverIntent detection 710 onInit: function(){}, // callback functions 711 onBeforeShow: function(){}, 712 onShow: function(){}, 713 onHide: function(){} 714 }; 715 $.fn.extend({ 716 hideSuperfishUl : function(){ 717 var o = sf.op, 718 not = (o.retainPath===true) ? o.$path : ''; 719 o.retainPath = false; 720 var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass) 721 .children('ul').addClass('sf-hidden'); 722 o.onHide.call($ul); 723 return this; 724 }, 725 showSuperfishUl : function(){ 726 var o = sf.op, 727 sh = sf.c.shadowClass+'-off', 728 $ul = this.addClass(o.hoverClass) 729 .children('ul.sf-hidden').hide().removeClass('sf-hidden'); 730 o.onBeforeShow.call($ul); 731 $ul.animate(o.animation,o.speed,function(){ o.onShow.call($ul); }); 732 return this; 733 } 734 }); 735})(jQuery);; 736/*! 737 * hoverIntent v1.8.0 // 2014.06.29 // jQuery v1.9.1+ 738 * http://cherne.net/brian/resources/jquery.hoverIntent.html 739 * 740 * You may use hoverIntent under the terms of the MIT license. Basically that 741 * means you are free to use hoverIntent as long as this header is left intact. 742 * Copyright 2007, 2014 Brian Cherne 743 */ 744(function($){$.fn.hoverIntent=function(handlerIn,handlerOut,selector){var cfg={interval:100,sensitivity:6,timeout:0};if(typeof handlerIn==="object"){cfg=$.extend(cfg,handlerIn)}else{if($.isFunction(handlerOut)){cfg=$.extend(cfg,{over:handlerIn,out:handlerOut,selector:selector})}else{cfg=$.extend(cfg,{over:handlerIn,out:handlerIn,selector:handlerOut})}}var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if(Math.sqrt((pX-cX)*(pX-cX)+(pY-cY)*(pY-cY))<cfg.sensitivity){$(ob).off("mousemove.hoverIntent",track);ob.hoverIntent_s=true;return cfg.over.apply(ob,[ev])}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=false;return cfg.out.apply(ob,[ev])};var handleHover=function(e){var ev=$.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t)}if(e.type==="mouseenter"){pX=ev.pageX;pY=ev.pageY;$(ob).on("mousemove.hoverIntent",track);if(!ob.hoverIntent_s){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}}else{$(ob).off("mousemove.hoverIntent",track);if(ob.hoverIntent_s){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob)},cfg.timeout)}}};return this.on({"mouseenter.hoverIntent":handleHover,"mouseleave.hoverIntent":handleHover},cfg.selector)}})(jQuery);; 745/* 746 * sf-Smallscreen v1.3b - Provides small-screen compatibility for the jQuery Superfish plugin. 747 * 748 * Developer's note: 749 * Built as a part of the Superfish project for Drupal (http://drupal.org/project/superfish) 750 * Found any bug? have any cool ideas? contact me right away! http://drupal.org/user/619294/contact 751 * 752 * jQuery version: 1.3.x or higher. 753 * 754 * Dual licensed under the MIT and GPL licenses: 755 * http://www.opensource.org/licenses/mit-license.php 756 * http://www.gnu.org/licenses/gpl.html 757 */ 758 759(function($){ 760 $.fn.sfsmallscreen = function(options){ 761 options = $.extend({ 762 mode: 'inactive', 763 type: 'accordion', 764 breakpoint: 768, 765 breakpointUnit: 'px', 766 useragent: '', 767 title: '', 768 addSelected: false, 769 menuClasses: false, 770 hyperlinkClasses: false, 771 excludeClass_menu: '', 772 excludeClass_hyperlink: '', 773 includeClass_menu: '', 774 includeClass_hyperlink: '', 775 accordionButton: 1, 776 expandText: 'Expand', 777 collapseText: 'Collapse' 778 }, options); 779 780 // We need to clean up the menu from anything unnecessary. 781 function refine(menu){ 782 var
783 refined = menu.clone(), 784 // Things that should not be in the small-screen menus. 785 rm = refined.find('span.sf-sub-indicator'), 786 // This is a helper class for those who need to add extra markup that shouldn't exist 787 // in the small-screen versions. 788 rh = refined.find('.sf-smallscreen-remove'), 789 // Mega-menus has to be removed too. 790 mm = refined.find('ul.sf-multicolumn'); 791 for (var a = 0; a < rh.length; a++){ 792 rh.eq(a).replaceWith(rh.eq(a).html()); 793 } 794 if (options.accordionButton == 2 || options.type == 'select'){ 795 for (var b = 0; b < rm.length; b++){ 796 rm.eq(b).remove(); 797 } 798 } 799 if (mm.length > 0){ 800 mm.removeClass('sf-multicolumn'); 801 var ol = refined.find('div.sf-multicolumn-column > ol'); 802 for (var o = 0; o < ol.length; o++){ 803 ol.eq(o).replaceWith('<ul>' + ol.eq(o).html() + '</ul>'); 804 } 805 var elements = ['div.sf-multicolumn-column','.sf-multicolumn-wrapper > ol','li.sf-multicolumn-wrapper']; 806 for (var i = 0; i < elements.length; i++){ 807 obj = refined.find(elements[i]); 808 for (var t = 0; t < obj.length; t++){ 809 obj.eq(t).replaceWith(obj.eq(t).html()); 810 } 811 } 812 refined.find('.sf-multicolumn-column').removeClass('sf-multicolumn-column'); 813 } 814 refined.add(refined.find('*')).css({width:''}); 815 return refined; 816 } 817 818 // Creating <option> elements out of the menu. 819 function toSelect(menu, level){ 820 var 821 items = '', 822 childLI = $(menu).children('li'); 823 for (var a = 0; a < childLI.length; a++){ 824 var list = childLI.eq(a), parent = list.children('a, span'); 825 for (var b = 0; b < parent.length; b++){ 826 var 827 item = parent.eq(b), 828 path = (item.is('a') && !!item.attr('href')) ? item.attr('href') : '', 829 // Class names modification. 830 itemClone = item.clone(), 831 classes = (options.hyperlinkClasses) ? ((options.excludeClass_hyperlink && itemClone.hasClass(options.excludeClass_hyperlink)) ? itemClone.removeClass(options.excludeClass_hyperlink).attr('class') : itemClone.attr('class')) : '', 832 classes = (options.includeClass_hyperlink && !itemClone.hasClass(options.includeClass_hyperlink)) ? ((options.hyperlinkClasses) ? itemClone.addClass(options.includeClass_hyperlink).attr('class') : options.includeClass_hyperlink) : classes; 833 // Retaining the active class if requested. 834 if (options.addSelected && item.hasClass('active')){ 835 classes += ' active'; 836 } 837 classes = (classes) ? ' class="' + classes + '"' : ''; 838 // <option> has to be disabled if the item is not a link. 839 disable = (path == '') || (path == '#') ? ' disabled="disabled"' : '', 840 // Crystal clear. 841 subIndicator = 1 < level ? Array(level).join('-') + ' ' : ''; 842 // Preparing the <option> element. 843 items += '<option value="' + path + '"' + classes + disable + '>' + subIndicator + $.trim(item.text()) +'</option>', 844 childUL = list.find('> ul'); 845 // Using the function for the sub-menu of this item. 846 for (var u = 0; u < childUL.length; u++){ 847 items += toSelect(childUL.eq(u), level + 1); 848 } 849 } 850 } 851 return items; 852 } 853 854 // Create the new version, hide the original. 855 function convert(menu){ 856 var menuID = menu.attr('id'), 857 // Creating a refined version of the menu. 858 refinedMenu = refine(menu); 859 // Currently the plugin provides two reactions to small screens. 860 // Converting the menu to a <select>
860 element, and converting to an accordion version of the menu. 861 if (options.type == 'accordion'){ 862 var 863 toggleID = menuID + '-toggle', 864 accordionID = menuID + '-accordion'; 865 // Making sure the accordion does not exist. 866 if ($('#' + accordionID).length == 0){ 867 var 868 // Getting the style class. 869 styleClass = menu.attr('class').split(' ').filter(function(item){ 870 return item.indexOf('sf-style-') > -1 ? item : ''; 871 }), 872 // Creating the accordion. 873 accordion = $(refinedMenu).attr('id', accordionID); 874 // Removing unnecessary classes. 875 accordion.removeClass('sf-horizontal sf-vertical sf-navbar sf-shadow sf-js-enabled'); 876 // Adding necessary classes. 877 accordion.addClass('sf-accordion sf-hidden'); 878 // Removing style attributes and any unnecessary class. 879 accordion.find('li').each(function(){ 880 $(this).removeAttr('style').removeClass('sfHover').attr('id', $(this).attr('id') + '-accordion'); 881 }); 882 // Doing the same and making sure all the sub-menus are off-screen (hidden). 883 accordion.children('ul').removeAttr('style').not('.sf-hidden').addClass('sf-hidden'); 884 // Creating the accordion toggle switch. 885 var toggle = '<div class="sf-accordion-toggle ' + styleClass + '"><a href="#" id="' + toggleID + '"><span>' + options.title + '</span></a></div>'; 886 887 // Adding Expand\Collapse buttons if requested. 888 if (options.accordionButton == 2){ 889 accordion.addClass('sf-accordion-with-buttons'); 890 var parent = accordion.find('li.menuparent'); 891 for (var i = 0; i < parent.length; i++){ 892 parent.eq(i).prepend('<a href="#" class="sf-accordion-button">' + options.expandText + '</a>'); 893 } 894 } 895 // Inserting the according and hiding the original menu. 896 menu.before(toggle).before(accordion).hide(); 897 898 var 899 accordionElement = $('#' + accordionID), 900 // Deciding what should be used as accordion buttons. 901 buttonElement = (options.accordionButton < 2) ? 'a.menuparent,span.nolink.menuparent' : 'a.sf-accordion-button', 902 button = accordionElement.find(buttonElement); 903 904 // Attaching a click event to the toggle switch. 905 $('#' + toggleID).on('click', function(e){ 906 // Preventing the click. 907 e.preventDefault(); 908 // Adding the sf-expanded class. 909 $(this).toggleClass('sf-expanded'); 910 911 if (accordionElement.hasClass('sf-expanded')){ 912 // If the accordion is already expanded: 913 // Hiding its expanded sub-menus and then the accordion itself as well. 914 accordionElement.add(accordionElement.find('li.sf-expanded')).removeClass('sf-expanded') 915 .end().children('ul').hide() 916 // This is a bit tricky, it's the same trick that has been in use in the main plugin for some time. 917 // Basically we'll add a class that keeps the sub-menu off-screen and still visible, 918 // and make it invisible and removing the class one moment before showing or hiding it. 919 // This helps screen reader software access all the menu items. 920 .end().hide().addClass('sf-hidden').show(); 921 // Changing the caption of any existing accordion buttons to 'Expand'. 922 if (options.accordionButton == 2){ 923 accordionElement.find('a.sf-accordion-button').text(options.expandText); 924 } 925 } 926 else { 927 // But if it's collapsed, 928 accordionElement.addClass('sf-expanded').hide().removeClass('sf-hidden').show(); 929 } 930 }); 931 932 // Attaching a click event to the buttons. 933 button.on('click', function(e){ 934 // Making sure the buttons does not exist already. 935 if ($(this).closest('li').children('ul').length > 0){ 936 e.preventDefault(); 937 // Selecting the parent menu items. 938 var parent = $(this).closest('li'); 939 // Creating and inserting Expand\Collapse buttons to the parent menu items, 940 // of course only if not already happened.
941 if (options.accordionButton == 1 && parent.children('a.menuparent,span.nolink.menuparent').length > 0 && parent.children('ul').children('li.sf-clone-parent').length == 0){ 942 var 943 // Cloning the hyperlink of the parent menu item. 944 cloneLink = parent.children('a.menuparent,span.nolink.menuparent').clone(); 945 // Removing unnecessary classes and element(s). 946 cloneLink.removeClass('menuparent sf-with-ul').children('.sf-sub-indicator').remove(); 947 // Wrapping the hyerplinks in <li>. 948 cloneLink = $('<li class="sf-clone-parent" />').html(cloneLink); 949 // Adding a helper class and attaching them to the sub-menus. 950 parent.children('ul').addClass('sf-has-clone-parent').prepend(cloneLink); 951 } 952 // Once the button is clicked, collapse the sub-menu if it's expanded. 953 if (parent.hasClass('sf-expanded')){ 954 parent.children('ul').slideUp('fast', function(){ 955 // Doing the accessibility trick after hiding the sub-menu. 956 $(this).closest('li').removeClass('sf-expanded').end().addClass('sf-hidden').show(); 957 }); 958 // Changing the caption of the inserted Collapse link to 'Expand', if any is inserted. 959 if (options.accordionButton == 2 && parent.children('.sf-accordion-button').length > 0){ 960 parent.children('.sf-accordion-button').text(options.expandText); 961 } 962 } 963 // Otherwise, expand the sub-menu. 964 else { 965 // Doing the accessibility trick and then showing the sub-menu. 966 parent.children('ul').hide().removeClass('sf-hidden').slideDown('fast') 967 // Changing the caption of the inserted Expand link to 'Collape', if any is inserted. 968 .end().addClass('sf-expanded').children('a.sf-accordion-button').text(options.collapseText) 969 // Hiding any expanded sub-menu of the same level. 970 .end().siblings('li.sf-expanded').children('ul') 971 .slideUp('fast', function(){ 972 // Doing the accessibility trick after hiding it. 973 $(this).closest('li').removeClass('sf-expanded').end().addClass('sf-hidden').show(); 974 }) 975 // Assuming Expand\Collapse buttons do exist, resetting captions, in those hidden sub-menus. 976 .parent().children('a.sf-accordion-button').text(options.expandText); 977 } 978 } 979 }); 980 } 981 } 982 else { 983 var 984 // Class names modification. 985 menuClone = menu.clone(), classes = (options.menuClasses) ? ((options.excludeClass_menu && menuClone.hasClass(options.excludeClass_menu)) ? menuClone.removeClass(options.excludeClass_menu).attr('class') : menuClone.attr('class')) : '', 986 classes = (options.includeClass_menu && !menuClone.hasClass(options.includeClass_menu)) ? ((options.menuClasses) ? menuClone.addClass(options.includeClass_menu).attr('class') : options.includeClass_menu) : classes, 987 classes = (classes) ? ' class="' + classes + '"' : ''; 988 989 // Making sure the <select> element does not exist already. 990 if ($('#' + menuID + '-select').length == 0){ 991 // Creating the <option> elements. 992 var newMenu = toSelect(refinedMenu, 1), 993 // Creating the <select> element and assigning an ID and class name. 994 selectList = $('<select' + classes + ' id="' + menuID + '-select"/>') 995 // Attaching the title and the items to the <select> element. 996 .html('<option>' + options.title + '</option>' + newMenu) 997 // Attaching an event then. 998 .change(function(){ 999 // Except for the first option that is the menu title and not a real menu item. 1000 if ($('option:selected', this).index()){ 1001 window.location = selectList.val(); 1002 } 1003 }); 1004 // Applying the addSelected option to it. 1005 if (options.addSelected){ 1006 selectList.find('.active').attr('selected', !0); 1007 } 1008 // Finally inserting the <select> element into the document then hiding the original menu. 1009 menu.before(selectList).hide(); 1010 } 1011 } 1012 } 1013 1014 // Turn everything back to normal. 1015 function turnBack(menu){ 1016 var 1017 id = '#' + menu.attr('id'); 1018 // Removing the small screen version. 1019 $(id + '-' + options.type).remove(); 1020 // Removing the accordion toggle switch as well. 1021 if (options.type == 'accordion'){ 1022 $(id + '-toggle').parent('div').remove(); 1023 } 1024 // Remove inline CSS display property; less clear than simply using .show(), but respects stylesheet 1025 $(id).css('display', ''); 1026 } 1027
1028 // Return original object to support chaining. 1029 // Although this is unnecessary because of the way the module uses these plugins. 1030 for (var s = 0; s < this.length; s++){ 1031 var 1032 menu = $(this).eq(s), 1033 mode = options.mode; 1034 // The rest is crystal clear, isn't it? :) 1035 if (mode == 'always_active'){ 1036 convert(menu); 1037 } 1038 else if (mode == 'window_width'){ 1039 var breakpoint = (options.breakpointUnit == 'em') ? (options.breakpoint * parseFloat($('body').css('font-size'))) : options.breakpoint, 1040 windowWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth, 1041 timer; 1042 if ((typeof Modernizr === 'undefined' || typeof Modernizr.mq !== 'function') && windowWidth < breakpoint){ 1043 convert(menu); 1044 } 1045 else if (typeof Modernizr !== 'undefined' && typeof Modernizr.mq === 'function' && Modernizr.mq('(max-width:' + (breakpoint - 1) + 'px)')) { 1046 convert(menu); 1047 } 1048 $(window).resize(function(){ 1049 clearTimeout(timer); 1050 timer = setTimeout(function(){ 1051 var windowWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; 1052 if ((typeof Modernizr === 'undefined' || typeof Modernizr.mq !== 'function') && windowWidth < breakpoint){ 1053 convert(menu); 1054 } 1055 else if (typeof Modernizr !== 'undefined' && typeof Modernizr.mq === 'function' && Modernizr.mq('(max-width:' + (breakpoint - 1) + 'px)')) { 1056 convert(menu); 1057 } 1058 else { 1059 turnBack(menu); 1060 } 1061 }, 50); 1062 }); 1063 } 1064 else if (mode == 'useragent_custom'){ 1065 if (options.useragent != ''){ 1066 var ua = RegExp(options.useragent, 'i'); 1067 if (navigator.userAgent.match(ua)){ 1068 convert(menu); 1069 } 1070 } 1071 } 1072 else if (mode == 'useragent_predefined' && navigator.userAgent.match(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i)){ 1073 convert(menu); 1074 } 1075 } 1076 return this; 1077 } 1078})(jQuery); 1079; 1080/* 1081 * Supposition v0.2 - an optional enhancer for Superfish jQuery menu widget. 1082 * 1083 * Copyright (c) 2008 Joel Birch - based mostly on work by Jesse Klaasse and credit goes largely to him. 1084 * Special thanks to Karl Swedberg for valuable input. 1085 * 1086 * Dual licensed under the MIT and GPL licenses: 1087 * http://www.opensource.org/licenses/mit-license.php 1088 * http://www.gnu.org/licenses/gpl.html 1089 */ 1090/* 1091 * This is not the original jQuery Supposition plugin. 1092 * Please refer to the README for more information. 1093 */ 1094 1095(function($){ 1096 $.fn.supposition = function(){ 1097 var $w = $(window), /*do this once instead of every onBeforeShow call*/ 1098 _offset = function(dir) { 1099 return window[dir == 'y' ? 'pageYOffset' : 'pageXOffset'] 1100 || document.documentElement && document.documentElement[dir=='y' ? 'scrollTop' : 'scrollLeft'] 1101 || document.body[dir=='y' ? 'scrollTop' : 'scrollLeft']; 1102 }, 1103 onHide = function(){ 1104 this.css({bottom:''}); 1105 }, 1106 onBeforeShow = function(){ 1107 this.each(function(){ 1108 var $u = $(this); 1109 $u.css('display','block'); 1110 var $mul = $u.closest('.sf-menu'), 1111 level = $u.parents('ul').length, 1112 menuWidth = $u.width(), 1113 menuParentWidth = $u.closest('li').outerWidth(true), 1114 menuParentLeft = $u.closest('li').offset().left, 1115 totalRight = $w.width() + _offset('x'), 1116 menuRight = $u.offset().left + menuWidth, 1117 exactMenuWidth = (menuRight > (menuParentWidth + menuParentLeft)) ? menuWidth - (menuRight - (menuParentWidth + menuParentLeft)) : menuWidth; 1118 if ($u.parents('.sf-js-enabled').hasClass('rtl')) { 1119 if (menuParentLeft < exactMenuWidth) { 1120 if (($mul.hasClass('sf-horizontal') && level == 1) || ($mul.hasClass('sf-navbar') && level == 2)){ 1121 $u.css({left:0,right:'auto'}); 1122 } 1123 else { 1124 $u.css({left:menuParentWidth + 'px',right:'auto'}); 1125 } 1126 } 1127 } 1128 else { 1129 if (menuRight > totalRight && menuParentLeft > menuWidth) { 1130 if (($mul.hasClass('sf-horizontal') && level == 1) || ($mul.hasClass('sf-navbar') && level == 2)){ 1131 $u.css({right:0,left:'auto'}); 1132 } 1133 else { 1134 $u.css({right:menuParentWidth + 'px',left:'auto'}); 1135 } 1136 } 1137 } 1138 var windowHeight = $w.height(), 1139 offsetTop = $u.offset().top, 1140 menuParentShadow = ($mul.hasClass('sf-shadow') && $u.css('padding-bottom').length > 0) ? parseInt($u.css('padding-bottom').slice(0,-2)) : 0, 1141 menuParentHeight = ($mul.hasClass('sf-vertical')) ? '-' + menuParentShadow : $u.parent().outerHeight(true) - menuParentShadow, 1142 menuHeight = $u.height(), 1143 baseline = windowHeight + _offset('y'); 1144 var expandUp = ((offsetTop + menuHeight > baseline) && (offsetTop > menuHeight)); 1145 if (expandUp) { 1146 $u.css({bottom:menuParentHeight + 'px',top:'auto'}); 1147 } 1148 $u.css('display','none'); 1149 }); 1150 }; 1151 1152 return this.each(function() { 1153 var o = $.fn.superfish.o[this.serial]; /* get this menu's options */ 1154 1155 /* if callbacks already set, store them */ 1156 var _onBeforeShow = o.onBeforeShow, 1157 _onHide = o.onHide; 1158 1159 $.extend($.fn.superfish.o[this.serial],{ 1160 onBeforeShow: function() { 1161 onBeforeShow.call(this); /* fire our Supposition callback */ 1162 _onBeforeShow.call(this); /* fire stored callbacks */ 1163 }, 1164 onHide: function() { 1165 onHide.call(this); /* fire our Supposition callback */ 1166 _onHide.call(this); /* fire stored callbacks */ 1167 } 1168 }); 1169 }); 1170 }; 1171})(jQuery);; 1172/* 1173 * Supersubs v0.4b - jQuery plugin 1174 * Copyright (c) 2013 Joel Birch 1175 * 1176 * Dual licensed under the MIT and GPL licenses: 1177 * http://www.opensource.org/licenses/mit-license.php 1178 * http://www.gnu.org/licenses/gpl.html 1179 * 1180 * This plugin automatically adjusts submenu widths of suckerfish-style menus to that of 1181 * their longest list item children. If you use this, please expect bugs and report them 1182 * to the jQuery Google Group with the word 'Superfish' in the subject line. 1183 * 1184 */ 1185/* 1186 * This is not the original jQuery Supersubs plugin. 1187 * Please refer to the README for more information. 1188 */ 1189 1190(function($){ // $ will refer to jQuery within this closure 1191 $.fn.supersubs = function(options){ 1192 var opts = $.extend({}, $.fn.supersubs.defaults, options);
1193 // return original object to support chaining 1194 // Although this is unnecessary due to the way the module uses these plugins. 1195 for (var a = 0; a < this.length; a++) { 1196 // cache selections 1197 var $$ = $(this).eq(a), 1198 // support metadata 1199 o = $.meta ? $.extend({}, opts, $$.data()) : opts; 1200 // Jump one level if it's a "NavBar" 1201 if ($$.hasClass('sf-navbar')) { 1202 $$ = $$.children('li').children('ul'); 1203 } 1204 // cache all ul elements 1205 var $ULs = $$.find('ul'), 1206 // get the font size of menu. 1207 // .css('fontSize') returns various results cross-browser, so measure an em dash instead 1208 fontsize = $('<li id="menu-fontsize">—</li>'), 1209 size = fontsize.attr('style','padding:0;position:absolute;top:-99999em;width:auto;') 1210 .appendTo($$)[0].clientWidth; //clientWidth is faster than width() 1211 // remove em dash 1212 fontsize.remove(); 1213 1214 // loop through each ul in menu 1215 for (var b = 0; b < $ULs.length; b++) { 1216 var 1217 // cache this ul 1218 $ul = $ULs.eq(b); 1219 // If a multi-column sub-menu, and only if correctly configured. 1220 if (o.multicolumn && $ul.hasClass('sf-multicolumn') && $ul.find('.sf-multicolumn-column').length > 0){ 1221 // Look through each column. 1222 var $column = $ul.find('div.sf-multicolumn-column > ol'), 1223 // Overall width. 1224 mwWidth = 0; 1225 for (var d = 0; d < $column.length; d++){ 1226 resize($column.eq(d)); 1227 // New column width, in pixels. 1228 var colWidth = $column.width(); 1229 // Just a trick to convert em unit to px. 1230 $column.css({width:colWidth}) 1231 // Making column parents the same size. 1232 .parents('.sf-multicolumn-column').css({width:colWidth}); 1233 // Overall width. 1234 mwWidth += parseInt(colWidth); 1235 } 1236 // Resizing the columns container too. 1237 $ul.add($ul.find('li.sf-multicolumn-wrapper, li.sf-multicolumn-wrapper > ol')).css({width:mwWidth}); 1238 } 1239 else { 1240 resize($ul); 1241 } 1242 } 1243 } 1244 function resize($ul){ 1245 var 1246 // get all (li) children of this ul 1247 $LIs = $ul.children(), 1248 // get all anchor grand-children 1249 $As = $LIs.children('a'); 1250 // force content to one line and save current float property 1251 $LIs.css('white-space','nowrap'); 1252 // remove width restrictions and floats so elements remain vertically stacked 1253 $ul.add($LIs).add($As).css({float:'none',width:'auto'}); 1254 // this ul will now be shrink-wrapped to longest li due to position:absolute 1255 // so save its width as ems. 1256 var emWidth = $ul.get(0).clientWidth / size; 1257 // add more width to ensure lines don't turn over at certain sizes in various browsers 1258 emWidth += o.extraWidth; 1259 // restrict to at least minWidth and at most maxWidth 1260 if (emWidth > o.maxWidth) {emWidth = o.maxWidth;} 1261 else if (emWidth < o.minWidth) {emWidth = o.minWidth;} 1262 emWidth += 'em'; 1263 // set ul to width in ems 1264 $ul.css({width:emWidth}); 1265 // restore li floats to avoid IE bugs 1266 // set li width to full width of this ul 1267 // revert white-space to normal 1268 $LIs.add($As).css({float:'',width:'',whiteSpace:''}); 1269 // update offset position of descendant ul to reflect new width of parent. 1270 // set it to 100% in case it isn't already set to this in the CSS 1271 for (var c = 0; c < $LIs.length; c++) { 1272 var $childUl = $LIs.eq(c).children('ul'); 1273 var offsetDirection = $childUl.css('left') !== undefined ? 'left' : 'right'; 1274 $childUl.css(offsetDirection,'100%'); 1275 } 1276 } 1277 return this; 1278 }; 1279 // expose defaults 1280 $.fn.supersubs.defaults = { 1281 multicolumn: true, // define width for multi-column sub-menus and their columns. 1282 minWidth: 12, // requires em unit. 1283 maxWidth: 27, // requires em unit. 1284 extraWidth: 1 // extra width can ensure lines don't sometimes turn over due to slight browser differences in how they round-off values 1285 }; 1286})(jQuery); // plugin code ends 1287; 1288/** 1289 * @file 1290 * The Superfish Drupal Behavior to apply the Superfish jQuery plugin to lists. 1291 */ 1292 1293(function ($, Drupal, drupalSettings) { 1294 1295 'use strict'; 1296 1297 /** 1298 * jQuery Superfish plugin. 1299 * 1300 * @type {Drupal~behavior} 1301 * 1302 * @prop {Drupal~behaviorAttach} attach 1303 * Attaches the behavior to an applicable <ul> element. 1304 */ 1305 Drupal.behaviors.superfish = { 1306 attach: function (context, drupalSettings) { 1307 // Take a look at each menu to apply Superfish to. 1308 $.each(drupalSettings.superfish || {}, function (index, options) { 1309 var $menu = $('ul#' + options.id, context); 1310 1311 // Check if we are to apply the Supersubs plug-in to it. 1312 if (options.plugins || false) { 1313 if (options.plugins.supersubs || false) { 1314 $menu.supersubs(options.plugins.supersubs); 1315 } 1316 } 1317 1318 // Apply Superfish to the menu. 1319 $menu.superfish(options.sf); 1320 1321 // Check if we are to apply any other plug-in to it. 1322 if (options.plugins || false) { 1323 if (options.plugins.touchscreen || false) { 1324 $menu.sftouchscreen(options.plugins.touchscreen); 1325 } 1326 if (options.plugins.smallscreen || false) { 1327 $menu.sfsmallscreen(options.plugins.smallscreen); 1328 } 1329 if (options.plugins.supposition || false) { 1330 $menu.supposition(); 1331 } 1332 } 1333 }); 1334 } 1335 }; 1336})(jQuery, Drupal, drupalSettings); 1337; 1338/** 1339 * @file 1340 * better_exposed_filters.js 1341 * 1342 * Provides some client-side functionality for the Better Exposed Filters module. 1343 */ 1344 1345(function ($, Drupal, drupalSettings) { 1346 Drupal.behaviors.betterExposedFilters = { 1347 attach: function (context, settings) { 1348 // Add highlight class to checked checkboxes for better theming. 1349 $('.bef-tree input[type=checkbox], .bef-checkboxes input[type=checkbox]') 1350 // Highlight newly selected checkboxes. 1351 .change(function () { 1352 _bef_highlight(this, context); 1353 }) 1354 .filter(':checked').closest('.form-item', context).addClass('highlight'); 1355 } 1356 }; 1357 1358 /* 1359 * Helper functions 1360 */ 1361 1362 /** 1363 * Adds/Removes the highlight class from the form-item div as appropriate. 1364 */ 1365 function _bef_highlight(elem, context) { 1366 $elem = $(elem, context); 1367 $elem.attr('checked') 1368 ? $elem.closest('.form-item', context).addClass('highlight') 1369 : $elem.closest('.form-item', context).removeClass('highlight'); 1370 } 1371 1372})(jQuery, Drupal, drupalSettings); 1373; 1374/** 1375* DO NOT EDIT THIS FILE. 1376* See the following change record for more information, 1377* https://www.drupal.org/node/2815083 1378* @preserve 1379**/ 1380 1381Drupal.debounce = function (func, wait, immediate) { 1382 var timeout = void 0; 1383 var result = void 0; 1384 return function () { 1385 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 1386 args[_key] = arguments[_key]; 1387 } 1388 1389 var context = this; 1390 var later = function later() { 1391 timeout = null; 1392 if (!immediate) {
1393 result = func.apply(context, args); 1394 } 1395 }; 1396 var callNow = immediate && !timeout; 1397 clearTimeout(timeout); 1398 timeout = setTimeout(later, wait); 1399 if (callNow) { 1400 result = func.apply(context, args); 1401 } 1402 return result; 1403 }; 1404};; 1405/** 1406 * @file 1407 * auto_submit.js 1408 * 1409 * Provides a "form auto-submit" feature for the Better Exposed Filters module. 1410 */ 1411 1412(function ($, Drupal) { 1413 1414 /** 1415 * To make a form auto submit, all you have to do is 3 things:. 1416 * 1417 * Use the "better_exposed_filters/auto_submit" js library. 1418 * 1419 * On gadgets you want to auto-submit when changed, add the 1420 * data-bef-auto-submit attribute. With FAPI, add: 1421 * @code 1422 * '#attributes' => array('data-bef-auto-submit' => ''), 1423 * @endcode 1424 * 1425 * If you want to have auto-submit for every form element, add the 1426 * data-bef-auto-submit-full-form to the form. With FAPI, add: 1427 * @code 1428 * '#attributes' => array('data-bef-auto-submit-full-form' => ''), 1429 * @endcode 1430 * 1431 * If you want to exclude a field from the bef-auto-submit-full-form auto 1432 * submission, add an attribute of data-bef-auto-submit-exclude to the form 1433 * element. With FAPI, add: 1434 * @code 1435 * '#attributes' => array('data-bef-auto-submit-exclude' => ''), 1436 * @endcode 1437 * 1438 * Finally, you have to identify which button you want clicked for autosubmit. 1439 * The behavior of this button will be honored if it's ajaxy or not: 1440 * @code 1441 * '#attributes' => array('data-bef-auto-submit-click' => ''), 1442 * @endcode 1443 * 1444 * Currently only 'select', 'radio', 'checkbox' and 'textfield' types are 1445 * supported. We probably could use additional support for HTML5 input types. 1446 */ 1447 Drupal.behaviors.betterExposedFiltersAutoSubmit = { 1448 attach: function (context) { 1449 // When exposed as a block, the form #attributes are moved from the form 1450 // to the block element, thus the second selector. 1451 // @see \Drupal\block\BlockViewBuilder::preRender 1452 var selectors = 'form[data-bef-auto-submit-full-form], [data-bef-auto-submit-full-form] form, [data-bef-auto-submit]'; 1453 1454 // The change event bubbles so we only need to bind it to the outer form 1455 // in case of a full form, or a single element when specified explicitly. 1456 $(selectors, context).addBack(selectors).each(function (i, e) { 1457 // Store the current form. 1458 var $form = $(e); 1459 1460 // Retrieve the autosubmit delay for this particular form.
1461 var autoSubmitDelay = $form.data('bef-auto-submit-delay') || 500; 1462 1463 // Attach event listeners. 1464 $form.once('bef-auto-submit') 1465 // On change, trigger the submit immediately. 1466 .on('change', triggerSubmit) 1467 // On keyup, wait for a specified number of milliseconds before 1468 // triggering autosubmit. Each new keyup event resets the timer. 1469 .on('keyup', Drupal.debounce(triggerSubmit, autoSubmitDelay)); 1470 }); 1471 1472 /** 1473 * Triggers form autosubmit when conditions are right. 1474 * 1475 * - Checks first that the element that was the target of the triggering 1476 * event is `:text` or `textarea`, but is not `.hasDatePicker`. 1477 * - Checks that the keycode of the keyup was not in the list of ignored 1478 * keys (navigation keys etc). 1479 * 1480 * @param {object} e - The triggering event. 1481 */ 1482 function triggerSubmit(e) { 1483 // e.keyCode: key. 1484 var ignoredKeyCodes = [ 1485 16, // Shift. 1486 17, // Ctrl. 1487 18, // Alt. 1488 20, // Caps lock. 1489 33, // Page up. 1490 34, // Page down. 1491 35, // End. 1492 36, // Home. 1493 37, // Left arrow. 1494 38, // Up arrow. 1495 39, // Right arrow. 1496 40, // Down arrow. 1497 9, // Tab. 1498 13, // Enter. 1499 27 // Esc. 1500 ]; 1501 1502 // Triggering element. 1503 var $target = $(e.target); 1504 var $submit = $target.closest('form').find('[data-bef-auto-submit-click]'); 1505 1506 // Don't submit on changes to excluded elements or a submit element. 1507 if ($target.is('[data-bef-auto-submit-exclude], :submit')) { 1508 return true; 1509 } 1510 1511 // Submit only if this is a non-datepicker textfield and if the 1512 // incoming keycode is not one of the excluded values. 1513 if ( 1514 $target.is(':text:not(.hasDatepicker), textarea') 1515 && $.inArray(e.keyCode, ignoredKeyCodes) === -1 1516 ) { 1517 $submit.click(); 1518 } 1519 // Only trigger submit if a change was the trigger (no keyup). 1520 else if (e.type === 'change') { 1521 $submit.click(); 1522 } 1523 } 1524 } 1525 } 1526 1527}(jQuery, Drupal)); 1528;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.