').css({ visibility: 'hidden', position: 'absolute', top: '-300px', width: '1px', height: '1px', overflow: 'hidden' }); if( $('html').attr('dir') == 'rtl' ){ elem.css({ right: '-300px' }); } else { elem.css({ left: '-300px' }); } elem.append( $('').addClass('ipsLoading ipsLoading_noAnim').css({ display: 'block' }) ); $('body').append( elem ); }, /** * Sets up our global ajax handlers * * @returns {void} */ _setAjaxConfig = function () { // Make sure all ajax requests have our secure key & adsess var data = { csrfKey: ips.getSetting('csrfKey') }; if( ips.getSetting('adsess') ){ _.extend( data, { adsess: ips.getSetting('adsess') }); } $.ajaxSetup({ data: data, cache: true }); // Add global loading indicator ability var count = 0; $( document ) .ajaxSend( function (event, request, settings) { request.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); if( !_.isUndefined( settings ) && settings.showLoading === true ){ if( !$('#elAjaxLoading').length ){ getContainer().append( templates.render('core.general.ajax') ); } count++; ips.utils.anim.go( 'fadeIn fast', $('#elAjaxLoading') ); } }) .ajaxComplete( function (event, request, settings) { if( !_.isUndefined( settings ) && settings.showLoading === true ){ count--; if( count === 0 ){ ips.utils.anim.go( 'fadeOut fast', $('#elAjaxLoading') ); } } // Check for redirect response if( !_.isUndefined( settings ) && !settings.bypassRedirect ){ var responseJson = null; if( !_.isUndefined( request.responseJSON ) && !_.isUndefined( request.responseJSON.redirect ) ) { responseJson = request.responseJSON; } else if( !_.isUndefined( request.responseText ) ) { try { var jsonResponse = $.parseJSON( request.responseText ); if( jsonResponse && !_.isUndefined( jsonResponse.redirect ) ) { responseJson = jsonResponse; } } catch( err ){} } if( responseJson ){ // Do we have a flash message to show? if( !_.isUndefined( responseJson.message ) && responseJson.message != '' ){ ips.utils.cookie.set( 'flmsg', responseJson.message ); } if ( responseJson.redirect.match( /#/ ) ) { window.location.href = responseJson.redirect; window.location.reload(); } else { window.location = responseJson.redirect; } } } // Re-parse cookies ips.utils.cookie.init(); }); }, /** * Config getter * * @param {string} key Setting key to return * @returns {mixed} Config setting, or undefined if it doesn't exist */ getSetting = function (key) { return _settings[ key ]; }, /** * Return full settings object * * @returns {object} Settings object */ getAllSettings = function () { return _settings; }, /** * Config setter * * @param {string} key Key to set * @param {mixed} value Setting value * @returns {void} */ setSetting = function (key, value) { _settings[ key ] = value; }, /** * Adds strings to our language object * * @param {mixed} strings Either an {object} of key/values, or a {string} as a key * @param {string} [...] If strings is a string, this param is the value * @returns {void} */ setString = function (strings) { if( _.isString( strings ) && arguments.length == 2 && _.isString( arguments[1] ) ){ strings = {}; strings[ arguments[0] ] = arguments[1]; } else if( !_.isObject( strings ) ){ Debug.warn("Invalid strings object passed to addString"); return; } $.each( strings, function (key, value ){ _strings[ key ] = value; }); }, /** * Detect if a language string exists * * @param {mixed} key The key * @returns {bool} */ haveString = function (key) { return !_.isUndefined( _strings[ key ] ); }, /** * Retrieves a string from storage, and interpolates values if needed * * @param {mixed} strings Either an {object} of key/values, or a {string} as a key * @param {string} [...] If strings is a string, this param is the value * @returns {string} The interpolated string (empty if the key does not exist) */ getString = function (key, values) { if( _.isUndefined( _strings[ key ] ) ){ Debug.warn("The string '" + key + "' doesn't exist"); return ''; } var thisString = _strings[ key ], values = values || {}; // Do we have special values to parse? if( !_.indexOf( thisString, '{{' ) ){ return thisString; } // Add some vars into the values _.extend( values, { baseURL: ips.getSetting('baseURL') }); try { return _.template( thisString )( values ); } catch (err) { return ( Debug.isEnabled() ) ? "[Error using language string " + key + "]" : ""; } }, /** * Returns the location in which we're running * * @returns {string} Location key */ getLocation = function () { return _location; }, /** * Create a module, checking that each namespace is ready to accept * modules. If the init method exists on the given module, it is added * to the document.ready queue. * * @param {string} name The full module path to create * @param {function} fn The module definition * @returns {void} */ createModule = function (name, fn) { var bits = name.split('.'), currentPath = window; var tmpName = []; // Loop through the path pieces and ensure they exist if( bits.length ){ for( var i = 0; i < bits.length; i++ ){ if( _.isUndefined( currentPath[ bits[i] ] ) ){ currentPath[ bits[i] ] = {}; } currentPath = currentPath[ bits[i] ]; } } else { return false; } // Assign our module to the path currentPath = _.extend( currentPath, fn.call( currentPath ) ); // Set up init if it exists if( _.isFunction( currentPath.init ) ){ $( document ).ready( function () { currentPath.init.call( currentPath ); }); } $( document ).trigger( 'moduleCreated', [ name ] ); }, /** * Provides a pluralized version of a string based on the supplied value * * @param {string} stringKey The key of the language string containing the pluralization tag * @param {number} value The value to be pluralized * @returns {void} */ pluralize = function (stringKey, params) { // Get the string we'll work with var word = stringKey; // Get the pluralization tags from it var i = 0; if( !_.isArray( params ) ){ params = [ params ]; } word = word.replace( /\{(!|\d+?)?#(.*?)\}/g, function (a,b,c,d) { // {# [1:count][?:counts]} if( !b || b == '!' ){ b = i; i++; } var value; var fallback; var output = ''; var replacement = params[ b ] + ''; c.replace( /\[(.+?):(.+?)\]/g, function (w,x,y,z) { var xLen = x.length * -1; if( x == '?' ){ fallback = y.replace( '#', replacement ); } else if( x.charAt(0) == '%' && x.substring( 1 ) == replacement.substring( 0, x.substring( 1 ).length ) ){ value = y.replace( '#', replacement ); } else if( x.charAt(0) == '*' && x.substring( 1 ) == replacement.substr( -x.substring( 1 ).length ) ){ value = y.replace( '#', replacement ); } else if( x == replacement ) { value = y.replace( '#', replacement ); } }); output = a.replace( /^\{/, '' ).replace(/\}$/, '' ).replace( '!#', '' ); output = output.replace( b + '#', replacement ).replace( '#', replacement ); output = $.trim( output.replace( /\[.+\]/, value == null ? fallback : value ) ); return output; }); return word; }, testConsole = function () { if( window.atob && window.console ){ console.log( window.atob("ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgd293ICAgICAgICAgICAgICAgICAgICAgICAgICAgI\ CAgIAogICAgICAgICAgICAgICAgICAgICAgICBzdWNoIGZvcnVtICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAga\ G93IGFqYXggICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICB2ZXJ5IGNvbW11bml0eSAgICAgIC\ AgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdWNoIG1lbWJlcgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg\ ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCg==") ); } return ''; }; var templates = function () { var _templateStore = {}; /** * Sets a mustache template * * @param {string} key Key name for this template * @param {mixed} template Template, as string or function which returns a string * @returns {void} */ var set = function (key, template) { _templateStore[ key ] = template; }, /** * Return a mustache template * * @param {string} key Key name for the template to retrieve * @returns {string} Template contents */ get = function (key) { if( _templateStore[ key ] ){ if( _.isFunction( _templateStore[ key ] ) ){ return _templateStore[ key ](); } else { return _templateStore[ key ]; } } return ''; }, /** * Renders a mustache template * * @param {string} key Key name for this template * @param {object} obj Object of values with which to render the template * @returns {string} The rendered contents */ render = function (key, obj) { // Add some common vars obj = _.extend( obj || {}, { baseURL: ips.getSetting('baseURL'), lang: _lang }); return Mustache.render( get( key ), obj ); }, /** * Returns a compile mustache template ready for us * * @param {string} key Key name for this template * @returns {function} A compiled template function */ compile = function (key) { if( _templateStore[ key ] ){ return Mustache.parse( get( key ) ); } return $.noop; }, /** * Returns a function that Mustache can use to swap out language strings * Allows {{#lang}}key{{/lang}} to be used in the templates * * @returns {function} A closure */ _lang = function () { return function (text, render) { return render( ips.getString( text ) ); } }; return { set: set, get: get, render: render, compile: compile }; }(); return { boot: boot, createModule: createModule, getSetting: getSetting, getAllSettings: getAllSettings, setSetting: setSetting, getAjax: getAjax, getContainer: getContainer, setString: setString, haveString: haveString, getString: getString, pluralize: pluralize, getLocation: getLocation, templates: templates, testConsole: testConsole }; }()); ips.boot( ipsSettings ); // Extend some core objects with useful methods String.prototype.startsWith = function (pattern) { return this.lastIndexOf(pattern, 0) === 0; }; }(jQuery, _));]]> = options.level && options.adapters.length ){ for( var i = 0; i < options.adapters.length; i++ ){ options.adapters[ i ].write( level, message ); } } return Debug; }, /** * Sets the enabled/disabled status of logging * * @param {boolean} enabled Whether logging should be enabled * @returns {object} Returns Debug */ setEnabled = function (enabled) { options.enabled = ( enabled === false ) ? false : true; return Debug; }, /** * See whether debugging is enabled * * @returns {boolean} */ isEnabled = function () { return options.enabled; }, /** * Sets the debugging severity threshold * * @param {number} level Level to set as minimum threshold * @returns {object} Returns Debug */ setLevel = function (level) { if( LEVEL[ level ] ){ options.level = LEVEL[ level ]; } return Debug; }, /** * Adds an adapter to use for logging * * @param {number} level Level to set as minimum threshold * @returns {object} Returns Debug */ addAdapter = function (adapter) { if( _.isObject( adapter ) ){ options.adapters.push( adapter ); } return Debug; }, /** * Clears all adapters * * @returns {object} Returns Debug */ clearAdapters = function () { options.adapters = []; return Debug; }; return { // logging methods debug: debug, log: debug, // Alias for matt info: info, warn: warn, error: error, // other methods setEnabled: setEnabled, setLevel: setLevel, addAdapter: addAdapter, clearAdapters: clearAdapters, isEnabled: isEnabled }; }(); /** Default Console adapter */ var Console = function() {}; Console.prototype.write = function ( level, msg ){ if( window.console ){ switch( level ){ case 1: if( _.isObject( msg ) ){ console.dir( msg ); } else { console.log( msg ); } break; case 2: console.info( msg ); break; case 3: console.warn( msg ); break; case 4: console.error( msg ); break; } } }; Debug.addAdapter( new Console ); if ( ipsDebug || ( !_.isUndefined( window.localStorage ) && window.localStorage.getItem('DEBUG') ) ) { Debug.setEnabled( true ).setLevel( 'DEBUG' ).info("Enabled logging"); } }(jQuery, _));]]> controllerOne( mixin1; mixin2 ), controllerTwo, controllerThree, returns: *
		 * {
		 * 	controllerOne: [ mixin1, mixin2 ],
		 *	controllerTwo: [],
		 * 	controllerThree: []
		 * }
		 * 
