From 4b83f2991a344898f7d4fabccfdf86c86fe58e38 Mon Sep 17 00:00:00 2001 From: Ludovic Dubost Date: Sun, 1 Apr 2018 18:52:21 +0200 Subject: [PATCH 01/35] Kanban prototype on cryptpad --- customize.dist/pages.js | 9 + .../src/less2/include/colortheme.less | 7 + customize.dist/src/less2/main.less | 1 + .../src/less2/pages/page-index.less | 1 + customize.dist/translations/messages.js | 5 + www/kanban/app-kanban.less | 671 ++++++++ www/kanban/index.html | 38 + www/kanban/inner.html | 43 + www/kanban/inner.js | 628 ++++++++ www/kanban/jkanban.css | 151 ++ www/kanban/jkanban.js | 1398 +++++++++++++++++ www/kanban/kanban.css | 25 + www/kanban/main.js | 43 + 13 files changed, 3020 insertions(+) create mode 100644 www/kanban/app-kanban.less create mode 100644 www/kanban/index.html create mode 100644 www/kanban/inner.html create mode 100644 www/kanban/inner.js create mode 100644 www/kanban/jkanban.css create mode 100644 www/kanban/jkanban.js create mode 100644 www/kanban/kanban.css create mode 100644 www/kanban/main.js diff --git a/customize.dist/pages.js b/customize.dist/pages.js index 4cd4f49f4..7e2cf4969 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -56,6 +56,7 @@ define([ footLink('/code/', 'main_code'), footLink('/slide/', 'main_slide'), footLink('/poll/', 'main_poll'), + footLink('/kanban/', 'main_kanban'), footLink('/whiteboard/', null, Msg.type.whiteboard) ]), footerCol('footer_aboutUs', [ @@ -557,6 +558,7 @@ define([ [ 'code', '/code/', Msg.main_codePad, 'fa-file-code-o' ], [ 'slide', '/slide/', Msg.main_slidePad, 'fa-file-powerpoint-o' ], [ 'poll', '/poll/', Msg.main_pollPad, 'fa-calendar' ], + [ 'kanban', '/kanban/', Msg.main_kanbanPad, 'fa-calendar' ], [ 'whiteboard', '/whiteboard/', Msg.main_whiteboardPad, 'fa-paint-brush' ], [ 'recent', '/drive/', Msg.main_localPads, 'fa-hdd-o' ] ].filter(function (x) { @@ -884,5 +886,12 @@ define([ ]; }; + Pages['/kanban/'] = Pages['/kanban/index.html'] = function () { + return [ + appToolbar(), + h('div#cp-app-kanban-content', []) + ]; + }; + return Pages; }); diff --git a/customize.dist/src/less2/include/colortheme.less b/customize.dist/src/less2/include/colortheme.less index 1bdb69291..e2406653d 100644 --- a/customize.dist/src/less2/include/colortheme.less +++ b/customize.dist/src/less2/include/colortheme.less @@ -61,6 +61,13 @@ @colortheme_poll-th-fg: #fff; @colortheme_poll-warn: #ffade3; +@colortheme_kanban-bg: #006304; +@colortheme_kanban-color: #fff; +@colortheme_kanban-help-bg: #bbffbb; +@colortheme_kanban-th-bg: #005bef; +@colortheme_kanban-th-fg: #fff; +@colortheme_kanban-warn: #ffade3; + @colortheme_whiteboard-bg: #800080; @colortheme_whiteboard-color: #fff; @colortheme_whiteboard-warn: #ffae00; diff --git a/customize.dist/src/less2/main.less b/customize.dist/src/less2/main.less index dadbef539..68f1ca9c8 100644 --- a/customize.dist/src/less2/main.less +++ b/customize.dist/src/less2/main.less @@ -34,6 +34,7 @@ body.cp-app-file { @import "../../../file/app-file.less"; } body.cp-app-filepicker { @import "../../../filepicker/app-filepicker.less"; } body.cp-app-contacts { @import "../../../contacts/app-contacts.less"; } body.cp-app-poll { @import "../../../poll/app-poll.less"; } +body.cp-app-kanban { @import "../../../kanban/app-kanban.less"; } body.cp-app-whiteboard { @import "../../../whiteboard/app-whiteboard.less"; } body.cp-app-todo { @import "../../../todo/app-todo.less"; } body.cp-app-profile { @import "../../../profile/app-profile.less"; } diff --git a/customize.dist/src/less2/pages/page-index.less b/customize.dist/src/less2/pages/page-index.less index 55671f913..6ddee6349 100644 --- a/customize.dist/src/less2/pages/page-index.less +++ b/customize.dist/src/less2/pages/page-index.less @@ -154,6 +154,7 @@ h4 { .cp-callout-code .fa { background-color: @colortheme_code-bg; } .cp-callout-slide .fa { background-color: @colortheme_slide-bg; } .cp-callout-poll .fa { background-color: @colortheme_poll-bg; } +.cp-callout-kanban .fa { background-color: @colortheme_kanban-bg; } .cp-callout-whiteboard .fa { background-color: @colortheme_whiteboard-bg; } .cp-callout-recent .fa { background-color: @colortheme_drive-bg; } .cp-hidden { display: none !important; } diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index 868d107cd..d6d186a15 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -8,6 +8,7 @@ define(function () { out.type.pad = 'Rich text'; out.type.code = 'Code'; out.type.poll = 'Poll'; + out.type.kanban = 'Kanban'; out.type.slide = 'Presentation'; out.type.drive = 'CryptDrive'; out.type.whiteboard = 'Whiteboard'; @@ -21,6 +22,7 @@ define(function () { out.button_newpoll = 'New Poll'; out.button_newslide = 'New Presentation'; out.button_newwhiteboard = 'New Whiteboard'; + out.button_newkanban = 'New Kanban'; // NOTE: Remove updated_0_ if we need an updated_1_ out.updated_0_common_connectionLost = "Server Connection Lost
You're now in read-only mode until the connection is back."; @@ -245,6 +247,9 @@ define(function () { out.pad_mediatagWidth = "Width (px)"; out.pad_mediatagHeight = "Height (px)"; + // Kanban + out.kanban_title = "Kanban"; + // Polls out.poll_title = "Zero Knowledge Date Picker"; diff --git a/www/kanban/app-kanban.less b/www/kanban/app-kanban.less new file mode 100644 index 000000000..a52ade01c --- /dev/null +++ b/www/kanban/app-kanban.less @@ -0,0 +1,671 @@ +@import (once) "../../customize/src/less2/include/browser.less"; +@import (once) "../../customize/src/less2/include/toolbar.less"; +@import (once) "../../customize/src/less2/include/markdown.less"; +@import (once) '../../customize/src/less2/include/fileupload.less'; +@import (once) '../../customize/src/less2/include/alertify.less'; +@import (once) '../../customize/src/less2/include/tokenfield.less'; +@import (once) '../../customize/src/less2/include/tools.less'; +@import (once) '../../customize/src/less2/include/avatar.less'; +@import (once) '../../customize/src/less2/include/creation.less'; + +.toolbar_main( + @bg-color: @colortheme_kanban-bg, + @warn-color: @colortheme_kanban-warn, + @color: @colortheme_kanban-color +); +.fileupload_main(); +.alertify_main(); +.tokenfield_main(); +.creation_main(); + +@kanban-fore: #555; + +@kanban-th-bg: @colortheme_kanban-th-bg; +@kanban-th-fg: @colortheme_kanban-th-fg; +@kanban-th-user-bg: darken(@kanban-th-bg, 10%); +@kanban-editing: lighten(@kanban-th-bg, 10%); +@kanban-winner: darken(@kanban-th-bg, 15%); +@kanban-td-bg: @kanban-th-bg; +@kanban-td-fg: @kanban-th-fg; + +@kanban-help-bg: @colortheme_kanban-help-bg; + +@kanban-uncommitted-cell: #eee; +@kanban-uncommitted-bg: #ddd; //lighten(@kanban-th-bg, 50%); +@kanban-uncommitted-text: black; + +@kanban-placeholder: #fff; +@kanban-border-color: #555; +@kanban-cover-color: #000; +@kanban-fg: #000; +@kanban-option-yellow: #ff5; +@kanban-option-gray: #ccc; + +@kanban-add-color: #fff; +@kanban-add-bg: #777; +@kanban-add-bg-alt: #444; + +.bottom-left(@s: 5px) { border-bottom-left-radius: @s; } +.top-left(@s: 5px) { border-top-left-radius: @s; } + +display: flex; +flex-flow: column; +overflow-x: hidden; + +#cp-app-kanban-content { + display: flex; + flex: 1; + min-height: 0; + #cp-app-kanban-form { + flex: 1; + overflow-y: auto; + &.cp-app-kanban-readonly { + #cp-app-kanban-table-scroll { + max-width: ~"calc(75% - 30px - 100px)"; + } + table { + width: 100%; + } + table tr td:last-child { + margin-left: 0; // uncommitted is hidden + } + td.cp-app-kanban-table-uncommitted { + display: none; + } + } + &.cp-app-kanban-published { + #cp-app-kanban-create-option { + display: none; + } + .cp-app-kanban-table-remove[data-rt-id^="y"], .cp-app-kanban-table-edit[data-rt-id^="y"] { + display: none; + } + tr.cp-app-kanban-table-uncommitted { + display: none; + } + } + } +} + +input[type="text"], textarea { + background-color: white; + color: black; + border: 0; +} + +input[type="text"][disabled], textarea[disabled] { + background-color: transparent; + border: 0px; +} + +// The placeholder color only seems to effect Safari when not set + +input[type="text"][disabled]::placeholder { + color: @kanban-placeholder; + opacity: 1; +} + +table#cp-app-kanban-table { + margin: 0px; + overflow: hidden; +} +#cp-app-kanban-table-container { + position: relative; + margin: 20px; +} +#cp-app-kanban-table-container button { + border-radius: 0; + border: 0; +} +#cp-app-kanban-create-user { + display: inline-flex; + height: 20px; + padding: 0 5px; + margin: 2px auto; + width: auto; + overflow: hidden; + color: @kanban-add-color; + background: @kanban-add-bg; + &:hover { + background: @kanban-add-bg-alt; + } +} +#cp-app-kanban-create-option { + order: 3; + display: inline-flex; + width: 46px; + height: 20px; + margin: 2px; + padding: 0; + color: @kanban-add-color; + background: @kanban-add-bg; + &:hover { + background: @kanban-add-bg-alt; + } +} +#cp-app-kanban-table-scroll { + overflow-y: hidden; + overflow-x: auto; + margin-left: 25%; + max-width: ~"calc(75% - 100px - 100px)"; + width: auto; + display: inline-block; +} +.cp-markdown-toolbar { + margin: auto; + min-width: 80%; + width: 80%; +} +#cp-app-kanban-description { + &~ .CodeMirror { + margin: auto; + min-width: 80%; + width: 80%; + min-height: 200px; + height: 200px; + border: 1px solid black; + .CodeMirror-placeholder { + color: #777; + } + } +} +#cp-app-kanban-description-published { + display: none; + padding: 15px; + margin: auto; + + min-width: 80%; + width: 80%; + min-height: 7em; + color: #000; + border: 1px solid transparent; + background-color: #eeeeee; + font: @colortheme_app-font; + text-align: left; + media-tag > * { + max-width: 100%; + max-height: 20em; + } +} +div.cp-app-kanban-published { + div.cp-app-kanban-realtime { + #cp-app-kanban-description { + display: none; + &~ .CodeMirror { + display: none; + } + } + #cp-app-kanban-description-published { + display: block; + &:empty { + display: none; + } + } + #cp-app-kanban-nocomments { + display: none; + } + #cp-app-kanban-comments { + display: block; + } + } +} + +#cp-app-kanban-help { + width: 100%; + margin: auto; + padding: 20px 10%; + background: @kanban-help-bg; +} + +// from cryptpad.less + +table { + border-collapse: collapse; + border-spacing: 0; + margin: 20px; +} +tbody { + * { + box-sizing: border-box; + } + tr { + text-align: center; + } + + td { + .tools_unselectable(); + border-right: 1px solid @kanban-border-color; + padding: 12px; + padding-top: 0px; + padding-bottom: 0px; + &:last-child { + border-right: none; + } + } +} + +div.cp-app-kanban-realtime { + display: block; + max-height: 100%; + max-width: 100%; + + input { + &[type="text"] { + height: 1em; + margin: 0px; + } + } + > textarea { + width: 50%; + height: 15vh; + } + + padding: 0px; + margin: 0px; + + .cp-app-kanban-table-scrolled { + tr td:last-child { + right: 0; + } + tr td:nth-last-child(2) { + right: 100px; + } + } + + table { + border-collapse: collapse; + width: ~"calc(100% - 1px)"; + .cp-app-kanban-table-editing { + background-color: @kanban-editing; + } + .cp-app-kanban-table-uncommitted { + .cp-app-kanban-table-cover { + background-color: @kanban-uncommitted-cell !important; + } + div.cp-app-kanban-table-text-cell { + background-color: @kanban-uncommitted-bg !important; + color: @kanban-uncommitted-text !important; + } + text-align: center; + background-color: @kanban-uncommitted-bg !important; + color: @kanban-uncommitted-text !important; + } + tr { + height: 28px; + /* Options */ + td:first-child { + position:absolute; + left: 0; + top: auto; + width: 25%; + } + /* Uncommitted column */ + td:nth-last-child(2) { + position: absolute; + top: auto; + width: 100px; + min-width: unset !important; + height: auto !important; + } + /* Results */ + td:last-child { + color: @kanban-th-fg; + position:absolute; + top: auto; + margin-left: 100px; + width: 100px; + min-width: unset !important; + background-color: @kanban-th-bg; + } + td { + padding: 0px; + margin: 0px; + + div.cp-app-kanban-table-text-cell { + height: 28px; + padding: 0px; + margin: 0px; + display: flex; + align-items: center; + .cp-app-kanban-table-remove { + order: 1; + } + .cp-app-kanban-table-edit { + order: 3; + } + input { + min-width: 0; + order: 2; + flex: 1; + height: 24px; + border: 0px; + margin: 2px; + &[disabled] { + background-color: transparent; + color: @kanban-td-fg; + //font-weight: bold; + } + } + } + + &.cp-app-kanban-table-checkbox-cell { + margin: 0px; + padding: 0px; + height: 100%; + min-width: 100px; + + div.cp-app-kanban-table-checkbox-contain { + display: inline-block; + height: 100%; + width: 100%; + position: relative; + + label { + background-color: transparent; + display: block; + position: absolute; + top: 0px; + left: 0px; + height: 100%; + width: 100%; + } + + input { + &[type="number"] { + &:not(.editable) { + display: none; + + ~ .cp-app-kanban-table-cover { + line-height: 28px; + display: block; + font-weight: bold; + height: 100%; + display: block; + + color: @kanban-cover-color; + + &:after { + height: 100%; + } + + } + } + } + } + + input[type="number"][value="0"] { + ~ .cp-app-kanban-table-cover { + background-color: @colortheme_cp-red; + &:after { content: "✖"; } + } + } + input[type="number"][value="1"] { + ~ .cp-app-kanban-table-cover { + background-color: @colortheme_cp-green; + &:after { content: "✔"; } + } + } + input[type="number"][value="2"] { + ~ .cp-app-kanban-table-cover { + background-color: @kanban-option-yellow; + &:after { content: "~"; } + } + } + input[type="number"][value="3"] { + ~ .cp-app-kanban-table-cover { + background-color: @kanban-option-gray; + &:after { content: "?"; } + } + } + } + } + } + } + + input { + &[type="text"] { + height: auto; + width: 80%; + } + } + span { + .tools_unselectable(); + } + thead { + height: 52px; + tr { + height: 52px; + } + td { + padding: 0px 5px; + background: @kanban-th-bg; + color: @kanban-th-fg; + &:not(:last-child) { + border-right: 1px solid rgba(255,255,255,0.2); + } + &:last-child { + height: 52px; + line-height: 52px; + text-align: center; + } + &:nth-last-child(2) { + border-right: 1px solid @kanban-border-color; + } + &.cp-app-kanban-table-own { + background: @kanban-th-user-bg; + .cp-app-kanban-table-lock { + cursor: default; + } + } + .cp-app-kanban-table-buttons { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + align-items: center; + span { + cursor: pointer; + width: 1em; + text-align: center; + } + .cp-app-kanban-table-bookmark { + color: darken(@kanban-th-fg, 30%); + &.cp-app-kanban-table-bookmark-full { + color: @kanban-th-fg; + } + } + } + input { + &[type="text"] { + overflow: hidden; + text-overflow: ellipsis; + break-after: always; + width: ~"calc(100% - 2px)"; // borders... + box-sizing: border-box; + padding: 1px 5px; + margin: 1px; + &[disabled] { + color: @kanban-th-fg; + } + } + } + } + } + + tbody { + td:first-child { + background: @kanban-td-bg; + color: @kanban-td-fg; + } + td.cp-app-kanban-table-winner { + background-color: @kanban-winner; + &:last-child { font-weight: bold; } + } + .cp-app-kanban-table-text-cell { + input[type="text"] { + width: ~"calc(100% - 50px)"; + padding: 0 0.5em; + } + .cp-app-kanban-table-edit { + float:right; + margin: 2px 10px 0 0; + } + .cp-app-kanban-table-remove { + float: left; + margin: 2px 0 0 10px; + } + } + tr:not(:first-child) { + td:not(:first-child) { + label { + border-top: 1px solid @kanban-border-color; + } + } + } + } + .cp-app-kanban-table-edit { + //color: @kanban-cover-color; + cursor: pointer; + float: left; + margin-left: 10px; + } + + thead { + tr { + th { + input[type="text"][disabled] { + background-color: transparent; + color: @kanban-fore; + font-weight: bold; + } + .cp-app-kanban-table-remove { + cursor: pointer; + font-size: 20px; + } + } + } + } + tbody { + tr { + td { + + } + } + } + tfoot { + display: none; + } + } + #cp-app-kanban-nocomments { + color: #999; + text-align: center; + margin: 20px; + font: @colortheme_app-font; + } + #cp-app-kanban-comments { + width: 50%; + margin: 20px auto; + min-width: 400px; + padding-bottom: 5px; + display: none; + button { + border-radius: 0; + } + #cp-app-kanban-comments-add { + input, textarea { + border: 1px solid black; + width: 90%; + margin: 5px 5%; + } + input { + padding: 5px; + height: 26px; + &[disabled] { + background: #eee; + } + } + textarea { + padding: 5px; + height: 8em; + line-height: 1.5em; + } + button { + padding: 10px; + } + text-align: center; + } + #cp-app-kanban-comments-list { + .cp-app-kanban-comments-list-el { + width: 90%; + margin: 5px 5%; + } + .cp-app-kanban-comments-list-msg { + display: flex; + background: #eee; + padding: 5px 10px; + .cp-app-kanban-comments-list-msg-text { + flex: 1; + white-space: pre-wrap; + } + .cp-app-kanban-comments-list-msg-actions { + button { + padding: 0; + width: 25px; + line-height: 20px; + } + } + } + .cp-app-kanban-comments-list-data { + background: #ddd; + padding: 5px 10px; + display: flex; + align-items: center; + .cp-app-kanban-comments-list-data-name { + margin-left: 10px; + flex: 1; + } + .cp-app-kanban-comments-list-data-avatar { .avatar_main(30px); } + } + } + } + + @media screen and (max-width: 500px) { + #cp-app-kanban-table-scroll { + max-width: 100%; + padding: 0; + margin: 0; + table { + tr { + td { + &:first-child { + position: unset; + min-width: 100px; + &:hover:not(:empty) { + position: absolute; + min-width: 100px; + width: auto; + z-index: 100; + } + } + &:nth-last-child(2) { + position: unset; + } + &:last-child { + position: unset; + } + } + } + } + } + #cp-app-kanban-comments { + min-width: 90%; + } + } +} + + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; +} + diff --git a/www/kanban/index.html b/www/kanban/index.html new file mode 100644 index 000000000..e3f7eacc4 --- /dev/null +++ b/www/kanban/index.html @@ -0,0 +1,38 @@ + + + + CryptPad + + + + + + + + + + diff --git a/www/kanban/inner.html b/www/kanban/inner.html index d201fce79..0cc1ecdb2 100644 --- a/www/kanban/inner.html +++ b/www/kanban/inner.html @@ -1,43 +1,23 @@ + - - + + +
+
+
+
+
+
+ + diff --git a/www/kanban/inner.js b/www/kanban/inner.js index 14ba346f7..080e2eabe 100644 --- a/www/kanban/inner.js +++ b/www/kanban/inner.js @@ -1,627 +1,282 @@ define([ 'jquery', - '/bower_components/chainpad-crypto/crypto.js', - '/common/toolbar3.js', - 'json.sortify', - '/common/common-util.js', '/bower_components/nthen/index.js', '/common/sframe-common.js', - '/common/common-interface.js', - '/api/config', - '/common/common-realtime.js', - '/customize/pages.js', + '/common/sframe-app-framework.js', + '/common/common-util.js', + '/common/common-hash.js', + '/common/modes.js', '/customize/messages.js', - '/customize/application_config.js', - '/common/common-thumbnail.js', - '/bower_components/chainpad/chainpad.dist.js', - - '/bower_components/secure-fabric.js/dist/fabric.min.js', - '/bower_components/file-saver/FileSaver.min.js', - - 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', - 'less!/bower_components/components-font-awesome/css/font-awesome.min.css', - 'less!/customize/src/less2/main.less', - 'css!/kanban/jkanban.css', '/kanban/jkanban.js', + 'css!/kanban/jkanban.css', ], function ( $, - Crypto, - Toolbar, - JSONSortify, - Util, nThen, SFCommon, - UI, - ApiConfig, - CommonRealtime, - Pages, - Messages, - AppConfig, - Thumb, - ChainPad) -{ - var saveAs = window.saveAs; - - var APP = window.APP = { - $: $ - }; - var Fabric = APP.Fabric = window.fabric; - - var stringify = function (obj) { - return JSONSortify(obj); - }; - - var toolbar; - - var andThen = function (common) { - var config = {}; - /* Initialize Fabric */ - var canvas = APP.canvas = null; - var $canvas = $('canvas'); - var readOnly = false; - - var setEditable = function (bool) { - APP.editable = bool; - if (readOnly && bool) { return; } - }; - - var saveImage = APP.saveImage = function () { - }; - - APP.FM = common.createFileManager({}); - APP.upload = function (title) { - }; - - var initializing = true; - var $bar = $('#cp-toolbar'); - var Title; - var cpNfInner; - var metadataMgr; - - config = { - readOnly: readOnly, - patchTransformer: ChainPad.NaiveJSONTransformer, - // cryptpad debug logging (default is 1) - // logLevel: 0, - validateContent: function (content) { - try { - JSON.parse(content); - return true; - } catch (e) { - console.log("Failed to parse, rejecting patch"); - return true; - } - } - }; - - var stringifyInner = function (textValue) { - var obj = { - content: textValue, - metadata: metadataMgr.getMetadataLazy() - }; - // stringify the json and send it into chainpad - return stringify(obj); - }; - - var onLocal = config.onLocal = function () { - if (initializing) { return; } - if (readOnly) { return; } - - var content = stringifyInner(Kanban.getBoardsJSON()); - console.log("Updating content " + content); - - try { - APP.realtime.contentUpdate(content); - } catch (e) { - APP.unrecoverable = true; - setEditable(false); - APP.toolbar.errorState(true, e.message); - var msg = Messages.chainpadError; - UI.errorLoadingScreen(msg, true, true); - console.error(e); - } - }; - - var initThumbnails = function () { - var oldThumbnailState; - var privateDat = metadataMgr.getPrivateData(); - if (!privateDat.thumbnails) { return; } - var hash = privateDat.availableHashes.editHash || - privateDat.availableHashes.viewHash; - var href = privateDat.pathname + '#' + hash; - var mkThumbnail = function () { - if (!hash) { return; } - if (initializing) { return; } - if (!APP.realtime) { return; } - var content = APP.realtime.getUserDoc(); - if (content === oldThumbnailState) { return; } - /* - var D = Thumb.getResizedDimensions($canvas[0], 'pad'); - Thumb.fromCanvas($canvas[0], D, function (err, b64) { - oldThumbnailState = content; - Thumb.setPadThumbnail(common, href, b64); - }); - */ - }; - window.setInterval(mkThumbnail, Thumb.UPDATE_INTERVAL); - window.setTimeout(mkThumbnail, Thumb.UPDATE_FIRST); - }; - - config.onInit = function (info) { - readOnly = metadataMgr.getPrivateData().readOnly; - - Title = common.createTitle({}); - - var configTb = { - displayed: [ - 'userlist', - 'title', - 'useradmin', - 'spinner', - 'newpad', - 'share', - 'limit', - 'unpinnedWarning' - ], - title: Title.getTitleConfig(), - metadataMgr: metadataMgr, - readOnly: readOnly, - realtime: info.realtime, - sfCommon: common, - $container: $bar, - $contentContainer: $('#cp-app-kanban-content') - }; - toolbar = APP.toolbar = Toolbar.create(configTb); - Title.setToolbar(toolbar); - - var $rightside = toolbar.$rightside; - var $drawer = toolbar.$drawer; - - /* save as template */ - if (!metadataMgr.getPrivateData().isTemplate) { - var templateObj = { - rt: info.realtime, - getTitle: function () { return metadataMgr.getMetadata().title; } - }; - var $templateButton = common.createButton('template', true, templateObj); - $rightside.append($templateButton); - } - - /* add an export button */ - var $export = common.createButton('export', true, {}, saveImage); - $drawer.append($export); - - if (common.isLoggedIn()) { - common.createButton('savetodrive', true, {}, function () {}) - .click(function () { - UI.prompt(Messages.exportPrompt, document.title + '.png', - function (name) { - if (name === null || !name.trim()) { return; } - APP.upload(name); - }); - }).appendTo($rightside); - - common.createButton('hashtag', true).appendTo($rightside); - } - - var $forget = common.createButton('forget', true, {}, function (err) { - if (err) { return; } - setEditable(false); - }); - $rightside.append($forget); - - var $properties = common.createButton('properties', true); - toolbar.$drawer.append($properties); - - var $appContainer = $('#cp-app-kanban-container'); - var helpMenu = common.createHelpMenu(['kanban']); - $appContainer.prepend(helpMenu.menu); - toolbar.$drawer.append(helpMenu.button); - - metadataMgr.onChange(function () { - var md = metadataMgr.getMetadata(); - }); - - }; - - config.onReady = function (info) { - if (APP.realtime !== info.realtime) { - APP.realtime = info.realtime; - } - - var userDoc = APP.realtime.getUserDoc(); - var isNew = false; - var newDoc = ''; - if (userDoc === "" || userDoc === "{}") { isNew = true; } - - if (userDoc !== "") { - var hjson = JSON.parse(userDoc); - - if (hjson && hjson.metadata) { - metadataMgr.updateMetadata(hjson.metadata); - } - if (typeof (hjson) !== 'object' || Array.isArray(hjson) || - (hjson.metadata && typeof(hjson.metadata.type) !== 'undefined' && - hjson.metadata.type !== 'kanban')) { - var errorText = Messages.typeError; - UI.errorLoadingScreen(errorText); - throw new Error(errorText); - } - newDoc = hjson.content; - - // launch the kanban code - config.initKanban(newDoc); - - } else { - Title.updateTitle(Title.defaultTitle); - config.initKanban(); - } - - nThen(function (waitFor) { - if (newDoc) { - } - }).nThen(function () { - setEditable(!readOnly); - initializing = false; - config.onLocal(); - UI.removeLoadingScreen(); - - initThumbnails(); - - - if (readOnly) { return; } - - var privateDat = metadataMgr.getPrivateData(); - var skipTemp = Util.find(privateDat, - ['settings', 'general', 'creation', 'noTemplate']); - var skipCreation = Util.find(privateDat, ['settings', 'general', 'creation', 'skip']); - if (isNew && (!AppConfig.displayCreationScreen || (!skipTemp && skipCreation))) { - common.openTemplatePicker(); - } - }); - }; - - config.onRemote = function () { - if (initializing) { return; } - var userDoc = APP.realtime.getUserDoc(); - - console.log("Received content: " + userDoc); - - var json = JSON.parse(userDoc); - var remoteDoc = json.content; - - var currentContent = stringify(Kanban.getBoardsJSON()); - var remoteContent = stringify(json.content); - - - if (currentContent !== remoteContent) { - // reinit kanban (TODO: optimize to diff only) - console.log("Content is different.. Applying content"); - config.Kanban.setBoards(remoteDoc); - common.notify(); - } - if (readOnly) { setEditable(false); } - }; - - config.onAbort = function () { - if (APP.unrecoverable) { return; } - // inform of network disconnect - setEditable(false); - toolbar.failed(); - UI.alert(Messages.common_connectionLost, undefined, true); - }; - - config.onConnectionChange = function (info) { - if (APP.unrecoverable) { return; } - setEditable(info.state); - if (info.state) { - initializing = true; - //UI.findOKButton().click(); - } else { - //UI.alert(Messages.common_connectionLost, undefined, true); - } - }; - - config.onError = function (err) { - common.onServerError(err, toolbar, function () { - APP.unrecoverable = true; - setEditable(false); - }); - }; - - config.initKanban = function(boards) { - var defaultBoards = [ - { - "id": "todo", - "title": "To Do", - "color": "blue", - "item": [ - { - "title": "Item 1" - }, - { - "title": "Item 2" - } + Framework, + Util, + Hash, + Modes, + Messages) { + + // Kanban code + var initKanban = function (framework, boards) { + var defaultBoards = [ + { + "id": "todo", + "title": "To Do", + "color": "blue", + "item": [ + { + "title": "Item 1" + }, + { + "title": "Item 2" + } ] }, - { - "id": "working", - "title": "Working", - "color": "orange", - "item": [ - { - "title": "Item 3", + { + "id": "working", + "title": "Working", + "color": "orange", + "item": [ + { + "title": "Item 3", }, - { - "title": "Item 4", + { + "title": "Item 4", } ] }, - { - "id": "done", - "title": "Done", - "color": "green", - "item": [ - { - "title": "Item 5", + { + "id": "done", + "title": "Done", + "color": "green", + "item": [ + { + "title": "Item 5", }, - { - "title": "Item 6", + { + "title": "Item 6", } ] }]; - - if (boards==null) { - console.log("Initializing with default boards content"); - boards = defaultBoards; - } else { - console.log("Initializing with boards content " + boards); - } - - // Remove any existing elements - $(".kanban-container-outer").remove(); - - window.Kanban = config.Kanban = new jKanban({ -element: '#cp-app-kanban-content', -gutter: '15px', -widthBoard: '300px', -onChange: function() { -console.log("Board object has changed"); -config.onLocal(); -} -,click: function (el) { - if (Kanban.inEditMode) { - console.log("An edit is already active"); - return; - } - Kanban.inEditMode = true; - var name = $(el).text(); - $(el).html(''); - $('') - .attr({ - 'type': 'text', - 'name': 'text', - 'id': 'kanban_edit', - 'size': '30', - 'value': name - }) - .appendTo(el); - $('#kanban_edit').focus(); - $('#kanban_edit').blur(function() { - var name = $('#kanban_edit').val(); - $(el).text(name); - var board = $(el.parentNode.parentNode).attr("data-id"); - var pos = Kanban.findElementPosition(el); - console.log(pos); - console.log(board); - Kanban.getBoardJSON(board).item[pos].title = name; - Kanban.onChange(); - Kanban.inEditMode = false; - }); -}, -boardTitleClick: function (el) { - if (Kanban.inEditMode) { - console.log("An edit is already active"); - return; - } - Kanban.inEditMode = true; - var name = $(el).text(); - $(el).html(''); - $('') - .attr({ - 'type': 'text', - 'name': 'text', - 'id': 'kanban_edit', - 'size': '30', - 'value': name - }) - .appendTo(el); - $('#kanban_edit').focus(); - $('#kanban_edit').blur(function() { - var name = $('#kanban_edit').val(); - $(el).text(name); - var board = $(el.parentNode.parentNode).attr("data-id"); - Kanban.getBoardJSON(board).title = name; - Kanban.onChange(); - Kanban.inEditMode = false; - }); + if (boards == null) { + console.log("Initializing with default boards content"); + boards = defaultBoards; + } else { + console.log("Initializing with boards content " + boards); + } -}, -colorClick: function (el, boardId) { - console.log("in color click"); - var board = $(el.parentNode).attr("data-id"); - var boardJSON = Kanban.getBoardJSON(board); - var currentColor = boardJSON.color; - console.log("Current color " + currentColor); - var index = Kanban.options.colors.findIndex(function(element) { return (element==currentColor) }) + 1; - console.log("Next index " + index); - if (index>=Kanban.options.colors.length) - index = 0; - var nextColor = Kanban.options.colors[index]; - console.log("Next color " + nextColor); - boardJSON.color = nextColor; - $(el).removeClass("kanban-header-" + currentColor); - $(el).addClass("kanban-header-" + nextColor); - Kanban.onChange(); - -}, -removeClick: function(el, boardId) { - if (confirm("Do you want to delete this board?")) { - console.log("Delete board"); - var boardName = $(el.parentNode.parentNode).attr("data-id"); - for (index in Kanban.options.boards) { - if (Kanban.options.boards[index].id == boardName) { - break; - } - index++; - } - Kanban.options.boards.splice(index, 1); - Kanban.removeBoard(boardName); - Kanban.onChange(); - } -}, -buttonClick: function (el, boardId) { -console.log(el); -console.log(boardId); -// create a form to enter element -var formItem = document.createElement('form'); -formItem.setAttribute("class", "itemform"); -formItem.innerHTML = '
' + // Remove any existing elements + $(".kanban-container-outer").remove(); + + var kanban = new jKanban({ + element: '#cp-app-kanban-content', + gutter: '15px', + widthBoard: '300px', + onChange: function () { + console.log("Board object has changed"); + framework.localChange(); + }, + click: function (el) { + if (kanban.inEditMode) { + console.log("An edit is already active"); + return; + } + kanban.inEditMode = true; + var name = $(el).text(); + $(el).html(''); + $('') + .attr({ + 'type': 'text', + 'name': 'text', + 'id': 'kanban_edit', + 'size': '30', + 'value': name + }) + .appendTo(el); + $('#kanban_edit').focus(); + $('#kanban_edit').blur(function () { + var name = $('#kanban_edit').val(); + $(el).text(name); + var board = $(el.parentNode.parentNode).attr("data-id"); + var pos = kanban.findElementPosition(el); + console.log(pos); + console.log(board); + kanban.getBoardJSON(board).item[pos].title = name; + kanban.onChange(); + kanban.inEditMode = false; + }); -Kanban.addForm(boardId, formItem); -formItem.addEventListener("submit", function (e) { - e.preventDefault(); - var text = e.target[0].value - Kanban.addElement(boardId, { - "title": text, - }) - formItem.parentNode.removeChild(formItem); - }); -document.getElementById('CancelBtn').onclick = function () { - formItem.parentNode.removeChild(formItem) -} -}, -addItemButton: true, - boards: boards -}); + }, + boardTitleClick: function (el) { + if (kanban.inEditMode) { + console.log("An edit is already active"); + return; + } + kanban.inEditMode = true; + var name = $(el).text(); + $(el).html(''); + $('') + .attr({ + 'type': 'text', + 'name': 'text', + 'id': 'kanban_edit', + 'size': '30', + 'value': name + }) + .appendTo(el); + $('#kanban_edit').focus(); + $('#kanban_edit').blur(function () { + var name = $('#kanban_edit').val(); + $(el).text(name); + var board = $(el.parentNode.parentNode).attr("data-id"); + kanban.getBoardJSON(board).title = name; + kanban.onChange(); + kanban.inEditMode = false; + }); -var addBoardDefault = document.getElementById('kanban-addboard'); -addBoardDefault.addEventListener('click', function () { - var counter = 1; - found = false; - while (found) { - for (var board in Kanban.options.boards) { - if (board.id == "board" + counter) { - counter++; - break; - } - } - found = true; - } + }, + colorClick: function (el, boardId) { + console.log("in color click"); + var board = $(el.parentNode).attr("data-id"); + var boardJSON = kanban.getBoardJSON(board); + var currentColor = boardJSON.color; + console.log("Current color " + currentColor); + var index = kanban.options.colors.findIndex(function (element) { + return (element == currentColor) + }) + 1; + console.log("Next index " + index); + if (index >= kanban.options.colors.length) + index = 0; + var nextColor = kanban.options.colors[index]; + console.log("Next color " + nextColor); + boardJSON.color = nextColor; + $(el).removeClass("kanban-header-" + currentColor); + $(el).addClass("kanban-header-" + nextColor); + kanban.onChange(); + + }, + removeClick: function (el, boardId) { + if (confirm("Do you want to delete this board?")) { + console.log("Delete board"); + var boardName = $(el.parentNode.parentNode).attr("data-id"); + for (index in kanban.options.boards) { + if (kanban.options.boards[index].id == boardName) { + break; + } + index++; + } + kanban.options.boards.splice(index, 1); + kanban.removeBoard(boardName); + kanban.onChange(); + } + }, + buttonClick: function (el, boardId) { + console.log(el); + console.log(boardId); + // create a form to enter element + var formItem = document.createElement('form'); + formItem.setAttribute("class", "itemform"); + formItem.innerHTML = '
' + + kanban.addForm(boardId, formItem); + formItem.addEventListener("submit", function (e) { + e.preventDefault(); + var text = e.target[0].value + kanban.addElement(boardId, { + "title": text, + }) + formItem.parentNode.removeChild(formItem); + }); + document.getElementById('CancelBtn').onclick = function () { + formItem.parentNode.removeChild(formItem) + } + }, + addItemButton: true, + boards: boards + }); - Kanban.addBoards( - [{ - "id" : "board" + counter, - "title": "New Board", - "color": "yellow", - "item": [ - { - "title": "Item 1", - } - ] - }] - ) - Kanban.onChange(); - }); - -/* -var toDoButton = document.getElementById('addToDo'); -toDoButton.addEventListener('click', function () { - Kanban.addElement( - "_todo", - { - "title": "Test Add", - } - ); - }); + var addBoardDefault = document.getElementById('kanban-addboard'); + addBoardDefault.addEventListener('click', function () { + var counter = 1; + found = false; + while (found) { + for (var board in kanban.options.boards) { + if (board.id == "board" + counter) { + counter++; + break; + } + } + found = true; + } -var addBoardDefault = document.getElementById('addDefault'); -addBoardDefault.addEventListener('click', function () { - Kanban.addBoards( + kanban.addBoards( [{ - "id": "_default", - "title": "Kanban Default", - "item": [ - { - "title": "Default Item", - }, - { - "title": "Default Item 2", - }, - { - "title": "Default Item 3", + "id": "board" + counter, + "title": "New Board", + "color": "yellow", + "item": [ + { + "title": "Item 1", } ] }] - ) - }); - -var removeBoard = document.getElementById('removeBoard'); -removeBoard.addEventListener('click', function () { - Kanban.removeBoard('_done'); - }); + ) + kanban.onChange(); + }); -var removeElement = document.getElementById('removeElement'); -removeElement.addEventListener('click', function () { - Kanban.removeElement('_test_delete'); - }); + return kanban; + }; -var allEle = Kanban.getBoardElements('_todo'); -allEle.forEach(function (item, index) { - //console.log(item); - }); -*/ -}; + // Start of the main loop + var andThen2 = function (framework) { - cpNfInner = common.startRealtime(config); - metadataMgr = cpNfInner.metadataMgr; + var kanban = initKanban(framework); - cpNfInner.onInfiniteSpinner(function () { - if (APP.unrecoverable) { return; } - setEditable(false); - UI.confirm(Messages.realtime_unrecoverableError, function (yes) { - if (!yes) { return; } - common.gotoURL(); - }); + framework.onContentUpdate(function (newContent) { + // Need to update the content + console.log("Content should be updated to " + newContent); + var currentContent = kanban.getBoardsJSON(); + var remoteContent = newContent.content; + + if (currentContent !== remoteContent) { + // reinit kanban (TODO: optimize to diff only) + console.log("Content is different.. Applying content"); + kanban.setBoards(remoteContent); + } }); - $('#save').on('click', function () { + framework.setContentGetter(function () { + // var content = $("#cp-app-kanban-content").val(); + var content = kanban.getBoardsJSON(); + console.log("Content current value is " + content); + return { + content: content + }; }); + framework.onReady(function (newPad) { + $("#cp-app-kanban-content").focus(); + }); - common.onLogout(function () { setEditable(false); }); + framework.start(); }; - - var main = function () { - var common; - + // var framework; nThen(function (waitFor) { - $(waitFor(function () { - UI.addLoadingScreen(); - var $div = $('
').append(Pages['/kanban/']()); - $('body').append($div.html()); - $('body').addClass("cp-app-kanban"); + + // Framework initialization + Framework.create({ + toolbarContainer: '#cme_toolbox', + contentContainer: '#cp-app-kanban-editor', + }, waitFor(function (fw) { + framework = fw; + andThen2(framework); })); - SFCommon.create(waitFor(function (c) { APP.common = common = c; })); - }).nThen(function (waitFor) { - common.getSframeChannel().onReady(waitFor()); - }).nThen(function (waitFor) { - common.handleNewFile(waitFor); - }).nThen(function (/*waitFor*/) { - andThen(common); }); }; main(); diff --git a/www/kanban/jkanban.css b/www/kanban/jkanban.css index 13e89c27d..86cda09e7 100644 --- a/www/kanban/jkanban.css +++ b/www/kanban/jkanban.css @@ -1,4 +1,3 @@ - .kanban-container-outer { position: relative; box-sizing: border-box; @@ -30,7 +29,7 @@ vertical-align: top; } -.kanban-board.disabled-board{ +.kanban-board.disabled-board { opacity: .3; } @@ -92,37 +91,52 @@ height: auto !important; } -.kanban-header-yellow { background: #FC3; } -.kanban-header-orange { background: #F91; } -.kanban-header-blue { background: #0AC; } -.kanban-header-red { background: #E43; } -.kanban-header-green { background: #8C4; } +.kanban-header-yellow { + background: #FC3; +} + +.kanban-header-orange { + background: #F91; +} + +.kanban-header-blue { + background: #0AC; +} + +.kanban-header-red { + background: #E43; +} + +.kanban-header-green { + background: #8C4; +} #kanban-addboard { - float: left; - margin: 30px; - margin-right: 10px; - padding: 5px; - padding-top: 3; - padding-bottom: 3px; - border: 1px solid; - width: 30px; - text-align: center; - background: #d4d4e8; - font-weight: bold; + float: left; + margin: 30px; + margin-right: 10px; + padding: 5px; + padding-top: 3; + padding-bottom: 3px; + border: 1px solid; + width: 30px; + text-align: center; + background: #d4d4e8; + font-weight: bold; } .kanban-removeboard { - float: right; - margin: 10px; - padding: 3px; - width: 30px; - text-align: center; - background: #eee; - font-weight: bold; + float: right; + margin: 10px; + padding: 3px; + width: 30px; + text-align: center; + background: #eee; + font-weight: bold; } /* Dragula CSS */ + .gu-mirror { position: fixed !important; margin: 0 !important; @@ -148,4 +162,4 @@ .form-group { text-align: right; margin-button: 5px; -} +} \ No newline at end of file diff --git a/www/kanban/jkanban.js b/www/kanban/jkanban.js index 60ca1dcdd..a2c5f3467 100644 --- a/www/kanban/jkanban.js +++ b/www/kanban/jkanban.js @@ -1,1398 +1,1552 @@ -(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 self.options.responsive) { - - //Init Drag Board - self.drakeBoard = self.dragula([self.container], { - moves: function (el, source, handle, sibling) { - if (!self.options.dragBoards) return false; - return (handle.classList.contains('kanban-board-header') || handle.classList.contains('kanban-title-board')); - }, - accepts: function (el, target, source, sibling) { - return target.classList.contains('kanban-container'); - }, - revertOnSpill: true, - direction: 'horizontal', - }) - .on('drag', function (el, source) { - el.classList.add('is-moving'); - self.options.dragBoard(el, source); - if (typeof(el.dragfn) === 'function') - el.dragfn(el, source); - }) - .on('dragend', function (el) { - el.classList.remove('is-moving'); - self.options.dragendBoard(el); - if (typeof(el.dragendfn) === 'function') - el.dragendfn(el); - }) - .on('drop', function (el, target, source, sibling) { - el.classList.remove('is-moving'); - self.options.dropBoard(el, target, source, sibling); - if (typeof(el.dropfn) === 'function') - el.dropfn(el, target, source, sibling); - - // TODO: update board object board order - console.log("Drop " + $(el).attr("data-id") + " just before " + (sibling ? $(sibling).attr("data-id") : " end ")); - var index1 = self.options.boards.findIndex(function(element) { return element.id==$(el).attr("data-id"); }); - var index2 = sibling ? self.options.boards.findIndex(function(element) { return element.id==$(sibling).attr("data-id"); }) : self.options.boards.length; - console.log("Switch " + index1 + " and " + index2); - if (index1 self.options.responsive) { + + //Init Drag Board + self.drakeBoard = self.dragula([self.container], { + moves: function (el, source, handle, sibling) { + if (!self.options.dragBoards) return false; + return (handle.classList.contains('kanban-board-header') || handle.classList.contains('kanban-title-board')); + }, + accepts: function (el, target, source, sibling) { + return target.classList.contains('kanban-container'); + }, + revertOnSpill: true, + direction: 'horizontal', + }) + .on('drag', function (el, source) { + el.classList.add('is-moving'); + self.options.dragBoard(el, source); + if (typeof (el.dragfn) === 'function') + el.dragfn(el, source); + }) + .on('dragend', function (el) { + el.classList.remove('is-moving'); + self.options.dragendBoard(el); + if (typeof (el.dragendfn) === 'function') + el.dragendfn(el); + }) + .on('drop', function (el, target, source, sibling) { + el.classList.remove('is-moving'); + self.options.dropBoard(el, target, source, sibling); + if (typeof (el.dropfn) === 'function') + el.dropfn(el, target, source, sibling); + + // TODO: update board object board order + console.log("Drop " + $(el).attr("data-id") + " just before " + (sibling ? $(sibling).attr("data-id") : " end ")); + var index1 = self.options.boards.findIndex(function (element) { + return element.id == $(el).attr("data-id"); + }); + var index2 = sibling ? self.options.boards.findIndex(function (element) { + return element.id == $(sibling).attr("data-id"); + }) : self.options.boards.length; + console.log("Switch " + index1 + " and " + index2); + if (index1 < index2) + index2 = index2 - 1; + self.options.boards.splice(index2, 0, self.options.boards.splice(index1, 1)[0]); + // send event that board has changed + self.onChange(); + + }); + + //Init Drag Item + self.drake = self.dragula(self.boardContainer, function () { + revertOnSpill: true + }) + .on('drag', function (el, source) { + // we need to calculate the position before starting to drag + self.dragItemPos = self.findElementPosition(el); + + el.classList.add('is-moving'); + var boardJSON = __findBoardJSON(source.parentNode.dataset.id); + if (boardJSON.dragTo !== undefined) { + self.options.boards.map(function (board) { + if (boardJSON.dragTo.indexOf(board.id) === -1 && board.id !== source.parentNode.dataset.id) { + self.findBoard(board.id).classList.add('disabled-board'); + } + }) + } - //Init Drag Item - self.drake = self.dragula(self.boardContainer, function () { - revertOnSpill: true - }) - .on('drag', function (el, source) { - // we need to calculate the position before starting to drag - self.dragItemPos = self.findElementPosition(el); - - el.classList.add('is-moving'); - var boardJSON = __findBoardJSON(source.parentNode.dataset.id); - if (boardJSON.dragTo !== undefined) { - self.options.boards.map(function (board) { - if (boardJSON.dragTo.indexOf(board.id) === -1 && board.id !== source.parentNode.dataset.id) { - self.findBoard(board.id).classList.add('disabled-board'); + self.options.dragEl(el, source); + if (el !== null && typeof (el.dragfn) === 'function') + el.dragfn(el, source); + }) + .on('dragend', function (el) { + console.log("In dragend"); + self.options.dragendEl(el); + if (el !== null && typeof (el.dragendfn) === 'function') + el.dragendfn(el); + }) + .on('cancel', function (el, container, source) { + console.log("In cancel"); + if (confirm("Do you want to remove this item?")) { + var board1 = self.options.boards.find(function (element) { + return element.id == $(source.parentNode).attr("data-id"); + }); + var pos1 = self.dragItemPos; + board1.item.splice(pos1, 1); + $(el).remove(); + self.onChange(); } }) - } + .on('drop', function (el, target, source, sibling) { + console.log("In drop"); + + // TODO: update board object board order + var board1 = self.options.boards.find(function (element) { + return element.id == $(source.parentNode).attr("data-id"); + }); + var board2 = self.options.boards.find(function (element) { + return element.id == $(target.parentNode).attr("data-id"); + }); + var pos1 = self.dragItemPos; + var pos2 = (sibling) ? self.findElementPosition(sibling) : (board2.item.length + 1); + console.log("Drop element " + pos1 + " before " + pos2); + + // TODO: update board object item order + + var allB = document.querySelectorAll('.kanban-board'); + if (allB.length > 0 && allB !== undefined) { + for (var i = 0; i < allB.length; i++) { + allB[i].classList.remove('disabled-board'); + } + } + var boardJSON = __findBoardJSON(source.parentNode.dataset.id); + if (boardJSON.dragTo !== undefined) { + if (boardJSON.dragTo.indexOf(target.parentNode.dataset.id) === -1 && target.parentNode.dataset.id !== source.parentNode.dataset.id) { + self.drake.cancel(true) + } + } + if (el !== null) { + self.options.dropEl(el, target, source, sibling); + el.classList.remove('is-moving'); + if (typeof (el.dropfn) === 'function') + el.dropfn(el, target, source, sibling); + } - self.options.dragEl(el, source); - if (el !== null && typeof(el.dragfn) === 'function') - el.dragfn(el, source); - }) - .on('dragend', function (el) { - console.log("In dragend"); - self.options.dragendEl(el); - if (el !== null && typeof(el.dragendfn) === 'function') - el.dragendfn(el); - }) - .on('cancel', function (el, container, source) { - console.log("In cancel"); - if (confirm("Do you want to remove this item?")) { - var board1 = self.options.boards.find(function(element) { return element.id==$(source.parentNode).attr("data-id"); }); - var pos1 = self.dragItemPos; - board1.item.splice(pos1, 1); - $(el).remove(); - self.onChange(); - } - }) - .on('drop', function (el, target, source, sibling) { - console.log("In drop"); - - // TODO: update board object board order - var board1 = self.options.boards.find(function(element) { return element.id==$(source.parentNode).attr("data-id"); }); - var board2 = self.options.boards.find(function(element) { return element.id==$(target.parentNode).attr("data-id"); }); - var pos1 = self.dragItemPos; - var pos2 = (sibling) ? self.findElementPosition(sibling) : (board2.item.length+1); - console.log("Drop element " + pos1 + " before " + pos2); - - // TODO: update board object item order - - var allB = document.querySelectorAll('.kanban-board'); - if (allB.length > 0 && allB !== undefined) { - for (var i = 0; i < allB.length; i++) { - allB[i].classList.remove('disabled-board'); - } + var item = board1.item[pos1]; + // if (board1==board2 && pos2' + headerBoard.appendChild(btn); + __onButtonClickHandler(btn, board.id); } - if (el !== null) { - self.options.dropEl(el, target, source, sibling); - el.classList.remove('is-moving'); - if (typeof(el.dropfn) === 'function') - el.dropfn(el, target, source, sibling); + //content board + var contentBoard = document.createElement('main'); + contentBoard.classList.add('kanban-drag'); + //add drag to array for dragula + self.boardContainer.push(contentBoard); + for (var itemkey in board.item) { + //create item + var itemKanban = board.item[itemkey]; + var nodeItem = document.createElement('div'); + nodeItem.classList.add('kanban-item'); + nodeItem.dataset.eid = itemKanban.id; + nodeItem.innerHTML = itemKanban.title; + //add function + nodeItem.clickfn = itemKanban.click; + nodeItem.dragfn = itemKanban.drag; + nodeItem.dragendfn = itemKanban.dragend; + nodeItem.dropfn = itemKanban.drop; + //add click handler of item + __onclickHandler(nodeItem); + contentBoard.appendChild(nodeItem); } - - var item = board1.item[pos1]; - // if (board1==board2 && pos2' - headerBoard.appendChild(btn); - __onButtonClickHandler(btn, board.id); - } - //content board - var contentBoard = document.createElement('main'); - contentBoard.classList.add('kanban-drag'); - //add drag to array for dragula - self.boardContainer.push(contentBoard); - for (var itemkey in board.item) { - //create item - var itemKanban = board.item[itemkey]; - var nodeItem = document.createElement('div'); - nodeItem.classList.add('kanban-item'); - nodeItem.dataset.eid = itemKanban.id; - nodeItem.innerHTML = itemKanban.title; - //add function - nodeItem.clickfn = itemKanban.click; - nodeItem.dragfn = itemKanban.drag; - nodeItem.dragendfn = itemKanban.dragend; - nodeItem.dropfn = itemKanban.drop; - //add click handler of item - __onclickHandler(nodeItem); - contentBoard.appendChild(nodeItem); - } - //footer board - var footerBoard = document.createElement('footer'); - //remove button - var removeBoard = document.createElement('div'); - $(removeBoard).text("-") - $(removeBoard).addClass("kanban-removeboard"); - footerBoard.appendChild(removeBoard); - __onRemoveClickHandler(removeBoard); - - //board assembly - boardNode.appendChild(headerBoard); - boardNode.appendChild(contentBoard); - boardNode.appendChild(footerBoard); - //board add - self.container.appendChild(boardNode); + return wrapper; } - // send event that board has changed - self.onChange(); + function unwrap(el, type, fn) { + var i = find(el, type, fn); + if (i) { + var wrapper = hardCache[i].wrapper; + hardCache.splice(i, 1); // free up a tad of memory + return wrapper; + } + } - return self; - } - - this.setBoards = function (boards) { - for (var boardkey in boards) { - // single board - var board = boards[boardkey]; - this.removeBoard(board.id); + function find(el, type, fn) { + var i, item; + for (i = 0; i < hardCache.length; i++) { + item = hardCache[i]; + if (item.element === el && item.type === type && item.fn === fn) { + return i; + } + } } - this.options.boards = []; - this.addBoards(boards); - } - - this.findBoard = function (id) { - var el = self.element.querySelector('[data-id="' + id + '"]'); - return el; - } - this.findElement = function (id) { - var el = self.element.querySelector('[data-eid="' + id + '"]'); - return el; - } - - this.findElementPosition = function (el) { - // we are looking at the element position in the child array - return $(el.parentNode.children).index(el); - } + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +}, { + "./eventmap": 6, + "custom-event": 7 + }], + 6: [function (require, module, exports) { + (function (global) { + 'use strict'; + + var eventmap = []; + var eventname = ''; + var ron = /^on/; + + for (eventname in global) { + if (ron.test(eventname)) { + eventmap.push(eventname.slice(2)); + } + } - this.getBoardElements = function (id) { - var board = self.element.querySelector('[data-id="' + id + '"] .kanban-drag'); - return (board.childNodes); - } + module.exports = eventmap; - this.removeElement = function (el) { - if (typeof(el) === 'string') - el = self.element.querySelector('[data-eid="' + el + '"]'); - el.remove(); - - // send event that board has changed - self.onChange(); + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +}, {}], + 7: [function (require, module, exports) { + (function (global) { - return self; - }; + var NativeCustomEvent = global.CustomEvent; - this.removeBoard = function (board) { - if (typeof(board) === 'string') - board = self.element.querySelector('[data-id="' + board + '"]'); - if (board) { - board.remove(); - - // send event that board has changed - self.onChange(); + function useNative() { + try { + var p = new NativeCustomEvent('cat', { + detail: { + foo: 'bar' + } + }); + return 'cat' === p.type && 'bar' === p.detail.foo; + } catch (e) {} + return false; } - - return self; - } - // board button on click function - this.onButtonClick = function (el) { + /** + * Cross-browser `CustomEvent` constructor. + * + * https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent.CustomEvent + * + * @public + */ + + module.exports = useNative() ? NativeCustomEvent : + + // IE >= 9 + 'function' === typeof document.createEvent ? function CustomEvent(type, params) { + var e = document.createEvent('CustomEvent'); + if (params) { + e.initCustomEvent(type, params.bubbles, params.cancelable, params.detail); + } else { + e.initCustomEvent(type, false, false, void 0); + } + return e; + } : + + // IE <= 8 + function CustomEvent(type, params) { + var e = document.createEventObject(); + e.type = type; + if (params) { + e.bubbles = Boolean(params.bubbles); + e.cancelable = Boolean(params.cancelable); + e.detail = params.detail; + } else { + e.bubbles = false; + e.cancelable = false; + e.detail = void 0; + } + return e; + } - } - - this.onChange = function() { - self.options.onChange(); + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +}, {}], + 8: [function (require, module, exports) { + 'use strict'; + + var cache = {}; + var start = '(?:^|\\s)'; + var end = '(?:\\s|$)'; + + function lookupClass(className) { + var cached = cache[className]; + if (cached) { + cached.lastIndex = 0; + } else { + cache[className] = cached = new RegExp(start + className + end, 'g'); + } + return cached; } - this.getBoardsJSON = function (id) { - return self.options.boards; - } - - this.getBoardJSON = function (id) { - return __findBoardJSON(id); - } - - //PRIVATE FUNCTION - function __extendDefaults(source, properties) { - var property; - for (property in properties) { - if (properties.hasOwnProperty(property)) { - source[property] = properties[property]; - } + function addClass(el, className) { + var current = el.className; + if (!current.length) { + el.className = className; + } else if (!lookupClass(className).test(current)) { + el.className += ' ' + className; } - return source; } - function __setBoard() { - self.element = document.querySelector(self.options.element); - //create container - var boardContainerOuter = document.createElement('div'); - boardContainerOuter.classList.add('kanban-container-outer'); - var boardContainer = document.createElement('div'); - boardContainer.classList.add('kanban-container'); - boardContainerOuter.appendChild(boardContainer); - var addBoard = document.createElement('div'); - addBoard.id = 'kanban-addboard'; - $(addBoard).text("+"); - boardContainerOuter.appendChild(addBoard); - - self.container = boardContainer; - //add boards - self.addBoards(self.options.boards); - //appends to container - self.element.appendChild(boardContainerOuter); - - // send event that board has changed - self.onChange(); + function rmClass(el, className) { + el.className = el.className.replace(lookupClass(className), ' ').trim(); + } + + module.exports = { + add: addClass, + rm: rmClass }; - function __onclickHandler(nodeItem, clickfn) { - nodeItem.addEventListener('click', function (e) { - e.preventDefault; - self.options.click(this); - if (typeof(this.clickfn) === 'function') - this.clickfn(this); - }); - } +}, {}], + 9: [function (require, module, exports) { + (function (global) { + 'use strict'; + + var emitter = require('contra/emitter'); + var crossvent = require('crossvent'); + var classes = require('./classes'); + var doc = document; + var documentElement = doc.documentElement; + + function dragula(initialContainers, options) { + var len = arguments.length; + if (len === 1 && Array.isArray(initialContainers) === false) { + options = initialContainers; + initialContainers = []; + } + var _mirror; // mirror image + var _source; // source container + var _item; // item being dragged + var _offsetX; // reference x + var _offsetY; // reference y + var _moveX; // reference move x + var _moveY; // reference move y + var _initialSibling; // reference sibling when grabbed + var _currentSibling; // reference sibling now + var _copy; // item used for copying + var _renderTimer; // timer for setTimeout renderMirrorImage + var _lastDropTarget = null; // last container item was over + var _grabbed; // holds mousedown context until first mousemove + + var o = options || {}; + if (o.moves === void 0) { + o.moves = always; + } + if (o.accepts === void 0) { + o.accepts = always; + } + if (o.invalid === void 0) { + o.invalid = invalidTarget; + } + if (o.containers === void 0) { + o.containers = initialContainers || []; + } + if (o.isContainer === void 0) { + o.isContainer = never; + } + if (o.copy === void 0) { + o.copy = false; + } + if (o.copySortSource === void 0) { + o.copySortSource = false; + } + if (o.revertOnSpill === void 0) { + o.revertOnSpill = false; + } + if (o.removeOnSpill === void 0) { + o.removeOnSpill = false; + } + if (o.direction === void 0) { + o.direction = 'vertical'; + } + if (o.ignoreInputTextSelection === void 0) { + o.ignoreInputTextSelection = true; + } + if (o.mirrorContainer === void 0) { + o.mirrorContainer = doc.body; + } - function __onboardTitleClickHandler(nodeItem, clickfn) { - nodeItem.addEventListener('click', function (e) { - e.preventDefault; - self.options.boardTitleClick(this); - if (typeof(this.clickfn) === 'function') - this.clickfn(this); - }); - } + var drake = emitter({ + containers: o.containers, + start: manualStart, + end: end, + cancel: cancel, + remove: remove, + destroy: destroy, + canMove: canMove, + dragging: false + }); - function __onColorClickHandler(nodeItem, clickfn) { - nodeItem.addEventListener('click', function (e) { - e.preventDefault; - self.options.colorClick(this); - if (typeof(this.clickfn) === 'function') - this.clickfn(this); - }); - } + if (o.removeOnSpill === true) { + drake.on('over', spillOver).on('out', spillOut); + } - function __onRemoveClickHandler(nodeItem, clickfn) { - nodeItem.addEventListener('click', function (e) { - e.preventDefault; - self.options.removeClick(this); - if (typeof(this.clickfn) === 'function') - this.clickfn(this); - }); - } + events(); - function __onButtonClickHandler(nodeItem, boardId) { - nodeItem.addEventListener('click', function (e) { - e.preventDefault; - self.options.buttonClick(this, boardId); - // if(typeof(this.clickfn) === 'function') - // this.clickfn(this); - }); - } + return drake; - function __findBoardJSON(id) { - var el = [] - self.options.boards.map(function (board) { - if (board.id === id) { - return el.push(board) + function isContainer(el) { + return drake.containers.indexOf(el) !== -1 || o.isContainer(el); } - }) - return el[0] - } + function events(remove) { + var op = remove ? 'remove' : 'add'; + touchy(documentElement, op, 'mousedown', grab); + touchy(documentElement, op, 'mouseup', release); + } - //init plugin - this.init(); - }; -}()); + function eventualMovements(remove) { + var op = remove ? 'remove' : 'add'; + touchy(documentElement, op, 'mousemove', startBecauseMouseMoved); + } + function movements(remove) { + var op = remove ? 'remove' : 'add'; + crossvent[op](documentElement, 'selectstart', preventGrabbed); // IE8 + crossvent[op](documentElement, 'click', preventGrabbed); + } -},{"dragula":9}],2:[function(require,module,exports){ -module.exports = function atoa (a, n) { return Array.prototype.slice.call(a, n); } + function destroy() { + events(true); + release({}); + } -},{}],3:[function(require,module,exports){ -'use strict'; + function preventGrabbed(e) { + if (_grabbed) { + e.preventDefault(); + } + } -var ticky = require('ticky'); + function grab(e) { + _moveX = e.clientX; + _moveY = e.clientY; + + var ignore = whichMouseButton(e) !== 1 || e.metaKey || e.ctrlKey; + if (ignore) { + return; // we only care about honest-to-god left clicks and touch events + } + var item = e.target; + var context = canStart(item); + if (!context) { + return; + } + _grabbed = context; + eventualMovements(); + if (e.type === 'mousedown') { + if (isInput(item)) { // see also: https://github.com/bevacqua/dragula/issues/208 + item.focus(); // fixes https://github.com/bevacqua/dragula/issues/176 + } else { + e.preventDefault(); // fixes https://github.com/bevacqua/dragula/issues/155 + } + } + } -module.exports = function debounce (fn, args, ctx) { - if (!fn) { return; } - ticky(function run () { - fn.apply(ctx || null, args || []); - }); -}; + function startBecauseMouseMoved(e) { + if (!_grabbed) { + return; + } + if (whichMouseButton(e) === 0) { + release({}); + return; // when text is selected on an input and then dragged, mouseup doesn't fire. this is our only hope + } + // truthy check fixes #239, equality fixes #207 + if (e.clientX !== void 0 && e.clientX === _moveX && e.clientY !== void 0 && e.clientY === _moveY) { + return; + } + if (o.ignoreInputTextSelection) { + var clientX = getCoord('clientX', e); + var clientY = getCoord('clientY', e); + var elementBehindCursor = doc.elementFromPoint(clientX, clientY); + if (isInput(elementBehindCursor)) { + return; + } + } -},{"ticky":10}],4:[function(require,module,exports){ -'use strict'; + var grabbed = _grabbed; // call to end() unsets _grabbed + eventualMovements(true); + movements(); + end(); + start(grabbed); -var atoa = require('atoa'); -var debounce = require('./debounce'); + var offset = getOffset(_item); + _offsetX = getCoord('pageX', e) - offset.left; + _offsetY = getCoord('pageY', e) - offset.top; -module.exports = function emitter (thing, options) { - var opts = options || {}; - var evt = {}; - if (thing === undefined) { thing = {}; } - thing.on = function (type, fn) { - if (!evt[type]) { - evt[type] = [fn]; - } else { - evt[type].push(fn); - } - return thing; - }; - thing.once = function (type, fn) { - fn._once = true; // thing.off(fn) still works! - thing.on(type, fn); - return thing; - }; - thing.off = function (type, fn) { - var c = arguments.length; - if (c === 1) { - delete evt[type]; - } else if (c === 0) { - evt = {}; - } else { - var et = evt[type]; - if (!et) { return thing; } - et.splice(et.indexOf(fn), 1); - } - return thing; - }; - thing.emit = function () { - var args = atoa(arguments); - return thing.emitterSnapshot(args.shift()).apply(this, args); - }; - thing.emitterSnapshot = function (type) { - var et = (evt[type] || []).slice(0); - return function () { - var args = atoa(arguments); - var ctx = this || thing; - if (type === 'error' && opts.throws !== false && !et.length) { throw args.length === 1 ? args[0] : args; } - et.forEach(function emitter (listen) { - if (opts.async) { debounce(listen, args, ctx); } else { listen.apply(ctx, args); } - if (listen._once) { thing.off(type, listen); } - }); - return thing; - }; - }; - return thing; -}; - -},{"./debounce":3,"atoa":2}],5:[function(require,module,exports){ -(function (global){ -'use strict'; - -var customEvent = require('custom-event'); -var eventmap = require('./eventmap'); -var doc = global.document; -var addEvent = addEventEasy; -var removeEvent = removeEventEasy; -var hardCache = []; - -if (!global.addEventListener) { - addEvent = addEventHard; - removeEvent = removeEventHard; -} - -module.exports = { - add: addEvent, - remove: removeEvent, - fabricate: fabricateEvent -}; - -function addEventEasy (el, type, fn, capturing) { - return el.addEventListener(type, fn, capturing); -} - -function addEventHard (el, type, fn) { - return el.attachEvent('on' + type, wrap(el, type, fn)); -} - -function removeEventEasy (el, type, fn, capturing) { - return el.removeEventListener(type, fn, capturing); -} - -function removeEventHard (el, type, fn) { - var listener = unwrap(el, type, fn); - if (listener) { - return el.detachEvent('on' + type, listener); - } -} - -function fabricateEvent (el, type, model) { - var e = eventmap.indexOf(type) === -1 ? makeCustomEvent() : makeClassicEvent(); - if (el.dispatchEvent) { - el.dispatchEvent(e); - } else { - el.fireEvent('on' + type, e); - } - function makeClassicEvent () { - var e; - if (doc.createEvent) { - e = doc.createEvent('Event'); - e.initEvent(type, true, true); - } else if (doc.createEventObject) { - e = doc.createEventObject(); - } - return e; - } - function makeCustomEvent () { - return new customEvent(type, { detail: model }); - } -} - -function wrapperFactory (el, type, fn) { - return function wrapper (originalEvent) { - var e = originalEvent || global.event; - e.target = e.target || e.srcElement; - e.preventDefault = e.preventDefault || function preventDefault () { e.returnValue = false; }; - e.stopPropagation = e.stopPropagation || function stopPropagation () { e.cancelBubble = true; }; - e.which = e.which || e.keyCode; - fn.call(el, e); - }; -} - -function wrap (el, type, fn) { - var wrapper = unwrap(el, type, fn) || wrapperFactory(el, type, fn); - hardCache.push({ - wrapper: wrapper, - element: el, - type: type, - fn: fn - }); - return wrapper; -} - -function unwrap (el, type, fn) { - var i = find(el, type, fn); - if (i) { - var wrapper = hardCache[i].wrapper; - hardCache.splice(i, 1); // free up a tad of memory - return wrapper; - } -} - -function find (el, type, fn) { - var i, item; - for (i = 0; i < hardCache.length; i++) { - item = hardCache[i]; - if (item.element === el && item.type === type && item.fn === fn) { - return i; - } - } -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./eventmap":6,"custom-event":7}],6:[function(require,module,exports){ -(function (global){ -'use strict'; - -var eventmap = []; -var eventname = ''; -var ron = /^on/; - -for (eventname in global) { - if (ron.test(eventname)) { - eventmap.push(eventname.slice(2)); - } -} - -module.exports = eventmap; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],7:[function(require,module,exports){ -(function (global){ - -var NativeCustomEvent = global.CustomEvent; - -function useNative () { - try { - var p = new NativeCustomEvent('cat', { detail: { foo: 'bar' } }); - return 'cat' === p.type && 'bar' === p.detail.foo; - } catch (e) { - } - return false; -} - -/** - * Cross-browser `CustomEvent` constructor. - * - * https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent.CustomEvent - * - * @public - */ - -module.exports = useNative() ? NativeCustomEvent : - -// IE >= 9 -'function' === typeof document.createEvent ? function CustomEvent (type, params) { - var e = document.createEvent('CustomEvent'); - if (params) { - e.initCustomEvent(type, params.bubbles, params.cancelable, params.detail); - } else { - e.initCustomEvent(type, false, false, void 0); - } - return e; -} : - -// IE <= 8 -function CustomEvent (type, params) { - var e = document.createEventObject(); - e.type = type; - if (params) { - e.bubbles = Boolean(params.bubbles); - e.cancelable = Boolean(params.cancelable); - e.detail = params.detail; - } else { - e.bubbles = false; - e.cancelable = false; - e.detail = void 0; - } - return e; -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],8:[function(require,module,exports){ -'use strict'; - -var cache = {}; -var start = '(?:^|\\s)'; -var end = '(?:\\s|$)'; - -function lookupClass (className) { - var cached = cache[className]; - if (cached) { - cached.lastIndex = 0; - } else { - cache[className] = cached = new RegExp(start + className + end, 'g'); - } - return cached; -} - -function addClass (el, className) { - var current = el.className; - if (!current.length) { - el.className = className; - } else if (!lookupClass(className).test(current)) { - el.className += ' ' + className; - } -} - -function rmClass (el, className) { - el.className = el.className.replace(lookupClass(className), ' ').trim(); -} - -module.exports = { - add: addClass, - rm: rmClass -}; - -},{}],9:[function(require,module,exports){ -(function (global){ -'use strict'; - -var emitter = require('contra/emitter'); -var crossvent = require('crossvent'); -var classes = require('./classes'); -var doc = document; -var documentElement = doc.documentElement; - -function dragula (initialContainers, options) { - var len = arguments.length; - if (len === 1 && Array.isArray(initialContainers) === false) { - options = initialContainers; - initialContainers = []; - } - var _mirror; // mirror image - var _source; // source container - var _item; // item being dragged - var _offsetX; // reference x - var _offsetY; // reference y - var _moveX; // reference move x - var _moveY; // reference move y - var _initialSibling; // reference sibling when grabbed - var _currentSibling; // reference sibling now - var _copy; // item used for copying - var _renderTimer; // timer for setTimeout renderMirrorImage - var _lastDropTarget = null; // last container item was over - var _grabbed; // holds mousedown context until first mousemove - - var o = options || {}; - if (o.moves === void 0) { o.moves = always; } - if (o.accepts === void 0) { o.accepts = always; } - if (o.invalid === void 0) { o.invalid = invalidTarget; } - if (o.containers === void 0) { o.containers = initialContainers || []; } - if (o.isContainer === void 0) { o.isContainer = never; } - if (o.copy === void 0) { o.copy = false; } - if (o.copySortSource === void 0) { o.copySortSource = false; } - if (o.revertOnSpill === void 0) { o.revertOnSpill = false; } - if (o.removeOnSpill === void 0) { o.removeOnSpill = false; } - if (o.direction === void 0) { o.direction = 'vertical'; } - if (o.ignoreInputTextSelection === void 0) { o.ignoreInputTextSelection = true; } - if (o.mirrorContainer === void 0) { o.mirrorContainer = doc.body; } - - var drake = emitter({ - containers: o.containers, - start: manualStart, - end: end, - cancel: cancel, - remove: remove, - destroy: destroy, - canMove: canMove, - dragging: false - }); - - if (o.removeOnSpill === true) { - drake.on('over', spillOver).on('out', spillOut); - } - - events(); - - return drake; - - function isContainer (el) { - return drake.containers.indexOf(el) !== -1 || o.isContainer(el); - } - - function events (remove) { - var op = remove ? 'remove' : 'add'; - touchy(documentElement, op, 'mousedown', grab); - touchy(documentElement, op, 'mouseup', release); - } - - function eventualMovements (remove) { - var op = remove ? 'remove' : 'add'; - touchy(documentElement, op, 'mousemove', startBecauseMouseMoved); - } - - function movements (remove) { - var op = remove ? 'remove' : 'add'; - crossvent[op](documentElement, 'selectstart', preventGrabbed); // IE8 - crossvent[op](documentElement, 'click', preventGrabbed); - } - - function destroy () { - events(true); - release({}); - } - - function preventGrabbed (e) { - if (_grabbed) { - e.preventDefault(); - } - } + classes.add(_copy || _item, 'gu-transit'); + renderMirrorImage(); + drag(e); + } - function grab (e) { - _moveX = e.clientX; - _moveY = e.clientY; + function canStart(item) { + if (drake.dragging && _mirror) { + return; + } + if (isContainer(item)) { + return; // don't drag container itself + } + var handle = item; + while (getParent(item) && isContainer(getParent(item)) === false) { + if (o.invalid(item, handle)) { + return; + } + item = getParent(item); // drag target should be a top element + if (!item) { + return; + } + } + var source = getParent(item); + if (!source) { + return; + } + if (o.invalid(item, handle)) { + return; + } + + var movable = o.moves(item, source, handle, nextEl(item)); + if (!movable) { + return; + } + + return { + item: item, + source: source + }; + } - var ignore = whichMouseButton(e) !== 1 || e.metaKey || e.ctrlKey; - if (ignore) { - return; // we only care about honest-to-god left clicks and touch events - } - var item = e.target; - var context = canStart(item); - if (!context) { - return; - } - _grabbed = context; - eventualMovements(); - if (e.type === 'mousedown') { - if (isInput(item)) { // see also: https://github.com/bevacqua/dragula/issues/208 - item.focus(); // fixes https://github.com/bevacqua/dragula/issues/176 - } else { - e.preventDefault(); // fixes https://github.com/bevacqua/dragula/issues/155 - } - } - } + function canMove(item) { + return !!canStart(item); + } - function startBecauseMouseMoved (e) { - if (!_grabbed) { - return; - } - if (whichMouseButton(e) === 0) { - release({}); - return; // when text is selected on an input and then dragged, mouseup doesn't fire. this is our only hope - } - // truthy check fixes #239, equality fixes #207 - if (e.clientX !== void 0 && e.clientX === _moveX && e.clientY !== void 0 && e.clientY === _moveY) { - return; - } - if (o.ignoreInputTextSelection) { - var clientX = getCoord('clientX', e); - var clientY = getCoord('clientY', e); - var elementBehindCursor = doc.elementFromPoint(clientX, clientY); - if (isInput(elementBehindCursor)) { - return; - } - } + function manualStart(item) { + var context = canStart(item); + if (context) { + start(context); + } + } - var grabbed = _grabbed; // call to end() unsets _grabbed - eventualMovements(true); - movements(); - end(); - start(grabbed); + function start(context) { + if (isCopy(context.item, context.source)) { + _copy = context.item.cloneNode(true); + drake.emit('cloned', _copy, context.item, 'copy'); + } - var offset = getOffset(_item); - _offsetX = getCoord('pageX', e) - offset.left; - _offsetY = getCoord('pageY', e) - offset.top; + _source = context.source; + _item = context.item; + _initialSibling = _currentSibling = nextEl(context.item); - classes.add(_copy || _item, 'gu-transit'); - renderMirrorImage(); - drag(e); - } + drake.dragging = true; + drake.emit('drag', _item, _source); + } - function canStart (item) { - if (drake.dragging && _mirror) { - return; - } - if (isContainer(item)) { - return; // don't drag container itself - } - var handle = item; - while (getParent(item) && isContainer(getParent(item)) === false) { - if (o.invalid(item, handle)) { - return; - } - item = getParent(item); // drag target should be a top element - if (!item) { - return; - } - } - var source = getParent(item); - if (!source) { - return; - } - if (o.invalid(item, handle)) { - return; - } + function invalidTarget() { + return false; + } - var movable = o.moves(item, source, handle, nextEl(item)); - if (!movable) { - return; - } + function end() { + if (!drake.dragging) { + return; + } + var item = _copy || _item; + drop(item, getParent(item)); + } - return { - item: item, - source: source - }; - } + function ungrab() { + _grabbed = false; + eventualMovements(true); + movements(true); + } - function canMove (item) { - return !!canStart(item); - } + function release(e) { + ungrab(); + + if (!drake.dragging) { + return; + } + var item = _copy || _item; + var clientX = getCoord('clientX', e); + var clientY = getCoord('clientY', e); + var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY); + var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY); + if (dropTarget && ((_copy && o.copySortSource) || (!_copy || dropTarget !== _source))) { + drop(item, dropTarget); + } else if (o.removeOnSpill) { + remove(); + } else { + cancel(); + } + } - function manualStart (item) { - var context = canStart(item); - if (context) { - start(context); - } - } + function drop(item, target) { + var parent = getParent(item); + if (_copy && o.copySortSource && target === _source) { + parent.removeChild(_item); + } + if (isInitialPlacement(target)) { + drake.emit('cancel', item, _source, _source); + } else { + drake.emit('drop', item, target, _source, _currentSibling); + } + cleanup(); + } - function start (context) { - if (isCopy(context.item, context.source)) { - _copy = context.item.cloneNode(true); - drake.emit('cloned', _copy, context.item, 'copy'); - } + function remove() { + if (!drake.dragging) { + return; + } + var item = _copy || _item; + var parent = getParent(item); + if (parent) { + parent.removeChild(item); + } + drake.emit(_copy ? 'cancel' : 'remove', item, parent, _source); + cleanup(); + } - _source = context.source; - _item = context.item; - _initialSibling = _currentSibling = nextEl(context.item); + function cancel(revert) { + if (!drake.dragging) { + return; + } + var reverts = arguments.length > 0 ? revert : o.revertOnSpill; + var item = _copy || _item; + var parent = getParent(item); + var initial = isInitialPlacement(parent); + if (initial === false && reverts) { + if (_copy) { + if (parent) { + parent.removeChild(_copy); + } + } else { + _source.insertBefore(item, _initialSibling); + } + } + if (initial || reverts) { + drake.emit('cancel', item, _source, _source); + } else { + drake.emit('drop', item, parent, _source, _currentSibling); + } + cleanup(); + } - drake.dragging = true; - drake.emit('drag', _item, _source); - } + function cleanup() { + var item = _copy || _item; + ungrab(); + removeMirrorImage(); + if (item) { + classes.rm(item, 'gu-transit'); + } + if (_renderTimer) { + clearTimeout(_renderTimer); + } + drake.dragging = false; + if (_lastDropTarget) { + drake.emit('out', item, _lastDropTarget, _source); + } + drake.emit('dragend', item); + _source = _item = _copy = _initialSibling = _currentSibling = _renderTimer = _lastDropTarget = null; + } - function invalidTarget () { - return false; - } + function isInitialPlacement(target, s) { + var sibling; + if (s !== void 0) { + sibling = s; + } else if (_mirror) { + sibling = _currentSibling; + } else { + sibling = nextEl(_copy || _item); + } + return target === _source && sibling === _initialSibling; + } - function end () { - if (!drake.dragging) { - return; - } - var item = _copy || _item; - drop(item, getParent(item)); - } + function findDropTarget(elementBehindCursor, clientX, clientY) { + var target = elementBehindCursor; + while (target && !accepted()) { + target = getParent(target); + } + return target; + + function accepted() { + var droppable = isContainer(target); + if (droppable === false) { + return false; + } - function ungrab () { - _grabbed = false; - eventualMovements(true); - movements(true); - } + var immediate = getImmediateChild(target, elementBehindCursor); + var reference = getReference(target, immediate, clientX, clientY); + var initial = isInitialPlacement(target, reference); + if (initial) { + return true; // should always be able to drop it right back where it was + } + return o.accepts(_item, target, _source, reference); + } + } - function release (e) { - ungrab(); + function drag(e) { + if (!_mirror) { + return; + } + e.preventDefault(); + + var clientX = getCoord('clientX', e); + var clientY = getCoord('clientY', e); + var x = clientX - _offsetX; + var y = clientY - _offsetY; + + _mirror.style.left = x + 'px'; + _mirror.style.top = y + 'px'; + + var item = _copy || _item; + var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY); + var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY); + var changed = dropTarget !== null && dropTarget !== _lastDropTarget; + if (changed || dropTarget === null) { + out(); + _lastDropTarget = dropTarget; + over(); + } + var parent = getParent(item); + if (dropTarget === _source && _copy && !o.copySortSource) { + if (parent) { + parent.removeChild(item); + } + return; + } + var reference; + var immediate = getImmediateChild(dropTarget, elementBehindCursor); + if (immediate !== null) { + reference = getReference(dropTarget, immediate, clientX, clientY); + } else if (o.revertOnSpill === true && !_copy) { + reference = _initialSibling; + dropTarget = _source; + } else { + if (_copy && parent) { + parent.removeChild(item); + } + return; + } + if ( + (reference === null && changed) || + reference !== item && + reference !== nextEl(item) + ) { + _currentSibling = reference; + dropTarget.insertBefore(item, reference); + drake.emit('shadow', item, dropTarget, _source); + } + + function moved(type) { + drake.emit(type, item, _lastDropTarget, _source); + } + + function over() { + if (changed) { + moved('over'); + } + } - if (!drake.dragging) { - return; - } - var item = _copy || _item; - var clientX = getCoord('clientX', e); - var clientY = getCoord('clientY', e); - var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY); - var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY); - if (dropTarget && ((_copy && o.copySortSource) || (!_copy || dropTarget !== _source))) { - drop(item, dropTarget); - } else if (o.removeOnSpill) { - remove(); - } else { - cancel(); - } - } + function out() { + if (_lastDropTarget) { + moved('out'); + } + } + } - function drop (item, target) { - var parent = getParent(item); - if (_copy && o.copySortSource && target === _source) { - parent.removeChild(_item); - } - if (isInitialPlacement(target)) { - drake.emit('cancel', item, _source, _source); - } else { - drake.emit('drop', item, target, _source, _currentSibling); - } - cleanup(); - } + function spillOver(el) { + classes.rm(el, 'gu-hide'); + } - function remove () { - if (!drake.dragging) { - return; - } - var item = _copy || _item; - var parent = getParent(item); - if (parent) { - parent.removeChild(item); - } - drake.emit(_copy ? 'cancel' : 'remove', item, parent, _source); - cleanup(); - } + function spillOut(el) { + if (drake.dragging) { + classes.add(el, 'gu-hide'); + } + } - function cancel (revert) { - if (!drake.dragging) { - return; - } - var reverts = arguments.length > 0 ? revert : o.revertOnSpill; - var item = _copy || _item; - var parent = getParent(item); - var initial = isInitialPlacement(parent); - if (initial === false && reverts) { - if (_copy) { - if (parent) { - parent.removeChild(_copy); - } - } else { - _source.insertBefore(item, _initialSibling); - } - } - if (initial || reverts) { - drake.emit('cancel', item, _source, _source); - } else { - drake.emit('drop', item, parent, _source, _currentSibling); - } - cleanup(); - } - - function cleanup () { - var item = _copy || _item; - ungrab(); - removeMirrorImage(); - if (item) { - classes.rm(item, 'gu-transit'); - } - if (_renderTimer) { - clearTimeout(_renderTimer); - } - drake.dragging = false; - if (_lastDropTarget) { - drake.emit('out', item, _lastDropTarget, _source); - } - drake.emit('dragend', item); - _source = _item = _copy = _initialSibling = _currentSibling = _renderTimer = _lastDropTarget = null; - } - - function isInitialPlacement (target, s) { - var sibling; - if (s !== void 0) { - sibling = s; - } else if (_mirror) { - sibling = _currentSibling; - } else { - sibling = nextEl(_copy || _item); - } - return target === _source && sibling === _initialSibling; - } + function renderMirrorImage() { + if (_mirror) { + return; + } + var rect = _item.getBoundingClientRect(); + _mirror = _item.cloneNode(true); + _mirror.style.width = getRectWidth(rect) + 'px'; + _mirror.style.height = getRectHeight(rect) + 'px'; + classes.rm(_mirror, 'gu-transit'); + classes.add(_mirror, 'gu-mirror'); + o.mirrorContainer.appendChild(_mirror); + touchy(documentElement, 'add', 'mousemove', drag); + classes.add(o.mirrorContainer, 'gu-unselectable'); + drake.emit('cloned', _mirror, _item, 'mirror'); + } - function findDropTarget (elementBehindCursor, clientX, clientY) { - var target = elementBehindCursor; - while (target && !accepted()) { - target = getParent(target); - } - return target; - - function accepted () { - var droppable = isContainer(target); - if (droppable === false) { - return false; - } - - var immediate = getImmediateChild(target, elementBehindCursor); - var reference = getReference(target, immediate, clientX, clientY); - var initial = isInitialPlacement(target, reference); - if (initial) { - return true; // should always be able to drop it right back where it was - } - return o.accepts(_item, target, _source, reference); - } - } + function removeMirrorImage() { + if (_mirror) { + classes.rm(o.mirrorContainer, 'gu-unselectable'); + touchy(documentElement, 'remove', 'mousemove', drag); + getParent(_mirror).removeChild(_mirror); + _mirror = null; + } + } - function drag (e) { - if (!_mirror) { - return; - } - e.preventDefault(); - - var clientX = getCoord('clientX', e); - var clientY = getCoord('clientY', e); - var x = clientX - _offsetX; - var y = clientY - _offsetY; - - _mirror.style.left = x + 'px'; - _mirror.style.top = y + 'px'; - - var item = _copy || _item; - var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY); - var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY); - var changed = dropTarget !== null && dropTarget !== _lastDropTarget; - if (changed || dropTarget === null) { - out(); - _lastDropTarget = dropTarget; - over(); - } - var parent = getParent(item); - if (dropTarget === _source && _copy && !o.copySortSource) { - if (parent) { - parent.removeChild(item); - } - return; - } - var reference; - var immediate = getImmediateChild(dropTarget, elementBehindCursor); - if (immediate !== null) { - reference = getReference(dropTarget, immediate, clientX, clientY); - } else if (o.revertOnSpill === true && !_copy) { - reference = _initialSibling; - dropTarget = _source; - } else { - if (_copy && parent) { - parent.removeChild(item); - } - return; - } - if ( - (reference === null && changed) || - reference !== item && - reference !== nextEl(item) - ) { - _currentSibling = reference; - dropTarget.insertBefore(item, reference); - drake.emit('shadow', item, dropTarget, _source); - } - function moved (type) { drake.emit(type, item, _lastDropTarget, _source); } - function over () { if (changed) { moved('over'); } } - function out () { if (_lastDropTarget) { moved('out'); } } - } - - function spillOver (el) { - classes.rm(el, 'gu-hide'); - } - - function spillOut (el) { - if (drake.dragging) { classes.add(el, 'gu-hide'); } - } - - function renderMirrorImage () { - if (_mirror) { - return; - } - var rect = _item.getBoundingClientRect(); - _mirror = _item.cloneNode(true); - _mirror.style.width = getRectWidth(rect) + 'px'; - _mirror.style.height = getRectHeight(rect) + 'px'; - classes.rm(_mirror, 'gu-transit'); - classes.add(_mirror, 'gu-mirror'); - o.mirrorContainer.appendChild(_mirror); - touchy(documentElement, 'add', 'mousemove', drag); - classes.add(o.mirrorContainer, 'gu-unselectable'); - drake.emit('cloned', _mirror, _item, 'mirror'); - } - - function removeMirrorImage () { - if (_mirror) { - classes.rm(o.mirrorContainer, 'gu-unselectable'); - touchy(documentElement, 'remove', 'mousemove', drag); - getParent(_mirror).removeChild(_mirror); - _mirror = null; - } - } + function getImmediateChild(dropTarget, target) { + var immediate = target; + while (immediate !== dropTarget && getParent(immediate) !== dropTarget) { + immediate = getParent(immediate); + } + if (immediate === documentElement) { + return null; + } + return immediate; + } - function getImmediateChild (dropTarget, target) { - var immediate = target; - while (immediate !== dropTarget && getParent(immediate) !== dropTarget) { - immediate = getParent(immediate); - } - if (immediate === documentElement) { - return null; - } - return immediate; - } - - function getReference (dropTarget, target, x, y) { - var horizontal = o.direction === 'horizontal'; - var reference = target !== dropTarget ? inside() : outside(); - return reference; - - function outside () { // slower, but able to figure out any position - var len = dropTarget.children.length; - var i; - var el; - var rect; - for (i = 0; i < len; i++) { - el = dropTarget.children[i]; - rect = el.getBoundingClientRect(); - if (horizontal && (rect.left + rect.width / 2) > x) { return el; } - if (!horizontal && (rect.top + rect.height / 2) > y) { return el; } - } - return null; - } + function getReference(dropTarget, target, x, y) { + var horizontal = o.direction === 'horizontal'; + var reference = target !== dropTarget ? inside() : outside(); + return reference; + + function outside() { // slower, but able to figure out any position + var len = dropTarget.children.length; + var i; + var el; + var rect; + for (i = 0; i < len; i++) { + el = dropTarget.children[i]; + rect = el.getBoundingClientRect(); + if (horizontal && (rect.left + rect.width / 2) > x) { + return el; + } + if (!horizontal && (rect.top + rect.height / 2) > y) { + return el; + } + } + return null; + } - function inside () { // faster, but only available if dropped inside a child element - var rect = target.getBoundingClientRect(); - if (horizontal) { - return resolve(x > rect.left + getRectWidth(rect) / 2); - } - return resolve(y > rect.top + getRectHeight(rect) / 2); - } + function inside() { // faster, but only available if dropped inside a child element + var rect = target.getBoundingClientRect(); + if (horizontal) { + return resolve(x > rect.left + getRectWidth(rect) / 2); + } + return resolve(y > rect.top + getRectHeight(rect) / 2); + } - function resolve (after) { - return after ? nextEl(target) : target; - } - } - - function isCopy (item, container) { - return typeof o.copy === 'boolean' ? o.copy : o.copy(item, container); - } -} - -function touchy (el, op, type, fn) { - var touch = { - mouseup: 'touchend', - mousedown: 'touchstart', - mousemove: 'touchmove' - }; - var pointers = { - mouseup: 'pointerup', - mousedown: 'pointerdown', - mousemove: 'pointermove' - }; - var microsoft = { - mouseup: 'MSPointerUp', - mousedown: 'MSPointerDown', - mousemove: 'MSPointerMove' - }; - if (global.navigator.pointerEnabled) { - crossvent[op](el, pointers[type], fn); - } else if (global.navigator.msPointerEnabled) { - crossvent[op](el, microsoft[type], fn); - } else { - crossvent[op](el, touch[type], fn); - crossvent[op](el, type, fn); - } -} - -function whichMouseButton (e) { - if (e.touches !== void 0) { return e.touches.length; } - if (e.which !== void 0 && e.which !== 0) { return e.which; } // see https://github.com/bevacqua/dragula/issues/261 - if (e.buttons !== void 0) { return e.buttons; } - var button = e.button; - if (button !== void 0) { // see https://github.com/jquery/jquery/blob/99e8ff1baa7ae341e94bb89c3e84570c7c3ad9ea/src/event.js#L573-L575 - return button & 1 ? 1 : button & 2 ? 3 : (button & 4 ? 2 : 0); - } -} - -function getOffset (el) { - var rect = el.getBoundingClientRect(); - return { - left: rect.left + getScroll('scrollLeft', 'pageXOffset'), - top: rect.top + getScroll('scrollTop', 'pageYOffset') - }; -} - -function getScroll (scrollProp, offsetProp) { - if (typeof global[offsetProp] !== 'undefined') { - return global[offsetProp]; - } - if (documentElement.clientHeight) { - return documentElement[scrollProp]; - } - return doc.body[scrollProp]; -} - -function getElementBehindPoint (point, x, y) { - var p = point || {}; - var state = p.className; - var el; - p.className += ' gu-hide'; - el = doc.elementFromPoint(x, y); - p.className = state; - return el; -} - -function never () { return false; } -function always () { return true; } -function getRectWidth (rect) { return rect.width || (rect.right - rect.left); } -function getRectHeight (rect) { return rect.height || (rect.bottom - rect.top); } -function getParent (el) { return el.parentNode === doc ? null : el.parentNode; } -function isInput (el) { return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.tagName === 'SELECT' || isEditable(el); } -function isEditable (el) { - if (!el) { return false; } // no parents were editable - if (el.contentEditable === 'false') { return false; } // stop the lookup - if (el.contentEditable === 'true') { return true; } // found a contentEditable element in the chain - return isEditable(getParent(el)); // contentEditable is set to 'inherit' -} - -function nextEl (el) { - return el.nextElementSibling || manually(); - function manually () { - var sibling = el; - do { - sibling = sibling.nextSibling; - } while (sibling && sibling.nodeType !== 1); - return sibling; - } -} - -function getEventHost (e) { - // on touchend event, we have to use `e.changedTouches` - // see http://stackoverflow.com/questions/7192563/touchend-event-properties - // see https://github.com/bevacqua/dragula/issues/34 - if (e.targetTouches && e.targetTouches.length) { - return e.targetTouches[0]; - } - if (e.changedTouches && e.changedTouches.length) { - return e.changedTouches[0]; - } - return e; -} - -function getCoord (coord, e) { - var host = getEventHost(e); - var missMap = { - pageX: 'clientX', // IE8 - pageY: 'clientY' // IE8 - }; - if (coord in missMap && !(coord in host) && missMap[coord] in host) { - coord = missMap[coord]; - } - return host[coord]; -} - -module.exports = dragula; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./classes":8,"contra/emitter":4,"crossvent":5}],10:[function(require,module,exports){ -var si = typeof setImmediate === 'function', tick; -if (si) { - tick = function (fn) { setImmediate(fn); }; -} else { - tick = function (fn) { setTimeout(fn, 0); }; -} - -module.exports = tick; -},{}]},{},[1]); + function resolve(after) { + return after ? nextEl(target) : target; + } + } + + function isCopy(item, container) { + return typeof o.copy === 'boolean' ? o.copy : o.copy(item, container); + } + } + + function touchy(el, op, type, fn) { + var touch = { + mouseup: 'touchend', + mousedown: 'touchstart', + mousemove: 'touchmove' + }; + var pointers = { + mouseup: 'pointerup', + mousedown: 'pointerdown', + mousemove: 'pointermove' + }; + var microsoft = { + mouseup: 'MSPointerUp', + mousedown: 'MSPointerDown', + mousemove: 'MSPointerMove' + }; + if (global.navigator.pointerEnabled) { + crossvent[op](el, pointers[type], fn); + } else if (global.navigator.msPointerEnabled) { + crossvent[op](el, microsoft[type], fn); + } else { + crossvent[op](el, touch[type], fn); + crossvent[op](el, type, fn); + } + } + + function whichMouseButton(e) { + if (e.touches !== void 0) { + return e.touches.length; + } + if (e.which !== void 0 && e.which !== 0) { + return e.which; + } // see https://github.com/bevacqua/dragula/issues/261 + if (e.buttons !== void 0) { + return e.buttons; + } + var button = e.button; + if (button !== void 0) { // see https://github.com/jquery/jquery/blob/99e8ff1baa7ae341e94bb89c3e84570c7c3ad9ea/src/event.js#L573-L575 + return button & 1 ? 1 : button & 2 ? 3 : (button & 4 ? 2 : 0); + } + } + + function getOffset(el) { + var rect = el.getBoundingClientRect(); + return { + left: rect.left + getScroll('scrollLeft', 'pageXOffset'), + top: rect.top + getScroll('scrollTop', 'pageYOffset') + }; + } + + function getScroll(scrollProp, offsetProp) { + if (typeof global[offsetProp] !== 'undefined') { + return global[offsetProp]; + } + if (documentElement.clientHeight) { + return documentElement[scrollProp]; + } + return doc.body[scrollProp]; + } + + function getElementBehindPoint(point, x, y) { + var p = point || {}; + var state = p.className; + var el; + p.className += ' gu-hide'; + el = doc.elementFromPoint(x, y); + p.className = state; + return el; + } + + function never() { + return false; + } + + function always() { + return true; + } + + function getRectWidth(rect) { + return rect.width || (rect.right - rect.left); + } + + function getRectHeight(rect) { + return rect.height || (rect.bottom - rect.top); + } + + function getParent(el) { + return el.parentNode === doc ? null : el.parentNode; + } + + function isInput(el) { + return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.tagName === 'SELECT' || isEditable(el); + } + + function isEditable(el) { + if (!el) { + return false; + } // no parents were editable + if (el.contentEditable === 'false') { + return false; + } // stop the lookup + if (el.contentEditable === 'true') { + return true; + } // found a contentEditable element in the chain + return isEditable(getParent(el)); // contentEditable is set to 'inherit' + } + + function nextEl(el) { + return el.nextElementSibling || manually(); + + function manually() { + var sibling = el; + do { + sibling = sibling.nextSibling; + } while (sibling && sibling.nodeType !== 1); + return sibling; + } + } + + function getEventHost(e) { + // on touchend event, we have to use `e.changedTouches` + // see http://stackoverflow.com/questions/7192563/touchend-event-properties + // see https://github.com/bevacqua/dragula/issues/34 + if (e.targetTouches && e.targetTouches.length) { + return e.targetTouches[0]; + } + if (e.changedTouches && e.changedTouches.length) { + return e.changedTouches[0]; + } + return e; + } + + function getCoord(coord, e) { + var host = getEventHost(e); + var missMap = { + pageX: 'clientX', // IE8 + pageY: 'clientY' // IE8 + }; + if (coord in missMap && !(coord in host) && missMap[coord] in host) { + coord = missMap[coord]; + } + return host[coord]; + } + + module.exports = dragula; + + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +}, { + "./classes": 8, + "contra/emitter": 4, + "crossvent": 5 + }], + 10: [function (require, module, exports) { + var si = typeof setImmediate === 'function', + tick; + if (si) { + tick = function (fn) { + setImmediate(fn); + }; + } else { + tick = function (fn) { + setTimeout(fn, 0); + }; + } + + module.exports = tick; +}, {}] +}, {}, [1]); \ No newline at end of file diff --git a/www/kanban/kanban.css b/www/kanban/kanban.css deleted file mode 100644 index ae001b198..000000000 --- a/www/kanban/kanban.css +++ /dev/null @@ -1,25 +0,0 @@ - html, body { - margin: 0px; - padding: 0px; - } - #sbox-iframe { - position:fixed; - top:0px; - left:0px; - bottom:0px; - right:0px; - width:100%; - height:100%; - border:none; - margin:0; - padding:0; - overflow:hidden; - } - #sbox-filePicker-iframe { - position: fixed; - top:0; left:0; - bottom:0; right:0; - width:100%; - height: 100%; - border: 0; - } diff --git a/www/kanban/main.js b/www/kanban/main.js deleted file mode 100644 index 7f2197b24..000000000 --- a/www/kanban/main.js +++ /dev/null @@ -1,43 +0,0 @@ -// Load #1, load as little as possible because we are in a race to get the loading screen up. -define([ - '/bower_components/nthen/index.js', - '/api/config', - '/common/dom-ready.js', - '/common/requireconfig.js', - '/common/sframe-common-outer.js', -], function (nThen, ApiConfig, DomReady, RequireConfig, SFCommonO) { - var requireConfig = RequireConfig(); - - // Loaded in load #2 - nThen(function (waitFor) { - DomReady.onReady(waitFor()); - }).nThen(function (waitFor) { - var req = { - cfg: requireConfig, - req: [ '/common/loading.js' ], - pfx: window.location.origin - }; - window.rc = requireConfig; - window.apiconf = ApiConfig; - document.getElementById('sbox-iframe').setAttribute('src', - ApiConfig.httpSafeOrigin + '/kanban/inner.html?' + requireConfig.urlArgs + - '#' + encodeURIComponent(JSON.stringify(req))); - - // This is a cheap trick to avoid loading sframe-channel in parallel with the - // loading screen setup. - var done = waitFor(); - var onMsg = function (msg) { - var data = JSON.parse(msg.data); - if (data.q !== 'READY') { return; } - window.removeEventListener('message', onMsg); - var _done = done; - done = function () { }; - _done(); - }; - window.addEventListener('message', onMsg); - }).nThen(function (/*waitFor*/) { - SFCommonO.start({ - useCreationScreen: true - }); - }); -}); From ee8651c74e33ebfe66364de37f54c8720e0c1b6c Mon Sep 17 00:00:00 2001 From: Ludovic Dubost Date: Mon, 2 Apr 2018 20:33:35 +0200 Subject: [PATCH 03/35] Kanban styles and color updating --- customize.dist/src/less2/include/colortheme.less | 4 ++-- customize.dist/src/less2/main.less | 3 +-- www/kanban/app-kanban.less | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/customize.dist/src/less2/include/colortheme.less b/customize.dist/src/less2/include/colortheme.less index e2406653d..fdf4ea972 100644 --- a/customize.dist/src/less2/include/colortheme.less +++ b/customize.dist/src/less2/include/colortheme.less @@ -61,12 +61,12 @@ @colortheme_poll-th-fg: #fff; @colortheme_poll-warn: #ffade3; -@colortheme_kanban-bg: #006304; +@colortheme_kanban-bg: #8C4; @colortheme_kanban-color: #fff; @colortheme_kanban-help-bg: #bbffbb; @colortheme_kanban-th-bg: #005bef; @colortheme_kanban-th-fg: #fff; -@colortheme_kanban-warn: #ffade3; +@colortheme_kanban-warn: #e6385d; @colortheme_whiteboard-bg: #800080; @colortheme_whiteboard-color: #fff; diff --git a/customize.dist/src/less2/main.less b/customize.dist/src/less2/main.less index f3c8478ce..1186465da 100644 --- a/customize.dist/src/less2/main.less +++ b/customize.dist/src/less2/main.less @@ -34,12 +34,11 @@ body.cp-app-file { @import "../../../file/app-file.less"; } body.cp-app-filepicker { @import "../../../filepicker/app-filepicker.less"; } body.cp-app-contacts { @import "../../../contacts/app-contacts.less"; } body.cp-app-poll { @import "../../../poll/app-poll.less"; } -body.cp-app-kanban { @import "../../../kanban/app-kanban.less"; } body.cp-app-whiteboard { @import "../../../whiteboard/app-whiteboard.less"; } body.cp-app-todo { @import "../../../todo/app-todo.less"; } body.cp-app-profile { @import "../../../profile/app-profile.less"; } body.cp-app-settings { @import "../../../settings/app-settings.less"; } body.cp-app-debug { @import "../../../debug/app-debug.less"; } body.cp-app-worker { @import "../../../worker/app-worker.less"; } -body.cp-app-miniapp { @import "../../../miniapp/app-miniapp.less"; } +body.cp-app-kanban { @import "../../../kanban/app-kanban.less"; } diff --git a/www/kanban/app-kanban.less b/www/kanban/app-kanban.less index c2108473d..db58861b6 100644 --- a/www/kanban/app-kanban.less +++ b/www/kanban/app-kanban.less @@ -1,9 +1,9 @@ @import (once) "../../customize/src/less2/include/browser.less"; @import (once) "../../customize/src/less2/include/framework.less"; -.framework_main( @bg-color: @colortheme_code-bg, -@warn-color: @colortheme_code-warn, -@color: @colortheme_code-color); +.framework_main( @bg-color: @colortheme_kanban-bg, +@warn-color: @colortheme_kanban-warn, +@color: @colortheme_kanban-color); // body &.cp-app-kanban { From 65a2083afcf30797738d7428cc8af99f59efa92b Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 15 May 2018 18:18:56 +0200 Subject: [PATCH 04/35] Suggest tags based on existing ones. Display existing tags in the drive. --- .jshintignore | 1 + .../src/less2/include/tokenfield.less | 22 +- customize.dist/translations/messages.fr.js | 3 + customize.dist/translations/messages.js | 3 + www/common/common-interface.js | 27 +- www/common/common-ui-elements.js | 33 ++- www/common/jquery-ui/jquery-ui.min.css | 7 + www/common/jquery-ui/jquery-ui.min.js | 6 + www/common/outer/async-store.js | 13 +- www/common/sframe-common-outer.js | 24 +- www/common/sframe-common.js | 9 +- www/common/sframe-protocol.js | 7 +- www/common/userObject.js | 15 ++ www/drive/app-drive.less | 15 ++ www/drive/inner.js | 237 +++++++++++------- 15 files changed, 268 insertions(+), 154 deletions(-) create mode 100644 www/common/jquery-ui/jquery-ui.min.css create mode 100644 www/common/jquery-ui/jquery-ui.min.js diff --git a/.jshintignore b/.jshintignore index b7a1c570e..aac65f7de 100644 --- a/.jshintignore +++ b/.jshintignore @@ -2,6 +2,7 @@ node_modules/ www/bower_components/ www/common/pdfjs/ www/common/tippy/ +www/common/jquery-ui/ server.js www/common/media-tag.js diff --git a/customize.dist/src/less2/include/tokenfield.less b/customize.dist/src/less2/include/tokenfield.less index 6604b4481..46ba3af09 100644 --- a/customize.dist/src/less2/include/tokenfield.less +++ b/customize.dist/src/less2/include/tokenfield.less @@ -1,25 +1,31 @@ @import (once) "./tools.less"; .tokenfield_main () { + .ui-autocomplete { + z-index: 100001; // alertify + 1 + } .tokenfield { .tools_unselectable(); + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; height: auto; min-height: 34px; padding-bottom: 0px; background-color: unset; border: none; - display: flex; - flex-wrap: wrap; - align-items: center; - padding: 0 10px; + margin: 0 10px; + padding: 0; + width: ~"calc(100% - 20px)"; .token { box-sizing: border-box; border-radius: 3px; - display: inline-block; + display: inline-flex; + align-items: center; border: 1px solid #d9d9d9; background-color: #ededed; white-space: nowrap; - margin: 10px 5px; + margin: 2px 0; height: 24px; vertical-align: middle; cursor: default; @@ -50,7 +56,7 @@ .close { font-family: Arial; display: inline-block; - line-height: 24px; + line-height: 1.49em; font-size: 1.1em; margin-left: 5px; float: none; @@ -73,6 +79,8 @@ margin: 0 !important; // Override alertify box-shadow: none; max-width: 100%; + width: 100%; + min-width: 100% !important; &:focus { border-color: transparent; outline: 0; diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js index cf7ddcf8c..67b8ebea6 100644 --- a/customize.dist/translations/messages.fr.js +++ b/customize.dist/translations/messages.fr.js @@ -367,6 +367,7 @@ define(function () { out.fm_searchName = "Recherche"; out.fm_recentPadsName = "Pads récents"; out.fm_ownedPadsName = "Pads en votre possession"; + out.fm_tagsName = "Mots-clés"; out.fm_searchPlaceholder = "Rechercher..."; out.fm_newButton = "Nouveau"; out.fm_newButtonTitle = "Créer un nouveau pad ou un dossier, importer un fichier dans le dossier courant"; @@ -429,6 +430,8 @@ define(function () { out.fm_padIsOwned = "Vous êtes le propriétaire de ce pad"; out.fm_padIsOwnedOther = "Ce pad est la propriété d'un autre utilisateur"; out.fm_deletedPads = "Ces pads n'existent plus sur le serveur, ils ont été supprimés de votre CryptDrive: {0}"; + out.fm_tags_name = "Mot-clé"; + out.fm_tags_used = "Nombre d'utilisations"; // File - Context menu out.fc_newfolder = "Nouveau dossier"; out.fc_rename = "Renommer"; diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index 18e295a4c..717623315 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -368,6 +368,7 @@ define(function () { out.fm_searchName = "Search"; out.fm_recentPadsName = "Recent pads"; out.fm_ownedPadsName = "Owned"; + out.fm_tagsName = "Tags"; out.fm_searchPlaceholder = "Search..."; out.fm_newButton = "New"; out.fm_newButtonTitle = "Create a new pad or folder, import a file in the current folder"; @@ -430,6 +431,8 @@ define(function () { out.fm_padIsOwned = "You are the owner of this pad"; out.fm_padIsOwnedOther = "This pad is owned by another user"; out.fm_deletedPads = "These pads no longer exist on the server, they've been removed from your CryptDrive: {0}"; + out.fm_tags_name = "Tag name"; + out.fm_tags_used = "Number of uses"; // File - Context menu out.fc_newfolder = "New folder"; out.fc_rename = "Rename"; diff --git a/www/common/common-interface.js b/www/common/common-interface.js index bf1d70738..5af92df64 100644 --- a/www/common/common-interface.js +++ b/www/common/common-interface.js @@ -12,8 +12,10 @@ define([ '/customize/loading.js', '/common/test.js', + '/common/jquery-ui/jquery-ui.min.js', '/bower_components/bootstrap-tokenfield/dist/bootstrap-tokenfield.js', 'css!/common/tippy/tippy.css', + 'css!/common/jquery-ui/jquery-ui.min.css' ], function ($, Messages, Util, Hash, Notifier, AppConfig, Alertify, Tippy, Pages, h, Loading, Test) { var UI = {}; @@ -183,11 +185,17 @@ define([ ]); }; - UI.tokenField = function (target) { + UI.tokenField = function (target, autocomplete) { var t = { element: target || h('input'), }; - var $t = t.tokenfield = $(t.element).tokenfield(); + var $t = t.tokenfield = $(t.element).tokenfield({ + autocomplete: { + source: autocomplete, + delay: 100 + }, + showAutocompleteOnFocus: false + }); t.getTokens = function (ignorePending) { var tokens = $t.tokenfield('getTokens').map(function (token) { @@ -210,10 +218,17 @@ define([ t.preventDuplicates = function (cb) { $t.on('tokenfield:createtoken', function (ev) { + // Close the suggest list when a token is added because we're going to wipe the input + var $input = $t.closest('.tokenfield').find('.token-input'); + $input.autocomplete('close'); + var val; ev.attrs.value = ev.attrs.value.toLowerCase(); if (t.getTokens(true).some(function (t) { - if (t === ev.attrs.value) { return ((val = t)); } + if (t === ev.attrs.value) { + ev.preventDefault(); + return ((val = t)); + } })) { ev.preventDefault(); if (typeof(cb) === 'function') { cb(val); } @@ -241,7 +256,7 @@ define([ return t; }; - dialog.tagPrompt = function (tags, cb) { + dialog.tagPrompt = function (tags, existing, cb) { var input = dialog.textInput(); var tagger = dialog.frame([ @@ -255,7 +270,7 @@ define([ dialog.nav(), ]); - var field = UI.tokenField(input).preventDuplicates(function (val) { + var field = UI.tokenField(input, existing).preventDuplicates(function (val) { UI.warn(Messages._getKey('tags_duplicate', [val])); }); @@ -396,7 +411,7 @@ define([ stopListening(listener); cb(); }); - listener = listenForKeys(close, close, ok); + listener = listenForKeys(close, close); var $ok = $(ok).click(close); document.body.appendChild(frame); diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index e085ea3a3..4aaad5b9b 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -23,20 +23,27 @@ define([ } UIElements.updateTags = function (common, href) { - var sframeChan = common.getSframeChannel(); - sframeChan.query('Q_TAGS_GET', href || null, function (err, res) { - if (err || res.error) { - if (res.error === 'NO_ENTRY') { - UI.alert(Messages.tags_noentry); + var existing, tags; + NThen(function(waitFor) { + common.getSframeChannel().query("Q_GET_ALL_TAGS", null, waitFor(function(err, res) { + if (err || res.error) { return void console.error(err || res.error); } + existing = Object.keys(res.tags).sort(); + })); + }).nThen(function (waitFor) { + common.getPadAttribute('tags', waitFor(function (err, res) { + if (err) { + if (err === 'NO_ENTRY') { + UI.alert(Messages.tags_noentry); + } + waitFor.abort(); + return void console.error(err); } - return void console.error(err || res.error); - } - UI.dialog.tagPrompt(res.data, function (tags) { - if (!Array.isArray(tags)) { return; } - sframeChan.event('EV_TAGS_SET', { - tags: tags, - href: href, - }); + tags = res || []; + }), href); + }).nThen(function () { + UI.dialog.tagPrompt(tags, existing, function (newTags) { + if (!Array.isArray(newTags)) { return; } + common.setPadAttribute('tags', newTags, null, href); }); }); }; diff --git a/www/common/jquery-ui/jquery-ui.min.css b/www/common/jquery-ui/jquery-ui.min.css new file mode 100644 index 000000000..1ff50449e --- /dev/null +++ b/www/common/jquery-ui/jquery-ui.min.css @@ -0,0 +1,7 @@ +/*! jQuery UI - v1.12.1 - 2018-05-15 +* http://jqueryui.com +* Includes: core.css, autocomplete.css, menu.css, theme.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=base&cornerRadiusShadow=8px&offsetLeftShadow=0px&offsetTopShadow=0px&thicknessShadow=5px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=666666&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cc0000&fcError=5f3f3f&borderColorError=f1a899&bgTextureError=flat&bgColorError=fddfdf&iconColorHighlight=777620&fcHighlight=777620&borderColorHighlight=dad55e&bgTextureHighlight=flat&bgColorHighlight=fffa90&iconColorActive=ffffff&fcActive=ffffff&borderColorActive=003eff&bgTextureActive=flat&bgColorActive=007fff&iconColorHover=555555&fcHover=2b2b2b&borderColorHover=cccccc&bgTextureHover=flat&bgColorHover=ededed&iconColorDefault=777777&fcDefault=454545&borderColorDefault=c5c5c5&bgTextureDefault=flat&bgColorDefault=f6f6f6&iconColorContent=444444&fcContent=333333&borderColorContent=dddddd&bgTextureContent=flat&bgColorContent=ffffff&iconColorHeader=444444&fcHeader=333333&borderColorHeader=dddddd&bgTextureHeader=flat&bgColorHeader=e9e9e9&cornerRadius=3px&fwDefault=normal&fsDefault=1em&ffDefault=Arial%2CHelvetica%2Csans-serif +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#003eff;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-checked{border:1px solid #dad55e;background:#fffa90}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666} \ No newline at end of file diff --git a/www/common/jquery-ui/jquery-ui.min.js b/www/common/jquery-ui/jquery-ui.min.js new file mode 100644 index 000000000..d17a46a44 --- /dev/null +++ b/www/common/jquery-ui/jquery-ui.min.js @@ -0,0 +1,6 @@ +/*! jQuery UI - v1.12.1 - 2018-05-15 +* http://jqueryui.com +* Includes: widget.js, position.js, keycode.js, unique-id.js, widgets/autocomplete.js, widgets/menu.js +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){t.ui=t.ui||{},t.ui.version="1.12.1";var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},l=e.split(".")[0];e=e.split(".")[1];var h=l+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][h.toLowerCase()]=function(e){return!!t.data(e,h)},t[l]=t[l]||{},n=t[l][e],o=t[l][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:l,widgetName:e,widgetFullName:h}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var s,n,o=i.call(arguments,1),a=0,r=o.length;r>a;a++)for(s in o[a])n=o[a][s],o[a].hasOwnProperty(s)&&void 0!==n&&(e[s]=t.isPlainObject(n)?t.isPlainObject(e[s])?t.widget.extend({},e[s],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,s){var n=s.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=i.call(arguments,1),l=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(l=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(l=i&&i.jquery?l.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):l=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new s(o,this))})),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{classes:{},disabled:!1,create:null},_createWidget:function(i,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var l=s.match(/^([\w:-]*)\s*(.*)$/),h=l[1]+o.eventNamespace,c=l[2];c?n.on(h,c,r):i.on(h,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,l=/top|center|bottom/,h=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("
"),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.widthi?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};h>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),l.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,l=n-r,h=r+e.collisionWidth-a-n;e.collisionWidth>a?l>0&&0>=h?(i=t.left+l+e.collisionWidth-a-n,t.left+=l-i):t.left=h>0&&0>=l?n:l>h?n+a-e.collisionWidth:n:l>0?t.left+=l:h>0?t.left-=h:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,l=n-r,h=r+e.collisionHeight-a-n;e.collisionHeight>a?l>0&&0>=h?(i=t.top+l+e.collisionHeight-a-n,t.top+=l-i):t.top=h>0&&0>=l?n:l>h?n+a-e.collisionHeight:n:l>0?t.top+=l:h>0?t.top-=h:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,l=n.isWindow?n.scrollLeft:n.offset.left,h=t.left-e.collisionPosition.marginLeft,c=h-l,u=h+e.collisionWidth-r-l,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-l,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,l=n.isWindow?n.scrollTop:n.offset.top,h=t.top-e.collisionPosition.marginTop,c=h-l,u=h+e.collisionHeight-r-l,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-l,(i>0||u>a(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.ui.safeActiveElement=function(t){var e;try{e=t.activeElement}catch(i){e=t.body}return e||(e=t.body),e.nodeName||(e=t.body),e},t.widget("ui.menu",{version:"1.12.1",defaultElement:"