From dc3005f8f7a46dcb1f5e85eeb20fea77c266f402 Mon Sep 17 00:00:00 2001 From: Vincent Vanwaelscappel Date: Thu, 22 Sep 2022 16:59:20 +0200 Subject: [PATCH] wip #4214 @5 --- package-lock.json | 44 +- .../fluidbook/toolbox/css/linkeditor.css | 553 --------- .../fluidbook/toolbox/css/linkeditor.css.map | 1 - .../fluidbook/toolbox/css/linkeditor.less | 615 ---------- .../fluidbook/toolbox/js/linkeditor.js | 768 ------------ resources/linkeditor/js/linkeditor.js | 1049 ++++------------- resources/linkeditor/js/linkeditor.links.js | 263 +++++ resources/linkeditor/js/linkeditor.loader.js | 59 + resources/linkeditor/js/linkeditor.resize.js | 30 + resources/linkeditor/js/linkeditor.rulers.js | 230 ++++ resources/linkeditor/js/linkeditor.save.js | 65 + resources/linkeditor/js/linkeditor.toolbar.js | 41 + resources/linkeditor/js/linkeditor.utils.js | 71 ++ resources/linkeditor/js/linkeditor.zoom.js | 99 ++ resources/linkeditor/style/links.sass | 1 + .../link_editor.blade.php | 4 +- 16 files changed, 1141 insertions(+), 2752 deletions(-) delete mode 100644 public/packages/fluidbook/toolbox/css/linkeditor.css delete mode 100644 public/packages/fluidbook/toolbox/css/linkeditor.css.map delete mode 100644 public/packages/fluidbook/toolbox/css/linkeditor.less delete mode 100644 public/packages/fluidbook/toolbox/js/linkeditor.js create mode 100644 resources/linkeditor/js/linkeditor.links.js create mode 100644 resources/linkeditor/js/linkeditor.loader.js create mode 100644 resources/linkeditor/js/linkeditor.resize.js create mode 100644 resources/linkeditor/js/linkeditor.rulers.js create mode 100644 resources/linkeditor/js/linkeditor.save.js create mode 100644 resources/linkeditor/js/linkeditor.toolbar.js create mode 100644 resources/linkeditor/js/linkeditor.utils.js create mode 100644 resources/linkeditor/js/linkeditor.zoom.js diff --git a/package-lock.json b/package-lock.json index 6d2a75db3..3db959012 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,12 +7,14 @@ "dependencies": { "command-line-args": "^5.2.1", "jquery.scrollto": "^2.1.3", + "keymaster": "^1.6.2", "lz4js": "^0.2.0", "pako": "^2.0.4", "pdfjs-dist": "^2.14.305", "pipwerks-scorm-api-wrapper": "^0.1.2", "plyr": "^3.7.2", - "puppeteer": "^17.0.0" + "puppeteer": "^17.0.0", + "tippy.js": "^6.3.7" }, "devDependencies": { "axios": "^0.19", @@ -1819,6 +1821,15 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -7646,6 +7657,11 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/keymaster": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/keymaster/-/keymaster-1.6.2.tgz", + "integrity": "sha512-OvA/AALN8IDKKkTk2Z+bDrzs/SQao4lo/QPbwSdDvm+frxfiYiYCSn1aHFUypJY3SruAO1y/c771agBmTXqUtg==" + }, "node_modules/killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -12634,6 +12650,14 @@ "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==", "dev": true }, + "node_modules/tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "dependencies": { + "@popperjs/core": "^2.9.0" + } + }, "node_modules/to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -16517,6 +16541,11 @@ "fastq": "^1.6.0" } }, + "@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" + }, "@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -21230,6 +21259,11 @@ "graceful-fs": "^4.1.6" } }, + "keymaster": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/keymaster/-/keymaster-1.6.2.tgz", + "integrity": "sha512-OvA/AALN8IDKKkTk2Z+bDrzs/SQao4lo/QPbwSdDvm+frxfiYiYCSn1aHFUypJY3SruAO1y/c771agBmTXqUtg==" + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -25316,6 +25350,14 @@ "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==", "dev": true }, + "tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "requires": { + "@popperjs/core": "^2.9.0" + } + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", diff --git a/public/packages/fluidbook/toolbox/css/linkeditor.css b/public/packages/fluidbook/toolbox/css/linkeditor.css deleted file mode 100644 index 03c0032a4..000000000 --- a/public/packages/fluidbook/toolbox/css/linkeditor.css +++ /dev/null @@ -1,553 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} -body { - background-color: #ebecee; -} -@media (prefers-color-scheme: dark) { - body { - background-color: #333; - } -} -img, -.division, -.info { - user-select: none; - user-drag: none; -} -body, -#linkeditor, -html { - height: 100%; - width: 100%; - overflow: hidden; -} -#linkeditor { - white-space: nowrap; - font-size: 0; - overflow: hidden; -} -#linkeditor aside, -#linkeditor #linkeditor-main { - display: inline-block; - height: 100%; - vertical-align: top; - text-align: left; -} -#linkeditor aside { - width: 40px; - background-color: #EBECEE; -} -@media (prefers-color-scheme: dark) { - #linkeditor aside { - background-color: #333; - } -} -#linkeditor #linkeditor-main { - width: calc(100% - 40px - 40px); -} -#linkeditor #linkeditor-main.grab { - cursor: grab; -} -#linkeditor #linkeditor-main.grabbing { - cursor: grabbing; -} -#linkeditor #linkeditor-main #linkeditor-toolbar { - background-color: #dbdddf; - color: #5d5d5d; - height: 40px; - padding: 5px; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-toolbar { - background-color: #444; - } -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-toolbar { - color: #bbb; - } -} -#linkeditor #linkeditor-main #linkeditor-toolbar nav { - padding: 2px; - display: inline-block; - height: 26px; - vertical-align: top; - width: 33%; -} -#linkeditor #linkeditor-main #linkeditor-toolbar nav#linkeditor-toolbar-center { - text-align: center; -} -#linkeditor #linkeditor-main #linkeditor-toolbar div { - display: inline-block; - font-size: 16px; -} -#linkeditor #linkeditor-main #linkeditor-toolbar .separator { - width: 0; - height: 26px; - margin: 0 2px; - border-left: 1px solid #5d5d5d; -} -#linkeditor #linkeditor-main #linkeditor-toolbar #linkeditor-page-field { - padding: 2px 10px; - background-color: #fff; - border: 1px solid #ccc; - border-radius: 5px; - cursor: text; - font-size: 13px; - position: relative; - top: -9px; - user-select: none; - margin: 0 8px; - font-weight: 600; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-toolbar #linkeditor-page-field { - background-color: #000; - border-color: #333; - } -} -#linkeditor #linkeditor-main #linkeditor-toolbar #linkeditor-page-field input { - vertical-align: top; - text-align: right; - border: 0; - background-color: transparent; - width: 20px; - color: #5d5d5d; - font-size: 13px; - appearance: textfield; - font-weight: 600; - position: relative; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-toolbar #linkeditor-page-field input { - color: #bbb; - } -} -#linkeditor #linkeditor-main #linkeditor-toolbar #linkeditor-page-field input::-webkit-outer-spin-button, -#linkeditor #linkeditor-main #linkeditor-toolbar #linkeditor-page-field input::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; -} -#linkeditor #linkeditor-main #linkeditor-toolbar #linkeditor-page-field input:hover, -#linkeditor #linkeditor-main #linkeditor-toolbar #linkeditor-page-field input:focus { - outline: 0; - border: 0; -} -#linkeditor #linkeditor-main #linkeditor-toolbar [data-icon] { - display: inline-block; - vertical-align: top; - height: 26px; - min-width: 26px; - padding: 3px; - border-radius: 5px; - margin: 0 3px; - text-align: center; - color: #5d5d5d; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-toolbar [data-icon] { - color: #bbb; - } -} -#linkeditor #linkeditor-main #linkeditor-toolbar [data-icon]:hover, -#linkeditor #linkeditor-main #linkeditor-toolbar [data-icon].hover { - background-color: #fff; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-toolbar [data-icon]:hover, - #linkeditor #linkeditor-main #linkeditor-toolbar [data-icon].hover { - background-color: #000; - } -} -#linkeditor #linkeditor-main #linkeditor-toolbar [data-icon].arrow { - padding: 1px; -} -#linkeditor #linkeditor-main #linkeditor-toolbar [data-icon].arrow svg { - height: 16px; -} -#linkeditor #linkeditor-main #linkeditor-toolbar [data-icon] svg { - position: relative; - top: 1px; - height: 18px; - width: auto; -} -#linkeditor #linkeditor-main #linkeditor-editor { - position: relative; - height: calc( 100% - 40px); - width: 100%; - overflow: hidden; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links { - position: relative; - z-index: 500; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link { - position: absolute; - outline: 1px solid currentColor; - cursor: cell; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link.selected .corners { - visibility: visible; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners { - visibility: hidden; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div { - position: absolute; - outline: 1px solid currentColor; - background-color: #fff; - width: 8px; - height: 8px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.nw { - cursor: nw-resize; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.n { - cursor: n-resize; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.ne { - cursor: ne-resize; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.e { - cursor: e-resize; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.se { - cursor: se-resize; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.s { - cursor: s-resize; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.sw { - cursor: sw-resize; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.w { - cursor: w-resize; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.n, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.nw, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.ne { - top: -4px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.e, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.w { - top: calc(50% - 4px); -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.sw, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.s, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.se { - bottom: -4px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.nw, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.w, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.sw { - left: -4px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.ne, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.e, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.se { - right: -4px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.n, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-links .link .corners > div.s { - left: calc(50% - 4px); -} -#linkeditor #linkeditor-main #linkeditor-editor .ruler { - position: absolute; - top: 0; - left: 0; - z-index: 600; - border-width: 0; - border-color: #0f0; - border-style: solid; -} -#linkeditor #linkeditor-main #linkeditor-editor .ruler:after { - position: absolute; - content: ""; - display: block; - height: 100%; - width: 100%; -} -#linkeditor #linkeditor-main #linkeditor-editor .ruler.pending-delete { - border-color: #f00 !important; - z-index: 1100; -} -#linkeditor #linkeditor-main #linkeditor-editor .ruler:hover { - border-color: #0ff; -} -#linkeditor #linkeditor-main #linkeditor-editor .ruler[data-axis="x"] { - width: 0px; - height: calc( 100% - 16px); - border-left-width: 1px; - cursor: col-resize; - top: 16px; -} -#linkeditor #linkeditor-main #linkeditor-editor .ruler[data-axis="x"]:after { - left: -2px; - width: 4px; -} -#linkeditor #linkeditor-main #linkeditor-editor .ruler[data-axis="y"] { - border-bottom-width: 1px; - height: 0px; - width: calc( 100% - 16px); - left: 16px; -} -#linkeditor #linkeditor-main #linkeditor-editor .ruler[data-axis="y"]:after { - top: -2px; - height: 4px; - cursor: row-resize; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers { - color: #333; - position: absolute; - top: 0px; - left: 0px; - width: 100%; - height: 100%; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers { - color: #eee; - } -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-corner { - position: absolute; - top: 0px; - left: 0px; - width: 16px; - height: 16px; - z-index: 5; - background-color: #aaa; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-corner { - background-color: #666; - } -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers .ruler-bar { - overflow: hidden; - position: absolute; - left: 0; - top: 0; - z-index: 1000; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers .ruler-bar .info { - position: absolute; - top: 0; - left: 0; - z-index: 3; - font-size: 12px; - line-height: 8px; - display: none; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers .ruler-bar .info span { - display: block; - position: absolute; - top: 0; - left: 0; - background-color: #fff; - color: #000; - padding: 3px; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers .ruler-bar .info span { - background-color: #000; - color: #fff; - } -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers .ruler-bar .division { - pointer-events: none; - position: absolute; - background: #fff; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers .ruler-bar .division { - background-color: #000; - } -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers .ruler-bar .division .value { - position: absolute; - font-size: 12px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers .ruler-bar .division .subdivision { - position: absolute; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-x { - height: 16px; - width: 100%; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-x .info { - height: 16px; - border-left: 1px dotted #333; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-x .info { - border-color: #eee; - } -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-x .division, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-x .subdivision { - width: 0px; - border-left: 1px solid #333; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-x .division, - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-x .subdivision { - border-color: #eee; - } -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-x .division { - height: 16px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-x .division .value { - bottom: 0px; - left: 3px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-x .subdivision { - bottom: 0; - height: 2px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-x .subdivision.middle { - height: 5px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y { - width: 16px; - height: 100%; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y .info { - width: 16px; - border-bottom: 1px dotted #333; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y .info { - border-color: #eee; - } -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y .info span { - transform-origin: 0 0; - transform: rotate(270deg); -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y .division, -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y .subdivision { - height: 0px; - border-bottom: 1px solid #333; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y .division, - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y .subdivision { - border-color: #eee; - } -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y .division { - width: 16px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y .division .value { - text-align: center; - max-width: 16px; - word-wrap: break-word; - white-space: normal; - line-height: 10px; - letter-spacing: 30px; - top: 3px; - left: 3px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y .division .subdivision { - right: 0; - width: 2px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-rulers #linkeditor-ruler-y .division .subdivision.middle { - width: 5px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-zoom { - width: 100%; - height: 100%; - max-width: 100%; - max-height: 100%; - min-height: 100%; - min-width: 100%; - transform-origin: 0 0; - overflow: hidden; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas { - background-color: #505050; - position: relative; - z-index: 1; - top: 16px; - left: 16px; - height: calc( 100% - 16px); - max-height: calc( 100% - 16px); - width: calc( 100% - 16px); - max-width: calc( 100% - 16px); - overflow: auto; -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas { - background-color: #222; - } -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas::-webkit-scrollbar { - width: 6px; - height: 6px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas::-webkit-scrollbar-track { - background: transparent; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas::-webkit-scrollbar-track:hover { - background-color: #000; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas::-webkit-scrollbar-thumb { - background-color: #aaa; - border: 1px solid #333; - border-radius: 20px; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas #linkeditor-fluidbook { - transform-origin: 0 0; - position: absolute; - top: 0; - left: 0; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas #linkeditor-fluidbook .linkeditor-page { - position: absolute; - top: 0px; - left: 0px; - background-color: rgba(255, 255, 255, 0.2); -} -@media (prefers-color-scheme: dark) { - #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas #linkeditor-fluidbook .linkeditor-page { - background-color: rgba(0, 0, 0, 0.2); - } -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas #linkeditor-fluidbook .linkeditor-page .contents { - background-color: #fff; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas #linkeditor-fluidbook .linkeditor-page .contents img { - display: block; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: auto; - z-index: 1; -} -#linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas #linkeditor-fluidbook .linkeditor-page .contents img.texts { - z-index: 2; -} -.simple #linkeditor #linkeditor-main #linkeditor-editor #linkeditor-canvas #linkeditor-fluidbook .linkeditor-page#linkeditor-page-right { - display: none; -} -#linkeditor-preload { - display: none; -} -/*# sourceMappingURL=linkeditor.css.map */ \ No newline at end of file diff --git a/public/packages/fluidbook/toolbox/css/linkeditor.css.map b/public/packages/fluidbook/toolbox/css/linkeditor.css.map deleted file mode 100644 index e8ef77f43..000000000 --- a/public/packages/fluidbook/toolbox/css/linkeditor.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["linkeditor.less"],"names":[],"mappings":"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","file":"linkeditor.css"} \ No newline at end of file diff --git a/public/packages/fluidbook/toolbox/css/linkeditor.less b/public/packages/fluidbook/toolbox/css/linkeditor.less deleted file mode 100644 index f21e16873..000000000 --- a/public/packages/fluidbook/toolbox/css/linkeditor.less +++ /dev/null @@ -1,615 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -@font-size: 16px; - -body { - background-color: #ebecee; - @media (prefers-color-scheme: dark) { - background-color: #333; - } -} - -img, .division, .info { - user-select: none; - user-drag: none; -} - -body, #linkeditor, html { - height: 100%; - width: 100%; - overflow: hidden; -} - -#linkeditor { - @sidebar-width: 40px; - @rulers-size: 16px; - white-space: nowrap; - font-size: 0; - overflow: hidden; - - aside, #linkeditor-main { - display: inline-block; - height: 100%; - vertical-align: top; - text-align: left; - } - - aside { - width: @sidebar-width; - background-color: #EBECEE; - @media (prefers-color-scheme: dark) { - background-color: #333; - } - } - - #linkeditor-main { - @toolbar-height: 40px; - - width: ~"calc(100% - @{sidebar-width} - @{sidebar-width})"; - - &.grab { - cursor: grab; - } - - &.grabbing { - cursor: grabbing; - } - - #linkeditor-toolbar { - - @toolbar-color: #5d5d5d; - @toolbar-color-dark: #bbb; - background-color: #dbdddf; - - @media (prefers-color-scheme: dark) { - background-color: #444; - } - color: @toolbar-color; - @media (prefers-color-scheme: dark) { - color: @toolbar-color-dark; - } - height: @toolbar-height; - padding: 5px; - - nav { - padding: 2px; - display: inline-block; - height: 26px; - vertical-align: top; - width: 33%; - - &#linkeditor-toolbar-center { - text-align: center; - } - - &#linkeditor-toolbar-right { - - } - } - - div { - display: inline-block; - font-size: @font-size; - } - - .separator { - width: 0; - height: 26px; - margin: 0 2px; - border-left: 1px solid @toolbar-color; - } - - #linkeditor-page-field { - padding: 2px 10px; - background-color: #fff; - @media (prefers-color-scheme: dark) { - background-color: #000; - border-color: #333; - } - border: 1px solid #ccc; - border-radius: 5px; - cursor: text; - font-size: 13px; - position: relative; - top: -9px; - user-select: none; - margin: 0 8px; - font-weight: 600; - - - input { - vertical-align: top; - text-align: right; - border: 0; - background-color: transparent; - width: 20px; - color: @toolbar-color; - @media (prefers-color-scheme: dark) { - color: @toolbar-color-dark; - } - font-size: 13px; - appearance: textfield; - - &::-webkit-outer-spin-button, &::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; - } - - font-weight: 600; - position: relative; - - - &:hover, &:focus { - outline: 0; - border: 0; - } - } - } - - [data-icon] { - display: inline-block; - vertical-align: top; - height: 26px; - min-width: 26px; - padding: 3px; - border-radius: 5px; - margin: 0 3px; - text-align: center; - color: @toolbar-color; - @media (prefers-color-scheme: dark) { - color: @toolbar-color-dark; - } - - &:hover, &.hover { - background-color: #fff; - @media (prefers-color-scheme: dark) { - background-color: #000; - } - } - - &.arrow { - padding: 1px; - - svg { - height: 16px; - } - } - - svg { - position: relative; - top: 1px; - height: 18px; - width: auto; - } - } - } - - #linkeditor-editor { - position: relative; - height: ~"calc( 100% - @{toolbar-height})"; - width: 100%; - overflow: hidden; - - @ruler-margin: 2px; - - #linkeditor-links { - .link { - position: absolute; - outline: 1px solid currentColor; - cursor: cell; - - &.selected { - .corners { - visibility: visible; - } - } - - .corners { - visibility: hidden; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - - > div { - position: absolute; - outline: 1px solid currentColor; - background-color: #fff; - width: 8px; - height: 8px; - - &.nw { - cursor: nw-resize; - } - - &.n { - cursor: n-resize; - } - - &.ne { - cursor: ne-resize; - } - - &.e { - cursor: e-resize; - } - - &.se { - cursor: se-resize; - } - - &.s { - cursor: s-resize; - } - - &.sw { - cursor: sw-resize; - } - - &.w { - cursor: w-resize; - } - - &.n, &.nw, &.ne { - top: -4px; - } - - &.e, &.w { - top: calc(50% - 4px); - } - - &.sw, &.s, &.se { - bottom: -4px; - } - - &.nw, &.w, &.sw { - left: -4px; - } - - &.ne, &.e, &.se { - right: -4px; - } - - &.n, &.s { - left: calc(50% - 4px); - } - } - } - } - - position: relative; - z-index: 500; - } - - .ruler { - position: absolute; - top: 0; - left: 0; - z-index: 600; - border-width: 0; - border-color: #0f0; - border-style: solid; - - &:after { - position: absolute; - content: ""; - display: block; - height: 100%; - width: 100%; - } - - &.pending-delete { - border-color: #f00 !important; - z-index: 1100; - } - - &:hover { - border-color: #0ff; - } - - &[data-axis="x"] { - width: 0px; - height: ~"calc( 100% - @{rulers-size})"; - border-left-width: 1px; - cursor: col-resize; - top: @rulers-size; - - &:after { - left: @ruler-margin*-1; - width: @ruler-margin*2; - } - } - - &[data-axis="y"] { - border-bottom-width: 1px; - height: 0px; - width: ~"calc( 100% - @{rulers-size})"; - left: @rulers-size; - - &:after { - top: @ruler-margin*-1; - height: @ruler-margin*2; - cursor: row-resize; - } - } - } - - - #linkeditor-rulers { - @rulers-color: #333; - @rulers-color-dark: #eee; - - @media (prefers-color-scheme: dark) { - color: @rulers-color-dark; - } - - color: @rulers-color; - position: absolute; - top: 0px; - left: 0px; - width: 100%; - height: 100%; - - #linkeditor-ruler-corner { - position: absolute; - top: 0px; - left: 0px; - width: @rulers-size; - height: @rulers-size; - z-index: 5; - background-color: #aaa; - @media (prefers-color-scheme: dark) { - background-color: #666; - } - - } - - .ruler-bar { - overflow: hidden; - position: absolute; - left: 0; - top: 0; - z-index: 1000; - - .info { - position: absolute; - top: 0; - left: 0; - z-index: 3; - font-size: 12px; - line-height: 8px; - display: none; - - span { - display: block; - position: absolute; - top: 0; - left: 0; - background-color: #fff; - color: #000; - @media (prefers-color-scheme: dark) { - background-color: #000; - color: #fff; - } - padding: 3px; - } - } - - .division { - pointer-events: none; - position: absolute; - background: #fff; - @media (prefers-color-scheme: dark) { - background-color: #000; - } - - .value { - position: absolute; - font-size: 12px; - } - - .subdivision { - position: absolute; - } - } - } - - #linkeditor-ruler-x { - height: @rulers-size; - width: 100%; - - .info { - height: @rulers-size; - border-left: 1px dotted @rulers-color; - @media (prefers-color-scheme: dark) { - border-color: @rulers-color-dark; - } - } - - .division, .subdivision { - width: 0px; - border-left: 1px solid @rulers-color; - @media (prefers-color-scheme: dark) { - border-color: @rulers-color-dark; - } - } - - .division { - height: @rulers-size; - - .value { - bottom: 0px; - left: 3px; - } - } - - .subdivision { - bottom: 0; - height: 2px; - - &.middle { - height: 5px; - } - } - } - - #linkeditor-ruler-y { - width: @rulers-size; - height: 100%; - - .info { - width: @rulers-size; - border-bottom: 1px dotted @rulers-color; - @media (prefers-color-scheme: dark) { - border-color: @rulers-color-dark; - } - - span { - transform-origin: 0 0; - transform: rotate(270deg); - } - } - - .division, .subdivision { - height: 0px; - border-bottom: 1px solid @rulers-color; - @media (prefers-color-scheme: dark) { - border-color: @rulers-color-dark; - } - } - - .division { - width: @rulers-size; - - .value { - text-align: center; - max-width: @rulers-size; - word-wrap: break-word; - white-space: normal; - line-height: 10px; - letter-spacing: 30px; - top: 3px; - left: 3px; - } - - .subdivision { - right: 0; - width: 2px; - - &.middle { - width: 5px; - } - } - } - } - } - - #linkeditor-zoom { - width: 100%; - height: 100%; - max-width: 100%; - max-height: 100%; - min-height: 100%; - min-width: 100%; - transform-origin: 0 0; - overflow: hidden; - } - - #linkeditor-canvas { - background-color: #505050; - @media (prefers-color-scheme: dark) { - background-color: #222; - } - - position: relative; - z-index: 1; - top: @rulers-size; - left: @rulers-size; - height: ~"calc( 100% - @{rulers-size})"; - max-height: ~"calc( 100% - @{rulers-size})"; - width: ~"calc( 100% - @{rulers-size})"; - max-width: ~"calc( 100% - @{rulers-size})"; - overflow: auto; - - &::-webkit-scrollbar { - width: 6px; - height: 6px; - } - - &::-webkit-scrollbar-track { - background: transparent; - - &:hover { - background-color: #000; - } - } - - &::-webkit-scrollbar-thumb { - background-color: #aaa; - border: 1px solid #333; - border-radius: 20px; - } - - - #linkeditor-fluidbook { - transform-origin: 0 0; - position: absolute; - top: 0; - left: 0; - - .linkeditor-page { - position: absolute; - top: 0px; - left: 0px; - background-color: rgba(255, 255, 255, 0.2); - @media (prefers-color-scheme: dark) { - background-color: rgba(0, 0, 0, 0.2); - } - - - .contents { - background-color: #fff; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - - img { - display: block; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: auto; - z-index: 1; - - &.texts { - z-index: 2; - } - } - } - - - &#linkeditor-page-right { - .simple & { - display: none; - } - } - } - } - } - } - } - - -} - -#linkeditor-preload { - display: none; -} diff --git a/public/packages/fluidbook/toolbox/js/linkeditor.js b/public/packages/fluidbook/toolbox/js/linkeditor.js deleted file mode 100644 index 7695d02ef..000000000 --- a/public/packages/fluidbook/toolbox/js/linkeditor.js +++ /dev/null @@ -1,768 +0,0 @@ -var single = ['mobilefirst', 'portrait'].indexOf(FLUIDBOOK_DATA.settings.mobileNavigationType) >= 0; -var pw = FLUIDBOOK_DATA.settings.width; -var ph = FLUIDBOOK_DATA.settings.height; -var fw = pw * (single ? 1 : 2); -var fh = ph; -var fs = 1; -var mx = 0, my = 0; -var zoom = 1; -var zoomdragging = false; -var dividers = [1, 2, 5, 10, 20, 50, 100, 200]; -var fluidbookRect, canvasRect, editorRect; -var currentPage; -var movingRuler = null; -var rasterizePages = splitPages(FLUIDBOOK_DATA.settings.rasterizePages); -var vectorPages = splitPages(FLUIDBOOK_DATA.settings.vectorPages); -var unsavedChanges = false; -var automaticSaveTimeout; -var runningAutomaticSaveTimeout = false; -var dimensionProperties = ['left', 'top', 'width', 'height']; -var rulersMagnetValuesX = []; -var rulersMagnetValuesY = []; -var currentSelection = []; - -$(function () { - init(); -}); - - -function init() { - $(window).on('hashchange', function () { - changePage(); - }); - $(window).on('resize', function () { - resize(); - }); - $(window).on('beforeunload', function () { - if (unsavedChanges) { - return TRANSLATIONS.warning_unsaved_changes; - } - }) - // Disable scroll by spacebar - $(window).on('keydown', function (e) { - if (e.keyCode == 32) { - $("#linkeditor-main").addClass('grab'); - return false; - } - moveRuler(); - }); - $(window).on('keyup', function (e) { - if (e.keyCode == 32) { - resetZoomDrag(); - } - moveRuler(); - }); - - $("#linkeditor-canvas").on('scroll', function () { - updateRulers(); - }); - $("#linkeditor-main").on('mousedown', function (e) { - if ($(this).hasClass('grab') && zoom > 1) { - zoomdragging = { - x: e.pageX, - y: e.pageY, - scrollX: $("#linkeditor-canvas").scrollLeft(), - scrollY: $("#linkeditor-canvas").scrollTop() - }; - $(this).addClass('grabbing'); - } else { - resetZoomDrag(); - } - deselectAllLinks(); - }); - - $(document).on('mousedown', '.link', function (e) { - if (!e.ctrlKey) { - deselectAllLinks(); - } - selectLink($(this)); - }); - - $("#linkeditor-ruler-x").on('mousedown', function (e) { - addRuler('y'); - }); - - $("#linkeditor-ruler-y").on('mousedown', function (e) { - addRuler('x'); - }); - - $(document).on('mousedown', ".ruler", function (e) { - movingRuler = $(this); - - }); - - $(window).on('mousemove', function (e) { - if (!$("#linkeditor-main").hasClass('grab') || zoom === 1) { - resetZoomDrag(); - } - if (zoomdragging !== false) { - moveZoomDrag(e); - } - updateMousePosition(e); - }); - $(window).on('mouseup', function (e) { - if (zoomdragging !== false) { - moveZoomDrag(e); - } - stopMoveRuler(); - resetZoomDrag(); - }); - $("#linkeditor-main").on('wheel', function (e) { - var delta = e.originalEvent.deltaY; - if (delta == 0) { - return true; - } - e.stopPropagation(); - e.stopImmediatePropagation(); - e.preventDefault(); - if (delta < 0) { - if (setZoom(zoom + 0.25)) { - moveZoom(e); - } - } else { - setZoom(zoom - 0.25); - } - return false; - }); - - if (single) { - $("#linkeditor").addClass('single'); - } else { - $("#linkeditor").addClass('double'); - } - $('.linkeditor-page').css({ - width: pw, height: ph - }); - $("#linkeditor-page-right").css({left: pw}) - $('#linkeditor-fluidbook').css({ - width: fw, height: ph - }); - initToolbar(); - resize(); - changePage(); -} - -function selectLink(l) { - if ($(l).find('.corners').length === 0) { - $(l).append('
') - } - $(l).addClass('selected'); - currentSelection.push(l); -} - -function deselectAllLinks() { - currentSelection = []; - $(".link.selected").removeClass('selected'); -} - -function initToolbar() { - $("#linkeditor-page-field input").on('change', function () { - changePage($(this).val()); - $(this).blur(); - return false; - }); - - $("#linkeditor-toolbar [data-icon]").each(function () { - $(this).append(getSpriteIcon('linkeditor-' + $(this).data('icon'))); - }); - - $("[data-key]").each(function () { - var e = $(this); - key($(this).data('key'), function () { - $(e).addClass('hover'); - runAction($(e).data('action')); - setTimeout(function () { - $(e).removeClass('hover') - }, 150); - return false; - }); - }); - - $('[data-action]').click(function () { - runAction($(this).data('action')); - return false; - }); - - $('[data-tooltip]').each(function () { - tippy($(this).get(0), {content: $(this).data('tooltip')}); - }); -} - -function runAction(act) { - window[act](); -} - -function saveLinks(message) { - if (message === undefined) { - message = TRANSLATIONS.manual_save_message; - } - $.ajax({ - url: '/fluidbook-publication/' + FLUIDBOOK_DATA.id + '/save/links', method: 'post', data: { - _method: 'put', 'message': message, rulers: window.RULERS, links: window.LINKS, - }, success: function (data) { - new Noty({ - type: "success", text: TRANSLATIONS.success_save, - }).show(); - clearTimeout(automaticSaveTimeout); - unsavedChanges = false; - runningAutomaticSaveTimeout = false; - }, error: function (jqXHR, status, error) { - hasChanged(); - new Noty({ - type: "error", text: TRANSLATIONS.error_save + ' : ' + error, - }).show(); - }, - }); -} - -function automaticSaveLinks() { - saveLinks(TRANSLATIONS.automatic_save_message); -} - -function firstPage() { - changePage(1); -} - -function nextPage() { - changePage(currentPage + (single ? 1 : 2)); -} - -function previousPage() { - changePage(currentPage - (single ? 1 : 2)); -} - -function lastPage() { - changePage(FLUIDBOOK_DATA.settings.pages); -} - -function focusPageField() { - var i = $("#linkeditor-page-field input").get(0); - i.focus(); - i.select(); -} - -function zoomReset() { - setZoom(1); - resetZoomDrag(); -} - -function generateUID() { - var length = 12; - var result = ''; - var characters = 'abcdefghijklmnopqrstuvwxyz0123456789'; - var charactersLength = characters.length; - for (var i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } - return result; -} - -function addRuler(axis, pos, uid) { - if (undefined === uid) { - uid = generateUID(); - RULERS[uid] = {page: currentPage, type: axis, uid: uid}; - hasChanged(); - } - var ruler = $('
'); - if (pos === undefined) { - movingRuler = ruler; - } else { - var dim = axis == 'x' ? 'left' : 'top'; - $(ruler).attr('fb-' + dim, pos); - } - $("#linkeditor-editor").append(ruler); - moveRuler(); -} - -function deleteRuler(ruler) { - if (ruler === undefined) { - ruler = movingRuler; - } - var uid = $(ruler).data('uid'); - delete RULERS[uid]; - $(ruler).remove(); - movingRuler = null; - hasChanged(); -} - -function hasChanged() { - unsavedChanges = true; - if (runningAutomaticSaveTimeout === false) { - runningAutomaticSaveTimeout = true; - automaticSaveTimeout = setTimeout(function () { - automaticSaveLinks(); - }, 1000 * 5 * 60); - } -} - -function moveRuler() { - if (movingRuler === null || movingRuler === undefined) { - return; - } - var magnet = !key.ctrl; - var editorMouse = globalToEditor(mx, my); - var fbMouse = globalToFluidbook(mx, my, false); - var css = {}; - var attrs = {}; - var v, fbv; - if ($(movingRuler).data('axis') === 'x') { - v = editorMouse.x; - fbv = attrs['fb-left'] = magnet ? magnetize(fbMouse.x, rulersMagnetValuesX) : fbMouse.x; - } else { - v = editorMouse.y; - fbv = attrs['fb-top'] = magnet ? magnetize(fbMouse.y, rulersMagnetValuesY) : fbMouse.y; - } - if (v < 16) { - $(movingRuler).addClass('pending-delete'); - } else { - $(movingRuler).removeClass('pending-delete'); - } - $(movingRuler).css(css).attr(attrs); - RULERS[$(movingRuler).data('uid')].pos = fbv; - updateFBElements(); -} - -function magnetize(value, values) { - var sensibility = 8 / (zoom * fs); - var min = 100000; - var magnetValue; - if (values.length === 0) { - return value; - } - - for (var i in values) { - var v = values[i]; - var diff = Math.abs(v - value); - if (diff < min) { - min = diff; - magnetValue = v; - } - } - - if (min > sensibility) { - return value; - } - return magnetValue; -} - -function getLinksOfPage(p) { - let pages = []; - if (!single) { - if (p % 2 === 1) { - p--; - } - pages.push(p); - pages.push(p + 1); - } else { - pages.push(p); - } - let res = {}; - $.each(LINKS, function (uid, link) { - if (pages.indexOf(parseInt(link.page)) >= 0) { - res[uid] = link; - } - }); - return res; -} - -function updateFBElements() { - $('[fb-ref]').each(function () { - var e = $(this); - var rect = $(this).attr('fb-ref'); - var css = {}; - $.each(dimensionProperties, function (k, dim) { - if ($(e).is('[fb-' + dim + ']')) { - var v = parseFloat($(e).attr('fb-' + dim)); - if (dim === 'width' || dim === 'height') { - css[dim] = v * (fs * zoom); - } else { - css[dim] = fluidbookTo(v, dim, rect); - } - } - }); - $(e).css(css); - }); -} - -function fluidbookTo(dim, name, rect) { - switch (rect) { - case 'editor': - rect = editorRect; - break; - case 'canvas': - rect = canvasRect; - break; - } - return fluidbookToGlobal(dim, name) - rect[name]; -} - -function stopMoveRuler() { - moveRuler(); - if ($(movingRuler).hasClass('pending-delete')) { - deleteRuler($(movingRuler)); - } - movingRuler = null; -} - -function updateMousePosition(e) { - mx = e.pageX; - my = e.pageY; - updateMousePositionRulers(); - moveRuler(); -} - -function updateMousePositionRulers() { - var rulersRect = $("#linkeditor-rulers").get(0).getBoundingClientRect(); - var rx = mx - rulersRect.x; - var ry = my - rulersRect.y; - $("#linkeditor-ruler-x .info").css('left', rx); - $("#linkeditor-ruler-y .info").css('top', ry); - - var rrect = $("#linkeditor-rulers").get(0).getBoundingClientRect(); - - if (mx - rrect.x < 0 || my - rrect.y < 0 || mx - rrect.x > rrect.width || my - rrect.y > rrect.height) { - $("#linkeditor-rulers .info").hide(); - return; - } - - var fb = globalToFluidbook(mx, my, true); - $("#linkeditor-ruler-y .info span").text(fb.y.toFixed(2)); - $("#linkeditor-ruler-x .info span").text(fb.x.toFixed(2)); - $("#linkeditor-rulers .info").css('display', 'inline-block'); -} - -function resetZoomDrag() { - $("#linkeditor-main").removeClass('grab').removeClass('grabbing'); - if (zoom === 1) { - $("#linkeditor-canvas").scrollTo({left: 0, top: 0}); - } - zoomdragging = false; -} - -function moveZoomDrag(e) { - var deltaX = e.pageX - zoomdragging.x; - var deltaY = e.pageY - zoomdragging.y; - $("#linkeditor-canvas").scrollTo({ - top: zoomdragging.scrollY - deltaY, left: zoomdragging.scrollX - deltaX - }); - updateRulers(); -} - -function moveZoom(e) { - var rect = $("#linkeditor-zoom").get(0).getBoundingClientRect(); - var lx = (e.originalEvent.pageX - rect.x) / rect.width; - var ly = (e.originalEvent.pageY - rect.y) / rect.height; - $("#linkeditor-canvas").scrollTo({left: pct(lx), top: pct(ly)}); - updateRulers(); -} - -function pct(v) { - return (v * 100) + '%'; -} - -function setZoom(z) { - z = Math.max(1, Math.min(6, z)); - if (z === zoom) { - return false; - } - zoom = z; - $("#linkeditor-canvas").attr('data-z', zoom); - $("#linkeditor-zoom").css({transform: 'scale(' + zoom + ')', overflow: 'visible'}); - - setTimeout(function () { - $("#linkeditor-zoom").css({overflow: 'hidden'}); - if (zoom === 1) { - resetZoomDrag(); - } - updateRulers(); - - }, 10); - - return true; -} - -function changePage(page) { - if (page === undefined) { - var h = window.location.hash; - if (h.length === 0) { - page = 0; - } else { - page = window.location.hash.substring(1); - } - } - page = parseInt(page); - if (page % 2 === 1 && !single) { - page--; - } - var normPage = Math.max(0, Math.min(page, FLUIDBOOK_DATA.settings.pages)); - if (normPage === currentPage) { - return; - } - currentPage = normPage; - - window.location.hash = '#' + currentPage; - clearLinksAndRulers(); - loadPage(currentPage, 'left'); - if (!single) { - loadPage(currentPage + 1, 'right'); - } - $("#linkeditor-page-field input").val(currentPage); - updateRulersMagnetValues(); - resize(); - preloadPages(); -} - -function updateRulersMagnetValues() { - rulersMagnetValuesX = [0, pw, pw * 2]; - rulersMagnetValuesY = [0, ph]; - $.each(getLinksOfPage(currentPage), function (uid, link) { - const left = parseFloat(link.left); - const top = parseFloat(link.top); - const width = parseFloat(link.width); - const height = parseFloat(link.height); - rulersMagnetValuesX.push(left, left + width); - rulersMagnetValuesY.push(top, top + height); - }); -} - -// Convert global coordinates to fluidbook ones -function globalToFluidbook(x, y, onePage) { - var res = _globalTo(x, y, fluidbookRect, 1 / (fs * zoom)); - if (onePage) { - res.xside = 'left'; - if (!single && res.x >= pw) { - res.xside = 'right'; - res.x -= pw; - } - } - return res; -} - -function fluidbookToGlobal(dim, name) { - return fluidbookRect[name] + (dim * fs * zoom); -} - -function globalToCanvas(x, y) { - return _globalTo(x, y, canvasRect, 1); -} - -function globalToEditor(x, y) { - return _globalTo(x, y, editorRect, 1); -} - -function _globalTo(x, y, rect, multi) { - return {x: multi * (x - rect.x), y: multi * (y - rect.y)}; -} - -function loadPage(p, side) { - var container = $("#linkeditor-page-" + side); - $(container).attr('data-page', p); - - if (p === 0 || p > FLUIDBOOK_DATA.settings.pages) { - $(container).html(''); - } else { - _loadPage(p, container); - } - - loadLinks(p, side); - loadRulers(p, side); -} - -function preloadPages() { - let j = 1; - for (let i = Math.max(1, currentPage - 4); i <= Math.min(currentPage + 16, FLUIDBOOK_DATA.settings.pages); i++) { - if ($('.preload[data-page="' + i + '"]').length >= 1) { - continue; - } - setTimeout(function () { - var c = $('
'); - $("#linkeditor-preload").append(c); - _loadPage(i, c); - }, j * 500); - j++; - } -} - -function _loadPage(p, container) { - var imageFormat = FLUIDBOOK_DATA.settings.imageFormat; - var c = '
'; - if (rasterizePages.indexOf(p) >= 0) { - c += ''; - } else if (vectorPages.indexOf(p) >= 0) { - c += ''; - } else { - c += ''; - c += ''; - } - c += '
'; - $(container).html(c); -} - -function loadLinks(page, side) { - $.each(LINKS, function (uid, link) { - if (link.page != page) { - return; - } - if (side === 'right') { - link.left = parseInt(link.left) + pw; - } - addLink(link, side); - }); -} - -function addLink(link) { - if (link.uid === undefined) { - link.uid = generateUID(); - LINKS[link.uid] = link; - updateRulersMagnetValues(); - hasChanged(); - } - - var attrs = {}; - $.each(link, function (k, v) { - if (dimensionProperties.indexOf(k) >= 0) { - attrs['fb-' + k] = v; - } else { - attrs['data-' + k] = v; - } - }); - - var e = $(''); - $(e).attr(attrs); - $("#linkeditor-links").append(e); -} - -function clearLinksAndRulers() { - $('#linkeditor-editor .ruler').remove(); -} - -function loadRulers(page, side) { - $.each(RULERS, function (uid, ruler) { - if (ruler.page != page) { - return; - } - addRuler(ruler.type, ruler.pos, ruler.uid); - }); -} - - -function resize() { - resizeCanvas(); - updateRulers(); -} - -function updateRulers() { - // Update rects - fluidbookRect = $("#linkeditor-fluidbook").get(0).getBoundingClientRect(); - - $("#linkeditor-ruler-y,#linkeditor-ruler-x").html(''); - // Measure of visible fluidbook px at current zoom - - var factor = fs / zoom; - var visible_w = (canvasRect.width / fs) / zoom; - var visible_h = (canvasRect.height / fs) / zoom; - - // Find the best divider to have around 10 main divisions - var divider = 0; - for (var i in dividers) { - divider = dividers[i]; - var v = visible_h / divider; - if (v <= 10) { - break; - } - } - - var divisionSize = divider * fs * zoom; - // Draw vertical ruler - var margin = 100; - var nbDivisions = Math.floor(visible_h / divider); - var y0 = 16 + fluidbookRect.y - canvasRect.y; - - var yruler = '
1234.12
'; - for (var y = -margin; y <= nbDivisions + (margin * 2) + 1; y++) { - // Draw subdivision - var v = divider * y; - var ystart = y0 + (y * divisionSize); - if (ystart + divisionSize < 0 || ystart > canvasRect.height) { - continue; - } - yruler += '
' + Math.abs(v) + '
'; - for (var i = 1; i <= 9; i++) { - yruler += '
'; - } - yruler += '
'; - } - $("#linkeditor-ruler-y").html(yruler); - - // Draw horizontal ruler - nbDivisions = Math.floor(visible_w / divider); - var x0 = 16 + fluidbookRect.x - canvasRect.x; - var xruler = '
'; - - for (var x = -margin; x <= nbDivisions + (margin * 2) + 1; x++) { - // Draw subdivision - var v = divider * x; - var xstart = x0 + (x * divisionSize); - if (xstart + divisionSize < 0 || xstart > canvasRect.width) { - continue; - } - xruler += '
' + Math.abs(v) + '
'; - for (var i = 1; i <= 9; i++) { - var cls = ''; - if (i === 5) { - cls += ' middle'; - } - xruler += '
'; - } - xruler += '
'; - } - // Draw right page horizontal ruler - if (!single) { - x0 = x0 + pw * fs * zoom; - for (var x = 0; x <= nbDivisions + margin + 1; x++) { - // Draw subdivision - var v = divider * x; - var xstart = x0 + (x * divisionSize); - if (xstart + divisionSize < 0 || xstart > canvasRect.width) { - continue; - } - xruler += '
' + Math.abs(v) + '
'; - for (var i = 1; i <= 9; i++) { - var cls = ''; - if (i === 5) { - cls += ' middle'; - } - xruler += '
'; - } - xruler += '
'; - } - } - $("#linkeditor-ruler-x").html(xruler); - updateFBElements() - updateMousePositionRulers(); -} - -function resizeCanvas() { - canvasRect = $("#linkeditor-canvas").get(0).getBoundingClientRect(); - editorRect = $("#linkeditor-editor").get(0).getBoundingClientRect(); - var aw = canvasRect.width - 30; - var ah = canvasRect.height - 30; - fs = Math.min(aw / fw, ah / fh); - var left = (canvasRect.width - fw * fs) / 2; - var top = (canvasRect.height - fh * fs) / 2; - $("#linkeditor-fluidbook").css({left: left, top: top, transform: 'scale(' + fs + ')'}); -} - - -function splitPages(str) { - str = str.toString(); - var res = []; - if (str == '') { - return res; - } - var pages = str.split(','); - for (var p in pages) { - res.push(parseInt(pages[p])); - } - return res; -} diff --git a/resources/linkeditor/js/linkeditor.js b/resources/linkeditor/js/linkeditor.js index 04b09d07a..7d8ffb453 100644 --- a/resources/linkeditor/js/linkeditor.js +++ b/resources/linkeditor/js/linkeditor.js @@ -1,856 +1,281 @@ window.$ = window.jQuery = require('jquery'); +window.key = require('keymaster'); import tippy from 'tippy.js'; import 'tippy.js/dist/tippy.css'; -import key from 'keymaster'; + +window.tippy = tippy; require('jquery.scrollto'); require('jquery-contextmenu'); -var single = ['mobilefirst', 'portrait'].indexOf(FLUIDBOOK_DATA.settings.mobileNavigationType) >= 0; -var pw = FLUIDBOOK_DATA.settings.width; -var ph = FLUIDBOOK_DATA.settings.height; -var fw = pw * (single ? 1 : 2); -var fh = ph; -var fs = 1; -var mx = 0, my = 0; -var zoom = 1; -var zoomdragging = false; -var dividers = [1, 2, 5, 10, 20, 50, 100, 200]; -var fluidbookRect, canvasRect, editorRect; -var currentPage; -var movingRuler = null; -var rasterizePages = splitPages(FLUIDBOOK_DATA.settings.rasterizePages); -var vectorPages = splitPages(FLUIDBOOK_DATA.settings.vectorPages); -var unsavedChanges = false; -var automaticSaveTimeout; -var runningAutomaticSaveTimeout = false; -var dimensionProperties = ['left', 'top', 'width', 'height']; -var rulersMagnetValuesX = []; -var rulersMagnetValuesY = []; -var currentSelection = []; -var dragLinkPos = null; - -$(function () { - init(); -}); - +import LinkeditorLinks from './linkeditor.links'; +import LinkeditorLoader from './linkeditor.loader'; +import LinkeditorResize from './linkeditor.resize'; +import LinkeditorRulers from './linkeditor.rulers'; +import LinkeditorToolbar from './linkeditor.toolbar'; +import LinkeditorUtils from './linkeditor.utils'; +import LinkeditorZoom from './linkeditor.zoom'; +import LinkeditorSave from './linkeditor.save'; + +function LinkEditor() { + this.single = ['mobilefirst', 'portrait'].indexOf(FLUIDBOOK_DATA.settings.mobileNavigationType) >= 0; + this.pw = FLUIDBOOK_DATA.settings.width; + this.ph = FLUIDBOOK_DATA.settings.height; + this.fw = this.pw * (this.single ? 1 : 2); + this.fh = this.ph; + this.fs = 1; + this.mx = 0; + this.my = 0; + + this.fluidbookRect = null; + this.canvasRect = null; + this.editorRect = null; + this.currentPage = -1; + + this.dimensionProperties = ['left', 'top', 'width', 'height']; + + this.init(); +} + +LinkEditor.prototype = { + init: function () { + this.toolbar = new LinkeditorToolbar(this); + this.resize = new LinkeditorResize(this); + this.rulers = new LinkeditorRulers(this); + this.zoom = new LinkeditorZoom(this); + this.links = new LinkeditorLinks(this); + this.utils = new LinkeditorUtils(this); + this.loader = new LinkeditorLoader(this); + this.save = new LinkeditorSave(this); + + this.initEvents(); + }, + + initEvents: function () { + var $this = this; + $(window).on('hashchange', function () { + $this.changePage(); + }); -function init() { - $(window).on('hashchange', function () { - changePage(); - }); - $(window).on('resize', function () { - resize(); - }); - $(window).on('beforeunload', function () { - if (unsavedChanges) { - return TRANSLATIONS.warning_unsaved_changes; - } - }) - // Disable scroll by spacebar - $(window).on('keydown', function (e) { - if (e.keyCode == 32) { - $("#linkeditor-main").addClass('grab'); - return false; - } - moveRuler(); - }); - $(window).on('keyup', function (e) { - if (e.keyCode == 32) { - resetZoomDrag(); - } - moveRuler(); - }); - - $("#linkeditor-canvas").on('scroll', function () { - updateRulers(); - }); - - $(document).on('mousedown', '.link', function (e) { - e.preventDefault(); - e.stopPropagation(); - if (!$(this).hasClass('selected')) { - if (!e.ctrlKey) { - deselectAllLinks(); + // Disable scroll by spacebar + $(window).on('keydown', function (e) { + if (e.keyCode == 32) { + $("#linkeditor-main").addClass('grab'); + return false; } - selectLink($(this)); - } - startDragLink(); - - return false; - }); - - $(document).on('mousedown', "#linkeditor-main", function (e) { - if ($(this).hasClass('grab') && zoom > 1) { - zoomdragging = { - x: e.pageX, - y: e.pageY, - scrollX: $("#linkeditor-canvas").scrollLeft(), - scrollY: $("#linkeditor-canvas").scrollTop() - }; - $(this).addClass('grabbing'); - } else { - resetZoomDrag(); - } - deselectAllLinks(); - }); - - - $("#linkeditor-ruler-x").on('mousedown', function (e) { - addRuler('y'); - }); + $this.rulers.moveRuler(); + }); + $(window).on('keyup', function (e) { + if (e.keyCode == 32) { + $this.zoom.resetZoomDrag(); + } + $this.rulers.moveRuler(); + }); - $("#linkeditor-ruler-y").on('mousedown', function (e) { - addRuler('x'); - }); + $(document).on('mousedown', "#linkeditor-main", function (e) { + if ($(this).hasClass('grab') && $this.zoom.zoom > 1) { + $this.zoomdragging = { + x: e.pageX, + y: e.pageY, + scrollX: $("#linkeditor-canvas").scrollLeft(), + scrollY: $("#linkeditor-canvas").scrollTop() + }; + $(this).addClass('grabbing'); + } else { + $this.zoom.resetZoomDrag(); + } + $this.links.deselectAllLinks(); + }); - $(document).on('mousedown', ".ruler", function (e) { - movingRuler = $(this); + $(window).on('mousemove', function (e) { + $this.updateMousePosition(e); + }); - }); + $(window).on('mouseup', function (e) { + $this.zoom.mouseUp(); + $this.rulers.mouseUp(); + $this.links.mouseUp(); + }); - $(window).on('mousemove', function (e) { - if (!$("#linkeditor-main").hasClass('grab') || zoom === 1) { - resetZoomDrag(); - } - if (zoomdragging !== false) { - moveZoomDrag(e); - } - updateMousePosition(e); - moveDragLink(); - }); - $(window).on('mouseup', function (e) { - if (zoomdragging !== false) { - moveZoomDrag(e); - } - stopDragLink(); - stopMoveRuler(); - resetZoomDrag(); - }); - $("#linkeditor-main").on('wheel', function (e) { - var delta = e.originalEvent.deltaY; - if (delta == 0) { - return true; - } - e.stopPropagation(); - e.stopImmediatePropagation(); - e.preventDefault(); - if (delta < 0) { - if (setZoom(zoom + 0.25)) { - moveZoom(e); - } + if (this.single) { + $("#linkeditor").addClass('single'); } else { - setZoom(zoom - 0.25); + $("#linkeditor").addClass('double'); } - return false; - }); - - if (single) { - $("#linkeditor").addClass('single'); - } else { - $("#linkeditor").addClass('double'); - } - $('.linkeditor-page').css({ - width: pw, height: ph - }); - $("#linkeditor-page-right").css({left: pw}) - $('#linkeditor-fluidbook').css({ - width: fw, height: ph - }); - - key('left', function () { - offsetSelectedLinks('left', -1); - }); - key('ctrl+left', function () { - offsetSelectedLinks('left', -10); - }); - key('right', function () { - offsetSelectedLinks('left', 1); - }); - key('ctrl+right', function () { - offsetSelectedLinks('left', 10); - }); - key('up', function () { - offsetSelectedLinks('top', -1); - }); - key('ctrl+up', function () { - offsetSelectedLinks('top', -10); - }); - key('down', function () { - offsetSelectedLinks('top', 1); - }); - key('ctrl+down', function () { - offsetSelectedLinks('top', 10); - }); - - - initToolbar(); - resize(); - changePage(); -} - -function startDragLink() { - dragLinkPos = {x: mx, y: my}; - $(".link.selected").each(function () { - $(this).data('drag-orig-left', parseFloat($(this).attr('fb-left'))); - $(this).data('drag-orig-top', parseFloat($(this).attr('fb-top'))); - }); -} - -function stopDragLink() { - moveDragLink(); - dragLinkPos = null; -} - -function moveDragLink() { - if (dragLinkPos === null) { - return; - } - var f = 1 / (fs * zoom); - var dx = (mx - dragLinkPos.x) * f; - var dy = (my - dragLinkPos.y) * f; - $(".link.selected").each(function () { - $(this).attr('fb-left', $(this).data('drag-orig-left') + dx).attr('fb-top', $(this).data('drag-orig-top') + dy).attr('fb-update', '1'); - }); - updateFBElements(false); -} - -function selectLink(l) { - if ($(l).find('.corners').length === 0) { - $(l).append('
') - } - $(l).addClass('selected'); - currentSelection.push(l); -} - - -function deselectAllLinks() { - currentSelection = []; - $(".link.selected").removeClass('selected'); -} - -function offsetSelectedLinks(dim, value) { - console.log(dim, value); - $('.link.selected').each(function () { - var v = parseFloat($(this).attr('fb-' + dim)); - $(this).attr('fb-' + dim, v + value).attr('fb-update', '1'); - }); - updateFBElements(); -} -function initToolbar() { - $("#linkeditor-page-field input").on('change', function () { - changePage($(this).val()); - $(this).blur(); - return false; - }); - - $("#linkeditor-toolbar [data-icon]").each(function () { - $(this).append(getSpriteIcon('linkeditor-' + $(this).data('icon'))); - }); - - $("[data-key]").each(function () { - var e = $(this); - key($(this).data('key'), function () { - $(e).addClass('hover'); - runAction($(e).data('action')); - setTimeout(function () { - $(e).removeClass('hover') - }, 150); - return false; + $('.linkeditor-page').css({ + width: this.pw, height: this.ph }); - }); - $('[data-action]').click(function () { - runAction($(this).data('action')); - return false; - }); - - $('[data-tooltip]').each(function () { - tippy($(this).get(0), {content: $(this).data('tooltip')}); - }); -} - -function runAction(act) { - eval(act + '()'); -} - -function saveLinks(message) { - if (message === undefined) { - message = TRANSLATIONS.manual_save_message; - } - $.ajax({ - url: '/fluidbook-publication/' + FLUIDBOOK_DATA.id + '/save/links', method: 'post', data: { - _method: 'put', 'message': message, rulers: window.RULERS, links: window.LINKS, - }, success: function (data) { - new Noty({ - type: "success", text: TRANSLATIONS.success_save, - }).show(); - clearTimeout(automaticSaveTimeout); - unsavedChanges = false; - runningAutomaticSaveTimeout = false; - }, error: function (jqXHR, status, error) { - hasChanged(); - new Noty({ - type: "error", text: TRANSLATIONS.error_save + ' : ' + error, - }).show(); - }, - }); -} - -function automaticSaveLinks() { - saveLinks(TRANSLATIONS.automatic_save_message); -} - -function firstPage() { - changePage(1); -} - -function nextPage() { - changePage(currentPage + (single ? 1 : 2)); -} - -function previousPage() { - changePage(currentPage - (single ? 1 : 2)); -} - -function lastPage() { - changePage(FLUIDBOOK_DATA.settings.pages); -} - -function focusPageField() { - var i = $("#linkeditor-page-field input").get(0); - i.focus(); - i.select(); -} - -function zoomReset() { - setZoom(1); - resetZoomDrag(); -} - -function generateUID() { - var length = 12; - var result = ''; - var characters = 'abcdefghijklmnopqrstuvwxyz0123456789'; - var charactersLength = characters.length; - for (var i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } - return result; -} - -function addRuler(axis, pos, uid) { - if (undefined === uid) { - uid = generateUID(); - RULERS[uid] = {page: currentPage, type: axis, uid: uid}; - hasChanged(); - } - var ruler = $('
'); - if (pos === undefined) { - movingRuler = ruler; - } else { - var dim = axis == 'x' ? 'left' : 'top'; - $(ruler).attr('fb-' + dim, pos); - } - $("#linkeditor-editor").append(ruler); - moveRuler(); -} - -function deleteRuler(ruler) { - if (ruler === undefined) { - ruler = movingRuler; - } - var uid = $(ruler).data('uid'); - delete RULERS[uid]; - $(ruler).remove(); - movingRuler = null; - hasChanged(); -} - -function hasChanged() { - unsavedChanges = true; - if (runningAutomaticSaveTimeout === false) { - runningAutomaticSaveTimeout = true; - automaticSaveTimeout = setTimeout(function () { - automaticSaveLinks(); - }, 1000 * 5 * 60); - } -} - -function moveRuler() { - if (movingRuler === null || movingRuler === undefined) { - return; - } - var magnet = !key.ctrl; - var editorMouse = globalToEditor(mx, my); - var fbMouse = globalToFluidbook(mx, my, false); - var css = {}; - var attrs = {'fb-update': '1'}; - var v, fbv; - if ($(movingRuler).data('axis') === 'x') { - v = editorMouse.x; - fbv = attrs['fb-left'] = magnet ? magnetize(fbMouse.x, rulersMagnetValuesX) : fbMouse.x; - } else { - v = editorMouse.y; - fbv = attrs['fb-top'] = magnet ? magnetize(fbMouse.y, rulersMagnetValuesY) : fbMouse.y; - } - if (v < 16) { - $(movingRuler).addClass('pending-delete'); - } else { - $(movingRuler).removeClass('pending-delete'); - } - $(movingRuler).css(css).attr(attrs); - RULERS[$(movingRuler).data('uid')].pos = fbv; - updateFBElements(); -} + $("#linkeditor-page-right").css({left: this.pw}) + $('#linkeditor-fluidbook').css({ + width: this.fw, height: this.ph + }); -function magnetize(value, values) { - var sensibility = 8 / (zoom * fs); - var min = 100000; - var magnetValue; - if (values.length === 0) { - return value; - } - - for (var i in values) { - var v = values[i]; - var diff = Math.abs(v - value); - if (diff < min) { - min = diff; - magnetValue = v; + this.resize.resize(); + this.changePage(); + }, + + runAction: function (act) { + var a = act.split('.'); + var o = this; + let po = this; + for (let i in a) { + po = o; + o = o[a[i]]; } - } - - if (min > sensibility) { - return value; - } - return magnetValue; -} + return o.call(po); + }, + + firstPage: function () { + this.changePage(1); + }, + + nextPage: function () { + this.changePage(this.currentPage + (this.single ? 1 : 2)); + }, + + previousPage: function () { + this.changePage(this.currentPage - (this.single ? 1 : 2)); + }, + + lastPage: function () { + this.changePage(FLUIDBOOK_DATA.settings.pages); + }, + + focusPageField: function () { + let i = $("#linkeditor-page-field input").get(0); + i.focus(); + i.select(); + }, + + hasChanged: function () { + this.save.hasChanged(); + }, + + updateFBElements: function (force) { + let $this = this; + requestAnimationFrame(function () { + $this._updateFBElements(force); + }); + }, -function getLinksOfPage(p) { - let pages = []; - if (!single) { - if (p % 2 === 1) { - p--; - } - pages.push(p); - pages.push(p + 1); - } else { - pages.push(p); - } - let res = {}; - $.each(LINKS, function (uid, link) { - if (pages.indexOf(parseInt(link.page)) >= 0) { - res[uid] = link; + _updateFBElements: function (force) { + let $this = this; + let selector = '[fb-ref]'; + if (force !== true) { + selector += '[fb-update="1"]'; } - }); - return res; -} -function updateFBElements(force) { - var selector = '[fb-ref]'; - if (force !== true) { - selector += '[fb-update="1"]'; - } - - $(selector).each(function () { - var e = $(this); - var rect = $(this).attr('fb-ref'); - var css = {}; - $.each(dimensionProperties, function (k, dim) { - if ($(e).is('[fb-' + dim + ']')) { - var v = parseFloat($(e).attr('fb-' + dim)); - if (dim === 'width' || dim === 'height') { - css[dim] = v * (fs * zoom); - } else { - css[dim] = fluidbookTo(v, dim, rect); + $(selector).each(function () { + let e = $(this); + let rect = $(this).attr('fb-ref'); + let css = {}; + $.each($this.dimensionProperties, function (k, dim) { + if ($(e).is('[fb-' + dim + ']')) { + let v = parseFloat($(e).attr('fb-' + dim)); + if (dim === 'width' || dim === 'height') { + css[dim] = v * ($this.fs * $this.zoom.zoom); + } else { + css[dim] = $this.fluidbookTo(v, dim, rect); + } } - } + }); + $(e).css(css).attr('fb-update', '0'); }); - $(e).css(css).attr('fb-update', '0'); - }); -} - -function fluidbookTo(dim, name, rect) { - switch (rect) { - case 'editor': - rect = editorRect; - break; - case 'canvas': - rect = canvasRect; - break; - } - return fluidbookToGlobal(dim, name) - rect[name]; -} - -function stopMoveRuler() { - moveRuler(); - if ($(movingRuler).hasClass('pending-delete')) { - deleteRuler($(movingRuler)); - } - movingRuler = null; -} - -function updateMousePosition(e) { - mx = e.pageX; - my = e.pageY; - updateMousePositionRulers(); - moveRuler(); -} - -function updateMousePositionRulers() { - var rulersRect = $("#linkeditor-rulers").get(0).getBoundingClientRect(); - var rx = mx - rulersRect.x; - var ry = my - rulersRect.y; - $("#linkeditor-ruler-x .info").css('left', rx); - $("#linkeditor-ruler-y .info").css('top', ry); - - var rrect = $("#linkeditor-rulers").get(0).getBoundingClientRect(); - - if (mx - rrect.x < 0 || my - rrect.y < 0 || mx - rrect.x > rrect.width || my - rrect.y > rrect.height) { - $("#linkeditor-rulers .info").hide(); - return; - } - - var fb = globalToFluidbook(mx, my, true); - $("#linkeditor-ruler-y .info span").text(fb.y.toFixed(2)); - $("#linkeditor-ruler-x .info span").text(fb.x.toFixed(2)); - $("#linkeditor-rulers .info").css('display', 'inline-block'); -} - -function resetZoomDrag() { - $("#linkeditor-main").removeClass('grab').removeClass('grabbing'); - if (zoom === 1) { - $("#linkeditor-canvas").scrollTo({left: 0, top: 0}); - } - zoomdragging = false; -} - -function moveZoomDrag(e) { - var deltaX = e.pageX - zoomdragging.x; - var deltaY = e.pageY - zoomdragging.y; - $("#linkeditor-canvas").scrollTo({ - top: zoomdragging.scrollY - deltaY, left: zoomdragging.scrollX - deltaX - }); - updateRulers(); -} - -function moveZoom(e) { - var rect = $("#linkeditor-zoom").get(0).getBoundingClientRect(); - var lx = (e.originalEvent.pageX - rect.x) / rect.width; - var ly = (e.originalEvent.pageY - rect.y) / rect.height; - $("#linkeditor-canvas").scrollTo({left: pct(lx), top: pct(ly)}); - updateRulers(); -} - -function pct(v) { - return (v * 100) + '%'; -} - -function setZoom(z) { - z = Math.max(1, Math.min(6, z)); - if (z === zoom) { - return false; - } - zoom = z; - $("#linkeditor-canvas").attr('data-z', zoom); - $("#linkeditor-zoom").css({transform: 'scale(' + zoom + ')', overflow: 'visible'}); - - setTimeout(function () { - $("#linkeditor-zoom").css({overflow: 'hidden'}); - if (zoom === 1) { - resetZoomDrag(); + }, + + fluidbookTo: function (dim, name, rect) { + switch (rect) { + case 'editor': + rect = this.editorRect; + break; + case 'canvas': + rect = this.canvasRect; + break; } - updateRulers(); - - }, 10); - - return true; -} - -function changePage(page) { - if (page === undefined) { - var h = window.location.hash; - if (h.length === 0) { - page = 0; - } else { - page = window.location.hash.substring(1); + return this.fluidbookToGlobal(dim, name) - rect[name]; + }, + + + updateMousePosition: function (e) { + this.mx = e.pageX; + this.my = e.pageY; + + this.rulers.updateMousePositionRulers(); + this.rulers.moveRuler(); + this.links.moveDragLink(); + this.links.moveResizeLink(); + this.zoom.updateMousePosition(); + }, + + changePage: function (page) { + if (page === undefined) { + let h = window.location.hash; + if (h.length === 0) { + page = 0; + } else { + page = window.location.hash.substring(1); + } } - } - page = parseInt(page); - if (page % 2 === 1 && !single) { - page--; - } - var normPage = Math.max(0, Math.min(page, FLUIDBOOK_DATA.settings.pages)); - if (normPage === currentPage) { - return; - } - currentPage = normPage; - - window.location.hash = '#' + currentPage; - clearLinksAndRulers(); - loadPage(currentPage, 'left'); - if (!single) { - loadPage(currentPage + 1, 'right'); - } - $("#linkeditor-page-field input").val(currentPage); - updateRulersMagnetValues(); - resize(); - preloadPages(); -} - -function updateRulersMagnetValues() { - rulersMagnetValuesX = [0, pw, pw * 2]; - rulersMagnetValuesY = [0, ph]; - $.each(getLinksOfPage(currentPage), function (uid, link) { - const left = parseFloat(link.left); - const top = parseFloat(link.top); - const width = parseFloat(link.width); - const height = parseFloat(link.height); - rulersMagnetValuesX.push(left, left + width); - rulersMagnetValuesY.push(top, top + height); - }); -} - -// Convert global coordinates to fluidbook ones -function globalToFluidbook(x, y, onePage) { - var res = _globalTo(x, y, fluidbookRect, 1 / (fs * zoom)); - if (onePage) { - res.xside = 'left'; - if (!single && res.x >= pw) { - res.xside = 'right'; - res.x -= pw; + let normPage = this.utils.normalizePage(page); + if (normPage === this.currentPage) { + return; } - } - return res; -} - -function fluidbookToGlobal(dim, name) { - return fluidbookRect[name] + (dim * fs * zoom); -} - -function globalToCanvas(x, y) { - return _globalTo(x, y, canvasRect, 1); -} - -function globalToEditor(x, y) { - return _globalTo(x, y, editorRect, 1); -} - -function _globalTo(x, y, rect, multi) { - return {x: multi * (x - rect.x), y: multi * (y - rect.y)}; -} - -function loadPage(p, side) { - var container = $("#linkeditor-page-" + side); - $(container).attr('data-page', p); - - if (p === 0 || p > FLUIDBOOK_DATA.settings.pages) { - $(container).html(''); - } else { - _loadPage(p, container); - } - - loadLinks(p, side); - loadRulers(p, side); -} + this.currentPage = normPage; -function preloadPages() { - let j = 1; - for (let i = Math.max(1, currentPage - 4); i <= Math.min(currentPage + 16, FLUIDBOOK_DATA.settings.pages); i++) { - if ($('.preload[data-page="' + i + '"]').length >= 1) { - continue; + window.location.hash = '#' + this.currentPage; + this.clearLinksAndRulers(); + this.loader.loadPage(this.currentPage, 'left'); + if (!this.loader.single) { + this.loader.loadPage(this.currentPage + 1, 'right'); } - setTimeout(function () { - var c = $('
'); - $("#linkeditor-preload").append(c); - _loadPage(i, c); - }, j * 500); - j++; - } -} + $("#linkeditor-page-field input").val(this.currentPage); + this.rulers.updateRulersMagnetValues(); + this.resize.resize(); + this.loader.preloadPages(); + }, -function _loadPage(p, container) { - var imageFormat = FLUIDBOOK_DATA.settings.imageFormat; - var c = '
'; - if (rasterizePages.indexOf(p) >= 0) { - c += ''; - } else if (vectorPages.indexOf(p) >= 0) { - c += ''; - } else { - c += ''; - c += ''; - } - c += '
'; - $(container).html(c); -} -function loadLinks(page, side) { - $.each(LINKS, function (uid, link) { - if (link.page != page) { - return; - } - if (side === 'right') { - link.left = parseInt(link.left) + pw; +// Convert global coordinates to fluidbook ones + globalToFluidbook: function (x, y, onePage) { + let res = this._globalTo(x, y, this.fluidbookRect, 1 / (this.fs * this.zoom.zoom)); + if (onePage) { + res.xside = 'left'; + if (!this.single && res.x >= this.pw) { + res.xside = 'right'; + res.x -= this.pw; + } } - addLink(link, side); - }); -} + return res; + }, -function addLink(link) { - if (link.uid === undefined) { - link.uid = generateUID(); - LINKS[link.uid] = link; - updateRulersMagnetValues(); - hasChanged(); - } - - var attrs = {}; - $.each(link, function (k, v) { - if (dimensionProperties.indexOf(k) >= 0) { - attrs['fb-' + k] = v; - } else { - attrs['data-' + k] = v; - } - }); + fluidbookToGlobal: function (dim, name) { + return this.fluidbookRect[name] + (dim * this.fs * this.zoom.zoom); + }, - var e = $(''); - $(e).attr(attrs); - $("#linkeditor-links").append(e); -} + globalToCanvas: function (x, y) { + return this._globalTo(x, y, this.canvasRect, 1); + }, -function clearLinksAndRulers() { - $('#linkeditor-editor .ruler').remove(); -} + globalToEditor: function (x, y) { + return this._globalTo(x, y, this.editorRect, 1); + }, -function loadRulers(page, side) { - $.each(RULERS, function (uid, ruler) { - if (ruler.page != page) { - return; - } - addRuler(ruler.type, ruler.pos, ruler.uid); - }); -} + _globalTo: function (x, y, rect, multi) { + return {x: multi * (x - rect.x), y: multi * (y - rect.y)}; + }, - -function resize() { - resizeCanvas(); - updateRulers(); + clearLinksAndRulers: function () { + this.rulers.clear(); + this.links.clear(); + }, } -function updateRulers() { - // Update rects - fluidbookRect = $("#linkeditor-fluidbook").get(0).getBoundingClientRect(); - - $("#linkeditor-ruler-y,#linkeditor-ruler-x").html(''); - // Measure of visible fluidbook px at current zoom - - var factor = fs / zoom; - var visible_w = (canvasRect.width / fs) / zoom; - var visible_h = (canvasRect.height / fs) / zoom; - // Find the best divider to have around 10 main divisions - var divider = 0; - for (var i in dividers) { - divider = dividers[i]; - var v = visible_h / divider; - if (v <= 10) { - break; - } - } - - var divisionSize = divider * fs * zoom; - // Draw vertical ruler - var margin = 100; - var nbDivisions = Math.floor(visible_h / divider); - var y0 = 16 + fluidbookRect.y - canvasRect.y; - - var yruler = '
1234.12
'; - for (var y = -margin; y <= nbDivisions + (margin * 2) + 1; y++) { - // Draw subdivision - var v = divider * y; - var ystart = y0 + (y * divisionSize); - if (ystart + divisionSize < 0 || ystart > canvasRect.height) { - continue; - } - yruler += '
' + Math.abs(v) + '
'; - for (var i = 1; i <= 9; i++) { - yruler += '
'; - } - yruler += '
'; - } - $("#linkeditor-ruler-y").html(yruler); - - // Draw horizontal ruler - nbDivisions = Math.floor(visible_w / divider); - var x0 = 16 + fluidbookRect.x - canvasRect.x; - var xruler = '
'; - - for (var x = -margin; x <= nbDivisions + (margin * 2) + 1; x++) { - // Draw subdivision - var v = divider * x; - var xstart = x0 + (x * divisionSize); - if (xstart + divisionSize < 0 || xstart > canvasRect.width) { - continue; - } - xruler += '
' + Math.abs(v) + '
'; - for (var i = 1; i <= 9; i++) { - var cls = ''; - if (i === 5) { - cls += ' middle'; - } - xruler += '
'; - } - xruler += '
'; - } - // Draw right page horizontal ruler - if (!single) { - x0 = x0 + pw * fs * zoom; - for (var x = 0; x <= nbDivisions + margin + 1; x++) { - // Draw subdivision - var v = divider * x; - var xstart = x0 + (x * divisionSize); - if (xstart + divisionSize < 0 || xstart > canvasRect.width) { - continue; - } - xruler += '
' + Math.abs(v) + '
'; - for (var i = 1; i <= 9; i++) { - var cls = ''; - if (i === 5) { - cls += ' middle'; - } - xruler += '
'; - } - xruler += '
'; - } - } - $("#linkeditor-ruler-x").html(xruler); - updateFBElements(true); - updateMousePositionRulers(); -} +$(function () { + window.linkeditor = new LinkEditor(); +}); -function resizeCanvas() { - canvasRect = $("#linkeditor-canvas").get(0).getBoundingClientRect(); - editorRect = $("#linkeditor-editor").get(0).getBoundingClientRect(); - var aw = canvasRect.width - 30; - var ah = canvasRect.height - 30; - fs = Math.min(aw / fw, ah / fh); - var left = (canvasRect.width - fw * fs) / 2; - var top = (canvasRect.height - fh * fs) / 2; - $("#linkeditor-fluidbook").css({left: left, top: top, transform: 'scale(' + fs + ')'}); -} -function splitPages(str) { - str = str.toString(); - var res = []; - if (str == '') { - return res; - } - var pages = str.split(','); - for (var p in pages) { - res.push(parseInt(pages[p])); - } - return res; -} diff --git a/resources/linkeditor/js/linkeditor.links.js b/resources/linkeditor/js/linkeditor.links.js new file mode 100644 index 000000000..d8b2511da --- /dev/null +++ b/resources/linkeditor/js/linkeditor.links.js @@ -0,0 +1,263 @@ +var LinkeditorLinks = function (linkeditor) { + this.linkeditor = linkeditor; + + this.currentSelection = []; + this.dragLinkPos = null; + this.resizeLinkPos = null; + + this.init(); +} + +LinkeditorLinks.prototype = { + init: function () { + var $this = this; + $(document).on('mousedown', '.link .corners div', function (e) { + e.preventDefault(); + e.stopPropagation(); + $this.deselectAllLinks(); + let link = $(this).closest('.link'); + $this.selectLink(link); + $this.startResizeLink($(this).attr('class')); + }); + + $(document).on('mousedown', '.link', function (e) { + e.preventDefault(); + e.stopPropagation(); + if (!$(this).hasClass('selected')) { + if (!e.ctrlKey) { + $this.deselectAllLinks(); + } + $this.selectLink($(this)); + } + $this.startDragLink(); + return false; + }); + + key('left', function () { + $this.offsetSelectedLinks('left', -1); + }); + key('ctrl+left', function () { + $this.offsetSelectedLinks('left', -10); + }); + key('right', function () { + $this.offsetSelectedLinks('left', 1); + }); + key('ctrl+right', function () { + $this.offsetSelectedLinks('left', 10); + }); + key('up', function () { + $this.offsetSelectedLinks('top', -1); + }); + key('ctrl+up', function () { + $this.offsetSelectedLinks('top', -10); + }); + key('down', function () { + $this.offsetSelectedLinks('top', 1); + }); + key('ctrl+down', function () { + $this.offsetSelectedLinks('top', 10); + }); + }, + + mouseUp: function () { + this.stopDragLink(); + this.stopResizeLink(); + }, + + startResizeLink: function (corner) { + this.resizeLinkPos = {x: this.linkeditor.mx, y: this.linkeditor.my, corner: corner}; + $(".link.selected").each(function () { + $(this).data('drag-orig-left', parseFloat($(this).attr('fb-left'))); + $(this).data('drag-orig-top', parseFloat($(this).attr('fb-top'))); + $(this).data('drag-orig-width', parseFloat($(this).attr('fb-width'))); + $(this).data('drag-orig-height', parseFloat($(this).attr('fb-height'))); + }); + console.log(this.resizeLinkPos); + }, + + stopResizeLink: function () { + this.moveResizeLink(); + this.resizeLinkPos = null; + }, + + moveResizeLink: function () { + if (this.resizeLinkPos === null) { + return; + } + var f = 1 / (this.linkeditor.fs * this.linkeditor.zoom.zoom); + var dx = (this.linkeditor.mx - this.resizeLinkPos.x) * f; + var dy = (this.linkeditor.my - this.resizeLinkPos.y) * f; + + var top = 0, left = 0, width = 0, height = 0; + + if (['n', 'ne', 'nw'].indexOf(this.resizeLinkPos.corner) >= 0) { + top = dy; + height = -dy; + } else if (['s', 'se', 'sw'].indexOf(this.resizeLinkPos.corner) >= 0) { + height = dy; + } + if (['nw', 'w', 'sw'].indexOf(this.resizeLinkPos.corner) >= 0) { + left = dx; + width = -dx; + } else if (['ne', 'e', 'se'].indexOf(this.resizeLinkPos.corner) >= 0) { + width = dx; + } + + $(".link.selected").each(function () { + var newWidth = $(this).data('drag-orig-width') + width; + var newHeight = $(this).data('drag-orig-height') + height; + + if (key.ctrl) { + // Keep ratio + var ratio = $(this).data('drag-orig-width') / $(this).data('drag-orig-height'); + var xscale = newWidth / $(this).data('drag-orig-width'); + var yscale = newHeight / $(this).data('drag-orig-height'); + if (['ne', 'nw', 'se', 'sw'].indexOf(this.resizeLinkPos.corner) >= 0) { + if (xscale < yscale) { + newHeight = newWidth / ratio; + } else { + newWidth = newHeight * ratio; + } + } else if (['e', 'w'].indexOf(this.resizeLinkPos.corner) >= 0) { + newHeight = newWidth / ratio; + } else if (['n', 's'].indexOf(this.resizeLinkPos.corner) >= 0) { + newWidth = newHeight * ratio; + } + + width = newWidth - $(this).data('drag-orig-width'); + height = newHeight - $(this).data('drag-orig-height'); + + if (['ne', 'e', 'se'].indexOf(this.resizeLinkPos.corner) >= 0) { + left = 0; + } else if (['nw', 'w', 'sw'].indexOf(this.resizeLinkPos.corner) >= 0) { + left = width; + } + if (['ne', 'n', 'nw'].indexOf(this.resizeLinkPos.corner) >= 0) { + top = height; + } else if (['se', 's', 'sw'].indexOf(this.resizeLinkPos.corner) >= 0) { + top = 0; + } + } + + var newLeft = $(this).data('drag-orig-left') + left; + var newTop = $(this).data('drag-orig-top') + top; + + $(this).attr('fb-left', newLeft) + .attr('fb-top', newTop) + .attr('fb-width', newWidth) + .attr('fb-height', newHeight) + .attr('fb-update', '1'); + }); + this.linkeditor.updateFBElements(false); + }, + + startDragLink: function () { + this.dragLinkPos = {x: this.linkeditor.mx, y: this.linkeditor.my}; + $(".link.selected").each(function () { + $(this).data('drag-orig-left', parseFloat($(this).attr('fb-left'))); + $(this).data('drag-orig-top', parseFloat($(this).attr('fb-top'))); + }); + }, + + stopDragLink: function () { + this.moveDragLink(); + this.dragLinkPos = null; + }, + + moveDragLink: function () { + if (this.dragLinkPos === null) { + return; + } + var f = 1 / (this.linkeditor.fs * this.linkeditor.zoom.zoom); + var dx = (this.linkeditor.mx - this.dragLinkPos.x) * f; + var dy = (this.linkeditor.my - this.dragLinkPos.y) * f; + $(".link.selected").each(function () { + $(this).attr('fb-left', $(this).data('drag-orig-left') + dx).attr('fb-top', $(this).data('drag-orig-top') + dy).attr('fb-update', '1'); + }); + this.linkeditor.updateFBElements(false); + }, + + selectLink: function (l) { + if ($(l).find('.corners').length === 0) { + $(l).append('
') + } + $(l).addClass('selected'); + this.currentSelection.push(l); + }, + + + deselectAllLinks: function () { + this.currentSelection = []; + $(".link.selected").removeClass('selected'); + }, + + offsetSelectedLinks: function (dim, value) { + $('.link.selected').each(function () { + var v = parseFloat($(this).attr('fb-' + dim)); + $(this).attr('fb-' + dim, v + value).attr('fb-update', '1'); + }); + this.linkeditor.updateFBElements(); + }, + + getLinksOfPage: function (p) { + let pages = []; + if (!this.linkeditor.single) { + if (p % 2 === 1) { + p--; + } + pages.push(p); + pages.push(p + 1); + } else { + pages.push(p); + } + let res = {}; + $.each(LINKS, function (uid, link) { + if (pages.indexOf(parseInt(link.page)) >= 0) { + res[uid] = link; + } + }); + return res; + }, + + loadLinks: function (page, side) { + var $this = this; + $.each(LINKS, function (uid, link) { + if (link.page != page) { + return; + } + if (side === 'right') { + link.left = parseInt(link.left) + $this.linkeditor.pw; + } + $this.addLink(link, side); + }); + }, + + addLink: function (link) { + var $this = this; + if (link.uid === undefined) { + link.uid = generateUID(); + LINKS[link.uid] = link; + this.linkeditor.rulers.updateRulersMagnetValues(); + this.linkeditor.hasChanged(); + } + + var attrs = {}; + $.each(link, function (k, v) { + if ($this.linkeditor.dimensionProperties.indexOf(k) >= 0) { + attrs['fb-' + k] = v; + } else { + attrs['data-' + k] = v; + } + }); + + var e = $(''); + $(e).attr(attrs); + $("#linkeditor-links").append(e); + }, + + + clear: function () { + + }, +}; +module.exports = LinkeditorLinks; diff --git a/resources/linkeditor/js/linkeditor.loader.js b/resources/linkeditor/js/linkeditor.loader.js new file mode 100644 index 000000000..00624cd92 --- /dev/null +++ b/resources/linkeditor/js/linkeditor.loader.js @@ -0,0 +1,59 @@ +function LinkeditorLoader(linkeditor) { + this.linkeditor = linkeditor; + this.init(); +} + +LinkeditorLoader.prototype = { + + init: function () { + this.rasterizePages = this.linkeditor.utils.splitPages(FLUIDBOOK_DATA.settings.rasterizePages); + this.vectorPages = this.linkeditor.utils.splitPages(FLUIDBOOK_DATA.settings.vectorPages); + }, + + loadPage: function (p, side) { + var container = $("#linkeditor-page-" + side); + $(container).attr('data-page', p); + + if (p === 0 || p > FLUIDBOOK_DATA.settings.pages) { + $(container).html(''); + } else { + this._loadPage(p, container); + } + + this.linkeditor.links.loadLinks(p, side); + this.linkeditor.rulers.loadRulers(p, side); + }, + + + preloadPages: function () { + let j = 1; + var $this = this; + for (let i = Math.max(1, this.linkeditor.currentPage - 4); i <= Math.min(this.linkeditor.currentPage + 16, FLUIDBOOK_DATA.settings.pages); i++) { + if ($('.preload[data-page="' + i + '"]').length >= 1) { + continue; + } + setTimeout(function () { + var c = $('
'); + $("#linkeditor-preload").append(c); + $this._loadPage(i, c); + }, j * 500); + j++; + } + }, + + _loadPage: function (p, container) { + var imageFormat = FLUIDBOOK_DATA.settings.imageFormat; + var c = '
'; + if (this.rasterizePages.indexOf(p) >= 0) { + c += ''; + } else if (this.vectorPages.indexOf(p) >= 0) { + c += ''; + } else { + c += ''; + c += ''; + } + c += '
'; + $(container).html(c); + }, +} +module.exports = LinkeditorLoader; diff --git a/resources/linkeditor/js/linkeditor.resize.js b/resources/linkeditor/js/linkeditor.resize.js new file mode 100644 index 000000000..7f3aa4495 --- /dev/null +++ b/resources/linkeditor/js/linkeditor.resize.js @@ -0,0 +1,30 @@ +function LinkeditorResize(linkeditor) { + this.linkeditor = linkeditor; + this.init(); +} + +LinkeditorResize.prototype = { + init: function () { + var $this = this; + $(window).on('resize', function () { + $this.resize(); + }); + }, + + resize: function () { + this.resizeCanvas(); + this.linkeditor.rulers.updateRulers(); + }, + + resizeCanvas: function () { + this.linkeditor.canvasRect = $("#linkeditor-canvas").get(0).getBoundingClientRect(); + this.linkeditor.editorRect = $("#linkeditor-editor").get(0).getBoundingClientRect(); + var aw = this.linkeditor.canvasRect.width - 30; + var ah = this.linkeditor.canvasRect.height - 30; + this.linkeditor.fs = Math.min(aw / this.linkeditor.fw, ah / this.linkeditor.fh); + var left = (this.linkeditor.canvasRect.width - this.linkeditor.fw * this.linkeditor.fs) / 2; + var top = (this.linkeditor.canvasRect.height - this.linkeditor.fh * this.linkeditor.fs) / 2; + $("#linkeditor-fluidbook").css({left: left, top: top, transform: 'scale(' + this.linkeditor.fs + ')'}); + }, +}; +module.exports = LinkeditorResize; diff --git a/resources/linkeditor/js/linkeditor.rulers.js b/resources/linkeditor/js/linkeditor.rulers.js new file mode 100644 index 000000000..014d16c13 --- /dev/null +++ b/resources/linkeditor/js/linkeditor.rulers.js @@ -0,0 +1,230 @@ +function LinkeditorRulers(linkeditor) { + this.linkeditor = linkeditor; + + this.movingRuler = null; + this.rulersMagnetValuesX = []; + this.rulersMagnetValuesY = []; + this.dividers = [1, 2, 5, 10, 20, 50, 100, 200]; + + this.init(); +} + +LinkeditorRulers.prototype = { + init: function () { + let $this = this; + $("#linkeditor-canvas").on('scroll', function () { + $this.updateRulers(); + }); + + $("#linkeditor-ruler-x").on('mousedown', function (e) { + $this.addRuler('y'); + }); + + $("#linkeditor-ruler-y").on('mousedown', function (e) { + $this.addRuler('x'); + }); + + $(document).on('mousedown', ".ruler", function (e) { + $this.movingRuler = $(this); + }); + }, + + mouseUp: function () { + this.stopMoveRuler(); + }, + + loadRulers: function (page, side) { + let $this = this; + $.each(RULERS, function (uid, ruler) { + if (ruler.page != page) { + return; + } + $this.addRuler(ruler.type, ruler.pos, ruler.uid); + }); + }, + + + updateRulers: function () { + // Update rects + this.linkeditor.fluidbookRect = $("#linkeditor-fluidbook").get(0).getBoundingClientRect(); + + $("#linkeditor-ruler-y,#linkeditor-ruler-x").html(''); + // Measure of visible fluidbook px at current zoom + + let factor = this.linkeditor.fs / this.linkeditor.zoom.zoom; + let visible_w = (this.linkeditor.canvasRect.width / this.linkeditor.fs) / this.linkeditor.zoom.zoom; + let visible_h = (this.linkeditor.canvasRect.height / this.linkeditor.fs) / this.linkeditor.zoom.zoom; + + // Find the best divider to have around 10 main divisions + let divider = 0; + for (let d in this.dividers) { + divider = this.dividers[d]; + let v = visible_h / divider; + if (v <= 10) { + break; + } + } + + let divisionSize = divider * this.linkeditor.fs * this.linkeditor.zoom.zoom; + // Draw vertical ruler + let margin = 100; + let nbDivisions = Math.floor(visible_h / divider); + let y0 = 16 + this.linkeditor.fluidbookRect.y - this.linkeditor.canvasRect.y; + + let yruler = '
1234.12
'; + for (let y = -margin; y <= nbDivisions + (margin * 2) + 1; y++) { + // Draw subdivision + let v = divider * y; + let ystart = y0 + (y * divisionSize); + if (ystart + divisionSize < 0 || ystart > this.linkeditor.canvasRect.height) { + continue; + } + yruler += '
' + Math.abs(v) + '
'; + for (let j = 1; j <= 9; j++) { + yruler += '
'; + } + yruler += '
'; + } + $("#linkeditor-ruler-y").html(yruler); + + // Draw horizontal ruler + nbDivisions = Math.floor(visible_w / divider); + let x0 = 16 + this.linkeditor.fluidbookRect.x - this.linkeditor.canvasRect.x; + let xruler = '
'; + + for (let x = -margin; x <= nbDivisions + (margin * 2) + 1; x++) { + // Draw subdivision + xruler += this._drawHorizontalSubdiv(x, x0, divider, divisionSize); + } + // Draw right page horizontal ruler + if (!this.linkeditor.single) { + x0 = x0 + this.linkeditor.pw * this.linkeditor.fs * this.linkeditor.zoom.zoom; + for (let x = 0; x <= nbDivisions + margin + 1; x++) { + // Draw subdivision + xruler += this._drawHorizontalSubdiv(x, x0, divider, divisionSize); + } + } + $("#linkeditor-ruler-x").html(xruler); + this.linkeditor.updateFBElements(true); + this.updateMousePositionRulers(); + }, + + _drawHorizontalSubdiv: function (x, x0, divider, divisionSize) { + let v = divider * x; + let xstart = x0 + (x * divisionSize); + if (xstart + divisionSize < 0 || xstart > this.linkeditor.canvasRect.width) { + return ''; + } + let res = '
' + Math.abs(v) + '
'; + for (let i = 1; i <= 9; i++) { + let cls = ''; + if (i === 5) { + cls += ' middle'; + } + res += '
'; + } + res += '
'; + return res; + }, + + updateRulersMagnetValues: function () { + var $this = this; + this.rulersMagnetValuesX = [0, this.linkeditor.pw, this.linkeditor.pw * 2]; + this.rulersMagnetValuesY = [0, this.linkeditor.ph]; + $.each(this.linkeditor.links.getLinksOfPage(this.linkeditor.currentPage), function (uid, link) { + const left = parseFloat(link.left); + const top = parseFloat(link.top); + const width = parseFloat(link.width); + const height = parseFloat(link.height); + $this.rulersMagnetValuesX.push(left, left + width); + $this.rulersMagnetValuesY.push(top, top + height); + }); + }, + + updateMousePositionRulers: function () { + let rulersRect = $("#linkeditor-rulers").get(0).getBoundingClientRect(); + let rx = this.linkeditor.mx - rulersRect.x; + let ry = this.linkeditor.my - rulersRect.y; + $("#linkeditor-ruler-x .info").css('left', rx); + $("#linkeditor-ruler-y .info").css('top', ry); + + let rrect = $("#linkeditor-rulers").get(0).getBoundingClientRect(); + + if (this.linkeditor.mx - rrect.x < 0 || this.linkeditor.my - rrect.y < 0 || this.linkeditor.mx - rrect.x > rrect.width || this.linkeditor.my - rrect.y > rrect.height) { + $("#linkeditor-rulers .info").hide(); + return; + } + + let fb = this.linkeditor.globalToFluidbook(this.linkeditor.mx, this.linkeditor.my, true); + $("#linkeditor-ruler-y .info span").text(fb.y.toFixed(2)); + $("#linkeditor-ruler-x .info span").text(fb.x.toFixed(2)); + $("#linkeditor-rulers .info").css('display', 'inline-block'); + }, + + stopMoveRuler: function () { + this.moveRuler(); + if ($(this.movingRuler).hasClass('pending-delete')) { + this.deleteRuler($(this.movingRuler)); + } + this.movingRuler = null; + }, + + moveRuler: function () { + if (this.movingRuler === null || this.movingRuler === undefined) { + return; + } + let magnet = !key.ctrl; + let editorMouse = this.linkeditor.globalToEditor(this.linkeditor.mx, this.linkeditor.my); + let fbMouse = this.linkeditor.globalToFluidbook(this.linkeditor.mx, this.linkeditor.my, false); + let css = {}; + let attrs = {'fb-update': '1'}; + let v, fbv; + if ($(this.movingRuler).data('axis') === 'x') { + v = editorMouse.x; + fbv = attrs['fb-left'] = magnet ? this.linkeditor.utils.magnetize(fbMouse.x, this.rulersMagnetValuesX) : fbMouse.x; + } else { + v = editorMouse.y; + fbv = attrs['fb-top'] = magnet ? this.linkeditor.utils.magnetize(fbMouse.y, this.rulersMagnetValuesY) : fbMouse.y; + } + if (v < 16) { + $(this.movingRuler).addClass('pending-delete'); + } else { + $(this.movingRuler).removeClass('pending-delete'); + } + $(this.movingRuler).css(css).attr(attrs); + RULERS[$(this.movingRuler).data('uid')].pos = fbv; + this.linkeditor.updateFBElements(); + }, + + addRuler: function (axis, pos, uid) { + if (undefined === uid) { + uid = this.linkeditor.utils.generateUID(); + RULERS[uid] = {page: this.linkeditor.currentPage, type: axis, uid: uid}; + this.linkeditor.hasChanged(); + } + let ruler = $('
'); + if (pos === undefined) { + this.movingRuler = ruler; + } else { + let dim = axis == 'x' ? 'left' : 'top'; + $(ruler).attr('fb-' + dim, pos); + } + $("#linkeditor-editor").append(ruler); + this.moveRuler(); + }, + + deleteRuler: function (ruler) { + if (ruler === undefined) { + ruler = this.movingRuler; + } + delete RULERS[$(ruler).data('uid')]; + $(ruler).remove(); + this.movingRuler = null; + this.linkeditor.hasChanged(); + }, + + clear: function () { + $('#linkeditor-editor .ruler').remove(); + }, +}; +module.exports = LinkeditorRulers; diff --git a/resources/linkeditor/js/linkeditor.save.js b/resources/linkeditor/js/linkeditor.save.js new file mode 100644 index 000000000..6ef30f9cd --- /dev/null +++ b/resources/linkeditor/js/linkeditor.save.js @@ -0,0 +1,65 @@ + +function LinkeditorSave(linkeditor) { + this.linkeditor = linkeditor; + this.init(); +} + +LinkeditorSave.prototype = { + init: function () { + let $this = this; + + this.automaticSaveFrequency = 1000 * 5 * 60; + this.unsavedChanges = false; + this.automaticSaveTimeout = null; + this.runningAutomaticSaveTimeout = false; + + $(window).on('beforeunload', function () { + if ($this.unsavedChanges) { + return TRANSLATIONS.warning_unsaved_changes; + } + }) + }, + + hasChanged: function () { + let $this = this; + this.unsavedChanges = true; + if (this.runningAutomaticSaveTimeout === false) { + this.runningAutomaticSaveTimeout = true; + this.automaticSaveTimeout = setTimeout(function () { + $this.automaticSave(); + }, this.automaticSaveFrequency); + } + }, + + save: function (message) { + var $this = this; + if (message === undefined) { + message = TRANSLATIONS.manual_save_message; + } + $.ajax({ + url: '/fluidbook-publication/' + FLUIDBOOK_DATA.id + '/save/links', method: 'post', data: { + _method: 'put', 'message': message, rulers: window.RULERS, links: window.LINKS, + }, + success: function (data) { + new Noty({ + type: "success", text: TRANSLATIONS.success_save, + }).show(); + clearTimeout(automaticSaveTimeout); + $this.unsavedChanges = false; + $this.runningAutomaticSaveTimeout = false; + }, + error: function (jqXHR, status, error) { + $this.linkeditor.hasChanged(); + new Noty({ + type: "error", text: TRANSLATIONS.error_save + ' : ' + error, + }).show(); + }, + }); + }, + + automaticSave: function () { + this.save(TRANSLATIONS.automatic_save_message); + }, +}; + +module.exports = LinkeditorSave; diff --git a/resources/linkeditor/js/linkeditor.toolbar.js b/resources/linkeditor/js/linkeditor.toolbar.js new file mode 100644 index 000000000..4c4e705f6 --- /dev/null +++ b/resources/linkeditor/js/linkeditor.toolbar.js @@ -0,0 +1,41 @@ +function LinkeditorToolbar(linkeditor) { + this.linkeditor = linkeditor; + this.init(); +} + +LinkeditorToolbar.prototype = { + init: function () { + var $this=this; + $("#linkeditor-page-field input").on('change', function () { + $this.linkeditor.changePage($(this).val()); + $(this).blur(); + return false; + }); + + $("#linkeditor-toolbar [data-icon]").each(function () { + $(this).append(getSpriteIcon('linkeditor-' + $(this).data('icon'))); + }); + + $("[data-key]").each(function () { + let e = $(this); + key($(this).data('key'), function () { + $(e).addClass('hover'); + $this.linkeditor.runAction($(e).data('action')); + setTimeout(function () { + $(e).removeClass('hover') + }, 150); + return false; + }); + }); + + $('[data-action]').click(function () { + $this.linkeditor.runAction($(this).data('action')); + return false; + }); + + $('[data-tooltip]').each(function () { + tippy($(this).get(0), {content: $(this).data('tooltip')}); + }); + }, +}; +module.exports = LinkeditorToolbar; diff --git a/resources/linkeditor/js/linkeditor.utils.js b/resources/linkeditor/js/linkeditor.utils.js new file mode 100644 index 000000000..f5122f7e2 --- /dev/null +++ b/resources/linkeditor/js/linkeditor.utils.js @@ -0,0 +1,71 @@ +var LinkeditorUtils = function (linkeditor) { + this.linkeditor = linkeditor; + this.init(); +}; + +LinkeditorUtils.prototype = { + init: function () { + + }, + + normalizePage: function (page) { + page = parseInt(page); + if (page % 2 === 1 && !this.linkeditor.single) { + page--; + } + return Math.max(0, Math.min(page, FLUIDBOOK_DATA.settings.pages)); + }, + + splitPages: function (str) { + str = str.toString(); + let res = []; + if (str == '') { + return res; + } + let pages = str.split(','); + for (let p in pages) { + res.push(parseInt(pages[p])); + } + return res; + }, + + pct: function (v) { + return (v * 100) + '%'; + }, + + generateUID: function () { + const length = 12; + let result = ''; + const characters = 'abcdefghijklmnopqrstuvwxyz0123456789'; + const charactersLength = characters.length; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; + }, + + magnetize: function (value, values) { + let sensibility = 8 / (this.linkeditor.zoom.zoom * this.linkeditor.fs); + let min = 100000; + let magnetValue; + if (values.length === 0) { + return value; + } + + for (let i in values) { + let v = values[i]; + let diff = Math.abs(v - value); + if (diff < min) { + min = diff; + magnetValue = v; + } + } + + if (min > sensibility) { + return value; + } + return magnetValue; + }, +}; + +module.exports = LinkeditorUtils; diff --git a/resources/linkeditor/js/linkeditor.zoom.js b/resources/linkeditor/js/linkeditor.zoom.js new file mode 100644 index 000000000..8ae298d94 --- /dev/null +++ b/resources/linkeditor/js/linkeditor.zoom.js @@ -0,0 +1,99 @@ +function LinkeditorZoom(linkeditor) { + this.linkeditor = linkeditor; + this.init(); +} + +LinkeditorZoom.prototype = { + init: function () { + var $this = this; + + this.zoom = 1; + this.zoomdragging = false; + + $("#linkeditor-main").on('wheel', function (e) { + let delta = e.originalEvent.deltaY; + if (delta == 0) { + return true; + } + e.stopPropagation(); + e.stopImmediatePropagation(); + e.preventDefault(); + if (delta < 0) { + if ($this.setZoom($this.zoom + 0.25)) { + $this.moveZoom(e); + } + } else { + $this.setZoom($this.zoom - 0.25); + } + return false; + }); + }, + + mouseUp: function () { + if (this.zoomdragging !== false) { + this.moveZoomDrag(e); + } + this.resetZoomDrag(); + }, + + updateMousePosition: function () { + if (!$("#linkeditor-main").hasClass('grab') || this.zoom === 1) { + this.resetZoomDrag(); + } + if (this.zoomdragging !== false) { + this.moveZoomDrag(e); + } + }, + + resetZoomDrag: function () { + $("#linkeditor-main").removeClass('grab').removeClass('grabbing'); + if (this.zoom === 1) { + $("#linkeditor-canvas").scrollTo({left: 0, top: 0}); + } + this.zoomdragging = false; + }, + + moveZoomDrag: function (e) { + let deltaX = e.pageX - this.zoomdragging.x; + let deltaY = e.pageY - this.zoomdragging.y; + $("#linkeditor-canvas").scrollTo({ + top: this.zoomdragging.scrollY - deltaY, left: this.zoomdragging.scrollX - deltaX + }); + this.linkeditor.rulers.updateRulers(); + }, + + moveZoom: function (e) { + let rect = $("#linkeditor-zoom").get(0).getBoundingClientRect(); + let lx = (e.originalEvent.pageX - rect.x) / rect.width; + let ly = (e.originalEvent.pageY - rect.y) / rect.height; + $("#linkeditor-canvas").scrollTo({left: this.linkeditor.utils.pct(lx), top: this.linkeditor.utils.pct(ly)}); + this.linkeditor.rulers.updateRulers(); + }, + + setZoom: function (z) { + let $this = this; + z = Math.max(1, Math.min(6, z)); + if (z === this.zoom) { + return false; + } + this.zoom = z; + $("#linkeditor-canvas").attr('data-z', this.zoom); + $("#linkeditor-zoom").css({transform: 'scale(' + this.zoom + ')', overflow: 'visible'}); + + setTimeout(function () { + $("#linkeditor-zoom").css({overflow: 'hidden'}); + if (this.zoom === 1) { + $this.resetZoomDrag(); + } + $this.linkeditor.rulers.updateRulers(); + + }, 10); + return true; + }, + + reset: function () { + setZoom(1); + resetZoomDrag(); + }, +}; +module.exports = LinkeditorZoom; diff --git a/resources/linkeditor/style/links.sass b/resources/linkeditor/style/links.sass index 7829cc61c..1ebef6f2c 100644 --- a/resources/linkeditor/style/links.sass +++ b/resources/linkeditor/style/links.sass @@ -7,6 +7,7 @@ cursor: cell &.selected + cursor: move .corners visibility: visible diff --git a/resources/views/fluidbook_publication/link_editor.blade.php b/resources/views/fluidbook_publication/link_editor.blade.php index 49f809b89..869b623d0 100644 --- a/resources/views/fluidbook_publication/link_editor.blade.php +++ b/resources/views/fluidbook_publication/link_editor.blade.php @@ -23,12 +23,12 @@