Howdy
\"});\n * modal.open({content: $(\"Howdy
\"), width: \"500px\", height: \"200px\"});\n * // Ajax\n * $.get('ajax.html', function(data){\n * modal.open({content: data});\n * });\n */\n\nvar $overlay,\n $modal,\n $content,\n $close,\n isOpen = false,\n preserve = false,\n is_animating = false,\n anim_end_event_name = 'animationend',\n anim_control_class = {\n fold: {\n inClass: 'fadeUp',\n outClass: 'fadeOut'\n },\n fade: {\n inClass: 'fadeUp',\n outClass: 'fadeOut'\n },\n slideTop: {\n inClass: 'slideDown',\n outClass: 'slideUp'\n }\n };\n\n/* transition helpers */\nfunction transition_el ( el, classList, fn ) {\n if ( is_animating ) {\n return false;\n }\n\n is_animating = true;\n\n el.addClass( classList ).on( anim_end_event_name, function () {\n fn && fn();\n el.off( anim_end_event_name );\n is_animating = false;\n reset_animation_state( el );\n } );\n}\n\nfunction reset_animation_state ( el ) {\n el.attr( 'class', el.data( 'origClassList' ) );\n}\n\nfunction pullDown ( el ) {\n var orgY = el.offset().top;\n\n el.css( {\n top: -el.height(),\n opacity: 0\n } ).animate( {\n top: orgY,\n opacity: 1\n }, 300 );\n\n}\n\nvar center = function ( position ) {\n var top,\n left,\n position = position || 'center',\n contentOffset = {\n height: $content[0].offsetHeight,\n width: $content[0].offsetWidth\n },\n $window = $( window );\n\n if ( 'top' === position ) {\n top = 0;\n }\n else {\n top = Math.max( $window.height() - contentOffset.height, 0 ) / 2;\n }\n left = Math.max( $window.width() - 20 - contentOffset.width, 0 ) / 2;\n\n $content.css( {\n top: contentOffset.height < $window.height()\n ? top\n : 0,\n left: left\n } );\n};\n\nvar setSize = function ( settings ) {\n var target = settings.target,\n width = settings.width,\n height = settings.height;\n\n $content.css( {\n width: '100%',\n 'max-width': target && parseInt( target.attr( 'data-modal-width' ), 10 ) || width || 'auto',\n height: target && target.attr( 'data-modal-height' ) || height || 'auto'\n } );\n};\n\nlet freezeScrollPose = null;\nvar toggleOverlay = function ( doApply ) {\n $( 'html' ).toggleClass( 'blur-body', doApply );\n // $( 'body' ).toggleClass( 'no-scroll', doApply );\n freezeScrollPose = doApply ? document.documentElement.scrollTop : null;\n};\n\nfunction preventScrolling ( e ) {\n if ( freezeScrollPose ) {\n document.documentElement.scrollTop = freezeScrollPose;\n }\n}\n\nvar createFrame = function ( src ) {\n var ifrm = document.createElement( 'iframe' );\n ifrm.setAttribute( 'src', src || '/' );\n ifrm.style.width = '100%';\n ifrm.style.height = 'auto';\n\n return ifrm;\n};\n\n/**\n * Open modal window specifying either the html content to display or a node selector who's content\n * will be displayed within page\n *\n * @param {Object} settings [, target, content, className ,width, height ]\n */\nvar open = function ( settings ) {\n settings = settings || {};\n\n $modal.trigger( 'modal:beforeopen' );\n\n $content.off().empty();\n\n var target;\n // if provided a target id then pluck from DOM and set preserve flag\n if ( settings.target ) {\n preserve = true;\n target = settings.target = $( settings.target ).clone( true ).removeClass( 'visually-hidden hidden-lightbox' );\n target.data( 'preserve', true );\n }\n\n setContent( target || settings.content );\n setSize( settings );\n\n settings.className && $content.addClass( settings.className );\n $modal.show();\n center( settings.position );\n toggleOverlay( true );\n\n // don't reposition modal for small devices OR \"FIXED\" modal option\n if ( window.matchMedia( 'screen and (min-width: 30em)' ).matches ) {\n var _resizeHandler = center.bind( this, settings.position );\n $( window ).on( 'resize.modal', _resizeHandler );\n $modal.on( 'modal:closecomplete', function () {\n $( window ).off( 'resize.modal', _resizeHandler );\n } )\n }\n\n // only trigger transitions if modal is not already open\n if ( !isOpen ) {\n transition_el( $content, anim_control_class.fade.inClass );\n }\n $overlay.show();\n $modal.trigger( 'modal:opencomplete' );\n isOpen = true;\n return this;\n};\n\nvar openTarget = function ( e ) {\n console.log( 'OPEN TARGET' );\n e.preventDefault();\n var targetDialog = $( e.currentTarget.getAttribute( 'data-modal' ) ).clone( true );\n\n if ( targetDialog[0] ) {\n open( {target: targetDialog} );\n }\n};\n\nvar setContent = function ( content ) {\n $content.empty().append( content );\n};\n\nvar close = function () {\n $modal.trigger( 'modal:beforeclose' );\n setTimeout( () => {\n // preserve modal content for reuse, this will preserve modals state upon previous open\n if ( preserve ) {\n // not already in DOM\n if ( !$( 'body' ).find( $content.children( 0 ).attr( 'id' ).length ) ) {\n $( $content.html() ).addClass( 'visually-hidden' ).appendTo( 'body' );\n }\n }\n\n toggleOverlay( false );\n clear_content();\n $( window ).unbind( 'resize.modal' );\n\n $modal.trigger( 'modal:closecomplete' );\n preserve = false;\n isOpen = false;\n }, 200 );\n};\n\nfunction handleClose ( e ) {\n if ( [$modal[0], $overlay[0], $close[0]].indexOf( e.target ) > -1 ) {\n e.preventDefault();\n close();\n }\n}\n\nfunction clear_content () {\n $modal.hide();\n // patch: set iframe src to current location to clear out iframes flash video for IE,\n // otherwise video continues playing in background - simply removing the content from page doesn't work\n $content.css( {top: 'auto', left: 'auto'} ).find( 'iframe' ).attr( 'src', window.location.href );\n\n $content.empty();\n $overlay.fadeOut( 300 );\n}\n\nconst Modal = {\n getInstance: function ( config ) {\n const modal = namespace( 'Modal' );\n\n if ( modal.instance ) {\n return modal.instance;\n }\n\n console.warn( '[upi.Modal Initialized]' );\n modal.instance = this._init( config );\n return modal.instance;\n },\n\n _init: function ( config ) {\n $overlay = $( '' );\n $modal = $( '' );\n $content = $( '' );\n $close = $( '' );\n\n this.el = $modal;\n this.selector = '#modal';\n\n // set metadata\n $modal.data( 'origClassList', $modal.attr( 'class' ) );\n $modal.hide();\n $overlay.hide();\n $modal.append( $content, $close );\n\n this._init_events( config );\n\n $( document ).ready( function () {\n $( 'body' ).append( $overlay, $modal );\n $( document ).on( 'click', '[data-modal]', openTarget );\n } );\n\n return this;\n },\n\n _init_events: function () {\n $( document ).on( 'click', handleClose );\n $( window ).on( 'close.modal modal:close', this.close );\n $( window ).on( 'scroll wheel', preventScrolling );\n this.el.on( 'click', '*[data-modal-close]', this.close );\n },\n\n center: center,\n open: open,\n close: close,\n setContent: content => {\n setContent( content );\n center();\n }\n};\n\nexport default Modal;\n","import * as packageInfo from '../../../package/package.json';\n\nexport const name = packageInfo.name;\nexport const version = packageInfo.version;\n\n","import {reverseString} from './StringUtils';\n\nexport const isNumber = value => !isNaN( parseInt( value, 10 ) );\n\nexport function toCurrency ( val, round_decimal = false ) {\n const num = Number( val );\n const decimal = round_decimal ? 0 : 2;\n\n if ( isNaN( num ) ) {\n throw new Error( `NumberUtil.toCurrency expects a number but received ${num} instead` );\n }\n\n let n = bankersRound( num, decimal ).toFixed( decimal );\n // convert currency to a string, add commas every 3 digits from left to right by reversing string\n n = reverseString( n );\n n = n.replace( /(\\d{3})(?=\\d)/g, '$1,' );\n return reverseString( n );\n}\n\nexport function bankersRound ( n, d = 2 ) {\n const x = n * Math.pow( 10, d );\n const r = Math.round( x );\n const br = Math.abs( x ) % 1 === 0.5 ? (r % 2 === 0 ? r : r - 1) : r;\n return br / Math.pow( 10, d );\n}\n\nexport function currencyToFloat ( value ) {\n let v = value;\n if ( typeof v === 'string' ) {\n if ( v.startsWith( '$' ) ) {\n v = v.substr( 1 );\n }\n v = v.replace( ',', '' );\n }\n\n return parseFloat( v );\n}","import {adopt} from 'react-adopt';\nimport {makeMutation} from '../../util/ContainerUtils';\nimport {AddPayment, GetCustomer} from './query.graphql';\n\nexport const CustomerMutations = adopt( {\n addPayment: makeMutation( {\n mutation: AddPayment,\n update: addPaymentUpdateStrategy\n } )\n\n} );\n\n/**\n * **********************\n * Note -> Update Strategies\n * **********************\n */\nexport function addPaymentUpdateStrategy ( store, {data: {addPayment}} ) {\n const data = store.readQuery( {\n query: GetCustomer,\n variables: {withWallet: true}\n } );\n\n // data.customer.wallet = addPayment.wallet;\n if ( data.customer.wallet ) {\n data.customer.wallet.creditCards = data.customer.wallet.creditCards || [];\n data.customer.wallet.creditCards.push( addPayment.addedPayment );\n }\n\n store.writeQuery( {\n query: GetCustomer,\n variables: {withWallet: true},\n data\n } );\n}\n\n\n/**\n * **********************\n * Note -> Apollo mutation input helpers\n * **********************\n */\nexport function toPaymentInput ( data ) {\n const {\n cardholder,\n cardType,\n expiresMonth,\n expiresYear,\n securityCode,\n billingAddress,\n billingAddressId,\n accessToken\n } = data;\n return {\n accessToken,\n cardholder,\n cardType,\n securityCode,\n billingAddress,\n billingAddressId: billingAddressId && parseInt( billingAddressId, 10 ),\n expirationDate: expiresMonth + '/' + expiresYear\n };\n\n}\n\nexport function toAddressInput ( data ) {\n const {address1, address2, city, state, postalCode} = data;\n return {\n address1,\n address2,\n city,\n state,\n postalCode: String( postalCode )\n };\n}\n\nexport function toProductOfferingLocationsInput ( data ) {\n return {\n productOfferingLocations: data.map( toProductOfferingLocationInput )\n }\n}\n\nexport function toProductOfferingLocationInput ( data ) {\n const {address, ...rest} = data;\n return {\n addressId: address.id,\n ...rest\n };\n}\n\n\n","// note -> deprecated (removed Modernizr transform)\nexport const transEndEventName = 'transitionend';\nexport const transStartEventName = 'transitionstart';\nexport const animEndEventName = 'animationend';\nexport const animStartEventName = 'animationstart';","import User from '@modules/User';\nimport {client} from '@core/GraphQLProvider';\nimport {\n GetOrder,\n GetOrderDetailHtml,\n GetOrderDetailWithTrackingHtml,\n GetOrderHeaders,\n GetOrders,\n GetPastPurchases,\n UpdatePendingOrderState\n} from './query.graphql';\n\nconst OrdersService = {\n\n async getOrderHeaders ( {numberOfDays, numberOfRows} = {numberOfDays: 180, numberOfRows: 50} ) {\n const resp = await client.query( {\n query: GetOrderHeaders,\n variables: {numberOfDays, numberOfRows}\n } );\n\n return resp.data;\n },\n\n async getOrders ( {numberOfDays, numberOfRows} = {numberOfDays: 180, numberOfRows: 50} ) {\n const resp = await client.query( {\n query: GetOrders,\n variables: {numberOfDays, numberOfRows}\n } );\n\n return resp.data.orders;\n },\n\n async getOrderById ( {orderNumber} = {} ) {\n const resp = await client.query( {\n query: GetOrder,\n variables: {orderNumber: parseInt( orderNumber, 10 )}\n } );\n\n return resp.data.order;\n },\n\n async getOrderDetailsHtml ( {orderNumber} = {} ) {\n const resp = await client.query( {\n fetchPolicy: 'network-only',\n query: GetOrderDetailHtml,\n variables: {orderNumber}\n } );\n\n return resp.data.orderHtml.orderDetailHtml;\n },\n\n async getOrderDetailsAndTrackingHtml ( {orderNumber} = {} ) {\n const resp = await client.query( {\n fetchPolicy: 'network-only',\n query: GetOrderDetailWithTrackingHtml,\n variables: {orderNumber}\n } );\n\n return resp.data.orderHtml.orderDetailWithShippingHtml;\n },\n\n async getPastPurchases ( resultLimit = 12, months = 9, filterCart = true ) {\n if ( !User.isLogged() ) {\n console.warn( '[OrdersService]:getPastPurchases - User is not logged in, returning empty list' );\n return [];\n }\n\n const resp = await client.query( {\n query: GetPastPurchases,\n variables: {\n resultLimit,\n months,\n filterCart\n }\n } );\n\n return resp.data.suggestedProducts;\n },\n\n async updateOrderPO ( {orderNumber, poNumber} ) {\n if ( !poNumber ) {\n throw new Error( `OrdersService.updateOrderPO missing required param \"poNumber\"; received ${poNumber} instead` );\n }\n\n const input = {\n orderNumber,\n poNumber\n };\n\n const resp = await client.mutate( {\n mutation: UpdatePendingOrderState,\n variables: {input}\n } );\n\n return resp.data.updatePendingOrder;\n },\n\n async approveOrder ( {orderNumber, poNumber} ) {\n const input = {\n orderNumber,\n poNumber,\n orderStatus: 'APPROVED'\n };\n\n const resp = await client.mutate( {\n mutation: UpdatePendingOrderState,\n variables: {input}\n } );\n\n return resp.data.updatePendingOrder;\n },\n\n async rejectOrder ( {orderNumber, adminNotes} ) {\n const input = {\n orderNumber,\n adminNotes,\n orderStatus: 'REJECTED'\n };\n\n const resp = await client.mutate( {\n mutation: UpdatePendingOrderState,\n variables: {input}\n } );\n\n return resp.data.updatePendingOrder;\n }\n\n};\n\nexport default OrdersService;\n","import propOr from 'ramda/src/propOr';\nimport pathOr from 'ramda/src/pathOr';\nimport identity from 'ramda/src/identity';\nimport memoizeWith from 'ramda/src/memoizeWith';\nimport either from 'ramda/src/either';\nimport propEq from 'ramda/src/propEq';\nimport filter from 'ramda/src/filter';\nimport flatten from 'ramda/src/flatten'\nimport concat from 'ramda/src/concat'\nimport find from 'ramda/src/find';\nimport CustomerService from '@services/Customer';\n\nconst Address = {\n async getAddressBook () {\n const customer = await CustomerService.getCustomer( {withAddresses: true} );\n return customer.addresses;\n },\n getSuggestedBillingAddress ( addresses ) {\n const primaryAddresses = addresses.filter( addr => addr.primary === true );\n return find( propEq( 'addressType', 'Billing' ) )( primaryAddresses );\n },\n getDedupedAddressList ( target, list ) {\n const addrToString = addr => `${addr.address1} ${addr.address2} ${addr.city} ${addr.state} ${addr.postalCode}`;\n const targetIter = target.map( addr => [addrToString( addr ).toLowerCase(), addr.id] );\n const targetMap = new Map( targetIter );\n const filteredList = list.filter( addr => !targetMap.has( addrToString( addr ).toLowerCase() ) );\n return target.concat( filteredList );\n }\n};\n\nconst Wallet = {\n async getPaymentMethods () {\n const customer = await CustomerService.getCustomer( {withWallet: true} );\n return concat( customer.creditCard, customer.paymentTerms );\n },\n\n normalizeWallet ( {creditCards, paymentTerms} ) {\n console.log('NORMALIZE_WALLET')\n const cards = Array.isArray( creditCards ) ? creditCards.map( this.normalizeCreditCard ) : [];\n const terms = Array.isArray( paymentTerms ) ? paymentTerms.map( this.normalizePaymentTerm ) : [];\n return flatten( [cards, terms] );\n },\n\n // note - extend Payment with paymentMethodType:'creditCard' to distinguish in UI\n normalizeCreditCard ( payment ) {\n payment.paymentMethodType = 'creditCard';\n return payment;\n },\n\n // note - extend Payment with paymentMethodType:'terms' to distinguish in UI\n normalizePaymentTerm ( payment ) {\n payment.paymentMethodType = 'terms';\n // apply meta data to terms items for\n {upi.i18n.getTextFromKey( 'lbl-ultradentResponded' )}\n {' '} - {' '}\n
*At least one reason is required
\n\n
\n Try changing your filter selection or\n {' '}\n Show all reviews\n
\n\n
{children}
\n ;\nexport const Title = ( {children} ) =>\n{children}
\n\nexport const PurchaseDate = ( {date} ) => {\n return${i18nText( 'lbl-CookiesBlocked', 'Your browser is currently set to block cookies.' )}
\n${i18nText( 'lbl-WhyCookies-',\n 'Cookies are small text files which are stored on your computer. We use cookies to tell us when you are logged in and help remember what is in your shopping cart. In order to take advantage of this feature please enable cookies.' )}
\n${i18nText( 'lbl-AllowCookies',\n 'To learn how to allow cookies, check the online help in your web browser.' )}
\nPlease do not click back or refresh your browser as it may result in an error.
\nWe are working on resolving a problem with our Payment Service Provider which is\n preventing us from accepting new cards at this time.
\nIf you need to add a credit card to complete your payment please \n contact our Customer Support team by calling ${upi.conf.phoneTollFree}\n
\n\n Note – Some ad blockers may interfere with this payment feature. If you are using an ad blocker please consider \n disabling it for this page.\n
\nPlease complete your order by using one of the existing payment options if available.
\nIf your client needs to add a new credit card please ask them to sign in under their own credentials or have them call Customer Service.
\n