diff --git a/pom.xml b/pom.xml
index 19b92da9d7..ad9db6a0a7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,6 +1,5 @@
-
+
4.0.0
@@ -332,6 +331,7 @@
wicket-facebook-parent
wicket-html5-parent
wicket-servlet3-parent
+ wicketstuff-clipboard-js-parent
wicketstuff-springreference-parent
wicket-security-parent
@@ -1193,7 +1193,7 @@
-
+
@@ -1214,7 +1214,7 @@
-
+
@@ -1235,7 +1235,7 @@
-
+
@@ -1345,4 +1345,4 @@
-
+
\ No newline at end of file
diff --git a/wicketstuff-clipboard-js-parent/README.md b/wicketstuff-clipboard-js-parent/README.md
new file mode 100644
index 0000000000..5ab55d8eaa
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/README.md
@@ -0,0 +1,3 @@
+An integration between Apache Wicket and Clipboard JS - copy text without Flash.
+
+For more information see https://clipboardjs.com/
diff --git a/wicketstuff-clipboard-js-parent/pom.xml b/wicketstuff-clipboard-js-parent/pom.xml
new file mode 100644
index 0000000000..ec7bb615b3
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/pom.xml
@@ -0,0 +1,37 @@
+
+
+
+ 4.0.0
+
+
+ org.wicketstuff
+ wicketstuff-core
+ 7.0-SNAPSHOT
+
+ wicketstuff-clipboardjs-parent
+ WicketStuff Clipboard JS Parent
+
+ pom
+
+ Parent project for WicketStuff Clipboard JS
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
+
+
+ wicketstuff-clipboardjs
+ wicketstuff-clipboardjs-examples
+
+
+
+
+ Martin Grigorov
+
+
+
+
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/pom.xml b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/pom.xml
new file mode 100644
index 0000000000..1d08d4d76a
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/pom.xml
@@ -0,0 +1,57 @@
+
+ 4.0.0
+
+ org.wicketstuff
+ wicketstuff-clipboardjs-parent
+ 7.0-SNAPSHOT
+
+
+ wicketstuff-clipboardjs-examples
+ war
+ WicketStuff Clipboard JS Example
+ Example usage of WicketStuff Clipboard JS
+
+
+ true
+ true
+ true
+
+
+
+
+ ${project.groupId}
+ wicketstuff-clipboardjs
+ ${project.parent.version}
+
+
+
+
+ org.slf4j
+ slf4j-log4j12
+
+
+ log4j
+ log4j
+
+
+
+
+ junit
+ junit
+
+
+
+
+ org.eclipse.jetty.aggregate
+ jetty-all-server
+
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+
+
+
+
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/java/org/wicketstuff/clipboardjs/example/ClipboardJsApplication.java b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/java/org/wicketstuff/clipboardjs/example/ClipboardJsApplication.java
new file mode 100644
index 0000000000..aa47a72242
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/java/org/wicketstuff/clipboardjs/example/ClipboardJsApplication.java
@@ -0,0 +1,12 @@
+package org.wicketstuff.clipboardjs.example;
+
+import org.apache.wicket.Page;
+import org.apache.wicket.protocol.http.WebApplication;
+
+public class ClipboardJsApplication extends WebApplication {
+ @Override
+ public Class extends Page> getHomePage()
+ {
+ return ClipboardJsDemoPage.class;
+ }
+}
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/java/org/wicketstuff/clipboardjs/example/ClipboardJsDemoPage.html b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/java/org/wicketstuff/clipboardjs/example/ClipboardJsDemoPage.html
new file mode 100644
index 0000000000..c7d16ca4d8
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/java/org/wicketstuff/clipboardjs/example/ClipboardJsDemoPage.html
@@ -0,0 +1,14 @@
+
+
+
+
+ ClipboardJs demo page
+
+
+
+
+
+
+
+
+
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/java/org/wicketstuff/clipboardjs/example/ClipboardJsDemoPage.java b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/java/org/wicketstuff/clipboardjs/example/ClipboardJsDemoPage.java
new file mode 100644
index 0000000000..c5b1b1b94c
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/java/org/wicketstuff/clipboardjs/example/ClipboardJsDemoPage.java
@@ -0,0 +1,30 @@
+package org.wicketstuff.clipboardjs.example;
+
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.form.TextArea;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.wicketstuff.clipboardjs.ClipboardJsBehavior;
+
+/**
+ * Demo page that just adds the default BrowserIdPanel and a feedback panel to show any errors
+ */
+public class ClipboardJsDemoPage extends WebPage
+{
+
+ private static final long serialVersionUID = 1L;
+
+ public ClipboardJsDemoPage(final PageParameters parameters)
+ {
+ super(parameters);
+
+ TextArea target = new TextArea("target");
+ add(target);
+
+ final WebMarkupContainer copyBtn = new WebMarkupContainer("copyBtn");
+ final ClipboardJsBehavior clipboardJsBehavior = new ClipboardJsBehavior();
+ clipboardJsBehavior.setTarget(target);
+ copyBtn.add(clipboardJsBehavior);
+ add(copyBtn);
+ }
+}
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/resources/log4j.properties b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..235c6db299
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/resources/log4j.properties
@@ -0,0 +1,10 @@
+log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.Stdout.layout.conversionPattern=%-5p - %-26.26c{1} - %m\n
+
+log4j.rootLogger=INFO,Stdout
+
+log4j.logger.org.apache.wicket=INFO
+log4j.logger.org.apache.wicket.protocol.http.HttpSessionStore=INFO
+log4j.logger.org.apache.wicket.version=INFO
+log4j.logger.org.apache.wicket.RequestCycle=INFO
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/webapp/WEB-INF/web.xml b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000..804f3027c9
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,23 @@
+
+
+
+ ClipboardJs example
+
+
+ wicket.clipboardjs
+ org.apache.wicket.protocol.http.WicketFilter
+
+ applicationClassName
+ org.wicketstuff.clipboardjs.example.ClipboardJsApplication
+
+
+
+
+ wicket.clipboardjs
+ /*
+
+
+
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/test/java/org/wicketstuff/clipboardjs/example/Start.java b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/test/java/org/wicketstuff/clipboardjs/example/Start.java
new file mode 100644
index 0000000000..fddcda7a68
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs-examples/src/test/java/org/wicketstuff/clipboardjs/example/Start.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wicketstuff.clipboardjs.example;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.bio.SocketConnector;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+public class Start
+{
+
+ public static void main(final String[] args) throws Exception
+ {
+ final Server server = new Server();
+ final SocketConnector connector = new SocketConnector();
+
+ // Set some timeout options to make debugging easier.
+ connector.setMaxIdleTime(1000 * 60 * 60);
+ connector.setSoLingerTime(-1);
+ connector.setPort(8080);
+ server.setConnectors(new Connector[] { connector });
+
+ final WebAppContext bb = new WebAppContext();
+ bb.setServer(server);
+ bb.setContextPath("/");
+ bb.setWar("src/main/webapp");
+
+ // START JMX SERVER
+ // MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+ // MBeanContainer mBeanContainer = new MBeanContainer(mBeanServer);
+ // server.getContainer().addEventListener(mBeanContainer);
+ // mBeanContainer.start();
+
+ server.setHandler(bb);
+
+ try
+ {
+ System.out.println(">>> STARTING EMBEDDED JETTY SERVER, PRESS ANY KEY TO STOP");
+ server.start();
+ System.in.read();
+ System.out.println(">>> STOPPING EMBEDDED JETTY SERVER");
+ // while (System.in.available() == 0) {
+ // Thread.sleep(5000);
+ // }
+ server.stop();
+ server.join();
+ }
+ catch (final Exception e)
+ {
+ e.printStackTrace();
+ System.exit(100);
+ }
+ }
+}
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/pom.xml b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/pom.xml
new file mode 100644
index 0000000000..d0859ca981
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ org.wicketstuff
+ wicketstuff-clipboardjs-parent
+ 7.0-SNAPSHOT
+
+
+ wicketstuff-clipboardjs
+ WicketStuff Clipboard JS
+ An integration of Clipboard JS with Apache Wicket
+
+
+
+ org.slf4j
+ slf4j-log4j12
+
+
+ log4j
+ log4j
+
+
+
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/ClipboardJsBehavior.java b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/ClipboardJsBehavior.java
new file mode 100644
index 0000000000..60c7c99e01
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/ClipboardJsBehavior.java
@@ -0,0 +1,68 @@
+package org.wicketstuff.clipboardjs;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.behavior.Behavior;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.JavaScriptHeaderItem;
+import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.string.Strings;
+
+/**
+ *
+ */
+public class ClipboardJsBehavior extends Behavior {
+
+ enum Action {
+ COPY,
+ CUT
+ }
+
+ private Component button;
+ private String target;
+ private Action action = Action.COPY;
+
+ public ClipboardJsBehavior setTarget(Component target) {
+ Args.notNull(target, "target");
+ target.setOutputMarkupId(true);
+ this.target = target.getMarkupId();
+ return this;
+ }
+
+ public ClipboardJsBehavior setAction(Action action) {
+ this.action = action != null ? action : Action.COPY;
+ return this;
+ }
+
+ @Override
+ public void bind(final Component component) {
+ super.bind(component);
+
+ if (button != null) {
+ throw new IllegalStateException(ClipboardJsBehavior.class.getName() + " can be assigned to only one button");
+ }
+ button = component.setOutputMarkupId(true);
+ }
+
+ @Override
+ public void onComponentTag(final Component component, final ComponentTag tag) {
+ super.onComponentTag(component, tag);
+
+ if (action == Action.CUT) {
+ tag.put("data-clipboard-action", "cut");
+ }
+
+ if (!Strings.isEmpty(target)) {
+ tag.put("data-clipboard-target", "#" + target);
+ }
+ }
+
+ @Override
+ public void renderHead(final Component component, final IHeaderResponse response) {
+ super.renderHead(component, response);
+
+ response.render(JavaScriptHeaderItem.forReference(ClipboardJsReference.INSTANCE));
+ response.render(OnDomReadyHeaderItem.forScript(String.format("new Clipboard('#%s')", button.getMarkupId())));
+ }
+}
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/ClipboardJsReference.java b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/ClipboardJsReference.java
new file mode 100644
index 0000000000..fb6632def3
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/ClipboardJsReference.java
@@ -0,0 +1,12 @@
+package org.wicketstuff.clipboardjs;
+
+import org.apache.wicket.request.resource.JavaScriptResourceReference;
+
+public class ClipboardJsReference extends JavaScriptResourceReference {
+
+ public static final ClipboardJsReference INSTANCE = new ClipboardJsReference();
+
+ private ClipboardJsReference() {
+ super(ClipboardJsReference.class, "res/clipboard.js");
+ }
+}
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/res/clipboard.js b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/res/clipboard.js
new file mode 100644
index 0000000000..f9b772b503
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/res/clipboard.js
@@ -0,0 +1,753 @@
+/*!
+ * clipboard.js v1.5.15
+ * https://zenorocha.github.io/clipboard.js
+ *
+ * Licensed MIT © Zeno Rocha
+ */
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Clipboard = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+ this.action = options.action;
+ this.emitter = options.emitter;
+ this.target = options.target;
+ this.text = options.text;
+ this.trigger = options.trigger;
+
+ this.selectedText = '';
+ }
+ }, {
+ key: 'initSelection',
+ value: function initSelection() {
+ if (this.text) {
+ this.selectFake();
+ } else if (this.target) {
+ this.selectTarget();
+ }
+ }
+ }, {
+ key: 'selectFake',
+ value: function selectFake() {
+ var _this = this;
+
+ var isRTL = document.documentElement.getAttribute('dir') == 'rtl';
+
+ this.removeFake();
+
+ this.fakeHandlerCallback = function () {
+ return _this.removeFake();
+ };
+ this.fakeHandler = document.body.addEventListener('click', this.fakeHandlerCallback) || true;
+
+ this.fakeElem = document.createElement('textarea');
+ // Prevent zooming on iOS
+ this.fakeElem.style.fontSize = '12pt';
+ // Reset box model
+ this.fakeElem.style.border = '0';
+ this.fakeElem.style.padding = '0';
+ this.fakeElem.style.margin = '0';
+ // Move element out of screen horizontally
+ this.fakeElem.style.position = 'absolute';
+ this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';
+ // Move element to the same position vertically
+ var yPosition = window.pageYOffset || document.documentElement.scrollTop;
+ this.fakeElem.addEventListener('focus', window.scrollTo(0, yPosition));
+ this.fakeElem.style.top = yPosition + 'px';
+
+ this.fakeElem.setAttribute('readonly', '');
+ this.fakeElem.value = this.text;
+
+ document.body.appendChild(this.fakeElem);
+
+ this.selectedText = (0, _select2.default)(this.fakeElem);
+ this.copyText();
+ }
+ }, {
+ key: 'removeFake',
+ value: function removeFake() {
+ if (this.fakeHandler) {
+ document.body.removeEventListener('click', this.fakeHandlerCallback);
+ this.fakeHandler = null;
+ this.fakeHandlerCallback = null;
+ }
+
+ if (this.fakeElem) {
+ document.body.removeChild(this.fakeElem);
+ this.fakeElem = null;
+ }
+ }
+ }, {
+ key: 'selectTarget',
+ value: function selectTarget() {
+ this.selectedText = (0, _select2.default)(this.target);
+ this.copyText();
+ }
+ }, {
+ key: 'copyText',
+ value: function copyText() {
+ var succeeded = void 0;
+
+ try {
+ succeeded = document.execCommand(this.action);
+ } catch (err) {
+ succeeded = false;
+ }
+
+ this.handleResult(succeeded);
+ }
+ }, {
+ key: 'handleResult',
+ value: function handleResult(succeeded) {
+ this.emitter.emit(succeeded ? 'success' : 'error', {
+ action: this.action,
+ text: this.selectedText,
+ trigger: this.trigger,
+ clearSelection: this.clearSelection.bind(this)
+ });
+ }
+ }, {
+ key: 'clearSelection',
+ value: function clearSelection() {
+ if (this.target) {
+ this.target.blur();
+ }
+
+ window.getSelection().removeAllRanges();
+ }
+ }, {
+ key: 'destroy',
+ value: function destroy() {
+ this.removeFake();
+ }
+ }, {
+ key: 'action',
+ set: function set() {
+ var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'copy';
+
+ this._action = action;
+
+ if (this._action !== 'copy' && this._action !== 'cut') {
+ throw new Error('Invalid "action" value, use either "copy" or "cut"');
+ }
+ },
+ get: function get() {
+ return this._action;
+ }
+ }, {
+ key: 'target',
+ set: function set(target) {
+ if (target !== undefined) {
+ if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) {
+ if (this.action === 'copy' && target.hasAttribute('disabled')) {
+ throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');
+ }
+
+ if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {
+ throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');
+ }
+
+ this._target = target;
+ } else {
+ throw new Error('Invalid "target" value, use a valid Element');
+ }
+ }
+ },
+ get: function get() {
+ return this._target;
+ }
+ }]);
+
+ return ClipboardAction;
+ }();
+
+ module.exports = ClipboardAction;
+});
+
+},{"select":5}],8:[function(require,module,exports){
+(function (global, factory) {
+ if (typeof define === "function" && define.amd) {
+ define(['module', './clipboard-action', 'tiny-emitter', 'good-listener'], factory);
+ } else if (typeof exports !== "undefined") {
+ factory(module, require('./clipboard-action'), require('tiny-emitter'), require('good-listener'));
+ } else {
+ var mod = {
+ exports: {}
+ };
+ factory(mod, global.clipboardAction, global.tinyEmitter, global.goodListener);
+ global.clipboard = mod.exports;
+ }
+})(this, function (module, _clipboardAction, _tinyEmitter, _goodListener) {
+ 'use strict';
+
+ var _clipboardAction2 = _interopRequireDefault(_clipboardAction);
+
+ var _tinyEmitter2 = _interopRequireDefault(_tinyEmitter);
+
+ var _goodListener2 = _interopRequireDefault(_goodListener);
+
+ function _interopRequireDefault(obj) {
+ return obj && obj.__esModule ? obj : {
+ default: obj
+ };
+ }
+
+ function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+ }
+
+ var _createClass = function () {
+ function defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ Object.defineProperty(target, descriptor.key, descriptor);
+ }
+ }
+
+ return function (Constructor, protoProps, staticProps) {
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) defineProperties(Constructor, staticProps);
+ return Constructor;
+ };
+ }();
+
+ function _possibleConstructorReturn(self, call) {
+ if (!self) {
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+ }
+
+ return call && (typeof call === "object" || typeof call === "function") ? call : self;
+ }
+
+ function _inherits(subClass, superClass) {
+ if (typeof superClass !== "function" && superClass !== null) {
+ throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
+ }
+
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
+ constructor: {
+ value: subClass,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
+ }
+
+ var Clipboard = function (_Emitter) {
+ _inherits(Clipboard, _Emitter);
+
+ /**
+ * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
+ * @param {Object} options
+ */
+ function Clipboard(trigger, options) {
+ _classCallCheck(this, Clipboard);
+
+ var _this = _possibleConstructorReturn(this, (Clipboard.__proto__ || Object.getPrototypeOf(Clipboard)).call(this));
+
+ _this.resolveOptions(options);
+ _this.listenClick(trigger);
+ return _this;
+ }
+
+ /**
+ * Defines if attributes would be resolved using internal setter functions
+ * or custom functions that were passed in the constructor.
+ * @param {Object} options
+ */
+
+
+ _createClass(Clipboard, [{
+ key: 'resolveOptions',
+ value: function resolveOptions() {
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+ this.action = typeof options.action === 'function' ? options.action : this.defaultAction;
+ this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;
+ this.text = typeof options.text === 'function' ? options.text : this.defaultText;
+ }
+ }, {
+ key: 'listenClick',
+ value: function listenClick(trigger) {
+ var _this2 = this;
+
+ this.listener = (0, _goodListener2.default)(trigger, 'click', function (e) {
+ return _this2.onClick(e);
+ });
+ }
+ }, {
+ key: 'onClick',
+ value: function onClick(e) {
+ var trigger = e.delegateTarget || e.currentTarget;
+
+ if (this.clipboardAction) {
+ this.clipboardAction = null;
+ }
+
+ this.clipboardAction = new _clipboardAction2.default({
+ action: this.action(trigger),
+ target: this.target(trigger),
+ text: this.text(trigger),
+ trigger: trigger,
+ emitter: this
+ });
+ }
+ }, {
+ key: 'defaultAction',
+ value: function defaultAction(trigger) {
+ return getAttributeValue('action', trigger);
+ }
+ }, {
+ key: 'defaultTarget',
+ value: function defaultTarget(trigger) {
+ var selector = getAttributeValue('target', trigger);
+
+ if (selector) {
+ return document.querySelector(selector);
+ }
+ }
+ }, {
+ key: 'defaultText',
+ value: function defaultText(trigger) {
+ return getAttributeValue('text', trigger);
+ }
+ }, {
+ key: 'destroy',
+ value: function destroy() {
+ this.listener.destroy();
+
+ if (this.clipboardAction) {
+ this.clipboardAction.destroy();
+ this.clipboardAction = null;
+ }
+ }
+ }]);
+
+ return Clipboard;
+ }(_tinyEmitter2.default);
+
+ /**
+ * Helper function to retrieve attribute value.
+ * @param {String} suffix
+ * @param {Element} element
+ */
+ function getAttributeValue(suffix, element) {
+ var attribute = 'data-clipboard-' + suffix;
+
+ if (!element.hasAttribute(attribute)) {
+ return;
+ }
+
+ return element.getAttribute(attribute);
+ }
+
+ module.exports = Clipboard;
+});
+
+},{"./clipboard-action":7,"good-listener":4,"tiny-emitter":6}]},{},[8])(8)
+});
\ No newline at end of file
diff --git a/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/res/clipboard.min.js b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/res/clipboard.min.js
new file mode 100644
index 0000000000..607a71df6e
--- /dev/null
+++ b/wicketstuff-clipboard-js-parent/wicketstuff-clipboardjs/src/main/java/org/wicketstuff/clipboardjs/res/clipboard.min.js
@@ -0,0 +1,7 @@
+/*!
+ * clipboard.js v1.5.15
+ * https://zenorocha.github.io/clipboard.js
+ *
+ * Licensed MIT © Zeno Rocha
+ */
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.Clipboard=e()}}(function(){var e,t,n;return function e(t,n,i){function o(a,c){if(!n[a]){if(!t[a]){var l="function"==typeof require&&require;if(!c&&l)return l(a,!0);if(r)return r(a,!0);var s=new Error("Cannot find module '"+a+"'");throw s.code="MODULE_NOT_FOUND",s}var u=n[a]={exports:{}};t[a][0].call(u.exports,function(e){var n=t[a][1][e];return o(n?n:e)},u,u.exports,e,t,n,i)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;a0&&void 0!==arguments[0]?arguments[0]:{};this.action=t.action,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}},{key:"initSelection",value:function e(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function e(){var t=this,n="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=document.body.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[n?"right":"left"]="-9999px";var i=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.addEventListener("focus",window.scrollTo(0,i)),this.fakeElem.style.top=i+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,document.body.appendChild(this.fakeElem),this.selectedText=(0,o.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function e(){this.fakeHandler&&(document.body.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(document.body.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function e(){this.selectedText=(0,o.default)(this.target),this.copyText()}},{key:"copyText",value:function e(){var t=void 0;try{t=document.execCommand(this.action)}catch(e){t=!1}this.handleResult(t)}},{key:"handleResult",value:function e(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function e(){this.target&&this.target.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function e(){this.removeFake()}},{key:"action",set:function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function e(){return this._action}},{key:"target",set:function e(t){if(void 0!==t){if(!t||"object"!==("undefined"==typeof t?"undefined":r(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function e(){return this._target}}]),e}();e.exports=c})},{select:5}],8:[function(t,n,i){!function(o,r){if("function"==typeof e&&e.amd)e(["module","./clipboard-action","tiny-emitter","good-listener"],r);else if("undefined"!=typeof i)r(n,t("./clipboard-action"),t("tiny-emitter"),t("good-listener"));else{var a={exports:{}};r(a,o.clipboardAction,o.tinyEmitter,o.goodListener),o.clipboard=a.exports}}(this,function(e,t,n,i){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function c(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t){var n="data-clipboard-"+e;if(t.hasAttribute(n))return t.getAttribute(n)}var s=o(t),u=o(n),f=o(i),d=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText}},{key:"listenClick",value:function e(t){var n=this;this.listener=(0,f.default)(t,"click",function(e){return n.onClick(e)})}},{key:"onClick",value:function e(t){var n=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new s.default({action:this.action(n),target:this.target(n),text:this.text(n),trigger:n,emitter:this})}},{key:"defaultAction",value:function e(t){return l("action",t)}},{key:"defaultTarget",value:function e(t){var n=l("target",t);if(n)return document.querySelector(n)}},{key:"defaultText",value:function e(t){return l("text",t)}},{key:"destroy",value:function e(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}]),t}(u.default);e.exports=h})},{"./clipboard-action":7,"good-listener":4,"tiny-emitter":6}]},{},[8])(8)});
\ No newline at end of file