/** * Invision Community * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * * ips.checkout.register.js - Register form during checkout * * Author: Rikki Tissier */ ;( function($, _, undefined){ "use strict"; ips.controller.register('nexus.front.checkout.register', { initialize: function () { this.on( 'click', '[data-action="newMember"]', this.showRegistrationForm ); if ( $(this.scope).attr('data-regform') ) { this._showRegistrationForm(); } }, showRegistrationForm: function (e) { e.preventDefault(); this._showRegistrationForm(); }, _showRegistrationForm: function() { this.scope.find('[data-role="memberChoice"]').hide(); this.scope.find('[data-role="newCustomerForm"]').show(); this.scope.find('[data-role="business"]').hide(); } }); }(jQuery, _)); button').prop( 'disabled', false ); } }); }(jQuery, _));]]> ').attr('data-role', 'loading').addClass('ipsLoading').hide(); scope.closest('[data-ipswizard]').append( loading ); } var dims = { width: wizardContainer.outerWidth(), height: wizardContainer.outerHeight() }; loading .css({ width: dims.width + 'px', height: dims.height + 'px' }) .show(); wizardContainer .hide() .after( loading.show() ); /* Stored card */ var savedCardId = $(this.scope).find('input[name="'+$(this.scope).attr('data-id')+'_card[stored]"]:checked').val(); if ( savedCardId > 0 ) { this.createPaymentIntent( savedCardId ); } /* New card */ else { var data = { billing_details: { address: {} } }; if ( scope.attr('data-city') ) { data.billing_details.address.city = scope.attr('data-city'); } if ( scope.attr('data-country') ) { data.billing_details.address.country = scope.attr('data-country'); } if ( scope.attr('data-address1') ) { data.billing_details.address.line1 = scope.attr('data-address1'); } if ( scope.attr('data-address2') ) { data.billing_details.address.line2 = scope.attr('data-address2'); } if ( scope.attr('data-zip') ) { data.billing_details.address.postal_code = scope.attr('data-zip'); } if ( scope.attr('data-state') ) { data.billing_details.address.state = scope.attr('data-state'); } if ( scope.attr('data-email') ) { data.billing_details.email = scope.attr('data-email'); } if ( scope.attr('data-name') ) { data.billing_details.name = scope.attr('data-name'); } if ( scope.attr('data-phone') ) { data.billing_details.phone = scope.attr('data-phone'); } if ( scope.attr('data-amount') && parseFloat( scope.attr('data-amount') ) > 0 ) { this.stripe.createPaymentMethod( 'card', this.cardNumber, data ).then( _.bind( this.receivedCardPaymentMethod, this ) ); } else { this.stripe.handleCardSetup( scope.attr('data-setupSecret'), this.cardNumber, { payment_method_data: data } ).then( function( result ){ if (result.error) { Debug.error(result.error); loading.remove(); wizardContainer.show(); ips.ui.alert.show({ type: 'alert', icon: 'warn', message: result.error.message }); } else { scope.closest('form').append( $('').attr( 'name', scope.attr('data-id') + '_card[token]' ).val( result.setupIntent.payment_method ) ); scope.closest('form').submit(); } } ); } } } }, /** * Create payment intent * * @param {mixed} paymentMethodId A Stripe payment method ID or a stored card ID * @returns {void} */ createPaymentIntent: function( paymentMethodId ) { var scope = $(this.scope); var loading = scope.closest('[data-ipswizard]').find('[data-role="loading"]'); var wizardContainer = scope.closest('[data-ipswizard]').find('[data-role="wizardContent"]'); ips.getAjax()( scope.closest('form').attr('action'), { method: 'post', data: { createPaymentIntent: paymentMethodId, savePaymentMethod: $( '#el' + scope.attr('data-id') + '_cardSave' ).prop('checked'), } } ) .done(function(response){ if ( response.response.status === 'requires_action' ) { this.stripe.handleCardAction( response.response.client_secret ).then(function(result) { if (result.error) { console.error(result.error); loading.remove(); wizardContainer.show(); ips.ui.alert.show({ type: 'alert', icon: 'warn', message: result.error.message }); } else { scope.closest('form').append( $('').attr( 'name', scope.attr('data-id') + '_card[token]' ).val( response.response.id ) ); scope.closest('form').submit(); } }); } else { scope.closest('form').append( $('').attr( 'name', scope.attr('data-id') + '_card[token]' ).val( response.response.id ) ); scope.closest('form').submit(); } }.bind(this)) .fail(function(response){ console.error(response); loading.remove(); wizardContainer.show(); ips.ui.alert.show({ type: 'alert', icon: 'warn', message: ips.getString('payment_error') }); }.bind(this)); }, /** * Callback after a Stripe Payment Method has been generated for a card * * @param {object} result The result * @returns {void} */ receivedCardPaymentMethod: function( result ) { /* Init */ var scope = $(this.scope); var loading = scope.closest('[data-ipswizard]').find('[data-role="loading"]'); var wizardContainer = scope.closest('[data-ipswizard]').find('[data-role="wizardContent"]'); /* If there was an error, show the form again */ if ( result.error ) { Debug.error(result.error); loading.remove(); wizardContainer.show(); if ( result.error.type == 'card_error' || result.error.type == 'validation_error' ) { ips.ui.alert.show({ type: 'alert', icon: 'warn', message: result.error.message }); } else { ips.ui.alert.show({ type: 'alert', icon: 'warn', message: ips.getString('payment_error') }); } } /* Otherwise, process... */ else { this.createPaymentIntent( result.paymentMethod.id ); } }, /** * Callback when the status of a source changes (i..e the customer has paid, or too much time has passed for them to be able to pay) * * @param {int} status Status Code * @param {Source} source Stripe Source object * @returns {void} */ pollCallback: function( status, source ) { if ( source.status !== 'pending' ) { $(this.scope).closest('form').submit(); } } }); }(jQuery, _));]]> /** * IPS Community Suite 4 * (c) 2017 Invision Power Services - http://www.invisionpower.com * * ips.gateways.stripepaymentrequest.js - Stripe Apple Pay Controller * * Author: Mark Wade */ ;( function($, _, undefined){ "use strict"; ips.controller.register('nexus.global.gateways.stripepaymentrequest', { strile: null, /** * Init */ initialize: function () { this.setup(); }, /** * Init */ setup: function(){ this.stripe = Stripe( this.scope.attr('data-key') ); var data = { country: this.scope.attr('data-country'), currency: this.scope.attr('data-currency'), total: { label: $('meta[property="og:site_name"]').attr('content'), amount: parseInt( this.scope.attr('data-amountAsCents') ) } }; var paymentRequest = this.stripe.paymentRequest(data); var elements = this.stripe.elements(); var prButton = elements.create('paymentRequestButton', { paymentRequest: paymentRequest }); var scope = this.scope; paymentRequest.canMakePayment().then(function(result) { if (result) { prButton.mount( '#paymentrequest-' + scope.attr('id') ); } else { ips.utils.cookie.set( 'PaymentRequestAPI', 0 ); var paymentMethodRadio = $( '#elRadio_payment_method_' + scope.attr('data-id') ); if ( paymentMethodRadio.length ) { if ( paymentMethodRadio.is(':checked') ) { paymentMethodRadio.closest('li').next('li').find('input[type="radio"]').click(); } paymentMethodRadio.closest('li').remove(); } else { window.location = window.location; } } } ); paymentRequest.on('source', function(ev) { ips.getAjax()( ips.getSetting('baseURL') + 'applications/nexus/interface/gateways/stripe-payrequest.php', { data: { token: ev.source.id, gateway: this.scope.attr('data-id'), currency: this.scope.attr('data-currency'), amount: this.scope.attr('data-amount'), invoice: this.scope.attr('data-invoice') } } ) .done(function(response){ if ( response.success ) { ev.complete('success'); window.location = response.url; } else { ev.complete('fail'); } }) .fail(function(){ ev.complete('fail'); }); }.bind(this)); }, }); }(jQuery, _)); /** * Invision Community * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * * ips.misc.print.js - Makes the page print * * Author: Rikki Tissier */ ;( function($, _, undefined){ "use strict"; ips.controller.register('nexus.global.misc.print', { /** * Init */ initialize: function () { window.print(); }, }); }(jQuery, _)); /** * Invision Community * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * * ips.notifications.pendingTransactions.js * * Author: Mark Wade */ ;( function($, _, undefined){ "use strict"; ips.controller.register('nexus.admin.notifications.pendingTransactions', { /** * Init */ initialize: function () { this.on( 'click', '[data-action="quickAction"]', this.doAction ); }, /** * Event handler for the buttons * * @param {event} e Event object * @returns {void} */ doAction: function (e) { e.preventDefault(); var self = this; var button = $( e.currentTarget ); var url = button.attr('href'); var type = button.attr('data-action'); var row = button.closest('[data-role="validatingRow"]'); var name = row.find('[data-role="userName"]').text(); var toggles = button.closest('[data-role="buttons"]'); ips.ui.alert.show({ type: 'confirm', callbacks: { 'ok': function() { toggles.find('a').addClass('ipsButton--disabled'); ips.getAjax()( url ) .done( function ( response ) { // Show flash msg if ( response.message ) { ips.ui.flashMsg.show( response.message ); } // Update HTML if ( response.queue ) { var newElement = $( response.queue ); $(self.scope).replaceWith( newElement ); $( document ).trigger( 'contentChange', [ newElement ] ); } else { ips.utils.anim.go( 'fadeOut', $(self.scope).closest('.cNotification') ); $('body').trigger('updateNotificationCount'); } }) .fail( function ( response ) { if ( response.responseJSON ) { ips.ui.alert.show({ type: 'alert', message: response.responseJSON, }); toggles.find('a').removeClass('ipsButton--disabled'); } else { window.location = url; } }); } }, }); } }); }(jQuery, _)); /** * Invision Community * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * * ips.store.cartReview.js - Cart review screen * * Author: Rikki Tissier */ ;( function($, _, undefined){ "use strict"; ips.controller.register('nexus.front.store.cartReview', { initialize: function () { this.on( 'click', '[data-action="removeFromCart"]', this.removeFromCart ); this.on( 'submit', '[data-role="quantityForm"]', this.quantityForm ); this.on( 'click', '[data-action="checkout"]', this.checkout ); }, /** * Prevent checkout button being clicked more than once * * @param {event} e Event object * @returns {void} */ checkout: function (e) { if ( $(e.target).hasClass('ipsButton--disabled') ) { e.preventDefault(); } else { $(e.target).addClass('ipsButton--disabled'); } }, /** * Removes the item from the cart * * @param {event} e Event object * @returns {void} */ removeFromCart: function (e) { e.preventDefault(); var self = this; var url = $( e.currentTarget ).attr('href'); ips.ui.alert.show({ type: 'confirm', message: ips.getString('confirmRemoveItem'), icon: 'warn', callbacks: { ok: function () { ips.getAjax()( url ) .done( function (response) { self.scope.find('[data-role="cart"]').html( response ); }); } } }); }, /** * Handles submitting the quantity form * * @param {event} e Event object * @returns {void} */ quantityForm: function (e) { e.preventDefault(); var self = this; var form = $( e.currentTarget ); var menu = form.closest('.ipsMenu'); // Set menu to loading and hide form menu .css({ height: menu.outerHeight() + 'px' }) .addClass('ipsLoading'); form.hide(); // Do ajax request to update it ips.getAjax()( form.attr('action'), { data: form.serialize() }) .done( function (response) { self.scope.find('[data-role="cart"]').html( response ); }) .fail(function(response){ menu.removeClass( 'ipsLoading' ); form.show(); ips.ui.alert.show( { type: 'alert', icon: 'warn', message: response.responseJSON }); }); } }); }(jQuery, _)); this.stateChange(e) ); }, /** * Changes the calendar view dynamically * * @param {Event} e Event object * @returns {void} */ changeView: function (e) { e.preventDefault(); if ( $(e.target).hasClass('ipsSideMenu_item') ) { $(e.target).toggleClass('ipsSideMenu_itemActive'); } // Load the url via ajax instead const url = $( e.currentTarget ).attr('href'); ips.utils.history.pushState( { controller: 'storeCategoryView' }, 'nexus.front.store.category', $(e.currentTarget).attr('href') ); }, /** * Event handler for history state changes * * @returns {void} */ stateChange: function () { const url = window.location.href; if (!('nexus.front.store.category' in ips.utils.history.getState())) { return; } // Track page view ips.utils.analytics.trackPageView( url ); this._updateView( url ) }, /** * Loads a new view * * @param {string} url URL to load * * @returns {Promise} */ async _updateView(url) { if( this._ajaxObj && _.isFunction( this._ajaxObj.abort ) ){ this._ajaxObj.abort(); } this._setLoading( true ); try { const response = await ips.fetch(url) $('[data-role="packageListContainer"]').html(response.contents); $('[data-role="categorySidebar"]').html(response.sidebar); $(document).trigger('contentChange', [$('[data-role="packageListContainer"]'), $('[data-role="categorySidebar"]')]); } catch (e) { Debug.log(`Failed to fetch data for a nexus store category after a filter/sort/view update from ${url}`) Debug.warn(e) } this._setLoading(false) }, /** * Toggles the loading state on the view * * @param {boolean} state Enable the loading state? * @returns {void} */ _setLoading: function (state) { if( state ){ $('[data-role="packageList"]').css( 'height', $('[data-role="packageList"]').height() ).html('').addClass('ipsLoading'); } else { $('[data-role="packageList"]').css( 'height', 'auto' ).removeClass('ipsLoading'); } } }); }(jQuery, _));]]> /** * Invision Community * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * * ips.store.currencySelect.js - Alert when changing currency * * Author: Mark Wade */ ;( function($, _, undefined){ "use strict"; ips.controller.register('nexus.front.store.currencySelect', { initialize: function () { this.on( 'click', 'a', this.currencyChangeWarning ); }, /** * Prevent checkout button being clicked more than once * * @param {event} e Event object * @returns {void} */ currencyChangeWarning: function (e) { e.preventDefault(); var url = $(e.currentTarget).attr('href'); ips.ui.alert.show({ type: 'confirm', message: ips.getString('store_currency_change_warning'), icon: 'warn', callbacks: { ok: function () { window.location = url; } } }); } }); }(jQuery, _)); ').addClass('ipsLoading'); form.after( loadingElem ); loadingElem.css({ top: formPos.offsetPos.top + 'px', left: formPos.offsetPos.left + 'px', width: formDims.outerWidth + 'px', height: formDims.outerHeight + 'px' }); this._productURL = form.attr('action'); // Trigger an event for adding to cart, so that we can capture it // and do something else with it if necessary this.trigger( 'addToCart.nexus', { url: this._productURL, formData: form.serialize() }); }, /** * Adds the item to cart via ajax, and creates a dialog to let the user know * * @param {event} e Event object * @param {object} data Event data object * @returns {void} */ addToCart: function (e, data) { // Since addToCart is responding to events at document level, we'll potentially be called for multiple // products on the page. Check the URL matches the expected one here, and ignore if it's for a different product. if( data.url !== this._productURL ){ return; } var self = this; ips.getAjax()( data.url, { data: data.formData, type: 'post' }) .done( function (response) { // Are we already running inside of a dialog? if( self.scope.closest('.ipsDialog').length ){ var dialogContent = self.scope.closest('.ipsDialog').find('.ipsDialog_content'); // We need to destroy this controller before updating the content so that event handlers are unregistered, // otherwise this controller will continue listening for addToCart events and trigger multiple dialogs. self.trigger('destroy'); dialogContent.html( response.dialog ).show(); $( document ).trigger( 'contentChange', [ dialogContent ] ); } else { var contentElem = $('
').html( response.dialog ); var loadingElem = self.scope.find('form').next('.ipsLoading'); ips.getContainer().append( contentElem ); // Show a dialog var dialogRef = ips.ui.dialog.create({ title: self.scope.attr('data-itemTitle'), content: contentElem, forceReload: true, size: 'medium' }); dialogRef.show(); $( document ).trigger( 'contentChange', [ contentElem ] ); // Remove loading elem loadingElem.remove(); self.updatePriceAndStock(); } if ( response.cart ) { console.log(response.cart); $('#elCart_container').replaceWith( $( '
' + response.cart + '
' ).find('#elCart_container') ); let cartCount = $( '
' + response.cart + '
' ).find('#elCart .ipsNotification').text(), showCart = Number(cartCount) > 0; // Hide or show the cart link in the mobile footer, and update the ipsNotification value document.getElementById('elCart_mobileFooterContainer').hidden = !showCart; document.querySelector('#elCart_mobileFooterContainer .ipsNotification').textContent = cartCount; } // Did we get any CSS files to output? // We have to do this last because a stylesheet may be included in the dialog initially but replaced out and no longer exist now if( !_.isUndefined( response.css ) ) { self.insertCssUrls( response.css ); } }) .fail(function(response){ var loadingElem = self.scope.find('form').next('.ipsLoading'); loadingElem.remove(); if ( response.responseJSON ) { ips.ui.alert.show({ type: 'alert', message: response.responseJSON, icon: 'warn' }); } else { var form = $(e.target).find('form'); try { var newForm = $(response.responseText); } catch (err) { form.attr('data-noajax', 'true'); form.submit(); } form.replaceWith( newForm ); $( document ).trigger('contentChange' ); } }); }, /** * Inserts CSS URLs if they are not already in the document * * @returns {void} */ insertCssUrls: function( urls ) { // If we don't have any, return if( !urls.length ) { return; } // Loop over the URLs _.each( urls, function( url ){ // Build the full URL with the cache bust key if( url.indexOf('?') != -1 ) { url = url + '&v=' + ips.getSetting('antiCache'); } else { url = url + '?v=' + ips.getSetting('antiCache'); } // Now see if it's already in the list of stylesheets loaded for the document. If not, add it, otherwise skip. if( !$('link[href="' + url +'"]').length ) { var stylesheet = document.createElement("link"); stylesheet.setAttribute( "href", url ); stylesheet.setAttribute( "rel", "stylesheet" ); stylesheet.setAttribute( "media", "all" ); $('head')[0].appendChild(stylesheet); Debug.log( "Added stylesheet " + url + " to document" ); } }); }, /** * Updates the stock and price information when custom fields change * * @returns {void} */ updatePriceAndStock: function () { var self = this; var form = this.scope.find('form'); ips.getAjax()( form.attr('action'), { dataType: 'json', data: form.serialize() + '&stockCheck=1', type: 'post' }) .done( function (response) { self.scope.find('[data-role="price"]').html( response.price ); self.scope.find('[data-role="stock"]').html( response.stock ); self.scope.find('[data-role="renewalTerm"]').html( response.renewal ); self.scope.find('[data-role="initialTerm"]').html( response.initialTerm ); if( response.okay ){ self.scope.find('button').removeAttr('disabled').text( ips.getString('add_to_cart_js') ); } else { self.scope.find('button').attr( 'disabled','disabled' ).text( ips.getString('out_of_stock') ); } }) .fail(function(response){ Debug.error(response); }); } }); }(jQuery, _));]]> /** * Invision Community * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * * ips.subscriptions.main.js - Register form during checkout * * Author: Rikki Tissier */ ;( function($, _, undefined){ "use strict"; ips.controller.register('nexus.front.subscriptions.main', { initialize: function () { this.on( 'click', '[data-change-subscription]', this.showAlert ); if ( $(this.scope).attr('data-regform') ) { this._showRegistrationForm(); } }, showAlert: function (e) { e.preventDefault(); ips.ui.alert.show({ type: 'confirm', message: $( e.currentTarget ).attr('data-change-message'), icon: 'warn', callbacks: { ok: function () { window.location = $( e.currentTarget ).attr('href'); }, cancel: function () { return false; } } }); } }); }(jQuery, _));
{{#thumb}} {{{thumb}}} {{/thumb}}

{{title}}

{{size}} {{#statusText}}· {{statusText}}{{/statusText}}

{{#status}}{{/status}}
×
`); ips.templates.set('nexus.store.imagesWrapper', `
{{{content}}}
`);]]>
\ \ \ ");]]> \ \
\ \
\ \ ");]]>
templates common/ips.loader.js common/ui common/utils common controllers underscore jquery mustache Debug.js app.js jquery.js jquery-migrate.js jquery.transform.js linkify.min.js linkify-jquery.min.js