/home/vianto5/ceibaresidencial.mx/wp-content/plugins/official-facebook-pixel/js
NameSizeModeActions
facebook_pixel_add_to_cart.js18280644editdlrm
facebook_signal.js110750644editdlrm
fbe_allinone.js8028760644editdlrm
settings_page.js158000644editdlrm
Edit: /home/vianto5/ceibaresidencial.mx/wp-content/plugins/official-facebook-pixel/js/fbe_allinone.js (802876B)
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0) { if (response.data.data.length === 1) { // Auto-select single pixel var pixelId = response.data.data[0].id; var pixelName = response.data.data[0].name || ''; _this.saveSettingsFBL4B(pixelId, businessId, pixelName); } else { // Multiple pixels — store on config for renderConnectedState to use window.fbl4bConfig.pendingPixels = response.data.data; // Force re-render with meaningful state change _this.setState({fbl4bPixels: response.data.data}); } } else { // Store empty array so renderConnectedState shows "no pixels" state window.fbl4bConfig.pendingPixels = []; _this.setState({fbl4bPixels: []}); } }, error: function(jqXHR, textStatus, errorThrown) { _this.consoleLog('FBL4B: Failed to fetch pixels: ' + errorThrown); // Store empty array so renderConnectedState shows "no pixels" state window.fbl4bConfig.pendingPixels = []; _this.setState({fbl4bPixels: []}); } }); }, /** * Clear all FBL4B stored data when user disconnects. * Calls the delete endpoint and reloads the page. */ clearFBL4BData: function clearFBL4BData() { var _this = this; jQuery.ajax({ type: 'post', url: window.fbl4bConfig.deleteConfigKeys, success: function onSuccess(data, _textStatus, _jqXHR) { // Clear local config window.fbl4bConfig.businessId = null; window.fbl4bConfig.pixelId = null; window.fbl4bConfig.installed = false; // Reload page to show fresh onboarding state window.location.reload(); }, error: function() { _this.consoleLog('FBL4B: Failed to clear stored data'); // Still reload to show onboarding window.location.reload(); } }); }, /** * Save settings for FBL4B flow. * * @param pixelId - The pixel ID to save * @param businessId - The client_business_id to save */ saveSettingsFBL4B: function saveSettingsFBL4B(pixelId, businessId, pixelName) { var _this = this; jQuery.ajax({ type: 'post', url: window.fbl4bConfig.setSaveSettingsRoute, data: ajaxParam({ pixelId: pixelId || '', businessId: businessId || '', pixelName: pixelName || '', }), success: function onSuccess(data, _textStatus, _jqXHR) { var response = data; if (response.success) { window.fbl4bConfig.businessId = businessId; window.fbl4bConfig.pixelId = pixelId; window.fbl4bConfig.pixelName = pixelName || ''; if (pixelId) { // Pixel selected — update config and re-render inline window.fbl4bConfig.installed = true; window.fbl4bConfig.pendingPixels = null; _this.setState({pixelId: pixelId, installed: 'true', businessId: businessId}); _this.showEventsManagerSection(pixelId); // Hide Ads sections for FBL4B (they require MBE scopes) _this.hideAdsPlugin(); } else { } } else { } }, error: function () { _this.consoleLog('FBL4B: There was a problem saving the settings'); _this.showFBL4BNotice('Failed to save connection. Please try again.', 'error'); } }); }, /** * Reload the FBL4B iframe with updated parameters. * Called after settings are saved to show the "connected" state. * Uses displayBusinessId (the id field) which is what the iframe expects. */ reloadFBL4BIframe: function reloadFBL4BIframe(pixelId, displayBusinessId) { var _this = this; var baseUrl = window.fbl4bConfig.iframeUrl; var params = 'app_id=' + window.fbl4bConfig.appId + '&config_id=' + window.fbl4bConfig.configId + '&installed=true' + '&version=' + window.fbl4bConfig.version; if (displayBusinessId) { params += '&business_id=' + displayBusinessId; } if (pixelId) { params += '&pixel_id=' + pixelId; } var newIframeUrl = baseUrl + params; // Update the iframe src jQuery('#fbe-iframe iframe').attr('src', newIframeUrl); }, saveSettings: function saveSettings( pixelId, accessToken, externalBusinessId ){ var _this = this; if(!pixelId){ console.error('Meta Business Extension Error: got no pixel_id'); return; } if(!accessToken){ console.error('Meta Business Extension Error: got no access token'); return; } if(!externalBusinessId){ console.error('Meta Business Extension Error: got no external business id'); return; } jQuery.ajax({ type: 'post', url: window.facebookBusinessExtensionConfig.setSaveSettingsRoute, async : false, data: ajaxParam({ pixelId: pixelId, accessToken: accessToken, externalBusinessId: externalBusinessId, }), success: function onSuccess(data, _textStatus, _jqXHR) { var response = data; let msg = ''; if (response.success) { _this.setState({pixelId: pixelId}); _this.showEventsManagerSection(pixelId); msg = "The Meta Pixel with ID: " + pixelId + " is now installed on your website."; } else { msg = "There was a problem saving the pixel. Please try again"; } }, error: function () { console.error('There was a problem saving the pixel with id', pixelId); } }); }, deleteFBAssets: function deleteFBAssets() { var _this = this; jQuery.ajax({ type: 'delete', url: window.facebookBusinessExtensionConfig.deleteConfigKeys, success: function onSuccess(data, _textStatus, _jqXHR) { let msg = ''; if(data.success) { msg = data.message; _this.hideEventsManagerSection(); }else { msg = data.error_message; } _this.setState({installed: 'false'}); }, error: function() { console.error('There was a problem deleting the connection, Please try again.'); } }); }, showAdsPlugin: function showAdsPlugin() { jQuery("#meta-ads-plugin").show(); }, hideAdsPlugin: function hideAdsPlugin() { jQuery("#meta-ads-plugin").hide(); }, componentDidMount: function componentDidMount() { this.bindMessageEvents(); // For FBL4B: If we have an access token but missing business_id or pixel_id, // fetch the missing data before rendering the iframe if (this.isFBL4BEnabled()) { this.initFBL4BData(); // Show the cancel link after 5s delay — only if still in loading state setTimeout(function() { var cancelLink = document.getElementById('fbl4b-cancel-link'); if (cancelLink) { cancelLink.style.display = 'block'; } }, 5000); // Handle inline pixel selection dropdown changes jQuery(document).on('change', '#fbl4b-pixel-select-inline', function() { var btn = jQuery('#fbl4b-select-pixel-inline-btn'); if (jQuery(this).val()) { btn.prop('disabled', false).removeClass('fbl4b-btn-disabled'); } else { btn.prop('disabled', true).addClass('fbl4b-btn-disabled'); } }); } }, /** * Initialize FBL4B data on page load. * Always validates the access token by calling /me API. * If token is revoked (user disconnected), clears all FBL4B data. */ initFBL4BData: function initFBL4BData() { var _this = this; var config = window.fbl4bConfig; // Check if FBL4B is connected (installed flag comes from connectionType) if (!config.installed) { return; } // Always validate the access token by calling /me API _this.validateFBL4BConnection(function(isValid) { if (!isValid) { _this.consoleLog("FBL4B: Access token is invalid/revoked, clearing stored data..."); _this.clearFBL4BData(); return; } // If we already have a pixel selected, verify it's still accessible if (config.pixelId) { _this.verifyPixelValidity(config.businessId, config.pixelId); return; } // If we have business_id but no pixel_id, fetch pixels // This only happens if user abandoned pixel selection if (config.businessId && !config.pixelId) { _this.fetchPixelsForBusiness(config.businessId); return; } // If we're missing business_id entirely, fetch it first if (!config.businessId) { _this.fetchPixelIdAndSave(); } }); }, /** * Validate the FBL4B connection by calling /me API. * If the access token is revoked, the API will return an error. * * @param callback - Callback function that receives a boolean (valid/invalid) */ validateFBL4BConnection: function validateFBL4BConnection(callback) { var _this = this; jQuery.ajax({ type: 'post', url: window.fbl4bConfig.validateTokenRoute, timeout: 30000, success: function onSuccess(response) { if (response.success && response.data && response.data.valid) { // Check if businessId is missing from stored config var storedBusinessId = window.fbl4bConfig.businessId; if (!storedBusinessId || storedBusinessId === '') { window.fbl4bConfig.businessId = response.data.client_business_id; // Save businessId to backend (partial update), then continue validation _this.saveSettingsFBL4B(null, response.data.client_business_id); } callback(true); } else { callback(false); } }, error: function(jqXHR, textStatus, errorThrown) { _this.consoleLog("FBL4B: Token validation failed - " + textStatus); _this.consoleLog('FBL4B: Token validation error: ' + errorThrown); callback(false); } }); }, /** * Verify the stored pixel is still accessible via the business's pixel list. * If the pixel was removed from the connected app on Meta's side, * it won't appear in the fetch results. Disconnects if no pixels remain, * otherwise prompts re-selection. */ verifyPixelValidity: function verifyPixelStillAccessible(businessId, pixelId) { var _this = this; if (!businessId) { return; } jQuery.ajax({ type: 'post', url: window.fbl4bConfig.fetchPixelsRoute, data: { businessId: businessId }, timeout: 15000, success: function(response) { if (response.success && response.data && response.data.data) { var pixels = response.data.data; var found = pixels.some(function(p) { return p.id === pixelId; }); if (!found) { _this.clearStoredPixel(); window.fbl4bConfig.pixelId = ''; window.fbl4bConfig.pixelName = ''; window.fbl4bConfig.pendingPixels = pixels; _this.setState({ fbl4bPixelId: '' }); } } else if (!response.success && response.data && response.data.code === 'no_pixels') { _this.clearFBL4BData(); } }, error: function() { } }); }, /** * Save the businessId to backend and reload page. * Used when businessId was missing from stored config but token is valid. */ saveBusinessIdAndReload: function saveBusinessIdAndReload(businessId) { var _this = this; var config = window.fbl4bConfig; jQuery.ajax({ type: 'post', url: config.setSaveSettingsRoute, data: { pixelId: config.pixelId, businessId: businessId }, success: function onSuccess(data, _textStatus, _jqXHR) { window.location.reload(); }, error: function() { // Continue anyway with updated local config } }); }, /** * Render the connected state UI (plugin-side, not iframe). * Shows Business ID, Pixel ID with Reconnect and Disconnect options. */ renderConnectedState: function renderConnectedState(config, pixels) { var _this = this; var disconnectUrl = FBL4B_DISCONNECT_URL + '?business_id=' + (config.businessId || ''); var hasPixel = config.pixelId && config.pixelId !== ''; var needsPixelSelection = !hasPixel && pixels && pixels.length > 0; var noPixelsAvailable = !hasPixel && pixels && pixels.length === 0; // Hide the fbe-iframe and render connected state in a sibling container var iframeEl = document.getElementById('fbe-iframe'); if (iframeEl) { iframeEl.style.display = 'none'; // Hide the back button if it exists var backBtnEl = document.getElementById('fbl4b-back-btn'); if (backBtnEl) { backBtnEl.style.display = 'none'; } // Hide the upgrade banner if it exists (server-rendered, stays after JS transition) var upgradeBanner = document.querySelector('.fbl4b-upgrade-notice'); if (upgradeBanner) { upgradeBanner.style.display = 'none'; } // Create or reuse a sibling container for the connected state var connectedEl = document.getElementById('fbl4b-connected'); if (!connectedEl) { connectedEl = document.createElement('div'); connectedEl.id = 'fbl4b-connected'; iframeEl.parentNode.insertBefore(connectedEl, iframeEl); } connectedEl.style.display = ''; // Render connected state into the sibling container ReactDOM.render(this._buildConnectedState(config, pixels, hasPixel, needsPixelSelection, noPixelsAvailable, disconnectUrl), connectedEl); return React.createElement('div', {style: {display: 'none'}}); } return this._buildConnectedState(config, pixels, hasPixel, needsPixelSelection, noPixelsAvailable, disconnectUrl); }, _buildConnectedState: function _buildConnectedState(config, pixels, hasPixel, needsPixelSelection, noPixelsAvailable, disconnectUrl) { var _this = this; return React.createElement( 'div', {className: 'fbl4b-connected-container'}, // Header React.createElement( 'div', {className: 'fbl4b-connected-header'}, React.createElement( 'div', {className: 'fbl4b-connected-header-left'}, React.createElement('span', { className: 'fbl4b-connected-logo', dangerouslySetInnerHTML: {__html: ''} }), React.createElement('span', {className: 'fbl4b-connected-logo-text'}, 'Meta'), React.createElement('span', {className: 'fbl4b-connected-title'}, 'Your Business is Connected to Meta'), React.createElement( 'span', {className: hasPixel ? 'fbl4b-connected-badge' : 'fbl4b-connected-badge fbl4b-connected-badge-setup'}, hasPixel ? '✓ Active' : '⚠ Setup Required' ) ) ), // Connection details React.createElement( 'div', {className: 'fbl4b-connected-details'}, // Business ID row React.createElement( 'div', {className: 'fbl4b-connected-row fbl4b-connected-row-border'}, React.createElement( 'div', {className: 'fbl4b-connected-label'}, React.createElement('span', null, 'Business ID') ), React.createElement('span', {className: 'fbl4b-connected-value'}, config.businessId) ), // Pixel row — shows ID when selected, or inline selection when pending React.createElement( 'div', {className: needsPixelSelection ? 'fbl4b-connected-row fbl4b-pixel-row-selection' : 'fbl4b-connected-row'}, React.createElement( 'div', {className: 'fbl4b-connected-label'}, React.createElement('span', null, 'Meta Pixel'), !hasPixel ? React.createElement( 'span', {className: 'fbl4b-selection-badge'}, '⚠ Selection required' ) : null ), hasPixel ? React.createElement('span', {className: 'fbl4b-connected-value'}, config.pixelName ? config.pixelName + ' (' + config.pixelId + ')' : config.pixelId) : needsPixelSelection ? React.createElement( 'div', {className: 'fbl4b-pixel-inline-select'}, React.createElement( 'select', { id: 'fbl4b-pixel-select-inline', className: 'fbl4b-pixel-select', onChange: function(e) { var btn = document.getElementById('fbl4b-select-pixel-inline-btn'); var selectEl = e.target; if (e.target.value) { if (btn) { btn.disabled = false; btn.className = 'fbl4b-btn-confirm'; } selectEl.style.borderColor = '#d1d5db'; selectEl.style.color = '#1c2b33'; } else { if (btn) { btn.disabled = true; btn.className = 'fbl4b-btn-confirm fbl4b-btn-disabled'; } selectEl.style.borderColor = '#dc2626'; selectEl.style.color = '#dc2626'; } } }, React.createElement('option', {value: ''}, 'Select Pixel'), pixels.map(function(pixel) { return React.createElement('option', {key: pixel.id, value: pixel.id, 'data-name': pixel.name || ''}, pixel.name + ' (' + pixel.id + ')'); }) ), React.createElement( 'button', { id: 'fbl4b-select-pixel-inline-btn', className: 'fbl4b-btn-confirm fbl4b-btn-disabled', onClick: function() { var selectEl = document.getElementById('fbl4b-pixel-select-inline'); var selectedPixelId = selectEl ? selectEl.value : ''; if (selectedPixelId) { var selectedOption = selectEl.options[selectEl.selectedIndex]; var selectedPixelName = selectedOption ? selectedOption.getAttribute('data-name') || '' : ''; _this.saveSettingsFBL4B(selectedPixelId, config.businessId, selectedPixelName); } } }, 'Confirm' ) ) : null ), // Helper text below pixel row needsPixelSelection ? React.createElement( 'p', {className: 'fbl4b-pixel-helper-text'}, 'Select a pixel to use on this WordPress site to start tracking conversions.' ) : null, // No pixels alert noPixelsAvailable ? React.createElement( 'div', {className: 'fbl4b-pixel-alert', style: {marginTop: '8px'}}, React.createElement('p', {className: 'fbl4b-pixel-alert-text'}, '⚠️ No Meta Pixels were found for your business. Please create a pixel in ', React.createElement('a', {href: 'https://business.facebook.com/events_manager', target: '_blank', className: 'fbl4b-link'}, 'Events Manager'), ', then click Refresh.' ), React.createElement( 'button', { onClick: function() { _this.fetchPixelsForBusiness(config.businessId); }, className: 'fbl4b-btn-primary', style: {marginRight: '10px'} }, 'Refresh Pixels' ) ) : null ), // Connection Settings accordion — collapses Reconnect & Disconnect React.createElement( 'div', {className: 'fbl4b-connected-section-last fbl4b-connection-settings'}, React.createElement( 'div', { className: 'fbl4b-connection-settings-header', onClick: function() { _this.setState({showConnectionSettings: !_this.state.showConnectionSettings}); } }, React.createElement('span', {className: 'fbl4b-connection-settings-title'}, 'Connection Settings'), React.createElement('span', {className: 'fbl4b-connection-settings-arrow'}, _this.state.showConnectionSettings ? '▴' : '▾') ), _this.state.showConnectionSettings ? React.createElement( 'div', {className: 'fbl4b-connection-settings-body'}, // Reconnect — only when fully connected hasPixel ? React.createElement( 'div', {className: 'fbl4b-connection-settings-item'}, React.createElement('h4', {className: 'fbl4b-connected-section-title'}, 'Reconnect'), React.createElement('p', {className: 'fbl4b-connected-section-desc'}, 'Re-run the connection flow to update your linked assets.' ), !_this.state.showReconnectConfirm ? React.createElement( 'button', { onClick: function() { _this.setState({showReconnectConfirm: true}); }, className: 'fbl4b-btn-primary' }, 'Reconnect' ) : React.createElement( 'div', {className: 'fbl4b-reconnect-confirm'}, React.createElement('p', {style: {margin: '0 0 12px 0', fontSize: '14px', color: '#1c2b33', lineHeight: '1.5'}}, 'This will start a new authentication flow. Your current pixel configuration will be preserved until you complete the new connection.' ), React.createElement( 'div', {style: {display: 'flex', gap: '8px'}}, React.createElement( 'button', { onClick: function() { _this.setState({showReconnectConfirm: false, showReconnectIframe: true}); }, className: 'fbl4b-btn-primary' }, 'Continue' ), React.createElement( 'button', { onClick: function() { _this.setState({showReconnectConfirm: false}); }, className: 'fbl4b-btn-secondary' }, 'Cancel' ) ) ) ) : null, // Disconnect React.createElement( 'div', {className: 'fbl4b-connection-settings-item'}, React.createElement('h4', {className: 'fbl4b-connected-section-title'}, 'Disconnect'), React.createElement( 'p', {className: 'fbl4b-connected-section-desc'}, 'This will remove the connection between this WordPress site and your Meta Business Portfolio. Your Pixel and other assets will remain accessible in ', React.createElement('a', {href: FBL4B_BUSINESS_MANAGER_URL + '?business_id=' + (config.businessId || ''), target: '_blank', className: 'fbl4b-link'}, 'Meta Business Manager'), '.' ), !_this.state.showDisconnectWarning ? React.createElement( 'button', { onClick: function() { _this.setState({showDisconnectWarning: true}); }, className: 'fbl4b-btn-danger' }, 'Disconnect from Meta' ) : React.createElement( 'div', {className: 'fbl4b-reconnect-confirm'}, React.createElement('p', {className: 'fbl4b-disconnect-warning-title'}, '⚠️ To complete disconnection:'), React.createElement( 'ol', {className: 'fbl4b-disconnect-warning-steps'}, React.createElement('li', null, 'Click "Continue" below to open Meta Business Settings'), React.createElement('li', null, 'Find and remove this WordPress integration'), React.createElement('li', null, 'Return here and refresh this page') ), React.createElement( 'div', {style: {display: 'flex', gap: '8px', marginTop: '12px'}}, React.createElement( 'button', { onClick: function() { window.open(disconnectUrl, '_blank'); }, className: 'fbl4b-btn-danger' }, 'Continue to Meta Business Settings' ), React.createElement( 'button', { onClick: function() { _this.setState({showDisconnectWarning: false}); }, className: 'fbl4b-btn-secondary' }, 'Cancel' ) ) ) ) ) : null ) ); }, /** * Show a WordPress-style admin notice for FBL4B events. * @param {string} message - The message to display * @param {string} type - 'error', 'success', or 'warning' */ showFBL4BNotice: function showFBL4BNotice(message, type) { // Remove any existing FBL4B notices var existing = document.querySelectorAll('.fbl4b-notice'); existing.forEach(function(el) { el.remove(); }); var notice = document.createElement('div'); notice.className = 'fbl4b-notice fbl4b-notice-' + type; var messageEl = document.createElement('p'); messageEl.textContent = message; notice.appendChild(messageEl); var dismissBtn = document.createElement('button'); dismissBtn.className = 'fbl4b-notice-dismiss'; dismissBtn.textContent = '×'; dismissBtn.onclick = function() { notice.remove(); }; notice.appendChild(dismissBtn); // Insert before the iframe container var iframeContainer = document.getElementById('fbe-iframe'); if (iframeContainer && iframeContainer.parentNode) { iframeContainer.parentNode.insertBefore(notice, iframeContainer); } // Auto-dismiss after 10 seconds setTimeout(function() { if (notice.parentNode) { notice.remove(); } }, 10000); }, consoleLog: function consoleLog(message) { var debug = this.isFBL4BEnabled() ? window.fbl4bConfig.debug : window.facebookBusinessExtensionConfig.debug; if(debug) { console.log(message); } }, /** * Build query params for FBL4B iframe. * FBL4B uses a simplified set of params compared to MBE. * When we have pixelId, include business_id and pixel_id. */ queryParamsFBL4B: function queryParamsFBL4B() { var config = window.fbl4bConfig; // app_id and config_id are already in the iframe URL from PHP var params = '&version=' + config.version; if (config.pixelId) { params += '&installed=true'; if (config.businessId) { params += '&business_id=' + config.businessId; } params += '&pixel_id=' + config.pixelId; } else { params += '&installed=false'; } return params; }, /** * Build query params for legacy MBE iframe. */ queryParams: function queryParams() { return 'app_id='+window.facebookBusinessExtensionConfig.appId + '&timezone='+window.facebookBusinessExtensionConfig.timeZone+ '&external_business_id='+window.facebookBusinessExtensionConfig.externalBusinessId+ '&installed='+this.state.installed+ '&system_user_name='+window.facebookBusinessExtensionConfig.systemUserName+ '&business_vertical='+window.facebookBusinessExtensionConfig.businessVertical+ '&version='+window.facebookBusinessExtensionConfig.version+ '¤cy='+ window.facebookBusinessExtensionConfig.currency + '&business_name='+ window.facebookBusinessExtensionConfig.businessName + '&channel=' + window.facebookBusinessExtensionConfig.channel + '&hide_create_ad_button=' + true; }, render: function render() { var _this = this; try { // For FBL4B: Check if we need to show pixel selection instead of iframe if (_this.isFBL4BEnabled()) { var config = window.fbl4bConfig; // Debug: Log all config values // If we have access token but missing pixel_id, check if we have // pending pixels to show for selection. If pendingPixels is set, // fall through to the connected state which renders the pixel selection UI. // If still fetching (pendingPixels not set), show loading placeholder. if (config.installed && !config.pixelId) { // If pendingPixels is set (including empty array), the pixel fetch // is complete — fall through to renderConnectedState which handles // pixel selection, no-pixels, and connected states. if (config.pendingPixels !== undefined && config.pendingPixels !== null) { return _this.renderConnectedState(config, config.pendingPixels); } // Still fetching pixels — show loading placeholder return React.createElement( 'div', { id: 'fbl4b-loading', className: 'fbl4b-loading-container' }, React.createElement('p', {className: 'fbl4b-loading-text'}, 'Configuring your Meta Business connection...' ), React.createElement( 'div', { id: 'fbl4b-cancel-link', style: {display: 'none'} }, React.createElement( 'button', { onClick: function() { if (confirm('This will disconnect your Meta Business connection. Continue?')) { _this.clearFBL4BData(); } }, className: 'fbl4b-link', style: {background: 'none', border: 'none', cursor: 'pointer', marginTop: '12px', fontSize: '13px'} }, 'Cancel and start over' ) ) ); } // If user clicked Reconnect, show the iframe for re-authentication if (_this.state.showReconnectIframe) { // Show the main container and hide the connected state var iframeEl = document.getElementById('fbe-iframe'); var connectedEl = document.getElementById('fbl4b-connected'); if (iframeEl) { iframeEl.style.display = ''; } if (connectedEl) { connectedEl.style.display = 'none'; } var iframeUrl = config.iframeUrl; // iframeUrl already includes app_id and config_id from PHP var reconnectParams = '&version=' + config.version + '&installed=false'; // Render back button outside fbe-iframe var backBtnEl = document.getElementById('fbl4b-back-btn'); if (!backBtnEl) { backBtnEl = document.createElement('div'); backBtnEl.id = 'fbl4b-back-btn'; backBtnEl.style.margin = '20px 20px 12px 0'; iframeEl.parentNode.insertBefore(backBtnEl, iframeEl); } backBtnEl.style.display = ''; ReactDOM.render( React.createElement( 'button', { onClick: function() { _this.setState({showReconnectIframe: false}); }, className: 'fbl4b-btn-secondary' }, '← Back to Connection Status' ), backBtnEl ); // Render just the iframe inside fbe-iframe return React.createElement( 'iframe', { src: iframeUrl + reconnectParams, className: 'fbl4b-iframe-full' } ); } // Connected state — show when we have businessId (with or without pixel) if (config.businessId) { var pendingPixels = config.pendingPixels || null; return _this.renderConnectedState(config, pendingPixels); } // Onboarding state - show iframe for initial setup var iframeUrl = config.iframeUrl; var queryParams = _this.queryParamsFBL4B(); // If upgrading from MBE, show a back button to return to MBE connected state if (config.upgradeFromMBE) { return React.createElement( 'div', null, React.createElement( 'button', { onClick: function() { // Clear upgrade flag and redirect back without the param var url = new URL(window.location.href); url.searchParams.delete('upgrade_to_fbl4b'); window.location.href = url.toString(); }, style: { marginBottom: '16px' }, className: 'fbl4b-btn-secondary' }, '← Back to Current Connection' ), React.createElement( 'iframe', { src: iframeUrl + queryParams, className: 'fbl4b-iframe-full' } ) ); } return React.createElement( 'iframe', { src: iframeUrl + queryParams, className: 'fbl4b-iframe-full' } ); } // Legacy MBE flow var iframeUrl = window.facebookBusinessExtensionConfig.fbeLoginUrl; var queryParams = _this.queryParams(); return React.createElement( 'iframe', { src: iframeUrl + queryParams, className: 'fbl4b-iframe-full' } ); } catch (err) { console.error(err); } }, hideEventsManagerSection: function hideEventsManagerSection() { jQuery(".events-manager-wrapper").hide(); jQuery('#ad-creation-plugin').hide(); jQuery('#ad-insights-plugin').hide(); jQuery("#fb-adv-conf").hide(); jQuery(".events-manager-wrapper input#pixel-id").val(''); }, showEventsManagerSection: function showEventsManagerSection(pixelId) { jQuery(".events-manager-wrapper").show(); jQuery('#ad-creation-plugin').show(); jQuery('#ad-insights-plugin').show(); jQuery("#fb-adv-conf").show(); jQuery(".events-manager-wrapper input#pixel-id").val(pixelId); // Update Events Manager link with the correct pixel ID var sanitizedPixelId = String(pixelId).replace(/[^0-9]/g, ''); jQuery(".meta-event-manager a").attr("href", "https://business.facebook.com/events_manager2/list/pixel/" + sanitizedPixelId ); } }); // Render ReactDOM.render( React.createElement(FBEFlowContainer, null), document.getElementById('fbe-iframe') ); // Code to display the above container. var displayFBModal = function displayFBModal() { if (FBUtils.isIE()) { IEOverlay().render(); } }; (function main() { // Logic for when to display the container. if (document.readyState === 'interactive') { // in case the document is already rendered displayFBModal(); } else if (document.addEventListener) { // modern browsers document.addEventListener('DOMContentLoaded', displayFBModal); } else { document.attachEvent('onreadystatechange', function () { // IE <= 8 if (document.readyState === 'complete') { displayFBModal(); } }); } })(); },{"./IEOverlay":1,"./Modal":2,"./utils":191,"react":190,"react-dom":35}],4:[function(require,module,exports){ (function (process){(function (){ /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ 'use strict'; var _assign = require('object-assign'); // -- Inlined from fbjs -- var emptyObject = {}; if (process.env.NODE_ENV !== 'production') { Object.freeze(emptyObject); } var validateFormat = function validateFormat(format) {}; if (process.env.NODE_ENV !== 'production') { validateFormat = function validateFormat(format) { if (format === undefined) { throw new Error('invariant requires an error message argument'); } }; } function _invariant(condition, format, a, b, c, d, e, f) { validateFormat(format); if (!condition) { var error; if (format === undefined) { error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); } else { var args = [a, b, c, d, e, f]; var argIndex = 0; error = new Error(format.replace(/%s/g, function () { return args[argIndex++]; })); error.name = 'Invariant Violation'; } error.framesToPop = 1; // we don't care about invariant's own frame throw error; } } var warning = function(){}; if (process.env.NODE_ENV !== 'production') { var printWarning = function printWarning(format) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } var argIndex = 0; var message = 'Warning: ' + format.replace(/%s/g, function () { return args[argIndex++]; }); if (typeof console !== 'undefined') { console.error(message); } try { // --- Welcome to debugging React --- // This error was thrown as a convenience so that you can use this stack // to find the callsite that caused this warning to fire. throw new Error(message); } catch (x) {} }; warning = function warning(condition, format) { if (format === undefined) { throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument'); } if (format.indexOf('Failed Composite propType: ') === 0) { return; // Ignore CompositeComponent proptype check. } if (!condition) { for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { args[_key2 - 2] = arguments[_key2]; } printWarning.apply(undefined, [format].concat(args)); } }; } // /-- Inlined from fbjs -- var MIXINS_KEY = 'mixins'; // Helper function to allow the creation of anonymous functions which do not // have .name set to the name of the variable being assigned to. function identity(fn) { return fn; } var ReactPropTypeLocationNames; if (process.env.NODE_ENV !== 'production') { ReactPropTypeLocationNames = { prop: 'prop', context: 'context', childContext: 'child context' }; } else { ReactPropTypeLocationNames = {}; } function factory(ReactComponent, isValidElement, ReactNoopUpdateQueue) { /** * Policies that describe methods in `ReactClassInterface`. */ var injectedMixins = []; /** * Composite components are higher-level components that compose other composite * or host components. * * To create a new type of `ReactClass`, pass a specification of * your new class to `React.createClass`. The only requirement of your class * specification is that you implement a `render` method. * * var MyComponent = React.createClass({ * render: function() { * return
Hello World
; * } * }); * * The class specification supports a specific protocol of methods that have * special meaning (e.g. `render`). See `ReactClassInterface` for * more the comprehensive protocol. Any other properties and methods in the * class specification will be available on the prototype. * * @interface ReactClassInterface * @internal */ var ReactClassInterface = { /** * An array of Mixin objects to include when defining your component. * * @type {array} * @optional */ mixins: 'DEFINE_MANY', /** * An object containing properties and methods that should be defined on * the component's constructor instead of its prototype (static methods). * * @type {object} * @optional */ statics: 'DEFINE_MANY', /** * Definition of prop types for this component. * * @type {object} * @optional */ propTypes: 'DEFINE_MANY', /** * Definition of context types for this component. * * @type {object} * @optional */ contextTypes: 'DEFINE_MANY', /** * Definition of context types this component sets for its children. * * @type {object} * @optional */ childContextTypes: 'DEFINE_MANY', // ==== Definition methods ==== /** * Invoked when the component is mounted. Values in the mapping will be set on * `this.props` if that prop is not specified (i.e. using an `in` check). * * This method is invoked before `getInitialState` and therefore cannot rely * on `this.state` or use `this.setState`. * * @return {object} * @optional */ getDefaultProps: 'DEFINE_MANY_MERGED', /** * Invoked once before the component is mounted. The return value will be used * as the initial value of `this.state`. * * getInitialState: function() { * return { * isOn: false, * fooBaz: new BazFoo() * } * } * * @return {object} * @optional */ getInitialState: 'DEFINE_MANY_MERGED', /** * @return {object} * @optional */ getChildContext: 'DEFINE_MANY_MERGED', /** * Uses props from `this.props` and state from `this.state` to render the * structure of the component. * * No guarantees are made about when or how often this method is invoked, so * it must not have side effects. * * render: function() { * var name = this.props.name; * return
Hello, {name}!
; * } * * @return {ReactComponent} * @required */ render: 'DEFINE_ONCE', // ==== Delegate methods ==== /** * Invoked when the component is initially created and about to be mounted. * This may have side effects, but any external subscriptions or data created * by this method must be cleaned up in `componentWillUnmount`. * * @optional */ componentWillMount: 'DEFINE_MANY', /** * Invoked when the component has been mounted and has a DOM representation. * However, there is no guarantee that the DOM node is in the document. * * Use this as an opportunity to operate on the DOM when the component has * been mounted (initialized and rendered) for the first time. * * @param {DOMElement} rootNode DOM element representing the component. * @optional */ componentDidMount: 'DEFINE_MANY', /** * Invoked before the component receives new props. * * Use this as an opportunity to react to a prop transition by updating the * state using `this.setState`. Current props are accessed via `this.props`. * * componentWillReceiveProps: function(nextProps, nextContext) { * this.setState({ * likesIncreasing: nextProps.likeCount > this.props.likeCount * }); * } * * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop * transition may cause a state change, but the opposite is not true. If you * need it, you are probably looking for `componentWillUpdate`. * * @param {object} nextProps * @optional */ componentWillReceiveProps: 'DEFINE_MANY', /** * Invoked while deciding if the component should be updated as a result of * receiving new props, state and/or context. * * Use this as an opportunity to `return false` when you're certain that the * transition to the new props/state/context will not require a component * update. * * shouldComponentUpdate: function(nextProps, nextState, nextContext) { * return !equal(nextProps, this.props) || * !equal(nextState, this.state) || * !equal(nextContext, this.context); * } * * @param {object} nextProps * @param {?object} nextState * @param {?object} nextContext * @return {boolean} True if the component should update. * @optional */ shouldComponentUpdate: 'DEFINE_ONCE', /** * Invoked when the component is about to update due to a transition from * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState` * and `nextContext`. * * Use this as an opportunity to perform preparation before an update occurs. * * NOTE: You **cannot** use `this.setState()` in this method. * * @param {object} nextProps * @param {?object} nextState * @param {?object} nextContext * @param {ReactReconcileTransaction} transaction * @optional */ componentWillUpdate: 'DEFINE_MANY', /** * Invoked when the component's DOM representation has been updated. * * Use this as an opportunity to operate on the DOM when the component has * been updated. * * @param {object} prevProps * @param {?object} prevState * @param {?object} prevContext * @param {DOMElement} rootNode DOM element representing the component. * @optional */ componentDidUpdate: 'DEFINE_MANY', /** * Invoked when the component is about to be removed from its parent and have * its DOM representation destroyed. * * Use this as an opportunity to deallocate any external resources. * * NOTE: There is no `componentDidUnmount` since your component will have been * destroyed by that point. * * @optional */ componentWillUnmount: 'DEFINE_MANY', /** * Replacement for (deprecated) `componentWillMount`. * * @optional */ UNSAFE_componentWillMount: 'DEFINE_MANY', /** * Replacement for (deprecated) `componentWillReceiveProps`. * * @optional */ UNSAFE_componentWillReceiveProps: 'DEFINE_MANY', /** * Replacement for (deprecated) `componentWillUpdate`. * * @optional */ UNSAFE_componentWillUpdate: 'DEFINE_MANY', // ==== Advanced methods ==== /** * Updates the component's currently mounted DOM representation. * * By default, this implements React's rendering and reconciliation algorithm. * Sophisticated clients may wish to override this. * * @param {ReactReconcileTransaction} transaction * @internal * @overridable */ updateComponent: 'OVERRIDE_BASE' }; /** * Similar to ReactClassInterface but for static methods. */ var ReactClassStaticInterface = { /** * This method is invoked after a component is instantiated and when it * receives new props. Return an object to update state in response to * prop changes. Return null to indicate no change to state. * * If an object is returned, its keys will be merged into the existing state. * * @return {object || null} * @optional */ getDerivedStateFromProps: 'DEFINE_MANY_MERGED' }; /** * Mapping from class specification keys to special processing functions. * * Although these are declared like instance properties in the specification * when defining classes using `React.createClass`, they are actually static * and are accessible on the constructor instead of the prototype. Despite * being static, they must be defined outside of the "statics" key under * which all other static methods are defined. */ var RESERVED_SPEC_KEYS = { displayName: function(Constructor, displayName) { Constructor.displayName = displayName; }, mixins: function(Constructor, mixins) { if (mixins) { for (var i = 0; i < mixins.length; i++) { mixSpecIntoComponent(Constructor, mixins[i]); } } }, childContextTypes: function(Constructor, childContextTypes) { if (process.env.NODE_ENV !== 'production') { validateTypeDef(Constructor, childContextTypes, 'childContext'); } Constructor.childContextTypes = _assign( {}, Constructor.childContextTypes, childContextTypes ); }, contextTypes: function(Constructor, contextTypes) { if (process.env.NODE_ENV !== 'production') { validateTypeDef(Constructor, contextTypes, 'context'); } Constructor.contextTypes = _assign( {}, Constructor.contextTypes, contextTypes ); }, /** * Special case getDefaultProps which should move into statics but requires * automatic merging. */ getDefaultProps: function(Constructor, getDefaultProps) { if (Constructor.getDefaultProps) { Constructor.getDefaultProps = createMergedResultFunction( Constructor.getDefaultProps, getDefaultProps ); } else { Constructor.getDefaultProps = getDefaultProps; } }, propTypes: function(Constructor, propTypes) { if (process.env.NODE_ENV !== 'production') { validateTypeDef(Constructor, propTypes, 'prop'); } Constructor.propTypes = _assign({}, Constructor.propTypes, propTypes); }, statics: function(Constructor, statics) { mixStaticSpecIntoComponent(Constructor, statics); }, autobind: function() {} }; function validateTypeDef(Constructor, typeDef, location) { for (var propName in typeDef) { if (typeDef.hasOwnProperty(propName)) { // use a warning instead of an _invariant so components // don't show up in prod but only in __DEV__ if (process.env.NODE_ENV !== 'production') { warning( typeof typeDef[propName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName ); } } } } function validateMethodOverride(isAlreadyDefined, name) { var specPolicy = ReactClassInterface.hasOwnProperty(name) ? ReactClassInterface[name] : null; // Disallow overriding of base class methods unless explicitly allowed. if (ReactClassMixin.hasOwnProperty(name)) { _invariant( specPolicy === 'OVERRIDE_BASE', 'ReactClassInterface: You are attempting to override ' + '`%s` from your class specification. Ensure that your method names ' + 'do not overlap with React methods.', name ); } // Disallow defining methods more than once unless explicitly allowed. if (isAlreadyDefined) { _invariant( specPolicy === 'DEFINE_MANY' || specPolicy === 'DEFINE_MANY_MERGED', 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name ); } } /** * Mixin helper which handles policy validation and reserved * specification keys when building React classes. */ function mixSpecIntoComponent(Constructor, spec) { if (!spec) { if (process.env.NODE_ENV !== 'production') { var typeofSpec = typeof spec; var isMixinValid = typeofSpec === 'object' && spec !== null; if (process.env.NODE_ENV !== 'production') { warning( isMixinValid, "%s: You're attempting to include a mixin that is either null " + 'or not an object. Check the mixins included by the component, ' + 'as well as any mixins they include themselves. ' + 'Expected object but got %s.', Constructor.displayName || 'ReactClass', spec === null ? null : typeofSpec ); } } return; } _invariant( typeof spec !== 'function', "ReactClass: You're attempting to " + 'use a component class or function as a mixin. Instead, just use a ' + 'regular object.' ); _invariant( !isValidElement(spec), "ReactClass: You're attempting to " + 'use a component as a mixin. Instead, just use a regular object.' ); var proto = Constructor.prototype; var autoBindPairs = proto.__reactAutoBindPairs; // By handling mixins before any other properties, we ensure the same // chaining order is applied to methods with DEFINE_MANY policy, whether // mixins are listed before or after these methods in the spec. if (spec.hasOwnProperty(MIXINS_KEY)) { RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins); } for (var name in spec) { if (!spec.hasOwnProperty(name)) { continue; } if (name === MIXINS_KEY) { // We have already handled mixins in a special case above. continue; } var property = spec[name]; var isAlreadyDefined = proto.hasOwnProperty(name); validateMethodOverride(isAlreadyDefined, name); if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) { RESERVED_SPEC_KEYS[name](Constructor, property); } else { // Setup methods on prototype: // The following member methods should not be automatically bound: // 1. Expected ReactClass methods (in the "interface"). // 2. Overridden methods (that were mixed in). var isReactClassMethod = ReactClassInterface.hasOwnProperty(name); var isFunction = typeof property === 'function'; var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false; if (shouldAutoBind) { autoBindPairs.push(name, property); proto[name] = property; } else { if (isAlreadyDefined) { var specPolicy = ReactClassInterface[name]; // These cases should already be caught by validateMethodOverride. _invariant( isReactClassMethod && (specPolicy === 'DEFINE_MANY_MERGED' || specPolicy === 'DEFINE_MANY'), 'ReactClass: Unexpected spec policy %s for key %s ' + 'when mixing in component specs.', specPolicy, name ); // For methods which are defined more than once, call the existing // methods before calling the new property, merging if appropriate. if (specPolicy === 'DEFINE_MANY_MERGED') { proto[name] = createMergedResultFunction(proto[name], property); } else if (specPolicy === 'DEFINE_MANY') { proto[name] = createChainedFunction(proto[name], property); } } else { proto[name] = property; if (process.env.NODE_ENV !== 'production') { // Add verbose displayName to the function, which helps when looking // at profiling tools. if (typeof property === 'function' && spec.displayName) { proto[name].displayName = spec.displayName + '_' + name; } } } } } } } function mixStaticSpecIntoComponent(Constructor, statics) { if (!statics) { return; } for (var name in statics) { var property = statics[name]; if (!statics.hasOwnProperty(name)) { continue; } var isReserved = name in RESERVED_SPEC_KEYS; _invariant( !isReserved, 'ReactClass: You are attempting to define a reserved ' + 'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' + 'as an instance property instead; it will still be accessible on the ' + 'constructor.', name ); var isAlreadyDefined = name in Constructor; if (isAlreadyDefined) { var specPolicy = ReactClassStaticInterface.hasOwnProperty(name) ? ReactClassStaticInterface[name] : null; _invariant( specPolicy === 'DEFINE_MANY_MERGED', 'ReactClass: You are attempting to define ' + '`%s` on your component more than once. This conflict may be ' + 'due to a mixin.', name ); Constructor[name] = createMergedResultFunction(Constructor[name], property); return; } Constructor[name] = property; } } /** * Merge two objects, but throw if both contain the same key. * * @param {object} one The first object, which is mutated. * @param {object} two The second object * @return {object} one after it has been mutated to contain everything in two. */ function mergeIntoWithNoDuplicateKeys(one, two) { _invariant( one && two && typeof one === 'object' && typeof two === 'object', 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.' ); for (var key in two) { if (two.hasOwnProperty(key)) { _invariant( one[key] === undefined, 'mergeIntoWithNoDuplicateKeys(): ' + 'Tried to merge two objects with the same key: `%s`. This conflict ' + 'may be due to a mixin; in particular, this may be caused by two ' + 'getInitialState() or getDefaultProps() methods returning objects ' + 'with clashing keys.', key ); one[key] = two[key]; } } return one; } /** * Creates a function that invokes two functions and merges their return values. * * @param {function} one Function to invoke first. * @param {function} two Function to invoke second. * @return {function} Function that invokes the two argument functions. * @private */ function createMergedResultFunction(one, two) { return function mergedResult() { var a = one.apply(this, arguments); var b = two.apply(this, arguments); if (a == null) { return b; } else if (b == null) { return a; } var c = {}; mergeIntoWithNoDuplicateKeys(c, a); mergeIntoWithNoDuplicateKeys(c, b); return c; }; } /** * Creates a function that invokes two functions and ignores their return vales. * * @param {function} one Function to invoke first. * @param {function} two Function to invoke second. * @return {function} Function that invokes the two argument functions. * @private */ function createChainedFunction(one, two) { return function chainedFunction() { one.apply(this, arguments); two.apply(this, arguments); }; } /** * Binds a method to the component. * * @param {object} component Component whose method is going to be bound. * @param {function} method Method to be bound. * @return {function} The bound method. */ function bindAutoBindMethod(component, method) { var boundMethod = method.bind(component); if (process.env.NODE_ENV !== 'production') { boundMethod.__reactBoundContext = component; boundMethod.__reactBoundMethod = method; boundMethod.__reactBoundArguments = null; var componentName = component.constructor.displayName; var _bind = boundMethod.bind; boundMethod.bind = function(newThis) { for ( var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++ ) { args[_key - 1] = arguments[_key]; } // User is trying to bind() an autobound method; we effectively will // ignore the value of "this" that the user is trying to use, so // let's warn. if (newThis !== component && newThis !== null) { if (process.env.NODE_ENV !== 'production') { warning( false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName ); } } else if (!args.length) { if (process.env.NODE_ENV !== 'production') { warning( false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName ); } return boundMethod; } var reboundMethod = _bind.apply(boundMethod, arguments); reboundMethod.__reactBoundContext = component; reboundMethod.__reactBoundMethod = method; reboundMethod.__reactBoundArguments = args; return reboundMethod; }; } return boundMethod; } /** * Binds all auto-bound methods in a component. * * @param {object} component Component whose method is going to be bound. */ function bindAutoBindMethods(component) { var pairs = component.__reactAutoBindPairs; for (var i = 0; i < pairs.length; i += 2) { var autoBindKey = pairs[i]; var method = pairs[i + 1]; component[autoBindKey] = bindAutoBindMethod(component, method); } } var IsMountedPreMixin = { componentDidMount: function() { this.__isMounted = true; } }; var IsMountedPostMixin = { componentWillUnmount: function() { this.__isMounted = false; } }; /** * Add more to the ReactClass base class. These are all legacy features and * therefore not already part of the modern ReactComponent. */ var ReactClassMixin = { /** * TODO: This will be deprecated because state should always keep a consistent * type signature and the only use case for this, is to avoid that. */ replaceState: function(newState, callback) { this.updater.enqueueReplaceState(this, newState, callback); }, /** * Checks whether or not this composite component is mounted. * @return {boolean} True if mounted, false otherwise. * @protected * @final */ isMounted: function() { if (process.env.NODE_ENV !== 'production') { warning( this.__didWarnIsMounted, '%s: isMounted is deprecated. Instead, make sure to clean up ' + 'subscriptions and pending requests in componentWillUnmount to ' + 'prevent memory leaks.', (this.constructor && this.constructor.displayName) || this.name || 'Component' ); this.__didWarnIsMounted = true; } return !!this.__isMounted; } }; var ReactClassComponent = function() {}; _assign( ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin ); /** * Creates a composite component class given a class specification. * See https://facebook.github.io/react/docs/top-level-api.html#react.createclass * * @param {object} spec Class specification (which must define `render`). * @return {function} Component constructor function. * @public */ function createClass(spec) { // To keep our warnings more understandable, we'll use a little hack here to // ensure that Constructor.name !== 'Constructor'. This makes sure we don't // unnecessarily identify a class without displayName as 'Constructor'. var Constructor = identity(function(props, context, updater) { // This constructor gets overridden by mocks. The argument is used // by mocks to assert on what gets mounted. if (process.env.NODE_ENV !== 'production') { warning( this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory' ); } // Wire up auto-binding if (this.__reactAutoBindPairs.length) { bindAutoBindMethods(this); } this.props = props; this.context = context; this.refs = emptyObject; this.updater = updater || ReactNoopUpdateQueue; this.state = null; // ReactClasses doesn't have constructors. Instead, they use the // getInitialState and componentWillMount methods for initialization. var initialState = this.getInitialState ? this.getInitialState() : null; if (process.env.NODE_ENV !== 'production') { // We allow auto-mocks to proceed as if they're returning null. if ( initialState === undefined && this.getInitialState._isMockFunction ) { // This is probably bad practice. Consider warning here and // deprecating this convenience. initialState = null; } } _invariant( typeof initialState === 'object' && !Array.isArray(initialState), '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent' ); this.state = initialState; }); Constructor.prototype = new ReactClassComponent(); Constructor.prototype.constructor = Constructor; Constructor.prototype.__reactAutoBindPairs = []; injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor)); mixSpecIntoComponent(Constructor, IsMountedPreMixin); mixSpecIntoComponent(Constructor, spec); mixSpecIntoComponent(Constructor, IsMountedPostMixin); // Initialize the defaultProps property after all mixins have been merged. if (Constructor.getDefaultProps) { Constructor.defaultProps = Constructor.getDefaultProps(); } if (process.env.NODE_ENV !== 'production') { // This is a tag to indicate that the use of these method names is ok, // since it's used with createClass. If it's not, then it's likely a // mistake so we'll warn you to use the static property, property // initializer or constructor respectively. if (Constructor.getDefaultProps) { Constructor.getDefaultProps.isReactClassApproved = {}; } if (Constructor.prototype.getInitialState) { Constructor.prototype.getInitialState.isReactClassApproved = {}; } } _invariant( Constructor.prototype.render, 'createClass(...): Class specification must implement a `render` method.' ); if (process.env.NODE_ENV !== 'production') { warning( !Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component' ); warning( !Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component' ); warning( !Constructor.prototype.UNSAFE_componentWillRecieveProps, '%s has a method called UNSAFE_componentWillRecieveProps(). ' + 'Did you mean UNSAFE_componentWillReceiveProps()?', spec.displayName || 'A component' ); } // Reduce time spent doing lookups by setting these on the prototype. for (var methodName in ReactClassInterface) { if (!Constructor.prototype[methodName]) { Constructor.prototype[methodName] = null; } } return Constructor; } return createClass; } module.exports = factory; }).call(this)}).call(this,require('_process')) },{"_process":29,"object-assign":28}],5:[function(require,module,exports){ (function (process){(function (){ 'use strict'; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @typechecks */ var emptyFunction = require('./emptyFunction'); /** * Upstream version of event listener. Does not take into account specific * nature of platform. */ var EventListener = { /** * Listen to DOM events during the bubble phase. * * @param {DOMEventTarget} target DOM element to register listener on. * @param {string} eventType Event type, e.g. 'click' or 'mouseover'. * @param {function} callback Callback function. * @return {object} Object with a `remove` method. */ listen: function listen(target, eventType, callback) { if (target.addEventListener) { target.addEventListener(eventType, callback, false); return { remove: function remove() { target.removeEventListener(eventType, callback, false); } }; } else if (target.attachEvent) { target.attachEvent('on' + eventType, callback); return { remove: function remove() { target.detachEvent('on' + eventType, callback); } }; } }, /** * Listen to DOM events during the capture phase. * * @param {DOMEventTarget} target DOM element to register listener on. * @param {string} eventType Event type, e.g. 'click' or 'mouseover'. * @param {function} callback Callback function. * @return {object} Object with a `remove` method. */ capture: function capture(target, eventType, callback) { if (target.addEventListener) { target.addEventListener(eventType, callback, true); return { remove: function remove() { target.removeEventListener(eventType, callback, true); } }; } else { if (process.env.NODE_ENV !== 'production') { console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.'); } return { remove: emptyFunction }; } }, registerDefault: function registerDefault() {} }; module.exports = EventListener; }).call(this)}).call(this,require('_process')) },{"./emptyFunction":12,"_process":29}],6:[function(require,module,exports){ /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ 'use strict'; var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement); /** * Simple, lightweight module assisting with the detection and context of * Worker. Helps avoid circular dependencies and allows code to reason about * whether or not they are in a Worker, even if they never include the main * `ReactWorker` dependency. */ var ExecutionEnvironment = { canUseDOM: canUseDOM, canUseWorkers: typeof Worker !== 'undefined', canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent), canUseViewport: canUseDOM && !!window.screen, isInWorker: !canUseDOM // For now, this is true - might change in the future. }; module.exports = ExecutionEnvironment; },{}],7:[function(require,module,exports){ "use strict"; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @typechecks */ var _hyphenPattern = /-(.)/g; /** * Camelcases a hyphenated string, for example: * * > camelize('background-color') * < "backgroundColor" * * @param {string} string * @return {string} */ function camelize(string) { return string.replace(_hyphenPattern, function (_, character) { return character.toUpperCase(); }); } module.exports = camelize; },{}],8:[function(require,module,exports){ /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @typechecks */ 'use strict'; var camelize = require('./camelize'); var msPattern = /^-ms-/; /** * Camelcases a hyphenated CSS property name, for example: * * > camelizeStyleName('background-color') * < "backgroundColor" * > camelizeStyleName('-moz-transition') * < "MozTransition" * > camelizeStyleName('-ms-transition') * < "msTransition" * * As Andi Smith suggests * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix * is converted to lowercase `ms`. * * @param {string} string * @return {string} */ function camelizeStyleName(string) { return camelize(string.replace(msPattern, 'ms-')); } module.exports = camelizeStyleName; },{"./camelize":7}],9:[function(require,module,exports){ 'use strict'; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * */ var isTextNode = require('./isTextNode'); /*eslint-disable no-bitwise */ /** * Checks if a given DOM node contains or is another DOM node. */ function containsNode(outerNode, innerNode) { if (!outerNode || !innerNode) { return false; } else if (outerNode === innerNode) { return true; } else if (isTextNode(outerNode)) { return false; } else if (isTextNode(innerNode)) { return containsNode(outerNode, innerNode.parentNode); } else if ('contains' in outerNode) { return outerNode.contains(innerNode); } else if (outerNode.compareDocumentPosition) { return !!(outerNode.compareDocumentPosition(innerNode) & 16); } else { return false; } } module.exports = containsNode; },{"./isTextNode":22}],10:[function(require,module,exports){ (function (process){(function (){ 'use strict'; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @typechecks */ var invariant = require('./invariant'); /** * Convert array-like objects to arrays. * * This API assumes the caller knows the contents of the data type. For less * well defined inputs use createArrayFromMixed. * * @param {object|function|filelist} obj * @return {array} */ function toArray(obj) { var length = obj.length; // Some browsers builtin objects can report typeof 'function' (e.g. NodeList // in old versions of Safari). !(!Array.isArray(obj) && (typeof obj === 'object' || typeof obj === 'function')) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Array-like object expected') : invariant(false) : void 0; !(typeof length === 'number') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Object needs a length property') : invariant(false) : void 0; !(length === 0 || length - 1 in obj) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Object should have keys for indices') : invariant(false) : void 0; !(typeof obj.callee !== 'function') ? process.env.NODE_ENV !== 'production' ? invariant(false, 'toArray: Object can\'t be `arguments`. Use rest params ' + '(function(...args) {}) or Array.from() instead.') : invariant(false) : void 0; // Old IE doesn't give collections access to hasOwnProperty. Assume inputs // without method will throw during the slice call and skip straight to the // fallback. if (obj.hasOwnProperty) { try { return Array.prototype.slice.call(obj); } catch (e) { // IE < 9 does not support Array#slice on collections objects } } // Fall back to copying key by key. This assumes all keys have a value, // so will not preserve sparsely populated inputs. var ret = Array(length); for (var ii = 0; ii < length; ii++) { ret[ii] = obj[ii]; } return ret; } /** * Perform a heuristic test to determine if an object is "array-like". * * A monk asked Joshu, a Zen master, "Has a dog Buddha nature?" * Joshu replied: "Mu." * * This function determines if its argument has "array nature": it returns * true if the argument is an actual array, an `arguments' object, or an * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()). * * It will return false for other array-like objects like Filelist. * * @param {*} obj * @return {boolean} */ function hasArrayNature(obj) { return ( // not null/false !!obj && ( // arrays are objects, NodeLists are functions in Safari typeof obj == 'object' || typeof obj == 'function') && // quacks like an array 'length' in obj && // not window !('setInterval' in obj) && // no DOM node should be considered an array-like // a 'select' element has 'length' and 'item' properties on IE8 typeof obj.nodeType != 'number' && ( // a real array Array.isArray(obj) || // arguments 'callee' in obj || // HTMLCollection/NodeList 'item' in obj) ); } /** * Ensure that the argument is an array by wrapping it in an array if it is not. * Creates a copy of the argument if it is already an array. * * This is mostly useful idiomatically: * * var createArrayFromMixed = require('createArrayFromMixed'); * * function takesOneOrMoreThings(things) { * things = createArrayFromMixed(things); * ... * } * * This allows you to treat `things' as an array, but accept scalars in the API. * * If you need to convert an array-like object, like `arguments`, into an array * use toArray instead. * * @param {*} obj * @return {array} */ function createArrayFromMixed(obj) { if (!hasArrayNature(obj)) { return [obj]; } else if (Array.isArray(obj)) { return obj.slice(); } else { return toArray(obj); } } module.exports = createArrayFromMixed; }).call(this)}).call(this,require('_process')) },{"./invariant":20,"_process":29}],11:[function(require,module,exports){ (function (process){(function (){ 'use strict'; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @typechecks */ /*eslint-disable fb-www/unsafe-html*/ var ExecutionEnvironment = require('./ExecutionEnvironment'); var createArrayFromMixed = require('./createArrayFromMixed'); var getMarkupWrap = require('./getMarkupWrap'); var invariant = require('./invariant'); /** * Dummy container used to render all markup. */ var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null; /** * Pattern used by `getNodeName`. */ var nodeNamePattern = /^\s*<(\w+)/; /** * Extracts the `nodeName` of the first element in a string of markup. * * @param {string} markup String of markup. * @return {?string} Node name of the supplied markup. */ function getNodeName(markup) { var nodeNameMatch = markup.match(nodeNamePattern); return nodeNameMatch && nodeNameMatch[1].toLowerCase(); } /** * Creates an array containing the nodes rendered from the supplied markup. The * optionally supplied `handleScript` function will be invoked once for each *