When starting up my server I am getting an error:
node_modules/clipboard/node_modules/good-listener/node_modules/delegate/node_modules/closest/node_modules/matches-selector/index.js:6
var proto = Element.prototype;
^
ReferenceError: Element is not defined
at Object.
at Module._compile (module.js:435:26)
at Module._extensions..js (module.js:442:10)
at Object.require.extensions.(anonymous function) as .js
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Module.require (module.js:366:17)
at require (module.js:385:17)
at Object.
at Module._compile (module.js:435:26)
at Module._extensions..js (module.js:442:10)
at Object.require.extensions.(anonymous function) as .js
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Module.require (module.js:366:17)
at require (module.js:385:17)
at Object.
at Module._compile (module.js:435:26)
at Module._extensions..js (module.js:442:10)
at Object.require.extensions.(anonymous function) as .js
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
[nodemon] app crashed - waiting for file changes before starting...
This is with a react project.
Please provide a minimal example using JSFiddle or something like so we can investigate it properly.
This happens if you do server rendering. If you require clipboard in node it crashes, even if you don't use it.
Example test.js:
var Clipboard = require('clipboard');
$ node test.js
That's because it needs browser APIs.
Yup, solution is to simply bring the dependency in manually with <script type='text/javascript' src='./clipboard.js'></script> so the server isn't trying to transpile the code that contains undefined browser APIs on the back end.
A solution in clipboard.js's code could be to check if any browser API methods are undefined and simply return nothing in the constructor if anything is undefined.
This library is only meant for the browser environment. There's no reason to check if it's undefined or not.
Would you send a pull request to jQuery source code with a bunch of if's on every single browser API? It's the same case here.
Good call.
I just thought I could require it without using the constructor when the server renders the view and then use the constructor in an event that is triggered in the browser. But I can work around it like you said @roscioli and add it to the html file. Thanks.
Hey guys,
Thanks for the great work on clipboard.js! I understand this library is meant for browser environment only @zenorocha.
However, most of the "modern" JS dev wants to test their app. In our case, here our React Components. React Components that used to be testable in Node land suddenly becomes untestable when depending on Clipboard.js unless we start a headless browser.
I really believe with React being adopted broadly, this request will keep showing up.
I thought what @crudh suggested does not really add a bunch of if everywhere.
As for jQuery, maybe the interest around testing in this scenario is not that big :smile:
Well, I'm open for pull requests. In the meanwhile, you can check https://www.npmjs.com/package/react-clipboard.js
Thanks a lot for your feedback @zenorocha. We are actually using react-clipboard.js which depends on clipboard.js. We therefore have the same errors as @roscioli pointed out.
But as the stack shows, the error is coming from one of clipboard.js dependencies' dependencies called matches-selector. So I'd rather create an issue on their side.
Here's a link to this issue for the record:
https://github.com/component/matches-selector/issues/13
Thanks a lot for your time on this.
Closing this since the issue was filled on matches-selector.
Hi, no, it's not. I have the same error using with React.
@zenorocha Just wanted to say that I am having the same problem (using react-clipboard, which, as it was mentioned above, depends on clipboard.js).
When I require the clipboard button from react-clipboard, I am getting the following error:
error: uncaughtException: Element is not defined.
The problematic part of the code must be here:
https://github.com/zenorocha/clipboard.js/blob/master/dist/clipboard.js#L11
* A polyfill for Element.matches()
*/
if (Element && !Element.prototype.matches) {
var proto = Element.prototype;
proto.matches = proto.matchesSelector ||
proto.mozMatchesSelector ||
proto.msMatchesSelector ||
proto.oMatchesSelector ||
proto.webkitMatchesSelector;
}
Curiously, there is nothing in the source files of Clipboard.js that uses this polyfill for Element.matches; it seems that the toublesome code is added during the build process (by Browserify or Babelify).
Could you perhaps tweak the way the module is packaged for npm?
Here's the fix: https://github.com/zenorocha/clipboard.js/issues/296#issuecomment-381124824