diff --git a/app/assets/javascripts/space/modaal.js b/app/assets/javascripts/space/modaal.js new file mode 100644 index 0000000..6d4f337 --- /dev/null +++ b/app/assets/javascripts/space/modaal.js @@ -0,0 +1,1390 @@ +/*! + Modaal - accessible modals - v0.4.4 + by Humaan, for all humans. + http://humaan.com + */ +/** + Modaal jQuery Plugin : Accessible Modals + + ==== General Options === + type (string) : ajax, inline, image, iframe, confirm. Defaults to 'inline' + content_source (stribg) : Accepts a string value for your target element, such as '#my-content'. This allows for when trigger element is + an `` link. Not to be confused with the already existing `source` event. + animation (string) : Fade, expand, down, up. Defaults to 'fade' + after_callback_delay (integer) : Specify a delay value for the after open callbacks. This is necessary because with the bundled animations + have a set duration in the bundled CSS. Specify a delay of the same amount as the animation duration in so + more accurately fire the after open/close callbacks. Defaults 350, does not apply if animation is 'none', + after open callbacks are dispatched immediately + + is_locked (boolean) : Set this to true to disable closing the modal via keypress or clicking the background. Beware that if + type != 'confirm' there will be no interface to dismiss the modal if is_locked = true, you'd have to + programmatically arrange to dismiss the modal. Confirm modals are always locked regardless of this option + Defaults to false + + hide_close (boolean) : Set this to true to hide the close modal button. Key press and overlay click will still close the modal. + This method is best used when you want to put a custom close button inside the modal container space. + + background (string) : Background overlay style. Defaults to '#000' + overlay_opacity (float) : Background overlay transparency. Defaults to 0.8 + overlay_close (boolean) : Set this to false if you want to disable click to close on overlay background. + + accessible_title (string) : Accessible title. Default 'Dialog Window' + start_open (boolean) : Set this to true to launch the Modaal window immediately on page open + fullscreen (boolean) : Set this to true to make the modaal fill the entire screen, false will default to own width/height attributes. + custom_class (string) : Fill in this string with a custom class that will be applied to the outer most modal wrapper. + + width (integer) : Desired width of the modal. Required for iframe type. Defaults to undefined //TODO + height (integer) : Desired height of the modal. Required for iframe type. Defaults to undefined //TODO + + background_scroll (boolean) : Set this to true to enable the page to scroll behind the open modal. + + should_open (boolean|function) : Boolean or closure that returns a boolean to determine whether to open the modal or not. + + close_text : String for close button text. Available for localisation and alternative languages to be used. + close_aria_label : String for close button aria-label attribute (value that screen readers will read out). Available for localisation and alternative languages to be used. + + === Events === + before_open (function) : Callback function executed before modal is opened + after_open (function) : Callback function executed after modal is opened + before_close (function) : Callback function executed before modal is closed + after_close (function) : Callback function executed after modal is closed + source (function(element, src)) : Callback function executed on the default source, it is intended to transform the + source (href in an AJAX modal or iframe). The function passes in the triggering element + as well as the default source depending of the modal type. The default output of the + function is an untransformed default source. + + + === Confirm Options & Events === + confirm_button_text (string) : Text on the confirm button. Defaults to 'Confirm' + confirm_cancel_button_text (string) : Text on the confirm modal cancel button. Defaults to 'Cancel' + confirm_title (string) : Title for confirm modal. Default 'Confirm Title' + confirm_content (string) : HTML content for confirm message + confirm_callback (function) : Callback function for when the confirm button is pressed as opposed to cancel + confirm_cancel_callback (function) : Callback function for when the cancel button is pressed + + + === Gallery Options & Events === + gallery_active_class (string) : Active class applied to the currently active image or image slide in a gallery 'gallery_active_item' + outer_controls (boolean) : Set to true to put the next/prev controls outside the Modaal wrapper, at the edges of the browser window. + before_image_change (function) : Callback function executed before the image slide changes in a gallery modal. Default function( current_item, incoming_item ) + after_image_change (function) : Callback function executed after the image slide changes in a gallery modal. Default function ( current_item ) + + + === AJAX Options & Events === + loading_content (string) : HTML content for loading message. Default 'Loading …' + loading_class (string) : Class name to be applied while content is loaded via AJAX. Default 'is_loading' + ajax_error_class (string) : Class name to be applied when content has failed to load. Default is 'modaal-error' + ajax_success (function) : Callback for when AJAX content is loaded in + + + === SOCIAL CONTENT === + instagram_id (string) : Unique photo ID for an Instagram photo. + +*/ +( function( $ ) { + + var modaal_loading_spinner = '
' + + var Modaal = { + init : function(options, elem) { + var self = this; + + self.dom = $('body'); + + self.$elem = $(elem); + self.options = $.extend({}, $.fn.modaal.options, self.$elem.data(), options); + self.xhr = null; + + // set up the scope + self.scope = { + is_open: false, + id: 'modaal_' + ( new Date().getTime() ) + ( Math.random().toString(16).substring(2) ), + source: self.options.content_source ? self.options.content_source : self.$elem.attr('href') + }; + + // add scope attribute to trigger element + self.$elem.attr('data-modaal-scope', self.scope.id); + + // private options + self.private_options = { + active_class: 'is_active' + }; + + self.lastFocus = null; + + // if is_locked + if ( self.options.is_locked || self.options.type == 'confirm' || self.options.hide_close ) { + self.scope.close_btn = ''; + } else { + self.scope.close_btn = ''; + } + + // reset animation_speed + if (self.options.animation === 'none' ){ + self.options.animation_speed = 0; + self.options.after_callback_delay = 0; + } + + // On click to open modal + $(elem).on('click.Modaal', function(e) { + e.preventDefault(); + self.create_modaal(self, e); + }); + + // Define next/prev buttons + if (self.options.outer_controls === true) { + var mod_class = 'outer'; + } else { + var mod_class = 'inner'; + } + self.scope.prev_btn = ''; + self.scope.next_btn = ''; + + // Check for start_open + if (self.options.start_open === true ){ + self.create_modaal( self ); + } + }, + + // Initial create to determine which content type it requires + // ---------------------------------------------------------------- + create_modaal : function(self, e) { + var self = this; + var source; + + // Save last active state before modal + self.lastFocus = self.$elem; + + if ( self.options.should_open === false || ( typeof self.options.should_open === 'function' && self.options.should_open() === false ) ) { + return; + } + + // CB: before_open + self.options.before_open.call(self, e); + + switch (self.options.type) { + case 'inline': + self.create_basic(); + break; + + case 'ajax': + source = self.options.source( self.$elem, self.scope.source ); + self.fetch_ajax( source ); + break; + + case 'confirm': + self.options.is_locked = true; + self.create_confirm(); + break; + + case 'image': + self.create_image(); + break; + + case 'iframe': + source = self.options.source( self.$elem, self.scope.source ); + self.create_iframe( source ); + break; + + case 'video': + self.create_video(self.scope.source); + break; + + case 'instagram': + self.create_instagram(); + break; + } + + // call events to be watched (click, tab, keyup, keydown etc.) + self.watch_events(); + }, + + // Watching Modal + // ---------------------------------------------------------------- + watch_events : function() { + var self = this; + + self.dom.off('click.Modaal keyup.Modaal keydown.Modaal'); + + // Body keydown + self.dom.on('keydown.Modaal', function(e) { + var key = e.keyCode; + var target = e.target; + + // look for tab change and reset focus to modal window + // done in keydown so the check fires repeatedly when you hold the tab key down + if (key == 9 && self.scope.is_open) { + if (!$.contains(document.getElementById(self.scope.id), target) ) { + $('#' + self.scope.id).find('*[tabindex="0"]').focus(); + } + } + }); + + // Body keyup + self.dom.on('keyup.Modaal', function(e) { + var key = e.keyCode; + var target = e.target; + + if ( (e.shiftKey && e.keyCode == 9) && self.scope.is_open) { + // Watch for shift + tab key press. if open shift focus to close button. + if (!$.contains(document.getElementById(self.scope.id), target) ) { + $('#' + self.scope.id).find('.modaal-close').focus(); + } + } + + if ( !self.options.is_locked ){ + // On escape key press close modal + if (key == 27 && self.scope.is_open ) { + if ( $(document.activeElement).is('input:not(:checkbox):not(:radio)') ) { + return false; + } + + self.modaal_close(); + return; + } + } + + // is gallery open and images length is > 1 + if ( self.options.type == 'image' ) { + // arrow left for back + if (key == 37 && self.scope.is_open && (!$('#' + self.scope.id + ' .modaal-gallery-prev').hasClass('is_hidden')) ) { + self.gallery_update('prev'); + } + // arrow right for next + if (key == 39 && self.scope.is_open && (!$('#' + self.scope.id + ' .modaal-gallery-next').hasClass('is_hidden')) ) { + self.gallery_update('next'); + } + return; + } + }); + + // Body click/touch + self.dom.on('click.Modaal', function(e) { + var trigger = $(e.target); + + // General Controls: If it's not locked allow greedy close + if ( !self.options.is_locked ){ + if ( (self.options.overlay_close && trigger.is('.modaal-inner-wrapper')) || trigger.is('.modaal-close') || trigger.closest('.modaal-close').length ) { + self.modaal_close(); + return; + } + } + + //Confirm Controls + if ( trigger.is('.modaal-confirm-btn' ) ){ + // if 'OK' button is clicked, run confirm_callback() + if ( trigger.is('.modaal-ok') ) { + self.options.confirm_callback.call(self, self.lastFocus); + } + + if ( trigger.is('.modaal-cancel') ) { + self.options.confirm_cancel_callback.call(self, self.lastFocus); + } + self.modaal_close(); + return; + } + + // Gallery Controls + if ( trigger.is( '.modaal-gallery-control' ) ){ + // it not active, don't do nuthin! + if ( trigger.hasClass('is_hidden') ) { + return; + } + + // trigger previous + if ( trigger.is('.modaal-gallery-prev') ) { + self.gallery_update('prev'); + } + // trigger next + if ( trigger.is('.modaal-gallery-next') ) { + self.gallery_update('next'); + } + return; + } + }); + }, + + // Append markup into DOM + build_modal : function(content) { + var self = this; + + // if is instagram + var igClass = ''; + if ( self.options.type == 'instagram' ) { + igClass = ' modaal-instagram'; + } + + var wrap_class = (self.options.type == 'video') ? 'modaal-video-wrap' : 'modaal-content'; + + /* + modaal-start_none : fully hidden via display:none; + modaal-start_fade : hidden via opacity:0 + modaal-start_slidedown : ... + + */ + var animation_class; + switch ( self.options.animation ) { + case 'fade' : + animation_class = ' modaal-start_fade'; + break; + case 'slide-down' : + animation_class = ' modaal-start_slidedown'; + break; + default : + animation_class = ' modaal-start_none' + } + + // fullscreen check + var fullscreen_class = ''; + if ( self.options.fullscreen ) { + fullscreen_class = ' modaal-fullscreen'; + } + + // custom class check + if ( self.options.custom_class !== '' || typeof(self.options.custom_class) !== 'undefined' ) { + self.options.custom_class = ' ' + self.options.custom_class; + } + + // if width and heights exists and is typeof number + var dimensionsStyle = ''; + if ( self.options.width && self.options.height && typeof self.options.width == 'number' && typeof self.options.height == 'number' ) { + // if width and height exist, and they are both numbers + dimensionsStyle = ' style="max-width:' + self.options.width + 'px;height:' + self.options.height + 'px;overflow:auto;"'; + } else if ( self.options.width && typeof self.options.width == 'number' ) { + // if only width + dimensionsStyle = ' style="max-width:' + self.options.width + 'px;"'; + } else if ( self.options.height && typeof self.options.height == 'number' ) { + // if only height + dimensionsStyle = ' style="height:' + self.options.height + 'px;overflow:auto;"'; + } + + // Reset dimensions style (width and height) for certain types + if ( self.options.type == 'image' || self.options.type == 'video' || self.options.type == 'instagram' || self.options.fullscreen ) { + dimensionsStyle = ''; + } + + // if is touch + // this is a bug fix for iOS to allow regular click events on div elements. + var touchTrigger = ''; + if ( self.is_touch() ) { + touchTrigger = ' style="cursor:pointer;"' + } + + var build_markup = '
'; + + // hide if video + if (self.options.type != 'video') { + build_markup += '
'; + } + + // add the guts of the content + build_markup += '' + self.scope.close_btn; + + // hide if video + if (self.options.type != 'video') { + build_markup += '
'; + } + + // close off modaal-inner-wrapper + build_markup += '
'; + + // If type is image AND outer_controls is true: add gallery next and previous controls. + if (self.options.type == 'image' && self.options.outer_controls === true) { + build_markup += self.scope.prev_btn + self.scope.next_btn; + } + + // close off modaal-wrapper + build_markup += '
'; + + // append ajax modal markup to dom + if ($('#' + self.scope.id + '_overlay').length < 1) { + self.dom.append(build_markup); + } + + // if inline, clone content into space + if (self.options.type == 'inline') { + content.appendTo('#' + self.scope.id + ' .modaal-content-container'); + } + + // Trigger overlay show (which triggers modal show) + self.modaal_overlay('show'); + }, + + // Create Basic Inline Modal + // ---------------------------------------------------------------- + create_basic : function() { + var self = this; + var target = $(self.scope.source); + var content = ''; + + if (target.length) { + content = target.contents().detach(); + target.empty(); + } else { + content = 'Content could not be loaded. Please check the source and try again.'; + } + + // now push content into markup + self.build_modal(content); + }, + + // Create Instagram Modal + // ---------------------------------------------------------------- + create_instagram : function() { + var self = this; + var id = self.options.instagram_id; + var content = ''; + + var error_msg = 'Instagram photo couldn\'t be loaded, please check the embed code and try again.'; + + self.build_modal('
' + self.options.loading_content + '
' ); + + // ID exists, is not empty null or undefined. + if ( id != '' && id !== null && id !== undefined ) { + // set up oembed url + var ig_url = 'https://api.instagram.com/oembed?url=http://instagr.am/p/' + id + '/'; + + $.ajax({ + url: ig_url, + dataType: "jsonp", + cache: false, + success: function (data) { + + // Create temp dom element from which we'll clone into the modaal instance. This is required to bypass the unusual small thumb issue instagram oembed was serving up + self.dom.append('
' + data.html + '
'); + + // Check if it has loaded once before. + // This is to stop the Embeds.process from throwing and error the first time it's being loaded. + // private_options are individual to a modaal_scope so will not work across multiple scopes when checking if true, only that one item. + if ( self.dom.attr('data-igloaded') ) { + window.instgrm.Embeds.process(); + } else { + // first time it's loaded, let's set a new private option to use next time it's opened. + self.dom.attr('data-igloaded', 'true'); + } + + // now set location for new content + // timeout is required as well to bypass the unusual small thumb issue instagram oembed was serving up + var target = '#' + self.scope.id + ' .modaal-content-container'; + if ( $(target).length > 0) { + setTimeout(function() { + $('#temp-ig').contents().clone().appendTo( target ); + $('#temp-ig').remove(); + }, 1000); + } + + }, + error: function() { + content = error_msg; + + // now set location for new content + var target = $('#' + self.scope.id + ' .modaal-content-container'); + if ( target.length > 0) { + target.removeClass( self.options.loading_class ).addClass( self.options.ajax_error_class ); + target.html(content); + } + } + }); + + } else { + content = error_msg; + } + + return false; + }, + + // Fetch Ajax Data + // ---------------------------------------------------------------- + fetch_ajax : function(url) { + var self = this; + var content = ''; + + // If no accessible title, set it to 'Dialog Window' + if ( self.options.accessible_title == null ) { + self.options.accessible_title = 'Dialog Window' + } + + if ( self.xhr !== null ){ + self.xhr.abort(); + self.xhr = null; + } + + self.build_modal('
' + self.options.loading_content + '
' ); + + self.xhr = $.ajax(url, { + success: function(data) { + // content fetch is successful so push it into markup + var target = $('#' + self.scope.id).find('.modaal-content-container'); + if ( target.length > 0){ + target.removeClass( self.options.loading_class ); + target.html( data ); + + self.options.ajax_success.call(self, target); + } + }, + error: function( xhr ) { + // There were some errors so return an error message + if ( xhr.statusText == 'abort' ){ + return; + } + + var target = $('#' + self.scope.id + ' .modaal-content-container'); + if ( target.length > 0){ + target.removeClass( self.options.loading_class ).addClass( self.options.ajax_error_class ); + target.html( 'Content could not be loaded. Please check the source and try again.' ); + } + } + }); + }, + + // Create Confirm Modal + // ---------------------------------------------------------------- + create_confirm : function() { + var self = this; + var content; + + content = '
' + + '

' + self.options.confirm_title + '

' + + '
' + self.options.confirm_content + '
' + + '
' + + '' + + '' + + '
' + + '
' + + ''; + + // now push content into markup + self.build_modal(content); + }, + + // Create Image/Gallery Modal + // ---------------------------------------------------------------- + create_image : function() { + var self = this; + var content; + + var modaal_image_markup = ''; + var gallery_total; + + // If has group attribute + if ( self.$elem.is('[data-group]') || self.$elem.is('[rel]') ) { + + // find gallery groups + var use_group = self.$elem.is('[data-group]'); + var gallery_group = use_group ? self.$elem.attr('data-group') : self.$elem.attr('rel'); + var gallery_group_items = use_group ? $('[data-group="' + gallery_group + '"]') : $('[rel="' + gallery_group + '"]'); + + // remove any previous active attribute to any in the group + gallery_group_items.removeAttr('data-gallery-active', 'is_active'); + // add active attribute to the item clicked + self.$elem.attr('data-gallery-active', 'is_active'); + + // how many in the grouping are there (-1 to connect with each function starting with 0) + gallery_total = gallery_group_items.length - 1; + + // prepare array for gallery data + var gallery = []; + + // start preparing markup + modaal_image_markup = ''; + + // Add next and previous buttons if outside + if (self.options.outer_controls != true) { + modaal_image_markup += self.scope.prev_btn + self.scope.next_btn; + } + } else { + // This is only a single gallery item so let's grab the necessary values + + // define the source, check if content_source option exists, and use that or fall back to href. + var this_img_src; + var img_src_error = false; + if ( self.$elem.attr('data-modaal-content-source') ) { + this_img_src = self.$elem.attr('data-modaal-content-source'); + } else if ( self.$elem.attr('href') ) { + this_img_src = self.$elem.attr('href'); + } else if ( self.$elem.attr('src') ) { + this_img_src = self.$elem.attr('src'); + } else { + this_img_src = 'trigger requires href or data-modaal-content-source attribute'; + img_src_error = true; + } + + var this_img_alt_txt = ''; + var this_img_alt = ''; + var aria_label = ''; + + if ( self.$elem.attr('data-modaal-desc') ) { + aria_label = self.$elem.attr('data-modaal-desc'); + this_img_alt_txt = self.$elem.attr('data-modaal-desc'); + this_img_alt = ''; + } else { + aria_label = "Image with no description"; + } + + // if image item has source error, output message rather than undefined image + var image_output = img_src_error ? this_img_src : ' '; + + // build up the html + modaal_image_markup = ''; + } + + // Update content variable + content = modaal_image_markup; + + // now push content into markup + self.build_modal(content); + + // setup next & prev buttons + if ( $('.modaal-gallery-item.is_active').is('.gallery-item-0') ) { + $('.modaal-gallery-prev').hide(); + } + if ( $('.modaal-gallery-item.is_active').is('.gallery-item-' + gallery_total) ) { + $('.modaal-gallery-next').hide(); + } + }, + + // Gallery Change Image + // ---------------------------------------------------------------- + gallery_update : function(direction) { + var self = this; + var this_gallery = $('#' + self.scope.id); + var this_gallery_item = this_gallery.find('.modaal-gallery-item'); + var this_gallery_total = this_gallery_item.length - 1; + + // if single item, don't proceed + if ( this_gallery_total == 0 ) { + return false; + } + + var prev_btn = this_gallery.find('.modaal-gallery-prev'), + next_btn = this_gallery.find('.modaal-gallery-next'); + + var duration = 250; + + var new_img_w = 0, + new_img_h = 0; + + // CB: Before image change + var current_item = this_gallery.find( '.modaal-gallery-item.' + self.private_options.active_class ), + incoming_item = ( direction == 'next' ? current_item.next( '.modaal-gallery-item' ) : current_item.prev( '.modaal-gallery-item' ) ); + self.options.before_image_change.call(self, current_item, incoming_item); + + // stop change if at start of end + if ( direction == 'prev' && this_gallery.find('.gallery-item-0').hasClass('is_active') ) { + return false; + } else if ( direction == 'next' && this_gallery.find('.gallery-item-' + this_gallery_total).hasClass('is_active') ) { + return false; + } + + + // lock dimensions + current_item.stop().animate({ + opacity: 0 + }, duration, function(){ + // Move to appropriate image + incoming_item.addClass('is_next').css({ + 'position': 'absolute', + 'display': 'block', + 'opacity': 0 + }); + + // Collect doc width + var doc_width = $(document).width(); + var width_threshold = doc_width > 1140 ? 280 : 50; + + // start toggle to 'is_next' + new_img_w = this_gallery.find('.modaal-gallery-item.is_next').width(); + new_img_h = this_gallery.find('.modaal-gallery-item.is_next').height(); + + var new_natural_w = this_gallery.find('.modaal-gallery-item.is_next img').prop('naturalWidth'); + var new_natural_h = this_gallery.find('.modaal-gallery-item.is_next img').prop('naturalHeight'); + + // if new image is wider than doc width + if ( new_natural_w > (doc_width - width_threshold) ) { + // set new width just below doc width + new_img_w = doc_width - width_threshold; + + // Set temp widths so we can calulate the correct height; + this_gallery.find('.modaal-gallery-item.is_next').css({ 'width': new_img_w }); + this_gallery.find('.modaal-gallery-item.is_next img').css({ 'width': new_img_w }); + + // Set new height variable + new_img_h = this_gallery.find('.modaal-gallery-item.is_next').find('img').height(); + } else { + // new img is not wider than screen, so let's set the new dimensions + new_img_w = new_natural_w; + new_img_h = new_natural_h; + } + + // resize gallery region + this_gallery.find('.modaal-gallery-item-wrap').stop().animate({ + 'width': new_img_w, + 'height': new_img_h + }, duration, function() { + // hide old active image + current_item.removeClass(self.private_options.active_class + ' ' + self.options.gallery_active_class).removeAttr('style'); + current_item.find('img').removeAttr('style'); + + // show new image + incoming_item.addClass(self.private_options.active_class + ' ' + self.options.gallery_active_class).removeClass('is_next').css('position',''); + + // animate in new image (now has the normal is_active class + incoming_item.stop().animate({ + opacity: 1 + }, duration, function(){ + $(this).removeAttr('style').css({ + 'width': '100%' + }); + $(this).find('img').css('width', '100%'); + + // remove dimension lock + this_gallery.find('.modaal-gallery-item-wrap').removeAttr('style'); + + // CB: After image change + self.options.after_image_change.call( self, incoming_item ); + }); + + // Focus on the new gallery item + this_gallery.find('.modaal-gallery-item').removeAttr('tabindex'); + this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class + '').attr('tabindex', '0').focus(); + + // hide/show next/prev + if ( this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-0') ) { + prev_btn.stop().animate({ + opacity: 0 + }, 150, function(){ + $(this).hide(); + }); + } else { + prev_btn.stop().css({ + 'display': 'block', + 'opacity': prev_btn.css('opacity') + }).animate({ + opacity: 1 + }, 150); + } + if ( this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-' + this_gallery_total) ) { + next_btn.stop().animate({ + opacity: 0 + }, 150, function(){ + $(this).hide(); + }); + } else { + next_btn.stop().css({ + 'display': 'block', + 'opacity': prev_btn.css('opacity') + }).animate({ + opacity: 1 + }, 150); + } + }); + }); + }, + + // Create Video Modal + // ---------------------------------------------------------------- + create_video : function(url) { + var self = this; + var content; + + // video markup + content = ''; + + // now push content into markup + self.build_modal('
' + content + '
'); + }, + + // Create iFrame Modal + // ---------------------------------------------------------------- + create_iframe : function(url) { + var self = this; + var content; + + if ( self.options.width !== null || self.options.width !== undefined || self.options.height !== null || self.options.height !== undefined ) { + // video markup + content = ''; + } else { + content = '
Please specify a width and height for your iframe
'; + } + + // now push content into markup + self.build_modal(content); + }, + + // Open Modaal + // ---------------------------------------------------------------- + modaal_open : function() { + var self = this; + var modal_wrapper = $( '#' + self.scope.id ); + var animation_type = self.options.animation; + + if (animation_type === 'none' ){ + modal_wrapper.removeClass('modaal-start_none'); + self.options.after_open.call(self, modal_wrapper); + } + + // Open with fade + if (animation_type === 'fade') { + modal_wrapper.removeClass('modaal-start_fade'); + } + + // Open with slide down + if (animation_type === 'slide-down') { + modal_wrapper.removeClass('modaal-start_slide_down'); + } + + var focusTarget = modal_wrapper; + + // Switch focusTarget tabindex (switch from other modal if exists) + $('.modaal-wrapper *[tabindex=0]').removeAttr('tabindex'); + + if ( self.options.type == 'image' ) { + focusTarget = $('#' + self.scope.id).find('.modaal-gallery-item.' + self.private_options.active_class); + + } else if ( modal_wrapper.find('.modaal-iframe-elem').length ) { + focusTarget = modal_wrapper.find('.modaal-iframe-elem'); + + } else if ( modal_wrapper.find('.modaal-video-wrap').length ) { + focusTarget = modal_wrapper.find('.modaal-video-wrap'); + + } else { + focusTarget = modal_wrapper.find('.modaal-focus'); + + } + + // now set the focus + focusTarget.attr('tabindex', '0').focus(); + + // Run after_open + if (animation_type !== 'none') { + // CB: after_open + setTimeout(function() { + self.options.after_open.call(self, modal_wrapper) + }, self.options.after_callback_delay); + } + }, + + // Close Modal + // ---------------------------------------------------------------- + modaal_close : function() { + var self = this; + var modal_wrapper = $( '#' + self.scope.id ); + + // CB: before_close + self.options.before_close.call(self, modal_wrapper); + + if (self.xhr !== null){ + self.xhr.abort(); + self.xhr = null; + } + + // Now we close the modal + if (self.options.animation === 'none' ){ + modal_wrapper.addClass('modaal-start_none'); + } + + // Close with fade + if (self.options.animation === 'fade') { + modal_wrapper.addClass('modaal-start_fade'); + } + + // Close with slide up (using initial slide down) + if (self.options.animation === 'slide-down') { + modal_wrapper.addClass('modaal-start_slide_down'); + } + + // CB: after_close and remove + setTimeout(function() { + // clone inline content back to origin place + if (self.options.type == 'inline') { + $('#' + self.scope.id + ' .modaal-content-container').contents().detach().appendTo( self.scope.source ) + } + // remove markup from dom + modal_wrapper.remove(); + // CB: after_close + self.options.after_close.call(self); + // scope is now closed + self.scope.is_open = false; + + }, self.options.after_callback_delay); + + // Call overlay hide + self.modaal_overlay('hide'); + + // Roll back to last focus state before modal open. If was closed programmatically, this might not be set + if (self.lastFocus != null) { + self.lastFocus.focus(); + } + }, + + // Overlay control (accepts action for show or hide) + // ---------------------------------------------------------------- + modaal_overlay : function(action) { + var self = this; + + if (action == 'show') { + // Modal is open so update scope + self.scope.is_open = true; + + // set body to overflow hidden if background_scroll is false + if (! self.options.background_scroll) { + self.dom.addClass('modaal-noscroll'); + } + + // append modaal overlay + if ($('#' + self.scope.id + '_overlay').length < 1) { + self.dom.append('
'); + } + + // now show + $('#' + self.scope.id + '_overlay').css('background', self.options.background).stop().animate({ + opacity: self.options.overlay_opacity + }, self.options.animation_speed, function(){ + // now open the modal + self.modaal_open(); + }); + + } else if (action == 'hide') { + + // now hide the overlay + $('#' + self.scope.id + '_overlay').stop().animate({ + opacity: 0 + }, self.options.animation_speed, function(){ + // remove overlay from dom + $(this).remove(); + + // remove body overflow lock + self.dom.removeClass('modaal-noscroll'); + }); + } + }, + + // Check if is touch + // ---------------------------------------------------------------- + is_touch : function() { + return 'ontouchstart' in window || navigator.maxTouchPoints; + } + }; + + // Define default object to store + var modaal_existing_selectors = []; + + // Declare the modaal jQuery method + // ------------------------------------------------------------ + $.fn.modaal = function(options) { + return this.each(function (i) { + var existing_modaal = $(this).data('modaal'); + + if ( existing_modaal ){ + // Checking for string value, used for methods + if (typeof(options) == 'string'){ + switch (options) { + case 'open': + // create the modal + existing_modaal.create_modaal(existing_modaal); + break; + case 'close': + existing_modaal.modaal_close(); + break; + } + } + } else { + // Not a string, so let's setup the modal ready to use + var modaal = Object.create(Modaal); + modaal.init(options, this); + $.data(this, "modaal", modaal); + + // push this select into existing selectors array which is referenced during modaal_dom_observer + modaal_existing_selectors.push({ + 'element': $(this).attr('class'), + 'options': options + }); + } + }); + }; + + // Default options + // ------------------------------------------------------------ + $.fn.modaal.options = { + + //General + type: 'inline', + content_source: null, + animation: 'fade', + animation_speed: 300, + after_callback_delay: 350, + is_locked: false, + hide_close: false, + background: '#000', + overlay_opacity: '0.8', + overlay_close: true, + accessible_title: 'Dialog Window', + start_open: false, + fullscreen: false, + custom_class: '', + background_scroll: false, + should_open: true, + close_text: 'Close', + close_aria_label: 'Close (Press escape to close)', + width: null, + height: null, + + //Events + before_open: function(){}, + after_open: function(){}, + before_close: function(){}, + after_close: function(){}, + source: function( element, src ){ + return src; + }, + + //Confirm Modal + confirm_button_text: 'Confirm', // text on confirm button + confirm_cancel_button_text: 'Cancel', + confirm_title: 'Confirm Title', // title for confirm modal + confirm_content: '

This is the default confirm dialog content. Replace me through the options

', // html for confirm message + confirm_callback: function() {}, + confirm_cancel_callback: function() {}, + + + //Gallery Modal + gallery_active_class: 'gallery_active_item', + outer_controls: false, + before_image_change: function( current_item, incoming_item ) {}, + after_image_change: function( current_item ) {}, + + //Ajax Modal + loading_content: modaal_loading_spinner, + loading_class: 'is_loading', + ajax_error_class: 'modaal-error', + ajax_success: function(){}, + + //Instagram + instagram_id: null + }; + + // Check and Set Inline Options + // ------------------------------------------------------------ + function modaal_inline_options(self) { + + // new empty options + var options = {}; + var inline_options = false; + + // option: type + if ( self.attr('data-modaal-type') ) { + inline_options = true; + options.type = self.attr('data-modaal-type'); + } + + // option: type + if ( self.attr('data-modaal-content-source') ) { + inline_options = true; + options.content_source = self.attr('data-modaal-content-source'); + } + + // option: animation + if ( self.attr('data-modaal-animation') ) { + inline_options = true; + options.animation = self.attr('data-modaal-animation'); + } + + // option: animation_speed + if ( self.attr('data-modaal-animation-speed') ) { + inline_options = true; + options.animation_speed = self.attr('data-modaal-animation-speed'); + } + + // option: after_callback_delay + if ( self.attr('data-modaal-after-callback-delay') ) { + inline_options = true; + options.after_callback_delay = self.attr('data-modaal-after-callback-delay'); + } + + // option: is_locked + if ( self.attr('data-modaal-is-locked') ) { + inline_options = true; + options.is_locked = (self.attr('data-modaal-is-locked') === 'true' ? true : false); + } + + // option: hide_close + if ( self.attr('data-modaal-hide-close') ) { + inline_options = true; + options.hide_close = (self.attr('data-modaal-hide-close') === 'true' ? true : false); + } + + // option: background + if ( self.attr('data-modaal-background') ) { + inline_options = true; + options.background = self.attr('data-modaal-background'); + } + + // option: overlay_opacity + if ( self.attr('data-modaal-overlay-opacity') ) { + inline_options = true; + options.overlay_opacity = self.attr('data-modaal-overlay-opacity'); + } + + // option: overlay_close + if ( self.attr('data-modaal-overlay-close') ) { + inline_options = true; + options.overlay_close = (self.attr('data-modaal-overlay-close') === 'false' ? false : true); + } + + // option: accessible_title + if ( self.attr('data-modaal-accessible-title') ) { + inline_options = true; + options.accessible_title = self.attr('data-modaal-accessible-title'); + } + + // option: start_open + if ( self.attr('data-modaal-start-open') ) { + inline_options = true; + options.start_open = (self.attr('data-modaal-start-open') === 'true' ? true : false); + } + + // option: fullscreen + if ( self.attr('data-modaal-fullscreen') ) { + inline_options = true; + options.fullscreen = (self.attr('data-modaal-fullscreen') === 'true' ? true : false); + } + + // option: custom_class + if ( self.attr('data-modaal-custom-class') ) { + inline_options = true; + options.custom_class = self.attr('data-modaal-custom-class'); + } + + // option: close_text + if ( self.attr('data-modaal-close-text') ) { + inline_options = true; + options.close_text = self.attr('data-modaal-close-text'); + } + + // option: close_aria_label + if ( self.attr('data-modaal-close-aria-label') ) { + inline_options = true; + options.close_aria_label = self.attr('data-modaal-close-aria-label'); + } + + // option: background_scroll + if ( self.attr('data-modaal-background-scroll') ) { + inline_options = true; + options.background_scroll = (self.attr('data-modaal-background-scroll') === 'true' ? true : false); + } + + // option: width + if ( self.attr('data-modaal-width') ) { + inline_options = true; + options.width = parseInt( self.attr('data-modaal-width') ); + } + + // option: height + if ( self.attr('data-modaal-height') ) { + inline_options = true; + options.height = parseInt( self.attr('data-modaal-height') ); + } + + // option: confirm_button_text + if ( self.attr('data-modaal-confirm-button-text') ) { + inline_options = true; + options.confirm_button_text = self.attr('data-modaal-confirm-button-text'); + } + + // option: confirm_cancel_button_text + if ( self.attr('data-modaal-confirm-cancel-button-text') ) { + inline_options = true; + options.confirm_cancel_button_text = self.attr('data-modaal-confirm-cancel-button-text'); + } + + // option: confirm_title + if ( self.attr('data-modaal-confirm-title') ) { + inline_options = true; + options.confirm_title = self.attr('data-modaal-confirm-title'); + } + + // option: confirm_content + if ( self.attr('data-modaal-confirm-content') ) { + inline_options = true; + options.confirm_content = self.attr('data-modaal-confirm-content'); + } + + // option: gallery_active_class + if ( self.attr('data-modaal-gallery-active-class') ) { + inline_options = true; + options.gallery_active_class = self.attr('data-modaal-gallery-active-class'); + } + + // option: loading_content + if ( self.attr('data-modaal-loading-content') ) { + inline_options = true; + options.loading_content = self.attr('data-modaal-loading-content'); + } + + // option: loading_class + if ( self.attr('data-modaal-loading-class') ) { + inline_options = true; + options.loading_class = self.attr('data-modaal-loading-class'); + } + + // option: ajax_error_class + if ( self.attr('data-modaal-ajax-error-class') ) { + inline_options = true; + options.ajax_error_class = self.attr('data-modaal-ajax-error-class'); + } + + // option: start_open + if ( self.attr('data-modaal-instagram-id') ) { + inline_options = true; + options.instagram_id = self.attr('data-modaal-instagram-id'); + } + + // now set it up for the trigger, but only if inline_options is true + if ( inline_options ) { + self.modaal(options); + } + }; + + // On body load (or now, if already loaded), init any modaals defined inline + // Ensure this is done after $.fn.modaal and default options are declared + // ---------------------------------------------------------------- + $(function(){ + + var single_modaal = $('.modaal'); + + // Check for existing modaal elements + if ( single_modaal.length ) { + single_modaal.each(function() { + var self = $(this); + modaal_inline_options(self); + }); + } + + // Obvserve DOM mutations for newly added triggers + var modaal_dom_observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.addedNodes && mutation.addedNodes.length > 0) { + // element added to DOM + var findElement = [].some.call(mutation.addedNodes, function(el) { + var elm = $(el); + if ( elm.is('a') || elm.is('button') ) { + + if ( elm.hasClass('modaal') ) { + // is inline Modaal, initialise options + modaal_inline_options(elm); + } else { + // is not inline modaal. Check for existing selector + modaal_existing_selectors.forEach(function(modaalSelector) { + if ( modaalSelector.element == elm.attr('class') ) { + $(elm).modaal( modaalSelector.options ); + return false; + } + }); + } + + } + }); + } + }); + }); + var observer_config = { + subtree: true, + attributes: true, + childList: true, + characterData: true + }; + + // pass in the target node, as well as the observer options + setTimeout(function() { + modaal_dom_observer.observe(document.body, observer_config); + }, 500); + + }); + +} ( jQuery, window, document ) ); \ No newline at end of file diff --git a/app/assets/javascripts/space/tingle.js b/app/assets/javascripts/space/tingle.js new file mode 100644 index 0000000..5bdf9f3 --- /dev/null +++ b/app/assets/javascripts/space/tingle.js @@ -0,0 +1,443 @@ +/* ! +* tingle.js +* @author robin_parisi +* @version 0.15.2 +* @url +*/ + +/* global define,module */ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + define(factory) + } else if (typeof exports === 'object') { + module.exports = factory() + } else { + root.tingle = factory() + } +}(this, function () { + /* ----------------------------------------------------------- */ + /* == modal */ + /* ----------------------------------------------------------- */ + + var isBusy = false + + function Modal (options) { + var defaults = { + onClose: null, + onOpen: null, + beforeOpen: null, + beforeClose: null, + stickyFooter: false, + footer: false, + cssClass: [], + closeLabel: 'Close', + closeMethods: ['overlay', 'button', 'escape'] + } + + // extends config + this.opts = extend({}, defaults, options) + + // init modal + this.init() + } + + Modal.prototype.init = function () { + if (this.modal) { + return + } + + _build.call(this) + _bindEvents.call(this) + + // insert modal in dom + document.body.appendChild(this.modal, document.body.firstChild) + + if (this.opts.footer) { + this.addFooter() + } + + return this + } + + Modal.prototype._busy = function (state) { + isBusy = state + } + + Modal.prototype._isBusy = function () { + return isBusy + } + + Modal.prototype.destroy = function () { + if (this.modal === null) { + return + } + + // restore scrolling + if (this.isOpen()) { + this.close(true) + } + + // unbind all events + _unbindEvents.call(this) + + // remove modal from dom + this.modal.parentNode.removeChild(this.modal) + + this.modal = null + } + + Modal.prototype.isOpen = function () { + return !!this.modal.classList.contains('tingle-modal--visible') + } + + Modal.prototype.open = function () { + if (this._isBusy()) return + this._busy(true) + + var self = this + + // before open callback + if (typeof self.opts.beforeOpen === 'function') { + self.opts.beforeOpen() + } + + if (this.modal.style.removeProperty) { + this.modal.style.removeProperty('display') + } else { + this.modal.style.removeAttribute('display') + } + + // prevent double scroll + this._scrollPosition = window.pageYOffset + document.body.classList.add('tingle-enabled') + document.body.style.top = -this._scrollPosition + 'px' + + // sticky footer + this.setStickyFooter(this.opts.stickyFooter) + + // show modal + this.modal.classList.add('tingle-modal--visible') + + // onOpen callback + if (typeof self.opts.onOpen === 'function') { + self.opts.onOpen.call(self) + } + + self._busy(false) + + // check if modal is bigger than screen height + this.checkOverflow() + + return this + } + + Modal.prototype.close = function (force) { + if (this._isBusy()) return + this._busy(true) + force = force || false + + // before close + if (typeof this.opts.beforeClose === 'function') { + var close = this.opts.beforeClose.call(this) + if (!close) { + this._busy(false) + return + } + } + + document.body.classList.remove('tingle-enabled') + document.body.style.top = null + window.scrollTo({ + top: this._scrollPosition, + behavior: 'instant' + }) + + this.modal.classList.remove('tingle-modal--visible') + + // using similar setup as onOpen + var self = this + + self.modal.style.display = 'none' + + // onClose callback + if (typeof self.opts.onClose === 'function') { + self.opts.onClose.call(this) + } + + // release modal + self._busy(false) + } + + Modal.prototype.setContent = function (content) { + // check type of content : String or Node + if (typeof content === 'string') { + this.modalBoxContent.innerHTML = content + } else { + this.modalBoxContent.innerHTML = '' + this.modalBoxContent.appendChild(content) + } + + if (this.isOpen()) { + // check if modal is bigger than screen height + this.checkOverflow() + } + + return this + } + + Modal.prototype.getContent = function () { + return this.modalBoxContent + } + + Modal.prototype.addFooter = function () { + // add footer to modal + _buildFooter.call(this) + + return this + } + + Modal.prototype.setFooterContent = function (content) { + // set footer content + this.modalBoxFooter.innerHTML = content + + return this + } + + Modal.prototype.getFooterContent = function () { + return this.modalBoxFooter + } + + Modal.prototype.setStickyFooter = function (isSticky) { + // if the modal is smaller than the viewport height, we don't need sticky + if (!this.isOverflow()) { + isSticky = false + } + + if (isSticky) { + if (this.modalBox.contains(this.modalBoxFooter)) { + this.modalBox.removeChild(this.modalBoxFooter) + this.modal.appendChild(this.modalBoxFooter) + this.modalBoxFooter.classList.add('tingle-modal-box__footer--sticky') + _recalculateFooterPosition.call(this) + this.modalBoxContent.style['padding-bottom'] = this.modalBoxFooter.clientHeight + 20 + 'px' + } + } else if (this.modalBoxFooter) { + if (!this.modalBox.contains(this.modalBoxFooter)) { + this.modal.removeChild(this.modalBoxFooter) + this.modalBox.appendChild(this.modalBoxFooter) + this.modalBoxFooter.style.width = 'auto' + this.modalBoxFooter.style.left = '' + this.modalBoxContent.style['padding-bottom'] = '' + this.modalBoxFooter.classList.remove('tingle-modal-box__footer--sticky') + } + } + + return this + } + + Modal.prototype.addFooterBtn = function (label, cssClass, callback) { + var btn = document.createElement('button') + + // set label + btn.innerHTML = label + + // bind callback + btn.addEventListener('click', callback) + + if (typeof cssClass === 'string' && cssClass.length) { + // add classes to btn + cssClass.split(' ').forEach(function (item) { + btn.classList.add(item) + }) + } + + this.modalBoxFooter.appendChild(btn) + + return btn + } + + Modal.prototype.resize = function () { + // eslint-disable-next-line no-console + console.warn('Resize is deprecated and will be removed in version 1.0') + } + + Modal.prototype.isOverflow = function () { + var viewportHeight = window.innerHeight + var modalHeight = this.modalBox.clientHeight + + return modalHeight >= viewportHeight + } + + Modal.prototype.checkOverflow = function () { + // only if the modal is currently shown + if (this.modal.classList.contains('tingle-modal--visible')) { + if (this.isOverflow()) { + this.modal.classList.add('tingle-modal--overflow') + } else { + this.modal.classList.remove('tingle-modal--overflow') + } + + // tODO: remove offset + // _offset.call(this); + if (!this.isOverflow() && this.opts.stickyFooter) { + this.setStickyFooter(false) + } else if (this.isOverflow() && this.opts.stickyFooter) { + _recalculateFooterPosition.call(this) + this.setStickyFooter(true) + } + } + } + + /* ----------------------------------------------------------- */ + /* == private methods */ + /* ----------------------------------------------------------- */ + + function closeIcon () { + return '' + } + + function _recalculateFooterPosition () { + if (!this.modalBoxFooter) { + return + } + this.modalBoxFooter.style.width = this.modalBox.clientWidth + 'px' + this.modalBoxFooter.style.left = this.modalBox.offsetLeft + 'px' + } + + function _build () { + // wrapper + this.modal = document.createElement('div') + this.modal.classList.add('tingle-modal') + + // remove cusor if no overlay close method + if (this.opts.closeMethods.length === 0 || this.opts.closeMethods.indexOf('overlay') === -1) { + this.modal.classList.add('tingle-modal--noOverlayClose') + } + + this.modal.style.display = 'none' + + // custom class + this.opts.cssClass.forEach(function (item) { + if (typeof item === 'string') { + this.modal.classList.add(item) + } + }, this) + + // close btn + if (this.opts.closeMethods.indexOf('button') !== -1) { + this.modalCloseBtn = document.createElement('button') + this.modalCloseBtn.type = 'button' + this.modalCloseBtn.classList.add('tingle-modal__close') + + this.modalCloseBtnIcon = document.createElement('span') + this.modalCloseBtnIcon.classList.add('tingle-modal__closeIcon') + this.modalCloseBtnIcon.innerHTML = closeIcon() + + this.modalCloseBtnLabel = document.createElement('span') + this.modalCloseBtnLabel.classList.add('tingle-modal__closeLabel') + this.modalCloseBtnLabel.innerHTML = this.opts.closeLabel + + this.modalCloseBtn.appendChild(this.modalCloseBtnIcon) + this.modalCloseBtn.appendChild(this.modalCloseBtnLabel) + } + + // modal + this.modalBox = document.createElement('div') + this.modalBox.classList.add('tingle-modal-box') + + // modal box content + this.modalBoxContent = document.createElement('div') + this.modalBoxContent.classList.add('tingle-modal-box__content') + + this.modalBox.appendChild(this.modalBoxContent) + + if (this.opts.closeMethods.indexOf('button') !== -1) { + this.modal.appendChild(this.modalCloseBtn) + } + + this.modal.appendChild(this.modalBox) + } + + function _buildFooter () { + this.modalBoxFooter = document.createElement('div') + this.modalBoxFooter.classList.add('tingle-modal-box__footer') + this.modalBox.appendChild(this.modalBoxFooter) + } + + function _bindEvents () { + this._events = { + clickCloseBtn: this.close.bind(this), + clickOverlay: _handleClickOutside.bind(this), + resize: this.checkOverflow.bind(this), + keyboardNav: _handleKeyboardNav.bind(this) + } + + if (this.opts.closeMethods.indexOf('button') !== -1) { + this.modalCloseBtn.addEventListener('click', this._events.clickCloseBtn) + } + + this.modal.addEventListener('mousedown', this._events.clickOverlay) + window.addEventListener('resize', this._events.resize) + document.addEventListener('keydown', this._events.keyboardNav) + } + + function _handleKeyboardNav (event) { + // escape key + if (this.opts.closeMethods.indexOf('escape') !== -1 && event.which === 27 && this.isOpen()) { + this.close() + } + } + + function _handleClickOutside (event) { + // on macOS, click on scrollbar (hidden mode) will trigger close event so we need to bypass this behavior by detecting scrollbar mode + var scrollbarWidth = this.modal.offsetWidth - this.modal.clientWidth + var clickedOnScrollbar = event.clientX >= this.modal.offsetWidth - 15 // 15px is macOS scrollbar default width + var isScrollable = this.modal.scrollHeight !== this.modal.offsetHeight + if (navigator.platform === 'MacIntel' && scrollbarWidth === 0 && clickedOnScrollbar && isScrollable) { + return + } + + // if click is outside the modal + if (this.opts.closeMethods.indexOf('overlay') !== -1 && !_findAncestor(event.target, 'tingle-modal') && + event.clientX < this.modal.clientWidth) { + this.close() + } + } + + function _findAncestor (el, cls) { + while ((el = el.parentElement) && !el.classList.contains(cls)); + return el + } + + function _unbindEvents () { + if (this.opts.closeMethods.indexOf('button') !== -1) { + this.modalCloseBtn.removeEventListener('click', this._events.clickCloseBtn) + } + this.modal.removeEventListener('mousedown', this._events.clickOverlay) + window.removeEventListener('resize', this._events.resize) + document.removeEventListener('keydown', this._events.keyboardNav) + } + + /* ----------------------------------------------------------- */ + /* == helpers */ + /* ----------------------------------------------------------- */ + + function extend () { + for (var i = 1; i < arguments.length; i++) { + for (var key in arguments[i]) { + if (arguments[i].hasOwnProperty(key)) { + arguments[0][key] = arguments[i][key] + } + } + } + return arguments[0] + } + + /* ----------------------------------------------------------- */ + /* == return */ + /* ----------------------------------------------------------- */ + + return { + modal: Modal + } +})) diff --git a/app/assets/stylesheets/space-frontend.scss b/app/assets/stylesheets/space-frontend.scss index 5017dae..792403c 100644 --- a/app/assets/stylesheets/space-frontend.scss +++ b/app/assets/stylesheets/space-frontend.scss @@ -6,6 +6,7 @@ display: flex; align-items: center; justify-content: center; + outline: 0; } .s-space.show-space .selection-box-label{ display: none; @@ -14,6 +15,13 @@ font-size: 8vw; position: relative; } +.popup{ + color: inherit !important; + margin-left: 2em; + @media (min-width: $screen-sm) { + display: none; + } +} .anchor{ position: absolute; left: 0.2em; @@ -32,13 +40,14 @@ left: 0%; background: #2196F3; color: white; - width: 650%; + width: 8em; + width: max-content; + min-width: 4em; padding: 0.2em; - font-size: 0.6em; - @media (min-width: $screen-sm) { - width: 450%; - font-size: 0.3em; - } + font-size: 0.8em; +} +a.s-space__pin-link{ + position: relative; } #full-layout-canvas { text-align: center; diff --git a/app/assets/stylesheets/space/modaal.css b/app/assets/stylesheets/space/modaal.css new file mode 100644 index 0000000..16a2920 --- /dev/null +++ b/app/assets/stylesheets/space/modaal.css @@ -0,0 +1,782 @@ +/*! + Modaal - accessible modals - v0.4.4 + by Humaan, for all humans. + http://humaan.com + */ + +.modaal-noscroll { + overflow: hidden; +} + +.modaal-accessible-hide { + position: absolute !important; + clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ + clip: rect(1px, 1px, 1px, 1px); + padding: 0 !important; + border: 0 !important; + height: 1px !important; + width: 1px !important; + overflow: hidden; +} + +.modaal-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999; + opacity: 0; +} + +.modaal-wrapper { + display: block; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 9999; + overflow: auto; + opacity: 1; + box-sizing: border-box; + -webkit-overflow-scrolling: touch; + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; +} + +.modaal-wrapper * { + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-backface-visibility: hidden; +} + +.modaal-wrapper .modaal-close { + border: none; + background: transparent; + padding: 0; + -webkit-appearance: none; +} + +.modaal-wrapper.modaal-start_none { + display: none; + opacity: 1; +} + +.modaal-wrapper.modaal-start_fade { + opacity: 0; +} + +.modaal-wrapper *[tabindex="0"] { + outline: none !important; +} + +.modaal-wrapper.modaal-fullscreen { + overflow: hidden; +} + +.modaal-outer-wrapper { + display: table; + position: relative; + width: 100%; + height: 100%; +} + +.modaal-fullscreen .modaal-outer-wrapper { + display: block; +} + +.modaal-inner-wrapper { + display: table-cell; + width: 100%; + height: 100%; + position: relative; + vertical-align: middle; + text-align: center; + padding: 80px 25px; +} + +.modaal-fullscreen .modaal-inner-wrapper { + padding: 0; + display: block; + vertical-align: top; +} + +.modaal-container { + position: relative; + display: inline-block; + width: 100%; + margin: auto; + text-align: left; + color: #000; + max-width: 1000px; + border-radius: 0px; + background: #fff; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); + cursor: auto; +} + +.modaal-container.is_loading { + height: 100px; + width: 100px; + overflow: hidden; +} + +.modaal-fullscreen .modaal-container { + max-width: none; + height: 100%; + overflow: auto; +} + +.modaal-close { + position: fixed; + right: 20px; + top: 20px; + color: #fff; + cursor: pointer; + opacity: 1; + width: 50px; + height: 50px; + background: rgba(0, 0, 0, 0); + border-radius: 100%; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +.modaal-close:focus, +.modaal-close:hover { + outline: none; + background: #fff; +} + +.modaal-close:focus:before, +.modaal-close:focus:after, +.modaal-close:hover:before, +.modaal-close:hover:after { + background: #b93d0c; +} + +.modaal-close span { + position: absolute !important; + clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ + clip: rect(1px, 1px, 1px, 1px); + padding: 0 !important; + border: 0 !important; + height: 1px !important; + width: 1px !important; + overflow: hidden; +} + +.modaal-close:before, +.modaal-close:after { + display: block; + content: " "; + position: absolute; + top: 14px; + left: 23px; + width: 4px; + height: 22px; + border-radius: 4px; + background: #fff; + -webkit-transition: background 0.2s ease-in-out; + transition: background 0.2s ease-in-out; +} + +.modaal-close:before { + -webkit-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + transform: rotate(-45deg); +} + +.modaal-close:after { + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); +} + +.modaal-fullscreen .modaal-close { + background: #afb7bc; + right: 10px; + top: 10px; +} + +.modaal-content-container { + padding: 30px; +} + +.modaal-confirm-wrap { + padding: 30px 0 0; + text-align: center; + font-size: 0; +} + +.modaal-confirm-btn { + font-size: 14px; + display: inline-block; + margin: 0 10px; + vertical-align: middle; + cursor: pointer; + border: none; + background: transparent; +} + +.modaal-confirm-btn.modaal-ok { + padding: 10px 15px; + color: #fff; + background: #555; + border-radius: 3px; + -webkit-transition: background 0.2s ease-in-out; + transition: background 0.2s ease-in-out; +} + +.modaal-confirm-btn.modaal-ok:hover { + background: #2f2f2f; +} + +.modaal-confirm-btn.modaal-cancel { + text-decoration: underline; +} + +.modaal-confirm-btn.modaal-cancel:hover { + text-decoration: none; + color: #2f2f2f; +} + +.modaal-instagram .modaal-container { + width: auto; + background: transparent; + box-shadow: none !important; +} + +.modaal-instagram .modaal-content-container { + padding: 0; + background: transparent; +} + +.modaal-instagram .modaal-content-container > blockquote { + width: 1px !important; + height: 1px !important; + opacity: 0 !important; +} + +.modaal-instagram iframe { + opacity: 0; + margin: -6px !important; + border-radius: 0 !important; + width: 1000px !important; + max-width: 800px !important; + box-shadow: none !important; + -webkit-animation: instaReveal 1s linear forwards; + animation: instaReveal 1s linear forwards; +} + +.modaal-image .modaal-inner-wrapper { + padding-left: 140px; + padding-right: 140px; +} + +.modaal-image .modaal-container { + width: auto; + max-width: 100%; +} + +.modaal-gallery-wrap { + position: relative; + color: #fff; +} + +.modaal-gallery-item { + display: none; +} + +.modaal-gallery-item img { + display: block; +} + +.modaal-gallery-item.is_active { + display: block; +} + +.modaal-gallery-label { + position: absolute; + left: 0; + width: 100%; + margin: 20px 0 0; + font-size: 18px; + text-align: center; + color: #fff; +} + +.modaal-gallery-label:focus { + outline: none; +} + +.modaal-gallery-control { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + opacity: 1; + cursor: pointer; + color: #fff; + width: 50px; + height: 50px; + background: rgba(0, 0, 0, 0); + border: none; + border-radius: 100%; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +.modaal-gallery-control.is_hidden { + opacity: 0; + cursor: default; +} + +.modaal-gallery-control:focus, +.modaal-gallery-control:hover { + outline: none; + background: #fff; +} + +.modaal-gallery-control:focus:before, +.modaal-gallery-control:focus:after, +.modaal-gallery-control:hover:before, +.modaal-gallery-control:hover:after { + background: #afb7bc; +} + +.modaal-gallery-control span { + position: absolute !important; + clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ + clip: rect(1px, 1px, 1px, 1px); + padding: 0 !important; + border: 0 !important; + height: 1px !important; + width: 1px !important; + overflow: hidden; +} + +.modaal-gallery-control:before, +.modaal-gallery-control:after { + display: block; + content: " "; + position: absolute; + top: 16px; + left: 25px; + width: 4px; + height: 18px; + border-radius: 4px; + background: #fff; + -webkit-transition: background 0.2s ease-in-out; + transition: background 0.2s ease-in-out; +} + +.modaal-gallery-control:before { + margin: -5px 0 0; + -webkit-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + transform: rotate(-45deg); +} + +.modaal-gallery-control:after { + margin: 5px 0 0; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); +} + +.modaal-gallery-next-inner { + left: 100%; + margin-left: 40px; +} + +.modaal-gallery-next-outer { + right: 45px; +} + +.modaal-gallery-prev:before, +.modaal-gallery-prev:after { + left: 22px; +} + +.modaal-gallery-prev:before { + margin: 5px 0 0; + -webkit-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + transform: rotate(-45deg); +} + +.modaal-gallery-prev:after { + margin: -5px 0 0; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); +} + +.modaal-gallery-prev-inner { + right: 100%; + margin-right: 40px; +} + +.modaal-gallery-prev-outer { + left: 45px; +} + +.modaal-video-wrap { + margin: auto 50px; + position: relative; +} + +.modaal-video-container { + position: relative; + padding-bottom: 56.25%; + height: 0; + overflow: hidden; + max-width: 100%; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + background: #000; + max-width: 1300px; + margin-left: auto; + margin-right: auto; +} + +.modaal-video-container iframe, +.modaal-video-container object, +.modaal-video-container embed { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.modaal-iframe .modaal-content { + width: 100%; + height: 100%; +} + +.modaal-iframe-elem { + width: 100%; + height: 100%; + display: block; +} + +.modaal-loading-spinner { + background: none; + position: absolute; + width: 200px; + height: 200px; + top: 50%; + left: 50%; + margin: -100px 0 0 -100px; + -webkit-transform: scale(0.25); + -ms-transform: scale(0.25); + transform: scale(0.25); +} + +.modaal-loading-spinner > div { + width: 24px; + height: 24px; + margin-left: 4px; + margin-top: 4px; + position: absolute; +} + +.modaal-loading-spinner > div > div { + width: 100%; + height: 100%; + border-radius: 15px; + background: #fff; +} + +.modaal-loading-spinner > div:nth-of-type(1) > div { + -webkit-animation: modaal-loading-spinner 1s linear infinite; + animation: modaal-loading-spinner 1s linear infinite; + -webkit-animation-delay: 0s; + animation-delay: 0s; +} + +.modaal-loading-spinner > div:nth-of-type(2) > div, +.modaal-loading-spinner > div:nth-of-type(3) > div { + -ms-animation: modaal-loading-spinner 1s linear infinite; + -moz-animation: modaal-loading-spinner 1s linear infinite; + -webkit-animation: modaal-loading-spinner 1s linear infinite; + -o-animation: modaal-loading-spinner 1s linear infinite; +} + +.modaal-loading-spinner > div:nth-of-type(1) { + -ms-transform: translate(84px, 84px) rotate(45deg) translate(70px, 0); + -webkit-transform: translate(84px, 84px) rotate(45deg) translate(70px, 0); + transform: translate(84px, 84px) rotate(45deg) translate(70px, 0); +} + +.modaal-loading-spinner > div:nth-of-type(2) > div { + -webkit-animation: modaal-loading-spinner 1s linear infinite; + animation: modaal-loading-spinner 1s linear infinite; + -webkit-animation-delay: .12s; + animation-delay: .12s; +} + +.modaal-loading-spinner > div:nth-of-type(2) { + -ms-transform: translate(84px, 84px) rotate(90deg) translate(70px, 0); + -webkit-transform: translate(84px, 84px) rotate(90deg) translate(70px, 0); + transform: translate(84px, 84px) rotate(90deg) translate(70px, 0); +} + +.modaal-loading-spinner > div:nth-of-type(3) > div { + -webkit-animation: modaal-loading-spinner 1s linear infinite; + animation: modaal-loading-spinner 1s linear infinite; + -webkit-animation-delay: .25s; + animation-delay: .25s; +} + +.modaal-loading-spinner > div:nth-of-type(4) > div, +.modaal-loading-spinner > div:nth-of-type(5) > div { + -ms-animation: modaal-loading-spinner 1s linear infinite; + -moz-animation: modaal-loading-spinner 1s linear infinite; + -webkit-animation: modaal-loading-spinner 1s linear infinite; + -o-animation: modaal-loading-spinner 1s linear infinite; +} + +.modaal-loading-spinner > div:nth-of-type(3) { + -ms-transform: translate(84px, 84px) rotate(135deg) translate(70px, 0); + -webkit-transform: translate(84px, 84px) rotate(135deg) translate(70px, 0); + transform: translate(84px, 84px) rotate(135deg) translate(70px, 0); +} + +.modaal-loading-spinner > div:nth-of-type(4) > div { + -webkit-animation: modaal-loading-spinner 1s linear infinite; + animation: modaal-loading-spinner 1s linear infinite; + -webkit-animation-delay: .37s; + animation-delay: .37s; +} + +.modaal-loading-spinner > div:nth-of-type(4) { + -ms-transform: translate(84px, 84px) rotate(180deg) translate(70px, 0); + -webkit-transform: translate(84px, 84px) rotate(180deg) translate(70px, 0); + transform: translate(84px, 84px) rotate(180deg) translate(70px, 0); +} + +.modaal-loading-spinner > div:nth-of-type(5) > div { + -webkit-animation: modaal-loading-spinner 1s linear infinite; + animation: modaal-loading-spinner 1s linear infinite; + -webkit-animation-delay: .5s; + animation-delay: .5s; +} + +.modaal-loading-spinner > div:nth-of-type(6) > div, +.modaal-loading-spinner > div:nth-of-type(7) > div { + -ms-animation: modaal-loading-spinner 1s linear infinite; + -moz-animation: modaal-loading-spinner 1s linear infinite; + -webkit-animation: modaal-loading-spinner 1s linear infinite; + -o-animation: modaal-loading-spinner 1s linear infinite; +} + +.modaal-loading-spinner > div:nth-of-type(5) { + -ms-transform: translate(84px, 84px) rotate(225deg) translate(70px, 0); + -webkit-transform: translate(84px, 84px) rotate(225deg) translate(70px, 0); + transform: translate(84px, 84px) rotate(225deg) translate(70px, 0); +} + +.modaal-loading-spinner > div:nth-of-type(6) > div { + -webkit-animation: modaal-loading-spinner 1s linear infinite; + animation: modaal-loading-spinner 1s linear infinite; + -webkit-animation-delay: .62s; + animation-delay: .62s; +} + +.modaal-loading-spinner > div:nth-of-type(6) { + -ms-transform: translate(84px, 84px) rotate(270deg) translate(70px, 0); + -webkit-transform: translate(84px, 84px) rotate(270deg) translate(70px, 0); + transform: translate(84px, 84px) rotate(270deg) translate(70px, 0); +} + +.modaal-loading-spinner > div:nth-of-type(7) > div { + -webkit-animation: modaal-loading-spinner 1s linear infinite; + animation: modaal-loading-spinner 1s linear infinite; + -webkit-animation-delay: .75s; + animation-delay: .75s; +} + +.modaal-loading-spinner > div:nth-of-type(7) { + -ms-transform: translate(84px, 84px) rotate(315deg) translate(70px, 0); + -webkit-transform: translate(84px, 84px) rotate(315deg) translate(70px, 0); + transform: translate(84px, 84px) rotate(315deg) translate(70px, 0); +} + +.modaal-loading-spinner > div:nth-of-type(8) > div { + -webkit-animation: modaal-loading-spinner 1s linear infinite; + animation: modaal-loading-spinner 1s linear infinite; + -webkit-animation-delay: .87s; + animation-delay: .87s; +} + +.modaal-loading-spinner > div:nth-of-type(8) { + -ms-transform: translate(84px, 84px) rotate(360deg) translate(70px, 0); + -webkit-transform: translate(84px, 84px) rotate(360deg) translate(70px, 0); + transform: translate(84px, 84px) rotate(360deg) translate(70px, 0); +} + +@media only screen and (min-width: 1400px) { + +.modaal-video-container { + padding-bottom: 0; + height: 731px; +} + +} + +@media only screen and (max-width: 1140px) { + +.modaal-image .modaal-inner-wrapper { + padding-left: 25px; + padding-right: 25px; +} + +.modaal-gallery-control { + top: auto; + bottom: 20px; + -webkit-transform: none; + -ms-transform: none; + transform: none; + background: rgba(0, 0, 0, 0.7); +} + +.modaal-gallery-control:before, +.modaal-gallery-control:after { + background: #fff; +} + +.modaal-gallery-next { + left: auto; + right: 20px; +} + +.modaal-gallery-prev { + left: 20px; + right: auto; +} + +} + +@media screen and (max-width: 900px) { + +.modaal-instagram iframe { + width: 500px !important; +} + +} + +@media only screen and (max-width: 600px) { + +.modaal-instagram iframe { + width: 280px !important; +} + +} + +@media screen and (max-height: 1100px) { + +.modaal-instagram iframe { + width: 700px !important; +} + +} + +@media screen and (max-height: 1000px) { + +.modaal-inner-wrapper { + padding-top: 60px; + padding-bottom: 60px; +} + +.modaal-instagram iframe { + width: 600px !important; +} + +} + +@media screen and (max-height: 900px) { + +.modaal-instagram iframe { + width: 500px !important; +} + +.modaal-video-container { + max-width: 900px; + max-height: 510px; +} + +} + +@media only screen and (max-height: 820px) { + +.modaal-gallery-label { + display: none; +} + +} + +@keyframes instaReveal { + +0% { + opacity: 0; +} + +100% { + opacity: 1; +} + +} + +@-webkit-keyframes instaReveal { + +0% { + opacity: 0; +} + +100% { + opacity: 1; +} + +} + +@-webkit-keyframes modaal-loading-spinner { + +0% { + opacity: 1; + -ms-transform: scale(1.5); + -webkit-transform: scale(1.5); + transform: scale(1.5); +} + +100% { + opacity: .1; + -ms-transform: scale(1); + -webkit-transform: scale(1); + transform: scale(1); +} + +} + +@keyframes modaal-loading-spinner { + +0% { + opacity: 1; + -ms-transform: scale(1.5); + -webkit-transform: scale(1.5); + transform: scale(1.5); +} + +100% { + opacity: .1; + -ms-transform: scale(1); + -webkit-transform: scale(1); + transform: scale(1); +} + +} + diff --git a/app/assets/stylesheets/space/tingle.css b/app/assets/stylesheets/space/tingle.css new file mode 100644 index 0000000..7044015 --- /dev/null +++ b/app/assets/stylesheets/space/tingle.css @@ -0,0 +1,278 @@ +/* ----------------------------------------------------------- */ +/* == tingle v0.15.2 */ +/* ----------------------------------------------------------- */ + +.tingle-modal * { + box-sizing: border-box; +} + +.tingle-modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1000; + display: flex; + visibility: hidden; + flex-direction: column; + align-items: center; + overflow: hidden; + -webkit-overflow-scrolling: touch; + background: rgba(0, 0, 0, .85); + opacity: 0; + user-select: none; + cursor: pointer; +} + +/* confirm and alerts +-------------------------------------------------------------- */ + +.tingle-modal--confirm .tingle-modal-box { + text-align: center; +} + +/* modal +-------------------------------------------------------------- */ + +.tingle-modal--noOverlayClose { + cursor: default; +} + +.tingle-modal--noClose .tingle-modal__close { + display: none; +} + +.tingle-modal__close { + position: fixed; + top: 2.5rem; + right: 2.5rem; + z-index: 1000; + padding: 0; + width: 2rem; + height: 2rem; + border: none; + background-color: transparent; + color: #fff; + cursor: pointer; +} + +.tingle-modal__close svg * { + fill: currentColor; +} + +.tingle-modal__closeLabel { + display: none; +} + +.tingle-modal__close:hover { + color: #fff; +} + +.tingle-modal-box { + position: relative; + flex-shrink: 0; + margin-top: auto; + margin-bottom: auto; + width: 60%; + border-radius: 4px; + background: #fff; + opacity: 1; + cursor: auto; + will-change: transform, opacity; +} + +.tingle-modal-box__content { + padding: 1em; +} + +.tingle-modal-box__footer { + padding: 1.5rem 2rem; + width: auto; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + background-color: #f5f5f5; + cursor: auto; +} + +.tingle-modal-box__footer::after { + display: table; + clear: both; + content: ""; +} + +.tingle-modal-box__footer--sticky { + position: fixed; + bottom: -200px; /* TODO : find a better way */ + z-index: 10001; + opacity: 1; + transition: bottom .3s ease-in-out .3s; +} + +/* state +-------------------------------------------------------------- */ + +.tingle-enabled { + position: fixed; + right: 0; + left: 0; + overflow: hidden; +} + +.tingle-modal--visible .tingle-modal-box__footer { + bottom: 0; +} + +.tingle-enabled .tingle-content-wrapper { + filter: blur(8px); +} + +.tingle-modal--visible { + visibility: visible; + opacity: 1; +} + +.tingle-modal--visible .tingle-modal-box { + animation: scale .2s cubic-bezier(.68, -.55, .265, 1.55) forwards; +} + +.tingle-modal--overflow { + overflow-y: scroll; + padding-top: 8vh; +} + +/* btn +-------------------------------------------------------------- */ + +.tingle-btn { + display: inline-block; + margin: 0 .5rem; + padding: 1rem 2rem; + border: none; + background-color: grey; + box-shadow: none; + color: #fff; + vertical-align: middle; + text-decoration: none; + font-size: inherit; + font-family: inherit; + line-height: normal; + cursor: pointer; + transition: background-color .4s ease; +} + +.tingle-btn--primary { + background-color: #3498db; +} + +.tingle-btn--danger { + background-color: #e74c3c; +} + +.tingle-btn--default { + background-color: #34495e; +} + +.tingle-btn--pull-left { + float: left; +} + +.tingle-btn--pull-right { + float: right; +} + +/* responsive +-------------------------------------------------------------- */ + +@media (max-width : 540px) { + .tingle-modal { + top: 0px; + display: block; + padding-top: 60px; + width: 100%; + } + + .tingle-modal-box { + width: auto; + border-radius: 0; + margin-top: 45px; + } + + .tingle-modal-box__content { + overflow-y: scroll; + max-height: 80vh; + } + + .tingle-modal--noClose { + top: 0; + } + + .tingle-modal--noOverlayClose { + padding-top: 0; + } + + .tingle-modal-box__footer .tingle-btn { + display: block; + float: none; + margin-bottom: 1rem; + width: 100%; + } + + .tingle-modal__close { + right: 0; + left: 0; + display: block; + width: 100%; + height: 60px; + border: none; + background-color: #2c3e50; + box-shadow: none; + color: #fff; + } + + .tingle-modal__closeLabel { + display: inline-block; + vertical-align: middle; + font-size: 1.6rem; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + } + + .tingle-modal__closeIcon { + display: inline-block; + margin-right: .8rem; + width: 1.6rem; + vertical-align: middle; + font-size: 0; + } +} + +@supports (backdrop-filter: blur(12px)) { + .tingle-modal:before { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + content: ""; + backdrop-filter: blur(18px); + pointer-events: none; + } + + .tingle-enabled .tingle-content-wrapper { + filter: none; + } +} + +/* animations +-------------------------------------------------------------- */ + +@keyframes scale { + 0% { + opacity: 0; + transform: scale(.9); + } + 100% { + opacity: 1; + transform: scale(1); + } +} diff --git a/app/assets/stylesheets/spaces.scss b/app/assets/stylesheets/spaces.scss index c226c4d..2ee91f5 100644 --- a/app/assets/stylesheets/spaces.scss +++ b/app/assets/stylesheets/spaces.scss @@ -363,6 +363,7 @@ display: flex; align-items: center; justify-content: center; + outline: 0; .selection-box-label.absolute-center{ display: none; } @@ -388,15 +389,15 @@ left: 0%; background: #2196F3; color: white; - width: 650%; + width: 8em; + width: max-content; + min-width: 4em; padding: 0.2em; - font-size: 0.6em; - @media (min-width: $screen-sm) { - width: 450%; - font-size: 0.3em; - } + font-size: 0.8em; +} +a.s-space__pin-link{ + position: relative; } - // Page specific styles .building-showcase { img { diff --git a/modules/space/show.html.erb b/modules/space/show.html.erb index 5d2d0ef..df78102 100644 --- a/modules/space/show.html.erb +++ b/modules/space/show.html.erb @@ -70,7 +70,7 @@ var text = $(this).find('.selection-box-label') text.append('
') temp.prepend('') - temp.find('.fa-map-marker').append(text) + temp.prepend(text) temp.find('.fa-map-marker').css('color',map_color) $(this).on('mouseover',function(){ $(this).css('background-color',block_color) diff --git a/modules/space/unit.html.erb b/modules/space/unit.html.erb index 5a77d28..199fcfb 100644 --- a/modules/space/unit.html.erb +++ b/modules/space/unit.html.erb @@ -1,3 +1,5 @@ + +
@@ -11,15 +13,16 @@
-
+
{{style_label}}