lib/assets/javascripts/react_ujs.js (368 lines of code) (raw):
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("react-dom"), require("react"), require("react-dom/server"));
else if(typeof define === 'function' && define.amd)
define(["react-dom", "react", "react-dom/server"], factory);
else if(typeof exports === 'object')
exports["ReactRailsUJS"] = factory(require("react-dom"), require("react"), require("react-dom/server"));
else
root["ReactRailsUJS"] = factory(root["ReactDOM"], root["React"], root["ReactDOMServer"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_5__, __WEBPACK_EXTERNAL_MODULE_6__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 7);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
// Assume className is simple and can be found at top-level (window).
// Fallback to eval to handle cases like 'My.React.ComponentName'.
// Also, try to gracefully import Babel 6 style default exports
var topLevel = typeof window === "undefined" ? this : window;
module.exports = function(className) {
var constructor;
// Try to access the class globally first
constructor = topLevel[className];
// If that didn't work, try eval
if (!constructor) {
constructor = eval(className);
}
// Lastly, if there is a default attribute try that
if (constructor && constructor['default']) {
constructor = constructor['default'];
}
return constructor;
}
/***/ }),
/* 1 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
var nativeEvents = __webpack_require__(8)
var pjaxEvents = __webpack_require__(9)
var turbolinksEvents = __webpack_require__(10)
var turbolinksClassicDeprecatedEvents = __webpack_require__(12)
var turbolinksClassicEvents = __webpack_require__(11)
// see what things are globally available
// and setup event handlers to those things
module.exports = function(ujs) {
if (ujs.handleEvent) {
// We're calling this a second time -- remove previous handlers
if (typeof Turbolinks !== "undefined" && typeof Turbolinks.EVENTS !== "undefined") {
turbolinksClassicEvents.teardown(ujs);
}
turbolinksEvents.teardown(ujs);
turbolinksClassicDeprecatedEvents.teardown(ujs);
pjaxEvents.teardown(ujs);
nativeEvents.teardown(ujs);
}
if ('addEventListener' in window) {
ujs.handleEvent = function(eventName, callback) {
document.addEventListener(eventName, callback);
};
ujs.removeEvent = function(eventName, callback) {
document.removeEventListener(eventName, callback);
};
} else {
ujs.handleEvent = function(eventName, callback) {
window.attachEvent(eventName, callback);
};
ujs.removeEvent = function(eventName, callback) {
window.detachEvent(eventName, callback);
};
}
// Detect which kind of events to set up:
if (typeof Turbolinks !== 'undefined' && Turbolinks.supported) {
if (typeof Turbolinks.EVENTS !== 'undefined') {
// Turbolinks.EVENTS is in classic version 2.4.0+
turbolinksClassicEvents.setup(ujs)
} else if (typeof Turbolinks.controller !== "undefined") {
// Turbolinks.controller is in version 5+
turbolinksEvents.setup(ujs);
} else {
turbolinksClassicDeprecatedEvents.setup(ujs);
}
} else if (typeof $ !== "undefined" && typeof $.pjax === 'function') {
pjaxEvents.setup(ujs);
} else {
nativeEvents.setup(ujs);
}
}
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
// Make a function which:
// - First tries to require the name
// - Then falls back to global lookup
var fromGlobal = __webpack_require__(0)
var fromRequireContext = __webpack_require__(13)
module.exports = function(reqctx) {
var fromCtx = fromRequireContext(reqctx)
return function(className) {
var component;
try {
// `require` will raise an error if this className isn't found:
component = fromCtx(className)
} catch (firstErr) {
// fallback to global:
try {
component = fromGlobal(className)
} catch (secondErr) {
console.error(firstErr)
console.error(secondErr)
}
}
return component
}
}
/***/ }),
/* 4 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony export (immutable) */ __webpack_exports__["supportsHydration"] = supportsHydration;
/* harmony export (immutable) */ __webpack_exports__["reactHydrate"] = reactHydrate;
/* harmony export (immutable) */ __webpack_exports__["createReactRootLike"] = createReactRootLike;
const ReactDOM = __webpack_require__(1)
function supportsHydration() {
return typeof ReactDOM.hydrate === "function" || typeof ReactDOM.hydrateRoot === "function"
}
function reactHydrate(node, component) {
if (typeof ReactDOM.hydrateRoot === "function") {
return ReactDOM.hydrateRoot(node, component)
} else {
return ReactDOM.hydrate(component, node)
}
}
function createReactRootLike(node) {
return ReactDOM.createRoot ? ReactDOM.createRoot(node) : legacyReactRootLike(node)
}
function legacyReactRootLike(node) {
const root = {
render(component) {
return ReactDOM.render(component, node)
}
}
return root
}
/***/ }),
/* 5 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_5__;
/***/ }),
/* 6 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_6__;
/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {
var React = __webpack_require__(5)
var ReactDOM = __webpack_require__(1)
var ReactDOMServer = __webpack_require__(6)
var detectEvents = __webpack_require__(2)
var constructorFromGlobal = __webpack_require__(0)
var constructorFromRequireContextWithGlobalFallback = __webpack_require__(3)
const { supportsHydration, reactHydrate, createReactRootLike } = __webpack_require__(4)
var ReactRailsUJS = {
// This attribute holds the name of component which should be mounted
// example: `data-react-class="MyApp.Items.EditForm"`
CLASS_NAME_ATTR: 'data-react-class',
// This attribute holds JSON stringified props for initializing the component
// example: `data-react-props="{\"item\": { \"id\": 1, \"name\": \"My Item\"} }"`
PROPS_ATTR: 'data-react-props',
// This attribute holds which method to use between: ReactDOM.hydrate, ReactDOM.render
RENDER_ATTR: 'data-hydrate',
// A unique identifier to identify a node
CACHE_ID_ATTR: "data-react-cache-id",
TURBOLINKS_PERMANENT_ATTR: "data-turbolinks-permanent",
// If jQuery is detected, save a reference to it for event handlers
jQuery: (typeof window !== 'undefined') && (typeof window.jQuery !== 'undefined') && window.jQuery,
components: {},
// helper method for the mount and unmount methods to find the
// `data-react-class` DOM elements
findDOMNodes: function(searchSelector) {
var classNameAttr = ReactRailsUJS.CLASS_NAME_ATTR
// we will use fully qualified paths as we do not bind the callbacks
var selector, parent;
switch (typeof searchSelector) {
case 'undefined':
selector = '[' + classNameAttr + ']';
parent = document;
break;
case 'object':
selector = '[' + classNameAttr + ']';
parent = searchSelector;
break;
case 'string':
selector = searchSelector + '[' + classNameAttr + '], ' +
searchSelector + ' [' + classNameAttr + ']';
parent = document;
break
default:
break;
}
if (ReactRailsUJS.jQuery) {
return ReactRailsUJS.jQuery(selector, parent);
} else {
return parent.querySelectorAll(selector);
}
},
// Get the constructor for a className (returns a React class)
// Override this function to lookup classes in a custom way,
// the default is ReactRailsUJS.ComponentGlobal
getConstructor: constructorFromGlobal,
// Given a Webpack `require.context`,
// try finding components with `require`,
// then falling back to global lookup.
useContext: function(requireContext) {
this.getConstructor = constructorFromRequireContextWithGlobalFallback(requireContext)
},
// Render `componentName` with `props` to a string,
// using the specified `renderFunction` from `react-dom/server`.
serverRender: function(renderFunction, componentName, props) {
var componentClass = this.getConstructor(componentName)
var element = React.createElement(componentClass, props)
return ReactDOMServer[renderFunction](element)
},
// Within `searchSelector`, find nodes which should have React components
// inside them, and mount them with their props.
mountComponents: function(searchSelector) {
var ujs = ReactRailsUJS
var nodes = ujs.findDOMNodes(searchSelector);
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
var className = node.getAttribute(ujs.CLASS_NAME_ATTR);
var constructor = ujs.getConstructor(className);
var propsJson = node.getAttribute(ujs.PROPS_ATTR);
var props = propsJson && JSON.parse(propsJson);
var hydrate = node.getAttribute(ujs.RENDER_ATTR);
var cacheId = node.getAttribute(ujs.CACHE_ID_ATTR);
var turbolinksPermanent = node.hasAttribute(ujs.TURBOLINKS_PERMANENT_ATTR);
if (!constructor) {
var message = "Cannot find component: '" + className + "'"
if (console && console.log) {
console.log("%c[react-rails] %c" + message + " for element", "font-weight: bold", "", node)
}
throw new Error(message + ". Make sure your component is available to render.")
} else {
var component = this.components[cacheId];
if(component === undefined) {
component = React.createElement(constructor, props);
if(turbolinksPermanent) {
this.components[cacheId] = component;
}
}
if (hydrate && supportsHydration()) {
component = reactHydrate(node, component);
} else {
const root = createReactRootLike(node)
component = root.render(component);
}
}
}
},
// Within `searchSelector`, find nodes which have React components
// inside them, and unmount those components.
unmountComponents: function(searchSelector) {
var nodes = ReactRailsUJS.findDOMNodes(searchSelector);
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
ReactDOM.unmountComponentAtNode(node);
}
},
// Check the global context for installed libraries
// and figure out which library to hook up to (pjax, Turbolinks, jQuery)
// This is called on load, but you can call it again if needed
// (It will unmount itself)
detectEvents: function() {
detectEvents(this)
},
}
// These stable references are so that handlers can be added and removed:
ReactRailsUJS.handleMount = function(e) {
var target = undefined;
if (e && e.target) {
target = e.target;
}
ReactRailsUJS.mountComponents(target);
}
ReactRailsUJS.handleUnmount = function(e) {
var target = undefined;
if (e && e.target) {
target = e.target;
}
ReactRailsUJS.unmountComponents(target);
}
if (typeof window !== "undefined") {
// Only setup events for browser (not server-rendering)
ReactRailsUJS.detectEvents()
}
// It's a bit of a no-no to populate the global namespace,
// but we really need it!
// We need access to this object for server rendering, and
// we can't do a dynamic `require`, so we'll grab it from here:
self.ReactRailsUJS = ReactRailsUJS
module.exports = ReactRailsUJS
/***/ }),
/* 8 */
/***/ (function(module, exports) {
module.exports = {
// Attach handlers to browser events to mount
// (There are no unmount handlers since the page is destroyed on navigation)
setup: function(ujs) {
if ('addEventListener' in window) {
ujs.handleEvent('DOMContentLoaded', ujs.handleMount);
} else {
// add support to IE8 without jQuery
ujs.handleEvent('onload', ujs.handleMount);
}
},
teardown: function(ujs) {
ujs.removeEvent('DOMContentLoaded', ujs.handleMount);
ujs.removeEvent('onload', ujs.handleMount);
}
}
/***/ }),
/* 9 */
/***/ (function(module, exports) {
module.exports = {
// pjax support
setup: function(ujs) {
ujs.handleEvent('ready', ujs.handleMount);
ujs.handleEvent('pjax:end', ujs.handleMount);
ujs.handleEvent('pjax:beforeReplace', ujs.handleUnmount);
},
teardown: function(ujs) {
ujs.removeEvent('ready', ujs.handleMount);
ujs.removeEvent('pjax:end', ujs.handleMount);
ujs.removeEvent('pjax:beforeReplace', ujs.handleUnmount);
},
}
/***/ }),
/* 10 */
/***/ (function(module, exports) {
module.exports = {
// Turbolinks 5+ got rid of named events (?!)
setup: function(ujs) {
ujs.handleEvent('turbolinks:load', ujs.handleMount);
},
teardown: function(ujs) {
ujs.removeEvent('turbolinks:load', ujs.handleMount);
},
}
/***/ }),
/* 11 */
/***/ (function(module, exports) {
module.exports = {
// Attach handlers to Turbolinks-Classic events
// for mounting and unmounting components
setup: function(ujs) {
ujs.handleEvent(Turbolinks.EVENTS.CHANGE, ujs.handleMount);
ujs.handleEvent(Turbolinks.EVENTS.BEFORE_UNLOAD, ujs.handleUnmount);
},
teardown: function(ujs) {
ujs.removeEvent(Turbolinks.EVENTS.CHANGE, ujs.handleMount);
ujs.removeEvent(Turbolinks.EVENTS.BEFORE_UNLOAD, ujs.handleUnmount);
}
}
/***/ }),
/* 12 */
/***/ (function(module, exports) {
module.exports = {
// Before Turbolinks 2.4.0, Turbolinks didn't
// have named events and didn't have a before-unload event.
// Also, it didn't work with the Turbolinks cache, see
// https://github.com/reactjs/react-rails/issues/87
setup: function(ujs) {
Turbolinks.pagesCached(0)
ujs.handleEvent('page:change', ujs.handleMount);
ujs.handleEvent('page:receive', ujs.handleUnmount);
},
teardown: function(ujs) {
ujs.removeEvent('page:change', ujs.handleMount);
ujs.removeEvent('page:receive', ujs.handleUnmount);
}
}
/***/ }),
/* 13 */
/***/ (function(module, exports) {
// Load React components by requiring them from "components/", for example:
//
// - "pages/index" -> `require("components/pages/index")`
// - "pages/show.Header" -> `require("components/pages/show").Header`
// - "pages/show.Body.Content" -> `require("components/pages/show").Body.Content`
//
module.exports = function(reqctx) {
return function(className) {
var parts = className.split(".")
var filename = parts.shift()
var keys = parts
// Load the module:
var component = reqctx("./" + filename)
// Then access each key:
keys.forEach(function(k) {
component = component[k]
})
// support `export default`
if (component.__esModule) {
component = component["default"]
}
return component
}
}
/***/ })
/******/ ]);
});