* * @returns {string} */ _getControllersAndMixins = function (controllerString) { var controllers = {}; var pieces = controllerString.split(','); for( var i = 0; i < pieces.length; i++ ){ pieces[i] = $.trim( pieces[i] ); // Fix case issues on user-submitted content if( !_.isUndefined( _controllerCaseMap[ pieces[i] ] ) ){ pieces[i] = _controllerCaseMap[ pieces[i] ]; } if( pieces[i].indexOf('(') === -1 ){ controllers[ pieces[i] ] = []; continue; } var p = pieces[i].match( /([a-zA-Z0-9.]+)\((.+?)\)/i ); var mixinPieces = []; _.each( p[2].split(';'), function (val) { mixinPieces.push( $.trim( val ) ); }); controllers[ p[1] ] = mixinPieces; } return controllers; }, /** * Returns an incremental controller ID * Controller IDs are used to enable controllers to identify events that they * emitted themselves. * * @returns {string} */ getInstanceID = function () { return 'ipscontroller' + (++instanceID); }, /** * Allows an element to be cleaned externally. If the element passed is not a controller scope, * it'll search down one level of the DOM to find controllers. * * @param {element} elem The element to clean * @returns {string} */ cleanContentsOf = function (elem) { Debug.log('Cleaning contents of controller'); $( elem ).find('[data-controller]') .each( function () { var loopController = $( this ); var controllers = loopController.data( '_controllerObjs' ) || []; if( controllers.length ){ loopController.data('_controllerObjs', []); for( var i = 0; i < controllers.length; i++ ){ controllers[i]._destroy.apply( controllers[i] ); delete controllers[i]; } } }); // Remove any widgets that exist in this elem ips.ui.destructAllWidgets( $( elem ) ); }, /** * Initializes a controller instance by creating a new function, extending it with * the controller methods then initializing it on the relevant dom node * * @param {element} elem The element that will form the scope of this controller * @param {string} controllerID ID of this controller * @returns {void} */ initControllerOnElem = function (elem, controllerID, mixins) { if( !_controllers[ controllerID ] ){ Debug.error("Controller '" + controllerID + "' has not been registered"); return; } if( _.isUndefined( $( elem ).data('_controllers') )){ $( elem ).data('_controllers', []); } $( elem ).data('_controllers').push( controllerID ); if( _.isUndefined( _prototypes[ controllerID ] ) ){ // Fetch our controller prototype _prototypes[ controllerID ] = getBaseController(); // Extend with our specific controller methods $.extend( true, _prototypes[ controllerID ].prototype, _controllers[ controllerID ] ); } // And init if( _.isUndefined( $( elem ).data( '_controllerObjs' ) ) ){ $( elem ).data( '_controllerObjs', [] ); } var controllers = $( elem ).data( '_controllerObjs' ); var obj = new _prototypes[ controllerID ](elem, controllerID); controllers.push( obj ); // Any mixins? // Auto mixins first if( !_.isUndefined( _autoMixins[ controllerID ] ) && _.size( _autoMixins[ controllerID ] ) ){ _.each( _autoMixins[ controllerID ], function (val, key) { _autoMixins[ controllerID ][ key ].call( obj ); }); } // Then the manually-specified ones if( mixins.length ){ for( var i = 0; i < mixins.length; i++ ){ if( !_.isUndefined( _manualMixins[ controllerID ] ) && !_.isUndefined( _manualMixins[ controllerID ][ mixins[i] ] ) ){ _manualMixins[ controllerID ][ mixins[i] ].call( obj ); } } } if( _.isFunction( obj.initialize ) ){ obj.initialize.call( obj ); } $( elem ).removeData( '_controller' + controllerID ); $( document ).trigger( 'controllerReady', { controllerID: obj.controllerID, controllerType: obj.controllerType, controllerElem: elem }); }, /** * Finds controllers within a node that have an ID matching the provided name * Wildcard character * supported at the front or end of the controller parameter * * @param {string} controller Controller name to find * @param {element} node Optional node to search in (document by default) * @returns {function} */ _findSubControllers = function (controller, node) { var results = []; node = ( node && ( _.isElement( node ) || node.jquery ) ) ? node : document; if( controller.indexOf('*') === -1 ){ results = $( node ).find('[data-controller*="' + controller + '"]'); } else { var pieces = controller.split('.'); if( pieces[0] == '*' ){ pieces.shift(); results = $( node ).find('[data-controller$="' + pieces.join('.') + '"]'); } else if( pieces[ pieces.length - 1 ] == '*' ){ pieces.pop(); results = $( node ).find('[data-controller^="' + pieces.join('.') + '"]'); } } return results; }, /** * Returns a new function that will form our controller prototype * * @returns {function} */ getBaseController = function () { /** Base controller definition */ var baseController = function (scope, type) { this.controllerType = type; this.controllerID = getInstanceID(); this.scope = $( scope ); this._eventListeners = []; var self = this; // Advice methods - inspired by http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/ // and Twitter Flight var adviceFuncs = { before: function (baseFn, newFn) { return function () { newFn.apply( this, arguments ); return baseFn.apply( this, arguments ); }; }, after: function (baseFn, newFn) { return function () { var toReturn = baseFn.apply( this, arguments ); newFn.apply( this, arguments ); return toReturn; } }, around: function (baseFn, newFn) { return function () { var args = ips.utils.argsToArray( arguments ); args.unshift( baseFn.bind( this ) ); return newFn.apply( this, args ); } } } _.each( ['before', 'after', 'around'], _.bind( function (type) { this[ type ] = function (base, fn) { if( _.isUndefined( this[ base ] ) || !_.isFunction( this[ base ] ) ){ Debug.log( "Method '" + base + '" is not present in controller ' + this.controllerID ); return; } // Replace our base method with a wrapped version this[ base ] = adviceFuncs[ type ]( this[ base ], fn ); }; }, this ) ); //Debug.info("Initialized " + this.controllerID + " of type " + this.controllerType); }; baseController.method('_destroy', function () { Debug.log( 'Destroyed instance ' + this.controllerID + ' of ' + this.controllerType ); // Remove each event listener that was created in this controller if( this._eventListeners.length ){ for( var i = 0; i < this._eventListeners.length; i++ ){ var data = this._eventListeners[i]; if( data['delegate'] ){ data['elem'].off( data['ev'], data['delegate'], data['fn'] ); } else { data['elem'].off( data['ev'], data['fn'] ); } } } if( _.isFunction( this.destroy ) ){ this.destroy.call( this ); } // Remove reference to scope so that GC can do its thing this.scope = null; }); // Searches for controllers within the current, triggers a destroy event and deletes the controller objs baseController.method('cleanContents', function () { Debug.log('Cleaning contents of controller'); this.scope.find('[data-controller]') .each( function () { var loopController = $( this ); var controllers = loopController.data( '_controllerObjs' ) || []; if( controllers.length ){ loopController.data('_controllerObjs', []); for( var i = 0; i < controllers.length; i++ ){ controllers[i]._destroy.apply( controllers[i] ); delete controllers[i]; } } }); // Remove any widgets that exist in this elem ips.ui.destructAllWidgets( this.scope ); }); baseController.method('trigger', function (elem, ev, data) { // Convert silly arguments object to an array var args = ips.utils.argsToArray( arguments ); elem = ( !_.isElement( elem ) && !elem.jquery ) ? this.scope : $( args.shift() ); ev = args[0]; data = args[1] || {}; // Add our origin to the event if( !data.stack ){ data.stack = []; } data.stack.push( 'controllers.' + this.controllerType + '.' + this.controllerID ); elem.trigger( ev, data ); }); baseController.method('on', function (elem, ev, delegate, fn) { // Convert silly arguments object to an array var args = ips.utils.argsToArray( arguments ); // Reconfigure our args as necessary elem = ( !_.isElement( elem ) && elem != document && elem != window ) ? this.scope : $( args.shift() ); ev = args[0]; fn = ( args.length == 3 ) ? args[2] : args[1]; delegate = ( args.length == 3 ) ? args[1] : undefined; if( !_.isFunction( fn ) ){ Debug.warn("Callback function for " + ev + " doesn't exist in " + this.controllerType + " (" + this.controllerID + ")"); return; } // Bind our callback to the controller fn = _.bind( fn, this ); // Set up the event if( delegate ){ elem.on( ev, delegate, fn ); this._eventListeners.push({ elem: elem, event: ev, delegate: delegate, fn: fn }); } else { elem.on( ev, fn ); this._eventListeners.push({ elem: elem, event: ev, fn: fn }); } }); baseController.method('triggerOn', function (controller, ev, data) { var toTrigger = _findSubControllers( controller, this.scope ); if( !toTrigger.length ){ return; } data = data || {}; // Add our origin to the event if( !data.stack ){ data.stack = []; } data.stack.push( 'controllers.' + this.controllerType + '.' + this.controllerID ); toTrigger.trigger( ev, data ); }); return baseController; }; return { initControllerOnElem: initControllerOnElem, register: register, mixin: mixin, isRegistered: isRegistered, init: init, cleanContentsOf: cleanContentsOf }; }); }( jQuery, _ ));]]>
') .attr( 'type', 'text' ) .attr( 'data-role', 'minimizedVersion' ) .attr( 'placeholder', ips.getString('specifyLocation') ) .on( 'focus', function (e) { // Hide the minimized version $( this ).hide(); // Set country if applicable if( options.country ){ $( elem ).find('[data-role="countrySelect"]').val( options.country ); } // Init init( elem, options, e ); // Show the main address fields elem.show().find('input').first().focus(); }); var value = []; // Build the existing value elem.find('input, select').each( function (addressPart) { if( $( this ).val() ){ if( $( this ).is('select') ){ value.push( $.trim( $( this ).find('option[value="' + $( this ).val() + '"]').text() ) ); } else { value.push( $.trim( $( this ).val() ) ); } } }); if( value.length ){ tempInput.val( value.join(', ') ); } elem .hide() .after( tempInput ); }; var countryChange = function(elem, options, e) { ips.getAjax()( ips.getSetting('baseURL') + 'index.php?app=core&module=system&controller=ajax&do=states&country=' + $( e.target ).val() ) .done( function (response) { if( response.length ) { if( !$( elem ).find('[data-role="regionSelect"]').length ) { var regionText = $( elem ).find('[data-role="regionText"]'); } else { var regionText = $( elem ).find('[data-role="regionSelect"]'); } var regionSelect = $(''); regionText.attr( 'name', regionSelect.attr('name') ).val( "" ); regionSelect.replaceWith( regionText ); } } } ); if ( typeof elem.attr('data-ipsAddressForm-googlePlaces') !== typeof undefined && elem.attr('data-ipsAddressForm-googlePlaces') !== false ) { if ( elem.attr( 'data-ipsAddressForm-googlePlaces' ) === 'loaded' ) { googlePlacesInit( elem ); } else { if ( typeof google === 'undefined' ) { ips.loader.get( [ 'https://maps.googleapis.com/maps/api/js?key=' + elem.attr('data-ipsAddressForm-googleApiKey') + '&libraries=places&sensor=false&callback=ips.ui.addressForm.googlePlacesCallback' ] ); $( window ).on( 'googlePlacesLoaded', function(){ elem.attr( 'data-ipsAddressForm-googlePlaces', 'loaded' ); googlePlacesInit( elem ); }); } else { elem.attr( 'data-ipsAddressForm-googlePlaces', 'loaded' ); googlePlacesInit( elem ); } } } }; var addAddressLine = function (elem, value) { var lastLine = elem.find('[data-role="addressLine"]').closest('li').last(); var newLine = lastLine.clone(); if( value ) { newLine.find('input').focus().val( value ); } lastLine.after( newLine ); }; var recalculateAddAddressLineButton = function (elem) { elem.find( '[data-role="addAddressLine"]' ).remove(); var button = $(''); button.click( function () { addAddressLine(elem, ''); recalculateAddAddressLineButton(elem); }); elem.find('[data-role="addressLine"]').last().after( button ); }; var googlePlacesInit = function (elem) { var googlePlacesInput = $(elem).find('[data-role="addressLine"]').first(); var options = { types: [ 'geocode' ], componentRestrictions: { country: $(elem).find('[data-role="countrySelect"]').val() } }; var autocomplete = new google.maps.places.Autocomplete( googlePlacesInput.get(0), options ); googlePlacesInput.on( 'focus', function () { if( navigator.geolocation ){ navigator.geolocation.getCurrentPosition( function (position) { var geolocation = new google.maps.LatLng( position.coords.latitude,position.coords.longitude ); autocomplete.setBounds( new google.maps.LatLngBounds( geolocation, geolocation ) ); }); } } ); googlePlacesInput.on( 'keypress', function(e) { if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) { return false; } } ); google.maps.event.addListener( autocomplete, 'place_changed', function () { var place = autocomplete.getPlace(); var i; var streetNumber; var addressLines = []; for( i in place.address_components ) { switch ( place.address_components[i].types[0] ) { case 'street_number': streetNumber = place.address_components[i].long_name; break; case 'street_address': case 'route': case 'sublocality': case 'neighborhood': case 'premise': case 'subpremise': addressLines.push( place.address_components[i].long_name ); break; case 'administrative_area_level_1': case 'administrative_area_level_2': elem.find('[data-role="regionSelect"]').val( place.address_components[i].long_name ); elem.find('[data-role="regionText"]').focus().val( place.address_components[i].long_name ); break; case 'locality': case 'postal_town': elem.find('[data-role="city"]').focus().val( place.address_components[i].long_name ); break; case 'postal_code': elem.find('[data-role="postalCode"]').focus().val( place.address_components[i].long_name ); break; } } for( var i = 0; i < $( elem ).find('[data-role="addressLine"]').length; i++ ){ $( elem ).find('[data-role="addressLine"]').val( '' ); } setTimeout( function () { var existingAddressLines = $( elem ).find('[data-role="addressLine"]').length; if( streetNumber && addressLines[0] ){ // Some locales don't use "{streetNumber} {addressLine}" so see if the first part of formatted_address looks like it matches, and if so, use that... var splitFormatted = place.formatted_address.split(','); if ( splitFormatted[0].indexOf( addressLines[0] ) != -1 ) { addressLines[0] = splitFormatted[0]; } // Otherwise, fallback to "{streetNumber} {addressLine}" else { addressLines[0] = streetNumber + ' ' + addressLines[0]; } } for( var i = 0; i < addressLines.length; i++ ){ if( existingAddressLines ){ $( elem ).find('[data-role="addressLine"]').slice( i, 1 ).focus().val( addressLines[i] ); existingAddressLines--; } else { addAddressLine(elem, addressLines[i]); } } }, 50 ); }); } // Register this module as a widget to enable the data API and // jQuery plugin functionality ips.ui.registerWidget( 'addressForm', ips.ui.addressForm, ['minimize','country','requireFullAddress'] ); return { respond: respond, googlePlacesCallback: googlePlacesCallback }; }); }(jQuery, _));]]> /* global ips, _, Debug */ /** * Invision Community * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * * ips.ui.alert.js - Alert widget for alerts, prompts, confirms. * * Author: Rikki Tissier */ ;( function($, _, undefined){ "use strict"; ips.createModule('ips.ui.alert', function(){ var respond = function (elem, options) { alertObj( options, elem ); }, show = function (options) { alertObj( options ); }; ips.ui.registerWidget('alert', ips.ui.alert, [ 'message', 'type', 'icon', 'focus' ] ); return { respond: respond, show: show }; }); /** * Alert instance * * @param {object} options The options passed into this instance * @returns {void} */ var alertObj = function (options) { var alert = null, modal = null; var _defaults = { type: 'alert', // alert, confirm, prompt, verify message: ips.getString('generic_confirm'), buttons: { ok: ips.getString('ok'), cancel: ips.getString('cancel'), yes: ips.getString('yes'), no: ips.getString('no') }, icon: 'info', showIcon: true, callbacks: {} }; var _icons = { warn: 'fa fa-exclamation-triangle', success: 'fa fa-check-circle', info: 'fa fa-info-circle', ok: 'fa fa-check-circle', question: 'fa fa-question-circle' }; options = _.defaults( options || {}, _defaults ); /** * Initialization * * @returns {void} */ var init = function () { // Build alert _buildAlert(); _setUpEvents(); }, /** * Set up events for the alert - button clicks, and document events for keyboard accessibility * * @returns {void} */ _setUpEvents = function () { alert.on( 'click', '[data-action]', _clickButton ); $( document ).on('keydown', function (e) { switch( e.keyCode ){ case ips.ui.key.ESCAPE: if( options.type == 'alert' ){ alert.find('[data-action="ok"]').click(); } else { alert.find('[data-action="cancel"], [data-action="no"]').click(); } break; case ips.ui.key.ENTER: alert.find('[data-action="ok"], [data-action="yes"]').click(); break; } }); }, /** * Event handler for clicking a button in the alert * Looks for a callback to execute, then removes the alert from the dom * * @param {event} e Event object * @returns {void} */ _clickButton = function (e) { var button = $( e.currentTarget ); var action = button.attr('data-action'); var value = null; if( options.type == 'prompt' ){ value = alert.find('[data-role="promptValue"]').val(); } if( _.isFunction( options.callbacks[ action ] ) ){ options.callbacks[ action ]( value ); } _remove(); }, /** * Removes the alert from the dom and unsets the events * * @returns {void} */ _remove = function () { modal.remove(); ips.utils.anim.go( 'fadeOutDown fast', alert ).done( function () { alert.remove(); }); }, /** * Builds the alert element based on options * * @returns {void} */ _buildAlert = function () { var parts = {}, buttons = []; // Icon if( options.showIcon ){ parts.icon = ips.templates.render( 'core.alert.icon', { icon: _icons[ options.icon ] || options.icon }); } parts.id = 'alert_' + ( Math.round( Math.random() * 10000000 ) ); parts.text = options.message; if( options.subText ){ parts.subtext = ips.templates.render( 'core.alert.subText', { text: options.subText }); } // Build buttons switch( options.type ){ case 'alert': buttons.push( ips.templates.render( 'core.alert.button', { action: 'ok', title: options.buttons.ok, extra: 'ipsButton_primary' })); break; case 'confirm': case 'prompt': buttons.push( ips.templates.render( 'core.alert.button', { action: 'ok', title: options.buttons.ok, extra: 'ipsButton_primary' })); buttons.push( ips.templates.render( 'core.alert.button', { action: 'cancel', title: options.buttons.cancel, extra: 'ipsButton_light' })); break; case 'verify': buttons.push( ips.templates.render( 'core.alert.button', { action: 'yes', title: options.buttons.yes, extra: 'ipsButton_primary' })); if( options.buttons.no ){ buttons.push( ips.templates.render( 'core.alert.button', { action: 'no', title: options.buttons.no, extra: 'ipsButton_light' })); } if( options.buttons.cancel ){ buttons.push( ips.templates.render( 'core.alert.button', { action: 'cancel', title: options.buttons.cancel, extra: 'ipsButton_light' })); } break; } parts.buttons = buttons.join(''); // Prompt? if( options.type == 'prompt' ){ parts.text += ips.templates.render( 'core.alert.prompt'); } // Build box var tmpAlert = $.parseHTML( $.trim( ips.templates.render( 'core.alert.box', parts ) ) ); alert = $( tmpAlert[0] ); $('body').append( alert ); // Build modal modal = ips.ui.getModal(); modal.css({ zIndex: ips.ui.zIndex() }).show(); alert.css( { zIndex: ips.ui.zIndex() } ); ips.utils.anim.go('zoomIn fast', alert ); // Focus the appropriate element if( options.focus ){ alert .find('[data-action="' + options.focus + '"]') .focus(); } else { if( options.type == 'prompt' ){ alert .find('[data-role="promptValue"]') .val( options.value || '' ) .focus(); } else { alert .find('[data-action="ok"], [data-action="yes"]') .focus(); } } }; init(); }; }(jQuery, _)); '); } else if( count.length === 0 ){ elem.find('.cAutoCheckIcon').html(''); } else { elem.find('.cAutoCheckIcon').html(''); } if( count.length ){ elem.find('[data-role="autoCheckCount"]').text( count.length ).show(); } else if( elem.find('[data-role="autoCheckCount"]').is(':visible') ) { ips.utils.anim.go( 'fadeOut', elem.find('[data-role="autoCheckCount"]') ); } return count.length; }; init(); return { destruct: destruct, refresh: refresh }; }; }(jQuery, _));]]> ", "'", "\"" ] ), unique: false, customValues: true, fieldTemplate: 'core.autocomplete.field', resultsTemplate: 'core.autocomplete.resultWrapper', resultItemTemplate: 'core.autocomplete.resultItem', tokenTemplate: 'core.autocomplete.token', addTokenTemplate: 'core.autocomplete.addToken', addTokenText: ips.getString( 'add_tag' ), queryParam: 'q', forceLower: false, minLength: 1, minAjaxLength: 1, commaTrigger: true }; var respond = function (elem, options) { if( !$( elem ).data('_autocomplete') ){ $( elem ).data('_autocomplete', autocompleteObj(elem, _.defaults( options, defaults ) ) ); } }, /** * Destruct the autocomplete widget on this elem * * @param {element} elem The element to check * @returns {void} */ destruct = function (elem) { var obj = getObj( elem ); if( !_.isUndefined( obj ) ){ obj.destruct(); } }, /** * Retrieve the autocomplete instance (if any) on the given element * * @param {element} elem The element to check * @returns {mixed} The dialog instance or undefined */ getObj = function (elem) { elem = $( elem ); if( elem.data('_autocomplete') ){ return elem.data('_autocomplete'); } else if( $( '[name="' + elem.attr('name') + '_original' + '"]' ).length && $( '[name="' + elem.attr('name') + '_original' + '"]' ).data('_autocomplete') ){ return $( '[name="' + elem.attr('name') + '_original' + '"]' ).data('_autocomplete'); } return undefined; }; ips.ui.registerWidget('autocomplete', ips.ui.autocomplete, [ 'multiValues', 'freeChoice', 'dataSource', 'maxItems', 'itemSep', 'resultsElem', 'unique', 'commaTrigger', 'fieldTemplate', 'resultsTemplate', 'resultItemTemplate', 'tokenTemplate', 'addTokenTemplate', 'addTokenText', 'queryParam', 'minLength', 'maxLength', 'forceLower', 'disallowedCharacters', 'minAjaxLength' ] ); return { respond: respond, destruct: destruct, getObj: getObj }; }); /** * autocomplete instance * * @param {element} elem The element this widget is being created on * @param {object} options The options passed into this instance * @returns {void} */ var autocompleteObj = function (elem, options, e) { var timer, blurTimer, lastValue = '', originalTextField, valueField, textField, dataSource, elemID = $( elem ).identify().attr('id'), wrapper, inputItem, resultsElem, selectedToken, disabled = false, required = false, tooltip = null, tooltipTimer = null, mouseOverResults = false, hasError = false; /** * Sets up this instance. The datasource object is chosen depending on what options and/or * attributes are provided. We can fetch results from a local , remotely via ajax * or not look up results from a data source at all. * * @returns {void} */ var init = function () { if( $( elem ).is('textarea, input[type="text"], input[type="search"]') ){ originalTextField = $( elem ); } else { originalTextField = $( elem ).find('textarea, input[type="text"], input[type="search"]').first(); } try { options.disallowedCharacters = $.parseJSON( options.disallowedCharacters ); } catch (err) { Debug.error("Couldn't parse disallowed characters option"); } // Add our autocomplete wrapper to the page, and move the element into it _buildWrapper(); // Set up the data source for this control _getDataSource(); // Remove list from original field originalTextField.removeAttr('list'); // Build the list if( dataSource.type != 'none' ){ _buildResultsList(); } if( originalTextField.is(':disabled') ){ disabled = true; } if( originalTextField.is('[required]') ){ required = true; originalTextField .removeProp('required') .removeAttr('aria-required'); } // Turn off autocomplete and spellcheck so the browser menu doesn't get in the way textField .prop( 'autocomplete', 'off' ) .prop( 'spellcheck', false ) .prop( 'disabled', disabled ) .attr( 'aria-autocomplete', 'list' ) .attr( 'aria-haspopup', 'true' ) .attr( 'tabindex', originalTextField.attr('tabindex') || '' ); if( options.maxLength ){ textField.attr( 'maxlength', options.maxLength + 1 ); } $( document ).on( 'click', _documentClick ); wrapper.click(function(e) { e.stopPropagation(); return false; }); // Set up events textField .on( 'focus', _focusField ) .on( 'blur', _blurField ) .on( 'keydown', _keydownField ) .on( 'keyup', _keyupField ) .on( 'keypress', _keypressField ); wrapper .on( 'click', _clickWrapper ) .on( 'click', '[data-action="addToken"]', _clickAddToken ) .on( 'keydown', _keydownWrapper ) .on( 'propChanged', _propChanged ) .toggleClass( 'ipsField_autocompleteDisabled', disabled ); _buildInitialTokens(); elem .on( 'blur', function () { // For closed tagging, our text field is the same element as the autocomplete widget // In that case, we don't want to blur otherwise we go into a death loop. if( textField !== elem ){ textField.trigger('blur'); } }) .trigger( 'autoCompleteReady', { elemID: elemID, elem: elem, currentValues: tokens.getValues() }); // Some widgets like prefixedAutocomplete may not set up until after this UI module runs, so make sure we trigger the 'ready' event when needed elem.on( 'reissueReady', function() { elem.trigger( 'autoCompleteReady', { elemID: elemID, elem: elem, currentValues: tokens.getValues() }); }); }, /** * Destruct * Removes event handlers assosciated with this instance * * @returns {void} */ destruct = function () { $( document ).off( 'click', _documentClick ); }, /** * Determines whether any errors are present in the autocomplete widget (e.g. duplicates) * * @returns {void} */ hasErrors = function () { return hasError; }, /** * Responds to the propChange event, which we use to determine whether the original field has been toggled * * @returns {void} */ _propChanged = function (e) { disabled = originalTextField.is(':disabled'); wrapper.toggleClass( 'ipsField_autocompleteDisabled', disabled ); }, /** * Builds tokens from whatever values exist in the original text field * * @returns {void} */ _buildInitialTokens = function () { var value = _getOriginalValue(); if( !value ){ return; } // Get individual values var splitValues = _.without( value.split( "\n" ), '' ); var itemCount = 0; itemCount = splitValues.length; // Clear field, as tokens.add() will re-add value originalTextField.val(''); if( splitValues.length ){ for( var i = 0; i < itemCount; i++ ){ _addToken( splitValues[i] ); } } }, /** * Returns the value from the original text field (i.e. the value provided by the backend on pag load) * * @returns {string} */ _getOriginalValue = function () { return originalTextField.val(); //return _.unescape( originalTextField.val() ).replace("'", "'").replace("'", "'"); }, /** * Builds the element that results will appear in * * @returns {void} */ _buildResultsList = function () { if( options.resultsElem && $( options.resultsElem ).length ){ resultsElem = $( options.resultsElem ); return; } var resultsList = ips.templates.render( options.resultsTemplate, { id: elemID }); wrapper.append( resultsList ); resultsElem = $('#' + elemID + '_results'); resultsElem .on('mouseover', '[data-value]', function (e) { results.select( $( e.currentTarget ) ); }) .on('mouseenter', function () { mouseOverResults = true; }) .on('mouseleave', function () { mouseOverResults = false; }) .on('click', '[data-value]', function (e) { _addToken( $( e.currentTarget ).attr('data-value') ); textField.focus(); }) .attr( 'aria-busy', 'false' ); }, /** * Builds the wrapper element that looks like a text input, but allows us to insert * items as tokens * * @returns {void} */ _buildWrapper = function () { var existingClasses = elem[0].className; $( elem ) .after( ips.templates.render( options.fieldTemplate, { id: elemID })) .removeClass( existingClasses ); wrapper = $( '#' + elemID + '_wrapper' ); inputItem = $( '#' + elemID + '_inputItem' ); // If users have to choose from a predefined list, we'll hide the text field // and build a link which will show the results panel if( !options.freeChoice ){ var insertElem = ips.templates.render('core.autocomplete.addToken', { text: options.addTokenText }); textField = elem; } else { var insertElem = $('').attr( { type: 'text', id: elemID + '_dummyInput' }) .prop( 'autocomplete', 'off' ); textField = insertElem; } // Make a copy of the original text field using its name. This is because it's difficult to set // arbitrary values in the original text field later if it's associated with a datalist. var name = originalTextField.attr('name'); originalTextField.attr( 'name', originalTextField.attr('name') + '_original' ); valueField = $('",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,la=/\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("