├── LICENSE ├── Quill Project 001 - Highlight ├── app.js ├── index.html ├── libs │ ├── highlight │ │ ├── highlight.pack.js │ │ └── styles │ │ │ └── atelier-cave-dark.css │ └── quill │ │ ├── quill.bubble.css │ │ ├── quill.core.css │ │ ├── quill.core.js │ │ ├── quill.js │ │ ├── quill.min.js │ │ ├── quill.min.js.map │ │ └── quill.snow.css └── styles.css ├── Quill Project 002 - Centralized Video ├── app.js ├── index.html ├── libs │ ├── highlight │ │ ├── highlight.pack.js │ │ └── styles │ │ │ └── atelier-cave-dark.css │ └── quill │ │ ├── quill.bubble.css │ │ ├── quill.core.css │ │ ├── quill.core.js │ │ ├── quill.js │ │ ├── quill.min.js │ │ ├── quill.min.js.map │ │ └── quill.snow.css └── styles.css ├── Quill Project 003 - Carousel ├── app.js ├── index.html ├── libs │ ├── highlight │ │ ├── highlight.pack.js │ │ └── styles │ │ │ └── atelier-cave-dark.css │ ├── jquery │ │ └── jquery-3.4.1.min.js │ ├── quill │ │ ├── quill.bubble.css │ │ ├── quill.core.css │ │ ├── quill.core.js │ │ ├── quill.js │ │ ├── quill.min.js │ │ ├── quill.min.js.map │ │ └── quill.snow.css │ └── slick │ │ ├── ajax-loader.gif │ │ ├── config.rb │ │ ├── fonts │ │ ├── slick.eot │ │ ├── slick.svg │ │ ├── slick.ttf │ │ └── slick.woff │ │ ├── slick-theme.css │ │ ├── slick-theme.less │ │ ├── slick-theme.scss │ │ ├── slick.css │ │ ├── slick.js │ │ ├── slick.less │ │ ├── slick.min.js │ │ └── slick.scss └── styles.css ├── Quill Project 004 - Customizable Tooltip ├── app.js ├── index.html ├── libs │ ├── highlight │ │ ├── highlight.pack.js │ │ └── styles │ │ │ └── atelier-cave-dark.css │ ├── jquery │ │ └── jquery-3.4.1.min.js │ └── quill │ │ ├── quill.bubble.css │ │ ├── quill.core.css │ │ ├── quill.core.js │ │ ├── quill.js │ │ ├── quill.min.js │ │ ├── quill.min.js.map │ │ └── quill.snow.css └── styles.css └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 loagit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Quill Project 001 - Highlight/app.js: -------------------------------------------------------------------------------- 1 | // ################################################################################# 2 | // TABS 3 | // ################################################################################# 4 | 5 | /** See: https://www.w3schools.com/howto/howto_js_tabs.asp */ 6 | function openTab(evt, tabName) { 7 | // Declare all variables 8 | var i, tabcontent, tabButtons; 9 | 10 | // Get all elements with class="tabcontent" and hide them 11 | tabcontent = document.getElementsByClassName("tab-content"); 12 | for (i = 0; i < tabcontent.length; i++) { 13 | tabcontent[i].style.display = "none"; 14 | } 15 | 16 | // Get all elements with class="tab-button" and remove the class "active" 17 | tabButtons = document.getElementsByClassName("tab-button"); 18 | for (i = 0; i < tabButtons.length; i++) { 19 | tabButtons[i].className = tabButtons[i].className.replace(" active", ""); 20 | } 21 | 22 | // Show the current tab, and add an "active" class to the button that opened the tab 23 | let openTabContent = document.getElementById(tabName); 24 | openTabContent.style.display = "block"; 25 | evt.currentTarget.className += " active"; 26 | 27 | updateOpenTab(openTabContent); 28 | } 29 | 30 | function updateOpenTab(tabContent) { 31 | if (!tabContent) { 32 | if (!(tabContent = getActiveTabContent())) return false; 33 | } 34 | 35 | // DELTA 36 | if (tabContent.id === 'tab-content-delta') { 37 | // Set delta length (#tab-content-delta > p) 38 | let p = tabContent.children[0]; 39 | p.innerHTML = 'Tamanho Delta: ' + quill.getLength(); 40 | p.style.padding = '4px 6px'; 41 | 42 | // Set data (#tab-content-delta > pre > code) 43 | let code = tabContent.children[1].children[0]; 44 | code.innerHTML = JSON.stringify(getContentDelta(), null, 2); 45 | 46 | hljs.highlightBlock(code); 47 | } 48 | // TEXT 49 | if (tabContent.id === 'tab-content-text') { 50 | // #tab-contnet-text > pre > code 51 | let code = tabContent.children[0].children[0]; 52 | code.innerHTML = getContentText(); 53 | 54 | hljs.highlightBlock(code); 55 | } 56 | // HTML 57 | if (tabContent.id === 'tab-content-html') { 58 | // #tab-content-html > pre > code 59 | let code = tabContent.children[0].children[0]; 60 | code.innerHTML = getContentHTML().replace(/ 5) { // Not bigger than 5. 176 | return false; 177 | } 178 | return true; 179 | } 180 | } 181 | 182 | TextHighlight.blotName = 'texthighlight'; 183 | TextHighlight.tagName = 'span'; 184 | 185 | Quill.register(TextHighlight); 186 | // Does the same as above. 187 | // Quill.register('formats/texthighlight' , TextHighlight); 188 | 189 | /** See: https://quilljs.com/docs/api/#getcontents */ 190 | function getContentDelta() { 191 | return quill.getContents(); 192 | } 193 | 194 | /** See: https://github.com/quilljs/quill/issues/2698 */ 195 | function getContentText() { 196 | return quill.getContents().ops.reduce((text, op) => { 197 | if (typeof op.insert === 'string') { 198 | return text + op.insert; 199 | } 200 | // If it is not a string, the newline character is set, which has 201 | // a length of only 1 character. 202 | else { 203 | return text + '\n'; 204 | } 205 | }, ''); 206 | } 207 | 208 | /** See: https://github.com/quilljs/quill/issues/903#issuecomment-243844178 */ 209 | function getContentHTML() { 210 | return quill.root.innerHTML; 211 | } 212 | 213 | // ################################################################################# 214 | // HIGHLIGHT 215 | // ################################################################################# 216 | 217 | function highlightSelectedText(hl) { 218 | // Is hl (highlight) a value between 0 and 5 (inclusive)? 219 | if (hl < 0 || hl > 5) return false; 220 | /* Filters which elements can be highlighted. There is a list that contains 221 | only the elements that can be highlighted. This check also allows highlights 222 | to be removed even when the selection contains elements that cannot be 223 | highlighted (hl> 0, because 0 clears any highlight).*/ 224 | // if (!isHighlightPermited() && hl > 0) return false; 225 | 226 | var range = quill.getSelection(); 227 | 228 | // Check selection... 229 | if (range && range.length > 0) { 230 | // Add 231 | if (hl > 0) { 232 | console.log('ADD - [hl: ' + hl + ', in: ' + range.index + ', le: ' + range.length + ']'); 233 | quill.format('texthighlight', hl); 234 | } 235 | // Remove 236 | else { 237 | console.log('REMOVE - [hl: ' + hl + ', in: ' + range.index + ', le: ' + range.length + ']'); 238 | quill.format('texthighlight', false); 239 | } 240 | } 241 | } 242 | 243 | /** This is not currently working. Try to select 2 paragraphs. */ 244 | function isHighlightPermited() { 245 | let el = getSelectionTextAndContainerElement().containerElement; 246 | let whitelist = ['P', 'LI', 'A']; 247 | 248 | if (whitelist.indexOf(el.tagName) != -1) { 249 | return true; 250 | } 251 | 252 | return false; 253 | } 254 | 255 | /** See: https://stackoverflow.com/a/4637223/2910546 */ 256 | function getSelectionTextAndContainerElement() { 257 | var text = "", containerElement = null; 258 | if (typeof window.getSelection != "undefined") { 259 | var sel = window.getSelection(); 260 | if (sel.rangeCount) { 261 | var node = sel.getRangeAt(0).commonAncestorContainer; 262 | containerElement = node.nodeType == 1 ? node : node.parentNode; 263 | text = sel.toString(); 264 | } 265 | } 266 | else if (typeof document.selection != "undefined" && 267 | document.selection.type != "Control") { 268 | var textRange = document.selection.createRange(); 269 | containerElement = textRange.parentElement(); 270 | text = textRange.text; 271 | } 272 | return { 273 | text: text, 274 | containerElement: containerElement 275 | }; 276 | } 277 | 278 | // ################################################################################# 279 | // MAIN 280 | // ################################################################################# 281 | 282 | $(document).ready(function () { 283 | 284 | /* The toolbar module is responsible for adding a listener to the events of 285 | it's controls (buttons and selects). This means that it is responsible for 286 | calling the appropriate handler (if present), as well as passing the value 287 | of the argument. For buttons, the value of the argument is obtained through 288 | the value="..." attribute of the html 54 | 55 | 56 | 57 | 58 |
59 | 60 |
61 |
62 |

...

63 |
64 |                     
65 |                         ...
66 |                     
67 |                 
68 |
69 |
70 |
71 |                     
72 |                         ...
73 |                     
74 |                 
75 |
76 |
77 |
78 |                     
79 |                         ...
80 |                     
81 |                 
82 |
83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Quill Project 002 - Centralized Video/libs/highlight/styles/atelier-cave-dark.css: -------------------------------------------------------------------------------- 1 | /* Base16 Atelier Cave Dark - Theme */ 2 | /* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave) */ 3 | /* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ 4 | 5 | /* Atelier-Cave Comment */ 6 | .hljs-comment, 7 | .hljs-quote { 8 | color: #7e7887; 9 | } 10 | 11 | /* Atelier-Cave Red */ 12 | .hljs-variable, 13 | .hljs-template-variable, 14 | .hljs-attribute, 15 | .hljs-regexp, 16 | .hljs-link, 17 | .hljs-tag, 18 | .hljs-name, 19 | .hljs-selector-id, 20 | .hljs-selector-class { 21 | color: #d4b13e; 22 | } 23 | 24 | /* Atelier-Cave Orange */ 25 | .hljs-number, 26 | .hljs-meta, 27 | .hljs-built_in, 28 | .hljs-builtin-name, 29 | .hljs-literal, 30 | .hljs-type, 31 | .hljs-params { 32 | color: #aa573c; 33 | } 34 | 35 | /* Atelier-Cave Green */ 36 | .hljs-string, 37 | .hljs-symbol, 38 | .hljs-bullet { 39 | color: #2a9292; 40 | } 41 | 42 | /* Atelier-Cave Blue */ 43 | .hljs-title, 44 | .hljs-section { 45 | color: #576ddb; 46 | } 47 | 48 | /* Atelier-Cave Purple */ 49 | .hljs-keyword, 50 | .hljs-selector-tag { 51 | color: #955ae7; 52 | } 53 | 54 | .hljs-deletion, 55 | .hljs-addition { 56 | color: #19171c; 57 | display: inline-block; 58 | width: 100%; 59 | } 60 | 61 | .hljs-deletion { 62 | background-color: #be4678; 63 | } 64 | 65 | .hljs-addition { 66 | background-color: #2a9292; 67 | } 68 | 69 | .hljs { 70 | display: block; 71 | overflow-x: auto; 72 | background: #19171c; 73 | color: #8b8792; 74 | padding: 0.5em; 75 | } 76 | 77 | .hljs-emphasis { 78 | font-style: italic; 79 | } 80 | 81 | .hljs-strong { 82 | font-weight: bold; 83 | } 84 | -------------------------------------------------------------------------------- /Quill Project 002 - Centralized Video/libs/quill/quill.core.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Quill Editor v1.3.6 3 | * https://quilljs.com/ 4 | * Copyright (c) 2014, Jason Chen 5 | * Copyright (c) 2013, salesforce.com 6 | */ 7 | .ql-container { 8 | box-sizing: border-box; 9 | font-family: Helvetica, Arial, sans-serif; 10 | font-size: 13px; 11 | height: 100%; 12 | margin: 0px; 13 | position: relative; 14 | } 15 | .ql-container.ql-disabled .ql-tooltip { 16 | visibility: hidden; 17 | } 18 | .ql-container.ql-disabled .ql-editor ul[data-checked] > li::before { 19 | pointer-events: none; 20 | } 21 | .ql-clipboard { 22 | left: -100000px; 23 | height: 1px; 24 | overflow-y: hidden; 25 | position: absolute; 26 | top: 50%; 27 | } 28 | .ql-clipboard p { 29 | margin: 0; 30 | padding: 0; 31 | } 32 | .ql-editor { 33 | box-sizing: border-box; 34 | line-height: 1.42; 35 | height: 100%; 36 | outline: none; 37 | overflow-y: auto; 38 | padding: 12px 15px; 39 | tab-size: 4; 40 | -moz-tab-size: 4; 41 | text-align: left; 42 | white-space: pre-wrap; 43 | word-wrap: break-word; 44 | } 45 | .ql-editor > * { 46 | cursor: text; 47 | } 48 | .ql-editor p, 49 | .ql-editor ol, 50 | .ql-editor ul, 51 | .ql-editor pre, 52 | .ql-editor blockquote, 53 | .ql-editor h1, 54 | .ql-editor h2, 55 | .ql-editor h3, 56 | .ql-editor h4, 57 | .ql-editor h5, 58 | .ql-editor h6 { 59 | margin: 0; 60 | padding: 0; 61 | counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 62 | } 63 | .ql-editor ol, 64 | .ql-editor ul { 65 | padding-left: 1.5em; 66 | } 67 | .ql-editor ol > li, 68 | .ql-editor ul > li { 69 | list-style-type: none; 70 | } 71 | .ql-editor ul > li::before { 72 | content: '\2022'; 73 | } 74 | .ql-editor ul[data-checked=true], 75 | .ql-editor ul[data-checked=false] { 76 | pointer-events: none; 77 | } 78 | .ql-editor ul[data-checked=true] > li *, 79 | .ql-editor ul[data-checked=false] > li * { 80 | pointer-events: all; 81 | } 82 | .ql-editor ul[data-checked=true] > li::before, 83 | .ql-editor ul[data-checked=false] > li::before { 84 | color: #777; 85 | cursor: pointer; 86 | pointer-events: all; 87 | } 88 | .ql-editor ul[data-checked=true] > li::before { 89 | content: '\2611'; 90 | } 91 | .ql-editor ul[data-checked=false] > li::before { 92 | content: '\2610'; 93 | } 94 | .ql-editor li::before { 95 | display: inline-block; 96 | white-space: nowrap; 97 | width: 1.2em; 98 | } 99 | .ql-editor li:not(.ql-direction-rtl)::before { 100 | margin-left: -1.5em; 101 | margin-right: 0.3em; 102 | text-align: right; 103 | } 104 | .ql-editor li.ql-direction-rtl::before { 105 | margin-left: 0.3em; 106 | margin-right: -1.5em; 107 | } 108 | .ql-editor ol li:not(.ql-direction-rtl), 109 | .ql-editor ul li:not(.ql-direction-rtl) { 110 | padding-left: 1.5em; 111 | } 112 | .ql-editor ol li.ql-direction-rtl, 113 | .ql-editor ul li.ql-direction-rtl { 114 | padding-right: 1.5em; 115 | } 116 | .ql-editor ol li { 117 | counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 118 | counter-increment: list-0; 119 | } 120 | .ql-editor ol li:before { 121 | content: counter(list-0, decimal) '. '; 122 | } 123 | .ql-editor ol li.ql-indent-1 { 124 | counter-increment: list-1; 125 | } 126 | .ql-editor ol li.ql-indent-1:before { 127 | content: counter(list-1, lower-alpha) '. '; 128 | } 129 | .ql-editor ol li.ql-indent-1 { 130 | counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 131 | } 132 | .ql-editor ol li.ql-indent-2 { 133 | counter-increment: list-2; 134 | } 135 | .ql-editor ol li.ql-indent-2:before { 136 | content: counter(list-2, lower-roman) '. '; 137 | } 138 | .ql-editor ol li.ql-indent-2 { 139 | counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9; 140 | } 141 | .ql-editor ol li.ql-indent-3 { 142 | counter-increment: list-3; 143 | } 144 | .ql-editor ol li.ql-indent-3:before { 145 | content: counter(list-3, decimal) '. '; 146 | } 147 | .ql-editor ol li.ql-indent-3 { 148 | counter-reset: list-4 list-5 list-6 list-7 list-8 list-9; 149 | } 150 | .ql-editor ol li.ql-indent-4 { 151 | counter-increment: list-4; 152 | } 153 | .ql-editor ol li.ql-indent-4:before { 154 | content: counter(list-4, lower-alpha) '. '; 155 | } 156 | .ql-editor ol li.ql-indent-4 { 157 | counter-reset: list-5 list-6 list-7 list-8 list-9; 158 | } 159 | .ql-editor ol li.ql-indent-5 { 160 | counter-increment: list-5; 161 | } 162 | .ql-editor ol li.ql-indent-5:before { 163 | content: counter(list-5, lower-roman) '. '; 164 | } 165 | .ql-editor ol li.ql-indent-5 { 166 | counter-reset: list-6 list-7 list-8 list-9; 167 | } 168 | .ql-editor ol li.ql-indent-6 { 169 | counter-increment: list-6; 170 | } 171 | .ql-editor ol li.ql-indent-6:before { 172 | content: counter(list-6, decimal) '. '; 173 | } 174 | .ql-editor ol li.ql-indent-6 { 175 | counter-reset: list-7 list-8 list-9; 176 | } 177 | .ql-editor ol li.ql-indent-7 { 178 | counter-increment: list-7; 179 | } 180 | .ql-editor ol li.ql-indent-7:before { 181 | content: counter(list-7, lower-alpha) '. '; 182 | } 183 | .ql-editor ol li.ql-indent-7 { 184 | counter-reset: list-8 list-9; 185 | } 186 | .ql-editor ol li.ql-indent-8 { 187 | counter-increment: list-8; 188 | } 189 | .ql-editor ol li.ql-indent-8:before { 190 | content: counter(list-8, lower-roman) '. '; 191 | } 192 | .ql-editor ol li.ql-indent-8 { 193 | counter-reset: list-9; 194 | } 195 | .ql-editor ol li.ql-indent-9 { 196 | counter-increment: list-9; 197 | } 198 | .ql-editor ol li.ql-indent-9:before { 199 | content: counter(list-9, decimal) '. '; 200 | } 201 | .ql-editor .ql-indent-1:not(.ql-direction-rtl) { 202 | padding-left: 3em; 203 | } 204 | .ql-editor li.ql-indent-1:not(.ql-direction-rtl) { 205 | padding-left: 4.5em; 206 | } 207 | .ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right { 208 | padding-right: 3em; 209 | } 210 | .ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right { 211 | padding-right: 4.5em; 212 | } 213 | .ql-editor .ql-indent-2:not(.ql-direction-rtl) { 214 | padding-left: 6em; 215 | } 216 | .ql-editor li.ql-indent-2:not(.ql-direction-rtl) { 217 | padding-left: 7.5em; 218 | } 219 | .ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right { 220 | padding-right: 6em; 221 | } 222 | .ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right { 223 | padding-right: 7.5em; 224 | } 225 | .ql-editor .ql-indent-3:not(.ql-direction-rtl) { 226 | padding-left: 9em; 227 | } 228 | .ql-editor li.ql-indent-3:not(.ql-direction-rtl) { 229 | padding-left: 10.5em; 230 | } 231 | .ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right { 232 | padding-right: 9em; 233 | } 234 | .ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right { 235 | padding-right: 10.5em; 236 | } 237 | .ql-editor .ql-indent-4:not(.ql-direction-rtl) { 238 | padding-left: 12em; 239 | } 240 | .ql-editor li.ql-indent-4:not(.ql-direction-rtl) { 241 | padding-left: 13.5em; 242 | } 243 | .ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right { 244 | padding-right: 12em; 245 | } 246 | .ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right { 247 | padding-right: 13.5em; 248 | } 249 | .ql-editor .ql-indent-5:not(.ql-direction-rtl) { 250 | padding-left: 15em; 251 | } 252 | .ql-editor li.ql-indent-5:not(.ql-direction-rtl) { 253 | padding-left: 16.5em; 254 | } 255 | .ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right { 256 | padding-right: 15em; 257 | } 258 | .ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right { 259 | padding-right: 16.5em; 260 | } 261 | .ql-editor .ql-indent-6:not(.ql-direction-rtl) { 262 | padding-left: 18em; 263 | } 264 | .ql-editor li.ql-indent-6:not(.ql-direction-rtl) { 265 | padding-left: 19.5em; 266 | } 267 | .ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right { 268 | padding-right: 18em; 269 | } 270 | .ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right { 271 | padding-right: 19.5em; 272 | } 273 | .ql-editor .ql-indent-7:not(.ql-direction-rtl) { 274 | padding-left: 21em; 275 | } 276 | .ql-editor li.ql-indent-7:not(.ql-direction-rtl) { 277 | padding-left: 22.5em; 278 | } 279 | .ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right { 280 | padding-right: 21em; 281 | } 282 | .ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right { 283 | padding-right: 22.5em; 284 | } 285 | .ql-editor .ql-indent-8:not(.ql-direction-rtl) { 286 | padding-left: 24em; 287 | } 288 | .ql-editor li.ql-indent-8:not(.ql-direction-rtl) { 289 | padding-left: 25.5em; 290 | } 291 | .ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right { 292 | padding-right: 24em; 293 | } 294 | .ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right { 295 | padding-right: 25.5em; 296 | } 297 | .ql-editor .ql-indent-9:not(.ql-direction-rtl) { 298 | padding-left: 27em; 299 | } 300 | .ql-editor li.ql-indent-9:not(.ql-direction-rtl) { 301 | padding-left: 28.5em; 302 | } 303 | .ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right { 304 | padding-right: 27em; 305 | } 306 | .ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right { 307 | padding-right: 28.5em; 308 | } 309 | .ql-editor .ql-video { 310 | display: block; 311 | max-width: 100%; 312 | } 313 | .ql-editor .ql-video.ql-align-center { 314 | margin: 0 auto; 315 | } 316 | .ql-editor .ql-video.ql-align-right { 317 | margin: 0 0 0 auto; 318 | } 319 | .ql-editor .ql-bg-black { 320 | background-color: #000; 321 | } 322 | .ql-editor .ql-bg-red { 323 | background-color: #e60000; 324 | } 325 | .ql-editor .ql-bg-orange { 326 | background-color: #f90; 327 | } 328 | .ql-editor .ql-bg-yellow { 329 | background-color: #ff0; 330 | } 331 | .ql-editor .ql-bg-green { 332 | background-color: #008a00; 333 | } 334 | .ql-editor .ql-bg-blue { 335 | background-color: #06c; 336 | } 337 | .ql-editor .ql-bg-purple { 338 | background-color: #93f; 339 | } 340 | .ql-editor .ql-color-white { 341 | color: #fff; 342 | } 343 | .ql-editor .ql-color-red { 344 | color: #e60000; 345 | } 346 | .ql-editor .ql-color-orange { 347 | color: #f90; 348 | } 349 | .ql-editor .ql-color-yellow { 350 | color: #ff0; 351 | } 352 | .ql-editor .ql-color-green { 353 | color: #008a00; 354 | } 355 | .ql-editor .ql-color-blue { 356 | color: #06c; 357 | } 358 | .ql-editor .ql-color-purple { 359 | color: #93f; 360 | } 361 | .ql-editor .ql-font-serif { 362 | font-family: Georgia, Times New Roman, serif; 363 | } 364 | .ql-editor .ql-font-monospace { 365 | font-family: Monaco, Courier New, monospace; 366 | } 367 | .ql-editor .ql-size-small { 368 | font-size: 0.75em; 369 | } 370 | .ql-editor .ql-size-large { 371 | font-size: 1.5em; 372 | } 373 | .ql-editor .ql-size-huge { 374 | font-size: 2.5em; 375 | } 376 | .ql-editor .ql-direction-rtl { 377 | direction: rtl; 378 | text-align: inherit; 379 | } 380 | .ql-editor .ql-align-center { 381 | text-align: center; 382 | } 383 | .ql-editor .ql-align-justify { 384 | text-align: justify; 385 | } 386 | .ql-editor .ql-align-right { 387 | text-align: right; 388 | } 389 | .ql-editor.ql-blank::before { 390 | color: rgba(0,0,0,0.6); 391 | content: attr(data-placeholder); 392 | font-style: italic; 393 | left: 15px; 394 | pointer-events: none; 395 | position: absolute; 396 | right: 15px; 397 | } 398 | -------------------------------------------------------------------------------- /Quill Project 002 - Centralized Video/styles.css: -------------------------------------------------------------------------------- 1 | /*###################### */ 2 | /* GLOBAL */ 3 | /*###################### */ 4 | 5 | * 6 | { 7 | margin: 0px; 8 | padding: 0px; 9 | } 10 | 11 | #all 12 | { 13 | margin: 30px; 14 | } 15 | 16 | /*###################### */ 17 | /* VIDEO */ 18 | /*###################### */ 19 | 20 | .ql-centralized-video 21 | { 22 | display: block; 23 | margin: 0 auto; 24 | text-align: center; 25 | max-width: 100%; 26 | } 27 | 28 | /*###################### */ 29 | /* DELTA, TEXT AND HTML */ 30 | /*###################### */ 31 | 32 | #content-delta, 33 | #content-html, 34 | #content-text { 35 | padding: 0px; 36 | } 37 | 38 | pre{ 39 | white-space: normal; 40 | } 41 | 42 | code{ 43 | white-space: pre-wrap; 44 | } 45 | 46 | #content-delta p{ 47 | font-family: Candara; 48 | } 49 | 50 | /*###################### */ 51 | /* TABS */ 52 | /*###################### */ 53 | 54 | /* Style the tab */ 55 | .tabs { 56 | overflow: hidden; 57 | border-right: 1px solid #ccc; 58 | border-left: 1px solid #ccc; 59 | border-bottom: 1px solid #ccc; 60 | background-color: #f1f1f1; 61 | } 62 | 63 | /* Style the buttons that are used to open the tab content */ 64 | .tabs button { 65 | background-color: inherit; 66 | float: left; 67 | border: none; 68 | outline: none; 69 | cursor: pointer; 70 | padding: 14px 16px; 71 | transition: 0.3s; 72 | } 73 | 74 | /* Change background color of buttons on hover */ 75 | .tabs button:hover { 76 | background-color: #ddd; 77 | } 78 | 79 | /* Create an active/current tablink class */ 80 | .tabs button.active { 81 | background-color: #ccc; 82 | } 83 | 84 | /* Style the tab content */ 85 | .abas-conteudo { 86 | display: none; 87 | padding: 6px 10px; 88 | border: 1px solid #ccc; 89 | border-top: none; 90 | } -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 |
33 | 34 | 35 |
36 | 37 | 38 |
39 | 40 | 41 | 42 |
43 | 44 | 45 |
46 |

...

47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 57 | 58 | -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/highlight/styles/atelier-cave-dark.css: -------------------------------------------------------------------------------- 1 | /* Base16 Atelier Cave Dark - Theme */ 2 | /* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave) */ 3 | /* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ 4 | 5 | /* Atelier-Cave Comment */ 6 | .hljs-comment, 7 | .hljs-quote { 8 | color: #7e7887; 9 | } 10 | 11 | /* Atelier-Cave Red */ 12 | .hljs-variable, 13 | .hljs-template-variable, 14 | .hljs-attribute, 15 | .hljs-regexp, 16 | .hljs-link, 17 | .hljs-tag, 18 | .hljs-name, 19 | .hljs-selector-id, 20 | .hljs-selector-class { 21 | color: #d4b13e; 22 | } 23 | 24 | /* Atelier-Cave Orange */ 25 | .hljs-number, 26 | .hljs-meta, 27 | .hljs-built_in, 28 | .hljs-builtin-name, 29 | .hljs-literal, 30 | .hljs-type, 31 | .hljs-params { 32 | color: #aa573c; 33 | } 34 | 35 | /* Atelier-Cave Green */ 36 | .hljs-string, 37 | .hljs-symbol, 38 | .hljs-bullet { 39 | color: #2a9292; 40 | } 41 | 42 | /* Atelier-Cave Blue */ 43 | .hljs-title, 44 | .hljs-section { 45 | color: #576ddb; 46 | } 47 | 48 | /* Atelier-Cave Purple */ 49 | .hljs-keyword, 50 | .hljs-selector-tag { 51 | color: #955ae7; 52 | } 53 | 54 | .hljs-deletion, 55 | .hljs-addition { 56 | color: #19171c; 57 | display: inline-block; 58 | width: 100%; 59 | } 60 | 61 | .hljs-deletion { 62 | background-color: #be4678; 63 | } 64 | 65 | .hljs-addition { 66 | background-color: #2a9292; 67 | } 68 | 69 | .hljs { 70 | display: block; 71 | overflow-x: auto; 72 | background: #19171c; 73 | color: #8b8792; 74 | padding: 0.5em; 75 | } 76 | 77 | .hljs-emphasis { 78 | font-style: italic; 79 | } 80 | 81 | .hljs-strong { 82 | font-weight: bold; 83 | } 84 | -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/quill/quill.core.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Quill Editor v1.3.6 3 | * https://quilljs.com/ 4 | * Copyright (c) 2014, Jason Chen 5 | * Copyright (c) 2013, salesforce.com 6 | */ 7 | .ql-container { 8 | box-sizing: border-box; 9 | font-family: Helvetica, Arial, sans-serif; 10 | font-size: 13px; 11 | height: 100%; 12 | margin: 0px; 13 | position: relative; 14 | } 15 | .ql-container.ql-disabled .ql-tooltip { 16 | visibility: hidden; 17 | } 18 | .ql-container.ql-disabled .ql-editor ul[data-checked] > li::before { 19 | pointer-events: none; 20 | } 21 | .ql-clipboard { 22 | left: -100000px; 23 | height: 1px; 24 | overflow-y: hidden; 25 | position: absolute; 26 | top: 50%; 27 | } 28 | .ql-clipboard p { 29 | margin: 0; 30 | padding: 0; 31 | } 32 | .ql-editor { 33 | box-sizing: border-box; 34 | line-height: 1.42; 35 | height: 100%; 36 | outline: none; 37 | overflow-y: auto; 38 | padding: 12px 15px; 39 | tab-size: 4; 40 | -moz-tab-size: 4; 41 | text-align: left; 42 | white-space: pre-wrap; 43 | word-wrap: break-word; 44 | } 45 | .ql-editor > * { 46 | cursor: text; 47 | } 48 | .ql-editor p, 49 | .ql-editor ol, 50 | .ql-editor ul, 51 | .ql-editor pre, 52 | .ql-editor blockquote, 53 | .ql-editor h1, 54 | .ql-editor h2, 55 | .ql-editor h3, 56 | .ql-editor h4, 57 | .ql-editor h5, 58 | .ql-editor h6 { 59 | margin: 0; 60 | padding: 0; 61 | counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 62 | } 63 | .ql-editor ol, 64 | .ql-editor ul { 65 | padding-left: 1.5em; 66 | } 67 | .ql-editor ol > li, 68 | .ql-editor ul > li { 69 | list-style-type: none; 70 | } 71 | .ql-editor ul > li::before { 72 | content: '\2022'; 73 | } 74 | .ql-editor ul[data-checked=true], 75 | .ql-editor ul[data-checked=false] { 76 | pointer-events: none; 77 | } 78 | .ql-editor ul[data-checked=true] > li *, 79 | .ql-editor ul[data-checked=false] > li * { 80 | pointer-events: all; 81 | } 82 | .ql-editor ul[data-checked=true] > li::before, 83 | .ql-editor ul[data-checked=false] > li::before { 84 | color: #777; 85 | cursor: pointer; 86 | pointer-events: all; 87 | } 88 | .ql-editor ul[data-checked=true] > li::before { 89 | content: '\2611'; 90 | } 91 | .ql-editor ul[data-checked=false] > li::before { 92 | content: '\2610'; 93 | } 94 | .ql-editor li::before { 95 | display: inline-block; 96 | white-space: nowrap; 97 | width: 1.2em; 98 | } 99 | .ql-editor li:not(.ql-direction-rtl)::before { 100 | margin-left: -1.5em; 101 | margin-right: 0.3em; 102 | text-align: right; 103 | } 104 | .ql-editor li.ql-direction-rtl::before { 105 | margin-left: 0.3em; 106 | margin-right: -1.5em; 107 | } 108 | .ql-editor ol li:not(.ql-direction-rtl), 109 | .ql-editor ul li:not(.ql-direction-rtl) { 110 | padding-left: 1.5em; 111 | } 112 | .ql-editor ol li.ql-direction-rtl, 113 | .ql-editor ul li.ql-direction-rtl { 114 | padding-right: 1.5em; 115 | } 116 | .ql-editor ol li { 117 | counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 118 | counter-increment: list-0; 119 | } 120 | .ql-editor ol li:before { 121 | content: counter(list-0, decimal) '. '; 122 | } 123 | .ql-editor ol li.ql-indent-1 { 124 | counter-increment: list-1; 125 | } 126 | .ql-editor ol li.ql-indent-1:before { 127 | content: counter(list-1, lower-alpha) '. '; 128 | } 129 | .ql-editor ol li.ql-indent-1 { 130 | counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 131 | } 132 | .ql-editor ol li.ql-indent-2 { 133 | counter-increment: list-2; 134 | } 135 | .ql-editor ol li.ql-indent-2:before { 136 | content: counter(list-2, lower-roman) '. '; 137 | } 138 | .ql-editor ol li.ql-indent-2 { 139 | counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9; 140 | } 141 | .ql-editor ol li.ql-indent-3 { 142 | counter-increment: list-3; 143 | } 144 | .ql-editor ol li.ql-indent-3:before { 145 | content: counter(list-3, decimal) '. '; 146 | } 147 | .ql-editor ol li.ql-indent-3 { 148 | counter-reset: list-4 list-5 list-6 list-7 list-8 list-9; 149 | } 150 | .ql-editor ol li.ql-indent-4 { 151 | counter-increment: list-4; 152 | } 153 | .ql-editor ol li.ql-indent-4:before { 154 | content: counter(list-4, lower-alpha) '. '; 155 | } 156 | .ql-editor ol li.ql-indent-4 { 157 | counter-reset: list-5 list-6 list-7 list-8 list-9; 158 | } 159 | .ql-editor ol li.ql-indent-5 { 160 | counter-increment: list-5; 161 | } 162 | .ql-editor ol li.ql-indent-5:before { 163 | content: counter(list-5, lower-roman) '. '; 164 | } 165 | .ql-editor ol li.ql-indent-5 { 166 | counter-reset: list-6 list-7 list-8 list-9; 167 | } 168 | .ql-editor ol li.ql-indent-6 { 169 | counter-increment: list-6; 170 | } 171 | .ql-editor ol li.ql-indent-6:before { 172 | content: counter(list-6, decimal) '. '; 173 | } 174 | .ql-editor ol li.ql-indent-6 { 175 | counter-reset: list-7 list-8 list-9; 176 | } 177 | .ql-editor ol li.ql-indent-7 { 178 | counter-increment: list-7; 179 | } 180 | .ql-editor ol li.ql-indent-7:before { 181 | content: counter(list-7, lower-alpha) '. '; 182 | } 183 | .ql-editor ol li.ql-indent-7 { 184 | counter-reset: list-8 list-9; 185 | } 186 | .ql-editor ol li.ql-indent-8 { 187 | counter-increment: list-8; 188 | } 189 | .ql-editor ol li.ql-indent-8:before { 190 | content: counter(list-8, lower-roman) '. '; 191 | } 192 | .ql-editor ol li.ql-indent-8 { 193 | counter-reset: list-9; 194 | } 195 | .ql-editor ol li.ql-indent-9 { 196 | counter-increment: list-9; 197 | } 198 | .ql-editor ol li.ql-indent-9:before { 199 | content: counter(list-9, decimal) '. '; 200 | } 201 | .ql-editor .ql-indent-1:not(.ql-direction-rtl) { 202 | padding-left: 3em; 203 | } 204 | .ql-editor li.ql-indent-1:not(.ql-direction-rtl) { 205 | padding-left: 4.5em; 206 | } 207 | .ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right { 208 | padding-right: 3em; 209 | } 210 | .ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right { 211 | padding-right: 4.5em; 212 | } 213 | .ql-editor .ql-indent-2:not(.ql-direction-rtl) { 214 | padding-left: 6em; 215 | } 216 | .ql-editor li.ql-indent-2:not(.ql-direction-rtl) { 217 | padding-left: 7.5em; 218 | } 219 | .ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right { 220 | padding-right: 6em; 221 | } 222 | .ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right { 223 | padding-right: 7.5em; 224 | } 225 | .ql-editor .ql-indent-3:not(.ql-direction-rtl) { 226 | padding-left: 9em; 227 | } 228 | .ql-editor li.ql-indent-3:not(.ql-direction-rtl) { 229 | padding-left: 10.5em; 230 | } 231 | .ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right { 232 | padding-right: 9em; 233 | } 234 | .ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right { 235 | padding-right: 10.5em; 236 | } 237 | .ql-editor .ql-indent-4:not(.ql-direction-rtl) { 238 | padding-left: 12em; 239 | } 240 | .ql-editor li.ql-indent-4:not(.ql-direction-rtl) { 241 | padding-left: 13.5em; 242 | } 243 | .ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right { 244 | padding-right: 12em; 245 | } 246 | .ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right { 247 | padding-right: 13.5em; 248 | } 249 | .ql-editor .ql-indent-5:not(.ql-direction-rtl) { 250 | padding-left: 15em; 251 | } 252 | .ql-editor li.ql-indent-5:not(.ql-direction-rtl) { 253 | padding-left: 16.5em; 254 | } 255 | .ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right { 256 | padding-right: 15em; 257 | } 258 | .ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right { 259 | padding-right: 16.5em; 260 | } 261 | .ql-editor .ql-indent-6:not(.ql-direction-rtl) { 262 | padding-left: 18em; 263 | } 264 | .ql-editor li.ql-indent-6:not(.ql-direction-rtl) { 265 | padding-left: 19.5em; 266 | } 267 | .ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right { 268 | padding-right: 18em; 269 | } 270 | .ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right { 271 | padding-right: 19.5em; 272 | } 273 | .ql-editor .ql-indent-7:not(.ql-direction-rtl) { 274 | padding-left: 21em; 275 | } 276 | .ql-editor li.ql-indent-7:not(.ql-direction-rtl) { 277 | padding-left: 22.5em; 278 | } 279 | .ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right { 280 | padding-right: 21em; 281 | } 282 | .ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right { 283 | padding-right: 22.5em; 284 | } 285 | .ql-editor .ql-indent-8:not(.ql-direction-rtl) { 286 | padding-left: 24em; 287 | } 288 | .ql-editor li.ql-indent-8:not(.ql-direction-rtl) { 289 | padding-left: 25.5em; 290 | } 291 | .ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right { 292 | padding-right: 24em; 293 | } 294 | .ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right { 295 | padding-right: 25.5em; 296 | } 297 | .ql-editor .ql-indent-9:not(.ql-direction-rtl) { 298 | padding-left: 27em; 299 | } 300 | .ql-editor li.ql-indent-9:not(.ql-direction-rtl) { 301 | padding-left: 28.5em; 302 | } 303 | .ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right { 304 | padding-right: 27em; 305 | } 306 | .ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right { 307 | padding-right: 28.5em; 308 | } 309 | .ql-editor .ql-video { 310 | display: block; 311 | max-width: 100%; 312 | } 313 | .ql-editor .ql-video.ql-align-center { 314 | margin: 0 auto; 315 | } 316 | .ql-editor .ql-video.ql-align-right { 317 | margin: 0 0 0 auto; 318 | } 319 | .ql-editor .ql-bg-black { 320 | background-color: #000; 321 | } 322 | .ql-editor .ql-bg-red { 323 | background-color: #e60000; 324 | } 325 | .ql-editor .ql-bg-orange { 326 | background-color: #f90; 327 | } 328 | .ql-editor .ql-bg-yellow { 329 | background-color: #ff0; 330 | } 331 | .ql-editor .ql-bg-green { 332 | background-color: #008a00; 333 | } 334 | .ql-editor .ql-bg-blue { 335 | background-color: #06c; 336 | } 337 | .ql-editor .ql-bg-purple { 338 | background-color: #93f; 339 | } 340 | .ql-editor .ql-color-white { 341 | color: #fff; 342 | } 343 | .ql-editor .ql-color-red { 344 | color: #e60000; 345 | } 346 | .ql-editor .ql-color-orange { 347 | color: #f90; 348 | } 349 | .ql-editor .ql-color-yellow { 350 | color: #ff0; 351 | } 352 | .ql-editor .ql-color-green { 353 | color: #008a00; 354 | } 355 | .ql-editor .ql-color-blue { 356 | color: #06c; 357 | } 358 | .ql-editor .ql-color-purple { 359 | color: #93f; 360 | } 361 | .ql-editor .ql-font-serif { 362 | font-family: Georgia, Times New Roman, serif; 363 | } 364 | .ql-editor .ql-font-monospace { 365 | font-family: Monaco, Courier New, monospace; 366 | } 367 | .ql-editor .ql-size-small { 368 | font-size: 0.75em; 369 | } 370 | .ql-editor .ql-size-large { 371 | font-size: 1.5em; 372 | } 373 | .ql-editor .ql-size-huge { 374 | font-size: 2.5em; 375 | } 376 | .ql-editor .ql-direction-rtl { 377 | direction: rtl; 378 | text-align: inherit; 379 | } 380 | .ql-editor .ql-align-center { 381 | text-align: center; 382 | } 383 | .ql-editor .ql-align-justify { 384 | text-align: justify; 385 | } 386 | .ql-editor .ql-align-right { 387 | text-align: right; 388 | } 389 | .ql-editor.ql-blank::before { 390 | color: rgba(0,0,0,0.6); 391 | content: attr(data-placeholder); 392 | font-style: italic; 393 | left: 15px; 394 | pointer-events: none; 395 | position: absolute; 396 | right: 15px; 397 | } 398 | -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loagit/Quill-Examples-and-FAQ/dfda8275abb6690d6332db1994fe571b77e678af/Quill Project 003 - Carousel/libs/slick/ajax-loader.gif -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/config.rb: -------------------------------------------------------------------------------- 1 | css_dir = "." 2 | sass_dir = "." 3 | images_dir = "." 4 | fonts_dir = "fonts" 5 | relative_assets = true 6 | 7 | output_style = :compact 8 | line_comments = false 9 | 10 | preferred_syntax = :scss -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/fonts/slick.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loagit/Quill-Examples-and-FAQ/dfda8275abb6690d6332db1994fe571b77e678af/Quill Project 003 - Carousel/libs/slick/fonts/slick.eot -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/fonts/slick.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by Fontastic.me 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/fonts/slick.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loagit/Quill-Examples-and-FAQ/dfda8275abb6690d6332db1994fe571b77e678af/Quill Project 003 - Carousel/libs/slick/fonts/slick.ttf -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/fonts/slick.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loagit/Quill-Examples-and-FAQ/dfda8275abb6690d6332db1994fe571b77e678af/Quill Project 003 - Carousel/libs/slick/fonts/slick.woff -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/slick-theme.css: -------------------------------------------------------------------------------- 1 | @charset 'UTF-8'; 2 | /* Slider */ 3 | .slick-loading .slick-list 4 | { 5 | background: #fff url('./ajax-loader.gif') center center no-repeat; 6 | } 7 | 8 | /* Icons */ 9 | @font-face 10 | { 11 | font-family: 'slick'; 12 | font-weight: normal; 13 | font-style: normal; 14 | 15 | src: url('./fonts/slick.eot'); 16 | src: url('./fonts/slick.eot?#iefix') format('embedded-opentype'), url('./fonts/slick.woff') format('woff'), url('./fonts/slick.ttf') format('truetype'), url('./fonts/slick.svg#slick') format('svg'); 17 | } 18 | /* Arrows */ 19 | .slick-prev, 20 | .slick-next 21 | { 22 | font-size: 0; 23 | line-height: 0; 24 | 25 | position: absolute; 26 | top: 50%; 27 | 28 | display: block; 29 | 30 | width: 20px; 31 | height: 20px; 32 | padding: 0; 33 | -webkit-transform: translate(0, -50%); 34 | -ms-transform: translate(0, -50%); 35 | transform: translate(0, -50%); 36 | 37 | cursor: pointer; 38 | 39 | color: transparent; 40 | border: none; 41 | outline: none; 42 | background: transparent; 43 | } 44 | .slick-prev:hover, 45 | .slick-prev:focus, 46 | .slick-next:hover, 47 | .slick-next:focus 48 | { 49 | color: transparent; 50 | outline: none; 51 | background: transparent; 52 | } 53 | .slick-prev:hover:before, 54 | .slick-prev:focus:before, 55 | .slick-next:hover:before, 56 | .slick-next:focus:before 57 | { 58 | opacity: 1; 59 | } 60 | .slick-prev.slick-disabled:before, 61 | .slick-next.slick-disabled:before 62 | { 63 | opacity: .25; 64 | } 65 | 66 | .slick-prev:before, 67 | .slick-next:before 68 | { 69 | font-family: 'slick'; 70 | font-size: 20px; 71 | line-height: 1; 72 | 73 | opacity: .75; 74 | color: white; 75 | 76 | -webkit-font-smoothing: antialiased; 77 | -moz-osx-font-smoothing: grayscale; 78 | } 79 | 80 | .slick-prev 81 | { 82 | left: -25px; 83 | } 84 | [dir='rtl'] .slick-prev 85 | { 86 | right: -25px; 87 | left: auto; 88 | } 89 | .slick-prev:before 90 | { 91 | content: '←'; 92 | } 93 | [dir='rtl'] .slick-prev:before 94 | { 95 | content: '→'; 96 | } 97 | 98 | .slick-next 99 | { 100 | right: -25px; 101 | } 102 | [dir='rtl'] .slick-next 103 | { 104 | right: auto; 105 | left: -25px; 106 | } 107 | .slick-next:before 108 | { 109 | content: '→'; 110 | } 111 | [dir='rtl'] .slick-next:before 112 | { 113 | content: '←'; 114 | } 115 | 116 | /* Dots */ 117 | .slick-dotted.slick-slider 118 | { 119 | margin-bottom: 30px; 120 | } 121 | 122 | .slick-dots 123 | { 124 | position: absolute; 125 | bottom: -25px; 126 | 127 | display: block; 128 | 129 | width: 100%; 130 | padding: 0; 131 | margin: 0; 132 | 133 | list-style: none; 134 | 135 | text-align: center; 136 | } 137 | .slick-dots li 138 | { 139 | position: relative; 140 | 141 | display: inline-block; 142 | 143 | width: 20px; 144 | height: 20px; 145 | margin: 0 5px; 146 | padding: 0; 147 | 148 | cursor: pointer; 149 | } 150 | .slick-dots li button 151 | { 152 | font-size: 0; 153 | line-height: 0; 154 | 155 | display: block; 156 | 157 | width: 20px; 158 | height: 20px; 159 | padding: 5px; 160 | 161 | cursor: pointer; 162 | 163 | color: transparent; 164 | border: 0; 165 | outline: none; 166 | background: transparent; 167 | } 168 | .slick-dots li button:hover, 169 | .slick-dots li button:focus 170 | { 171 | outline: none; 172 | } 173 | .slick-dots li button:hover:before, 174 | .slick-dots li button:focus:before 175 | { 176 | opacity: 1; 177 | } 178 | .slick-dots li button:before 179 | { 180 | font-family: 'slick'; 181 | font-size: 6px; 182 | line-height: 20px; 183 | 184 | position: absolute; 185 | top: 0; 186 | left: 0; 187 | 188 | width: 20px; 189 | height: 20px; 190 | 191 | content: '•'; 192 | text-align: center; 193 | 194 | opacity: .25; 195 | color: black; 196 | 197 | -webkit-font-smoothing: antialiased; 198 | -moz-osx-font-smoothing: grayscale; 199 | } 200 | .slick-dots li.slick-active button:before 201 | { 202 | opacity: .75; 203 | color: black; 204 | } 205 | -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/slick-theme.less: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | // Default Variables 4 | 5 | @slick-font-path: "./fonts/"; 6 | @slick-font-family: "slick"; 7 | @slick-loader-path: "./"; 8 | @slick-arrow-color: white; 9 | @slick-dot-color: black; 10 | @slick-dot-color-active: @slick-dot-color; 11 | @slick-prev-character: "←"; 12 | @slick-next-character: "→"; 13 | @slick-dot-character: "•"; 14 | @slick-dot-size: 6px; 15 | @slick-opacity-default: 0.75; 16 | @slick-opacity-on-hover: 1; 17 | @slick-opacity-not-active: 0.25; 18 | 19 | /* Slider */ 20 | .slick-loading .slick-list{ 21 | background: #fff url('@{slick-loader-path}ajax-loader.gif') center center no-repeat; 22 | } 23 | 24 | /* Arrows */ 25 | .slick-prev, 26 | .slick-next { 27 | position: absolute; 28 | display: block; 29 | height: 20px; 30 | width: 20px; 31 | line-height: 0px; 32 | font-size: 0px; 33 | cursor: pointer; 34 | background: transparent; 35 | color: transparent; 36 | top: 50%; 37 | -webkit-transform: translate(0, -50%); 38 | -ms-transform: translate(0, -50%); 39 | transform: translate(0, -50%); 40 | padding: 0; 41 | border: none; 42 | outline: none; 43 | &:hover, &:focus { 44 | outline: none; 45 | background: transparent; 46 | color: transparent; 47 | &:before { 48 | opacity: @slick-opacity-on-hover; 49 | } 50 | } 51 | &.slick-disabled:before { 52 | opacity: @slick-opacity-not-active; 53 | } 54 | } 55 | 56 | .slick-prev:before, .slick-next:before { 57 | font-family: @slick-font-family; 58 | font-size: 20px; 59 | line-height: 1; 60 | color: @slick-arrow-color; 61 | opacity: @slick-opacity-default; 62 | -webkit-font-smoothing: antialiased; 63 | -moz-osx-font-smoothing: grayscale; 64 | 65 | & when ( @slick-font-family = 'slick' ) { 66 | /* Icons */ 67 | @font-face { 68 | font-family: 'slick'; 69 | font-weight: normal; 70 | font-style: normal; 71 | src: url('@{slick-font-path}slick.eot'); 72 | src: url('@{slick-font-path}slick.eot?#iefix') format('embedded-opentype'), url('@{slick-font-path}slick.woff') format('woff'), url('@{slick-font-path}slick.ttf') format('truetype'), url('@{slick-font-path}slick.svg#slick') format('svg'); 73 | } 74 | } 75 | } 76 | 77 | .slick-prev { 78 | left: -25px; 79 | [dir="rtl"] & { 80 | left: auto; 81 | right: -25px; 82 | } 83 | &:before { 84 | content: @slick-prev-character; 85 | [dir="rtl"] & { 86 | content: @slick-next-character; 87 | } 88 | } 89 | } 90 | 91 | .slick-next { 92 | right: -25px; 93 | [dir="rtl"] & { 94 | left: -25px; 95 | right: auto; 96 | } 97 | &:before { 98 | content: @slick-next-character; 99 | [dir="rtl"] & { 100 | content: @slick-prev-character; 101 | } 102 | } 103 | } 104 | 105 | /* Dots */ 106 | 107 | .slick-dotted .slick-slider { 108 | margin-bottom: 30px; 109 | } 110 | 111 | .slick-dots { 112 | position: absolute; 113 | bottom: -25px; 114 | list-style: none; 115 | display: block; 116 | text-align: center; 117 | padding: 0; 118 | margin: 0; 119 | width: 100%; 120 | li { 121 | position: relative; 122 | display: inline-block; 123 | height: 20px; 124 | width: 20px; 125 | margin: 0 5px; 126 | padding: 0; 127 | cursor: pointer; 128 | button { 129 | border: 0; 130 | background: transparent; 131 | display: block; 132 | height: 20px; 133 | width: 20px; 134 | outline: none; 135 | line-height: 0px; 136 | font-size: 0px; 137 | color: transparent; 138 | padding: 5px; 139 | cursor: pointer; 140 | &:hover, &:focus { 141 | outline: none; 142 | &:before { 143 | opacity: @slick-opacity-on-hover; 144 | } 145 | } 146 | &:before { 147 | position: absolute; 148 | top: 0; 149 | left: 0; 150 | content: @slick-dot-character; 151 | width: 20px; 152 | height: 20px; 153 | font-family: @slick-font-family; 154 | font-size: @slick-dot-size; 155 | line-height: 20px; 156 | text-align: center; 157 | color: @slick-dot-color; 158 | opacity: @slick-opacity-not-active; 159 | -webkit-font-smoothing: antialiased; 160 | -moz-osx-font-smoothing: grayscale; 161 | } 162 | } 163 | &.slick-active button:before { 164 | color: @slick-dot-color-active; 165 | opacity: @slick-opacity-default; 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/slick-theme.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | // Default Variables 4 | 5 | // Slick icon entity codes outputs the following 6 | // "\2190" outputs ascii character "←" 7 | // "\2192" outputs ascii character "→" 8 | // "\2022" outputs ascii character "•" 9 | 10 | $slick-font-path: "./fonts/" !default; 11 | $slick-font-family: "slick" !default; 12 | $slick-loader-path: "./" !default; 13 | $slick-arrow-color: white !default; 14 | $slick-dot-color: black !default; 15 | $slick-dot-color-active: $slick-dot-color !default; 16 | $slick-prev-character: "\2190" !default; 17 | $slick-next-character: "\2192" !default; 18 | $slick-dot-character: "\2022" !default; 19 | $slick-dot-size: 6px !default; 20 | $slick-opacity-default: 0.75 !default; 21 | $slick-opacity-on-hover: 1 !default; 22 | $slick-opacity-not-active: 0.25 !default; 23 | 24 | @function slick-image-url($url) { 25 | @if function-exists(image-url) { 26 | @return image-url($url); 27 | } 28 | @else { 29 | @return url($slick-loader-path + $url); 30 | } 31 | } 32 | 33 | @function slick-font-url($url) { 34 | @if function-exists(font-url) { 35 | @return font-url($url); 36 | } 37 | @else { 38 | @return url($slick-font-path + $url); 39 | } 40 | } 41 | 42 | /* Slider */ 43 | 44 | .slick-list { 45 | .slick-loading & { 46 | background: #fff slick-image-url("ajax-loader.gif") center center no-repeat; 47 | } 48 | } 49 | 50 | /* Icons */ 51 | @if $slick-font-family == "slick" { 52 | @font-face { 53 | font-family: "slick"; 54 | src: slick-font-url("slick.eot"); 55 | src: slick-font-url("slick.eot?#iefix") format("embedded-opentype"), slick-font-url("slick.woff") format("woff"), slick-font-url("slick.ttf") format("truetype"), slick-font-url("slick.svg#slick") format("svg"); 56 | font-weight: normal; 57 | font-style: normal; 58 | } 59 | } 60 | 61 | /* Arrows */ 62 | 63 | .slick-prev, 64 | .slick-next { 65 | position: absolute; 66 | display: block; 67 | height: 20px; 68 | width: 20px; 69 | line-height: 0px; 70 | font-size: 0px; 71 | cursor: pointer; 72 | background: transparent; 73 | color: transparent; 74 | top: 50%; 75 | -webkit-transform: translate(0, -50%); 76 | -ms-transform: translate(0, -50%); 77 | transform: translate(0, -50%); 78 | padding: 0; 79 | border: none; 80 | outline: none; 81 | &:hover, &:focus { 82 | outline: none; 83 | background: transparent; 84 | color: transparent; 85 | &:before { 86 | opacity: $slick-opacity-on-hover; 87 | } 88 | } 89 | &.slick-disabled:before { 90 | opacity: $slick-opacity-not-active; 91 | } 92 | &:before { 93 | font-family: $slick-font-family; 94 | font-size: 20px; 95 | line-height: 1; 96 | color: $slick-arrow-color; 97 | opacity: $slick-opacity-default; 98 | -webkit-font-smoothing: antialiased; 99 | -moz-osx-font-smoothing: grayscale; 100 | } 101 | } 102 | 103 | .slick-prev { 104 | left: -25px; 105 | [dir="rtl"] & { 106 | left: auto; 107 | right: -25px; 108 | } 109 | &:before { 110 | content: $slick-prev-character; 111 | [dir="rtl"] & { 112 | content: $slick-next-character; 113 | } 114 | } 115 | } 116 | 117 | .slick-next { 118 | right: -25px; 119 | [dir="rtl"] & { 120 | left: -25px; 121 | right: auto; 122 | } 123 | &:before { 124 | content: $slick-next-character; 125 | [dir="rtl"] & { 126 | content: $slick-prev-character; 127 | } 128 | } 129 | } 130 | 131 | /* Dots */ 132 | 133 | .slick-dotted.slick-slider { 134 | margin-bottom: 30px; 135 | } 136 | 137 | .slick-dots { 138 | position: absolute; 139 | bottom: -25px; 140 | list-style: none; 141 | display: block; 142 | text-align: center; 143 | padding: 0; 144 | margin: 0; 145 | width: 100%; 146 | li { 147 | position: relative; 148 | display: inline-block; 149 | height: 20px; 150 | width: 20px; 151 | margin: 0 5px; 152 | padding: 0; 153 | cursor: pointer; 154 | button { 155 | border: 0; 156 | background: transparent; 157 | display: block; 158 | height: 20px; 159 | width: 20px; 160 | outline: none; 161 | line-height: 0px; 162 | font-size: 0px; 163 | color: transparent; 164 | padding: 5px; 165 | cursor: pointer; 166 | &:hover, &:focus { 167 | outline: none; 168 | &:before { 169 | opacity: $slick-opacity-on-hover; 170 | } 171 | } 172 | &:before { 173 | position: absolute; 174 | top: 0; 175 | left: 0; 176 | content: $slick-dot-character; 177 | width: 20px; 178 | height: 20px; 179 | font-family: $slick-font-family; 180 | font-size: $slick-dot-size; 181 | line-height: 20px; 182 | text-align: center; 183 | color: $slick-dot-color; 184 | opacity: $slick-opacity-not-active; 185 | -webkit-font-smoothing: antialiased; 186 | -moz-osx-font-smoothing: grayscale; 187 | } 188 | } 189 | &.slick-active button:before { 190 | color: $slick-dot-color-active; 191 | opacity: $slick-opacity-default; 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/slick.css: -------------------------------------------------------------------------------- 1 | /* Slider */ 2 | .slick-slider 3 | { 4 | position: relative; 5 | 6 | display: block; 7 | box-sizing: border-box; 8 | 9 | -webkit-user-select: none; 10 | -moz-user-select: none; 11 | -ms-user-select: none; 12 | user-select: none; 13 | 14 | -webkit-touch-callout: none; 15 | -khtml-user-select: none; 16 | -ms-touch-action: pan-y; 17 | touch-action: pan-y; 18 | -webkit-tap-highlight-color: transparent; 19 | } 20 | 21 | .slick-list 22 | { 23 | position: relative; 24 | 25 | display: block; 26 | overflow: hidden; 27 | 28 | margin: 0; 29 | padding: 0; 30 | } 31 | .slick-list:focus 32 | { 33 | outline: none; 34 | } 35 | .slick-list.dragging 36 | { 37 | cursor: pointer; 38 | cursor: hand; 39 | } 40 | 41 | .slick-slider .slick-track, 42 | .slick-slider .slick-list 43 | { 44 | -webkit-transform: translate3d(0, 0, 0); 45 | -moz-transform: translate3d(0, 0, 0); 46 | -ms-transform: translate3d(0, 0, 0); 47 | -o-transform: translate3d(0, 0, 0); 48 | transform: translate3d(0, 0, 0); 49 | } 50 | 51 | .slick-track 52 | { 53 | position: relative; 54 | top: 0; 55 | left: 0; 56 | 57 | display: block; 58 | margin-left: auto; 59 | margin-right: auto; 60 | } 61 | .slick-track:before, 62 | .slick-track:after 63 | { 64 | display: table; 65 | 66 | content: ''; 67 | } 68 | .slick-track:after 69 | { 70 | clear: both; 71 | } 72 | .slick-loading .slick-track 73 | { 74 | visibility: hidden; 75 | } 76 | 77 | .slick-slide 78 | { 79 | display: none; 80 | float: left; 81 | 82 | height: 100%; 83 | min-height: 1px; 84 | } 85 | [dir='rtl'] .slick-slide 86 | { 87 | float: right; 88 | } 89 | .slick-slide img 90 | { 91 | display: block; 92 | } 93 | .slick-slide.slick-loading img 94 | { 95 | display: none; 96 | } 97 | .slick-slide.dragging img 98 | { 99 | pointer-events: none; 100 | } 101 | .slick-initialized .slick-slide 102 | { 103 | display: block; 104 | } 105 | .slick-loading .slick-slide 106 | { 107 | visibility: hidden; 108 | } 109 | .slick-vertical .slick-slide 110 | { 111 | display: block; 112 | 113 | height: auto; 114 | 115 | border: 1px solid transparent; 116 | } 117 | .slick-arrow.slick-hidden { 118 | display: none; 119 | } 120 | -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/slick.less: -------------------------------------------------------------------------------- 1 | /* Slider */ 2 | 3 | .slick-slider { 4 | position: relative; 5 | display: block; 6 | box-sizing: border-box; 7 | -webkit-touch-callout: none; 8 | -webkit-user-select: none; 9 | -khtml-user-select: none; 10 | -moz-user-select: none; 11 | -ms-user-select: none; 12 | user-select: none; 13 | -ms-touch-action: pan-y; 14 | touch-action: pan-y; 15 | -webkit-tap-highlight-color: transparent; 16 | } 17 | .slick-list { 18 | position: relative; 19 | overflow: hidden; 20 | display: block; 21 | margin: 0; 22 | padding: 0; 23 | 24 | &:focus { 25 | outline: none; 26 | } 27 | 28 | &.dragging { 29 | cursor: pointer; 30 | cursor: hand; 31 | } 32 | } 33 | .slick-slider .slick-track, 34 | .slick-slider .slick-list { 35 | -webkit-transform: translate3d(0, 0, 0); 36 | -moz-transform: translate3d(0, 0, 0); 37 | -ms-transform: translate3d(0, 0, 0); 38 | -o-transform: translate3d(0, 0, 0); 39 | transform: translate3d(0, 0, 0); 40 | } 41 | 42 | .slick-track { 43 | position: relative; 44 | left: 0; 45 | top: 0; 46 | display: block; 47 | margin-left: auto; 48 | margin-right: auto; 49 | 50 | &:before, 51 | &:after { 52 | content: ""; 53 | display: table; 54 | } 55 | 56 | &:after { 57 | clear: both; 58 | } 59 | 60 | .slick-loading & { 61 | visibility: hidden; 62 | } 63 | } 64 | .slick-slide { 65 | float: left; 66 | height: 100%; 67 | min-height: 1px; 68 | [dir="rtl"] & { 69 | float: right; 70 | } 71 | img { 72 | display: block; 73 | } 74 | &.slick-loading img { 75 | display: none; 76 | } 77 | 78 | display: none; 79 | 80 | &.dragging img { 81 | pointer-events: none; 82 | } 83 | 84 | .slick-initialized & { 85 | display: block; 86 | } 87 | 88 | .slick-loading & { 89 | visibility: hidden; 90 | } 91 | 92 | .slick-vertical & { 93 | display: block; 94 | height: auto; 95 | border: 1px solid transparent; 96 | } 97 | } 98 | .slick-arrow.slick-hidden { 99 | display: none; 100 | } 101 | -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/libs/slick/slick.scss: -------------------------------------------------------------------------------- 1 | /* Slider */ 2 | 3 | .slick-slider { 4 | position: relative; 5 | display: block; 6 | box-sizing: border-box; 7 | -webkit-touch-callout: none; 8 | -webkit-user-select: none; 9 | -khtml-user-select: none; 10 | -moz-user-select: none; 11 | -ms-user-select: none; 12 | user-select: none; 13 | -ms-touch-action: pan-y; 14 | touch-action: pan-y; 15 | -webkit-tap-highlight-color: transparent; 16 | } 17 | .slick-list { 18 | position: relative; 19 | overflow: hidden; 20 | display: block; 21 | margin: 0; 22 | padding: 0; 23 | 24 | &:focus { 25 | outline: none; 26 | } 27 | 28 | &.dragging { 29 | cursor: pointer; 30 | cursor: hand; 31 | } 32 | } 33 | .slick-slider .slick-track, 34 | .slick-slider .slick-list { 35 | -webkit-transform: translate3d(0, 0, 0); 36 | -moz-transform: translate3d(0, 0, 0); 37 | -ms-transform: translate3d(0, 0, 0); 38 | -o-transform: translate3d(0, 0, 0); 39 | transform: translate3d(0, 0, 0); 40 | } 41 | 42 | .slick-track { 43 | position: relative; 44 | left: 0; 45 | top: 0; 46 | display: block; 47 | margin-left: auto; 48 | margin-right: auto; 49 | 50 | &:before, 51 | &:after { 52 | content: ""; 53 | display: table; 54 | } 55 | 56 | &:after { 57 | clear: both; 58 | } 59 | 60 | .slick-loading & { 61 | visibility: hidden; 62 | } 63 | } 64 | .slick-slide { 65 | float: left; 66 | height: 100%; 67 | min-height: 1px; 68 | [dir="rtl"] & { 69 | float: right; 70 | } 71 | img { 72 | display: block; 73 | } 74 | &.slick-loading img { 75 | display: none; 76 | } 77 | 78 | display: none; 79 | 80 | &.dragging img { 81 | pointer-events: none; 82 | } 83 | 84 | .slick-initialized & { 85 | display: block; 86 | } 87 | 88 | .slick-loading & { 89 | visibility: hidden; 90 | } 91 | 92 | .slick-vertical & { 93 | display: block; 94 | height: auto; 95 | border: 1px solid transparent; 96 | } 97 | } 98 | .slick-arrow.slick-hidden { 99 | display: none; 100 | } 101 | -------------------------------------------------------------------------------- /Quill Project 003 - Carousel/styles.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0px; 3 | padding: 0px; 4 | } 5 | 6 | #all{ 7 | margin: 50px; 8 | } 9 | 10 | /* See: https://stackoverflow.com/a/9314458 */ 11 | .noselect { 12 | -webkit-touch-callout: none; /* iOS Safari */ 13 | -webkit-user-select: none; /* Safari */ 14 | -khtml-user-select: none; /* Konqueror HTML */ 15 | -moz-user-select: none; /* Firefox */ 16 | -ms-user-select: none; /* Internet Explorer/Edge */ 17 | user-select: none; /* Non-prefixed version, currently 18 | supported by Chrome and Opera */ 19 | } 20 | 21 | /* ################################################################################ */ 22 | /* TOOLTIP */ 23 | /* ################################################################################ */ 24 | 25 | /* ############################ */ 26 | /* Image Tooltip (container) */ 27 | /* ############################ */ 28 | 29 | .tooltip-img-slider-container { 30 | width: 300px; 31 | position: absolute; 32 | z-index: 999; 33 | display: none; 34 | background: white; 35 | border: 1px solid #ccc; 36 | box-shadow: 0px 0px 5px #ddd; 37 | font-family: Helvetica, Arial, sans-serif; 38 | } 39 | 40 | .tooltip-img-slider-container svg { 41 | display: block; 42 | margin: 0 auto; 43 | } 44 | 45 | /* ############################ */ 46 | /* Header Buttons */ 47 | /* ############################ */ 48 | 49 | .tooltip-img-slider-header { 50 | padding: 6px; 51 | display: flex; 52 | } 53 | 54 | .tooltip-img-slider-header #title{ 55 | flex-grow: 2; 56 | margin-left: 6px; 57 | margin-right: 6px; 58 | line-height: 26px; 59 | color: #606060; 60 | } 61 | 62 | .tooltip-img-slider-header #mover{ 63 | /*flex-grow: 1;*/ 64 | width: 80px; 65 | margin-right: 6px; 66 | cursor: grab; 67 | 68 | color: #8d8d8d; 69 | border: solid 1px #8d8d8d; 70 | margin-right: 6px; 71 | text-align: center; 72 | line-height: 26px; 73 | } 74 | 75 | .tooltip-img-slider-header #conclude{ 76 | /*flex-grow: 1;*/ 77 | width: 80px; 78 | cursor: pointer; 79 | 80 | color: #1abc9c; 81 | border: solid 1px #1abc9c; 82 | background: none; 83 | } 84 | 85 | .tooltip-img-slider-header #mover:hover{ background: #f1f1f1; } 86 | .tooltip-img-slider-header #mover:active { 87 | cursor: grabbing; 88 | background: none; 89 | border-color: #f7b97e; 90 | color: #f7b97e; 91 | } 92 | 93 | .tooltip-img-slider-header #conclude:hover{ background: #bdf5ea; } 94 | 95 | /* ############################ */ 96 | /* Tab and tab buttons */ 97 | /* ############################ */ 98 | 99 | .tooltip-img-slider-tabs { 100 | display: flex; 101 | } 102 | 103 | .tooltip-img-slider-tabs button { 104 | width: 50%; /* better than... 105 | flex-grow: 1;*/ 106 | 107 | background: #f1f1f1; 108 | border-bottom: solid 1px #ccc; 109 | border-top: solid 1px #ccc; 110 | border-left: none; 111 | border-right: none; 112 | outline: none; 113 | cursor: pointer; 114 | padding: 10px 10px; 115 | color: #606060; 116 | } 117 | 118 | .tooltip-img-slider-tabs .active-tab { 119 | background: #ccc; 120 | } 121 | 122 | .tooltip-img-slider-tabs button:nth-child(1) { 123 | border-right: solid 1px #ccc; 124 | } 125 | 126 | .tooltip-img-slider-tabs button:hover { 127 | background: #ddd; 128 | } 129 | 130 | /* ############################ */ 131 | /* Config */ 132 | /* ############################ */ 133 | 134 | .tooltip-img-slider-config { 135 | padding: 6px; 136 | } 137 | 138 | .tooltip-img-slider-config .config-container { 139 | border: solid 1px #ccc; 140 | padding: 8px; 141 | } 142 | 143 | .tooltip-img-slider-config .one-column-config { 144 | width: 100%; 145 | margin-bottom: 6px; 146 | } 147 | 148 | .tooltip-img-slider-config .bottom-container { 149 | display: flex; 150 | } 151 | 152 | .tooltip-img-slider-config .two-column-config { 153 | width: 50%; /* better than... 154 | flex-grow: 1;*/ 155 | } 156 | 157 | /* First column */ 158 | .tooltip-img-slider-config .two-column-config:nth-child(1) { 159 | margin-right: 6px; 160 | } 161 | 162 | .tooltip-img-slider-config .config-value { 163 | float: right; 164 | } 165 | 166 | .tooltip-img-slider-config .two-column-config input { 167 | display: block; 168 | width: 100%; 169 | margin-top: 6px; 170 | } 171 | 172 | /* SWITCHER SLIDER */ 173 | 174 | /* The switch - the box around the slider */ 175 | .switcher { 176 | position: relative; 177 | /* display: inline-block; */ 178 | width: 50px; 179 | height: 22px; 180 | float: right; 181 | top: -3px; 182 | } 183 | 184 | /* Hide default HTML checkbox */ 185 | .switcher input { 186 | opacity: 0; 187 | width: 0; 188 | height: 0; 189 | } 190 | 191 | /* The slider */ 192 | .slider { 193 | position: absolute; 194 | cursor: pointer; 195 | top: 0; 196 | left: 0; 197 | right: 0; 198 | bottom: 0; 199 | background-color: #ccc; 200 | -webkit-transition: .2s; 201 | transition: .2s; 202 | } 203 | 204 | /* The real slider */ 205 | .slider:before { 206 | position: absolute; 207 | content: ""; 208 | height: 16px; 209 | width: 16px; 210 | left: 3px; 211 | top: 3px; 212 | background-color: white; 213 | -webkit-transition: .2s; 214 | transition: .2s; 215 | } 216 | 217 | .switcher input:checked + .slider { 218 | background-color: #99ff99; 219 | } 220 | 221 | .switcher input:focus + .slider { 222 | box-shadow: 0 0 1px #99ff99; 223 | } 224 | 225 | .switcher input:checked + .slider:before { 226 | -webkit-transform: translateX(28px); 227 | -ms-transform: translateX(28px); 228 | transform: translateX(28px); 229 | } 230 | 231 | /* ############################ */ 232 | /* Image Fields */ 233 | /* ############################ */ 234 | 235 | .tooltip-img-slider-images{ 236 | padding: 6px; 237 | } 238 | 239 | .tooltip-img-slider-images-buttons { 240 | display: flex; 241 | } 242 | 243 | .tooltip-img-slider-images-buttons button { 244 | width: 50%;/* better than... 245 | flex-grow: 1;*/ 246 | 247 | height: 28px; 248 | } 249 | 250 | /* Botão de novo campo. */ 251 | .tooltip-img-slider-images-buttons #button-new-field { 252 | cursor: pointer; 253 | color: #1abc9c; 254 | border: solid 1px #1abc9c; 255 | background: none; 256 | } 257 | 258 | .tooltip-img-slider-images-buttons #button-new-field:hover { background: #bdf5ea; } 259 | 260 | /* Botão de limpeza de campos. */ 261 | .tooltip-img-slider-images-buttons #button-clear-fields { 262 | cursor: pointer; 263 | color: #FAA954; 264 | border: solid 1px #FAA954; 265 | background: none; 266 | margin-left: 6px; 267 | } 268 | 269 | .tooltip-img-slider-images-buttons #button-clear-fields:hover { background: #ffeedd; } 270 | 271 | .tooltip-img-slider-images-fields .img-field { 272 | display: flex; 273 | margin-top: 6px; 274 | border: solid 1px #ccc; 275 | border-radius: 2px; 276 | height: 28px; 277 | } 278 | 279 | .tooltip-img-slider-images-fields input { 280 | flex-grow: 2; 281 | padding-left: 6px; 282 | height: 100%; 283 | border: none; 284 | } 285 | 286 | .tooltip-img-slider-images-fields button { 287 | cursor: pointer; 288 | width: 28px; 289 | height: 28px; 290 | 291 | background: none; 292 | border: none; 293 | } 294 | 295 | .tooltip-img-slider-images-fields .x-icon { 296 | fill: #ff8989; 297 | } 298 | 299 | .tooltip-img-slider-images-fields button:hover .x-icon, 300 | .tooltip-img-slider-images-fields .x-icon:hover { 301 | fill: #ffaaaa; 302 | } 303 | 304 | /* ################################################################################ */ 305 | /* BLOT AND SLICK */ 306 | /* ################################################################################ */ 307 | 308 | .ql-slider-images { 309 | width: 90%; 310 | margin: 0 auto; 311 | } 312 | 313 | /* Container interno do slick que contém slides (.slick-slide). */ 314 | /* 315 | .slick-track { 316 | display: flex !important; 317 | } 318 | */ 319 | 320 | /* Slides de container interno do slick (.slick-track). */ 321 | 322 | .slick-track { 323 | display: flex; 324 | } 325 | 326 | .slick-slide { 327 | display: flex; 328 | height: auto; 329 | align-items: center; 330 | justify-content: center; 331 | } 332 | 333 | /* 334 | .slick-prev, 335 | .slick-next{ 336 | background: #db6262; 337 | } 338 | */ 339 | 340 | .slick-prev::before, 341 | .slick-next::before { 342 | color:#ccc; 343 | } 344 | 345 | /* 346 | .ql-slider-images:active { 347 | background: #1abc9c; 348 | } 349 | */ 350 | 351 | /* ################################################################################ */ 352 | /* TABS */ 353 | /* ################################################################################ */ 354 | 355 | /* Style the tab */ 356 | .tab { 357 | overflow: hidden; 358 | border: 1px solid #ccc; 359 | background-color: #f1f1f1; 360 | } 361 | 362 | /* Style the buttons that are used to open the tab content */ 363 | .tab button { 364 | background-color: inherit; 365 | float: left; 366 | border: none; 367 | outline: none; 368 | cursor: pointer; 369 | padding: 14px 16px; 370 | transition: 0.3s; 371 | } 372 | 373 | /* Change background color of buttons on hover */ 374 | .tab button:hover { 375 | background-color: #ddd; 376 | } 377 | 378 | /* Create an active/current tablink class */ 379 | .tab button.active { 380 | background-color: #ccc; 381 | } 382 | 383 | /* Style the tab content */ 384 | .tab-content { 385 | display: none; 386 | padding: 6px 12px; 387 | border: 1px solid #ccc; 388 | border-top: none; 389 | } 390 | 391 | 392 | /*###################### */ 393 | /* DELTA, TEXT AND HTML */ 394 | /*###################### */ 395 | 396 | #tab-content-delta, 397 | #tab-content-html, 398 | #tab-content-text { 399 | padding: 0px; 400 | } 401 | 402 | pre{ 403 | white-space: normal; 404 | } 405 | 406 | code{ 407 | white-space: pre-wrap; 408 | } 409 | 410 | #tab-content-delta p{ 411 | font-family: Candara; 412 | } 413 | -------------------------------------------------------------------------------- /Quill Project 004 - Customizable Tooltip/app.js: -------------------------------------------------------------------------------- 1 | // ################################################################################# 2 | // LOWER TABS - DELTA, TEXT AND HTML 3 | // ################################################################################# 4 | 5 | /** See: https://www.w3schools.com/howto/howto_js_tabs.asp */ 6 | function openTab(evt, tabName) { 7 | // Declare all variables 8 | var i, tabcontent, tabButtons; 9 | 10 | // Get all elements with class="tabcontent" and hide them 11 | tabcontent = document.getElementsByClassName("tab-content"); 12 | for (i = 0; i < tabcontent.length; i++) { 13 | tabcontent[i].style.display = "none"; 14 | } 15 | 16 | // Get all elements with class="tab-button" and remove the class "active" 17 | tabButtons = document.getElementsByClassName("tab-button"); 18 | for (i = 0; i < tabButtons.length; i++) { 19 | tabButtons[i].className = tabButtons[i].className.replace(" active", ""); 20 | } 21 | 22 | // Show the current tab, and add an "active" class to the button that opened the tab 23 | let openTabContent = document.getElementById(tabName); 24 | openTabContent.style.display = "block"; 25 | evt.currentTarget.className += " active"; 26 | 27 | updateOpenTab(openTabContent); 28 | } 29 | 30 | function updateOpenTab(tabContent) { 31 | if (!tabContent) { 32 | if (!(tabContent = getActiveTabContent())) return false; 33 | } 34 | 35 | // DELTA 36 | if (tabContent.id === 'tab-content-delta') { 37 | // Set delta length (#tab-content-delta > p) 38 | let p = tabContent.children[0]; 39 | p.innerHTML = 'Size: ' + quill.getLength(); 40 | p.style.padding = '4px 6px'; 41 | 42 | // Set data (#tab-content-delta > pre > code) 43 | let code = tabContent.children[1].children[0]; 44 | code.innerHTML = JSON.stringify(getContentDelta(), null, 2); 45 | 46 | hljs.highlightBlock(code); 47 | } 48 | // TEXT 49 | if (tabContent.id === 'tab-content-text') { 50 | // #tab-contnet-text > pre > code 51 | let code = tabContent.children[0].children[0]; 52 | code.innerHTML = getContentText(); 53 | 54 | hljs.highlightBlock(code); 55 | } 56 | // HTML 57 | if (tabContent.id === 'tab-content-html') { 58 | // #tab-content-html > pre > code 59 | let code = tabContent.children[0].children[0]; 60 | code.innerHTML = getContentHTML().replace(/ -1; 89 | } 90 | 91 | /** See: https://quilljs.com/docs/api/#getcontents */ 92 | function getContentDelta() { 93 | return quill.getContents(); 94 | } 95 | 96 | /** See: https://github.com/quilljs/quill/issues/2698 */ 97 | function getContentText() { 98 | return quill.getContents().ops.reduce((text, op) => { 99 | if (typeof op.insert === 'string') { 100 | return text + op.insert; 101 | } 102 | // If it is not a string, the newline character is set, which has 103 | // a length of only 1 character. 104 | else { 105 | return text + '\n'; 106 | } 107 | }, ''); 108 | } 109 | 110 | /** See: https://github.com/quilljs/quill/issues/903#issuecomment-243844178 */ 111 | function getContentHTML() { 112 | return quill.root.innerHTML; 113 | } 114 | 115 | function extractVideoUrl(url) { 116 | let match = 117 | url.match(/^(?:(https?):\/\/)?(?:(?:www|m)\.)?youtube\.com\/watch.*v=([a-zA-Z0-9_-]+)/,) || 118 | url.match(/^(?:(https?):\/\/)?(?:(?:www|m)\.)?youtu\.be\/([a-zA-Z0-9_-]+)/); 119 | 120 | if (match) { 121 | return `${match[1] || 'https'}://www.youtube.com/embed/${match[2]}?showinfo=0`; 122 | } 123 | 124 | // eslint-disable-next-line no-cond-assign 125 | if ((match = url.match(/^(?:(https?):\/\/)?(?:www\.)?vimeo\.com\/(\d+)/))) { 126 | return `${match[1] || 'https'}://player.vimeo.com/video/${match[2]}/`; 127 | } 128 | 129 | return url; 130 | } 131 | 132 | // ################################################################################# 133 | // TOOLTIP 134 | // ################################################################################# 135 | 136 | /** Customizable tooltip, which follows the same design as Quill Editor's native 137 | * tooltip. Below are all the configurations that can be made, as well as a 138 | * description of what each one represents. 139 | * 140 | * [OPTIONS] 141 | * format = The format to be worked by tooltip. 142 | * inputLabel = Left label given to value input. 143 | * inputLabelClass = Overrides CSS class for value input label styling. 144 | * inputPlaceholder = Value input placeholder text (). 145 | * inputClass = Overrides CSS class for value input styling. 146 | * actionText = Text for action "button" to the right of value input. 147 | * actionClass = Overrides CSS class for action text (the "button"). 148 | * containerClass = Replaces CSS class for element that contains all others. 149 | * hideOnTyping = If true, tooltip will be hidden when typing in Quill. 150 | * hideOnAction = If true, tooltip will be hidden by clicking action text. 151 | * clearAfterHide = If true, the value input has its text cleared after tooltip is hidden. 152 | * defaultValue = Defines a default value for value input. If set, clearAfterHide is always false. 153 | * onAction = Function called when action text is clicked by the user. Setting a value for this property makes the user responsible for the tooltip action. 154 | * onShow = Function called when tooltip is revealed. 155 | * onHide = Function called when tooltip is hidden. 156 | */ 157 | class CustomizableTooltip { 158 | constructor(format , quill , options) { 159 | // Is everything ok here? 160 | this.checkState(format , quill); 161 | this.checkOptions(options); 162 | 163 | // Everything seems ok here... 164 | this.quill = quill; 165 | this.format = format; 166 | 167 | // Lets build... 168 | this.buildInterface(); 169 | 170 | var thisTooltip = this; 171 | this.quill.getModule("toolbar").addHandler(this.format , function(){ 172 | thisTooltip.toolbarButtonPressed(); 173 | }); 174 | 175 | this.quill.container.appendChild(this.container); 176 | this.hide(); 177 | } 178 | 179 | // This prevents a surprise from appearing while using the editor. If a 180 | // problem exists, it will appear when the tooltip is being built. 181 | checkState(format , quill) { 182 | // Is Quill reference useful? 183 | if (quill === null || typeof quill !== 'object') 184 | throw 'Quill reference was not passed in argument, or is null.'; 185 | 186 | // Was the format specified? 187 | if(!format || format.length <= 0) 188 | throw 'No format was specified.'; 189 | 190 | // Is the format registered? 191 | if(!Quill.import('formats/' + format)) 192 | throw 'No format "' + format + '" found. Please, be sure to pass a format that is registered within Quill.'; 193 | } 194 | 195 | /** Checks whether properties have been set correctly, or need to be 196 | * overwritten if not. */ 197 | checkOptions(options) { 198 | if (!options || options == null) options = {}; 199 | 200 | if (!options.inputLabel || options.inputLabel.length <= 0) 201 | options.inputLabel = 'Value'; 202 | if (!options.inputLabelClass || options.inputLabelClass.length <= 0) 203 | options.inputLabelClass = 'rs-tooltip-label'; 204 | if (!options.inputPlaceholer || options.inputPlaceholer.left <= 0) 205 | options.inputPlaceholer = 'Insert value here...'; 206 | if (!options.inputClass || options.inputClass.length <= 0) 207 | options.inputClass = 'rs-tooltip-input'; 208 | if (!options.actionText || options.actionText.length <= 0) 209 | options.actionText = 'Conclude'; 210 | if (!options.actionClass || options.actionClass.length <= 0) 211 | options.actionClass = 'rs-tooltip-action'; 212 | if (!options.containerClass || options.containerClass.length <= 0) 213 | options.containerClass = 'rs-tooltip-container'; 214 | if (!options.hideOnTyping) 215 | options.hideOnTyping = false; 216 | if (options.clearAfterHide && options.defaultValue && options.defaultValue.length >= 0) 217 | options.clearAfterHide = false; 218 | if (!options.hideOnAction || options.hideOnAction == false) 219 | options.hideOnAction = true; 220 | 221 | this.op = options; 222 | } 223 | 224 | buildInterface() { 225 | this.buildContainer(); 226 | this.buildInputLabel(); 227 | this.buildInput(); 228 | this.buildAction(); 229 | 230 | // Adds built elements into this tooltip container. 231 | this.container.appendChild(this.inputLabel); 232 | this.container.appendChild(this.input); 233 | this.container.appendChild(this.action); 234 | } 235 | 236 | buildContainer() { 237 | var thisTooltip = this; 238 | var container = document.createElement('DIV'); 239 | container.classList.add(this.op.containerClass); 240 | 241 | // Hide tooltip by clicking outside of it. 242 | document.body.addEventListener('click', event => { 243 | // Was it clicked off? 244 | if (!hasClass(event.target, thisTooltip.op.containerClass)) { 245 | // Prevents tooltip from ever appearing if its button is clicked. 246 | // The button can have several internal elements. You can even 247 | // click on the SVG element without clicking the button (the 248 | // button icon, or the elements representing the icon). We take 249 | // this into account with closest, and verify that in addition 250 | // to the button, some element of it has been clicked. 251 | if (hasClass(event.target , 'ql-' + thisTooltip.format) || 252 | event.target.closest('.ql-' + thisTooltip.format)) { 253 | return; 254 | } 255 | 256 | thisTooltip.hide(); 257 | } 258 | }); 259 | 260 | // Prevents tooltip from being hidden if its content is clicked. 261 | container.addEventListener('click', event => { 262 | event.stopPropagation(); 263 | }); 264 | 265 | // Hide tooltip when typing text in the editor. 266 | if (this.op.hideOnTyping) { 267 | this.quill.on('text-change', function (delta, oldDelta, source) { 268 | if (source === 'user') { 269 | thisTooltip.hide(); 270 | } 271 | }); 272 | } 273 | 274 | this.container = container; 275 | } 276 | 277 | buildInputLabel() { 278 | var label = document.createElement('SPAN'); 279 | label.innerText = this.op.inputLabel; 280 | label.classList.add(this.op.inputLabelClass); 281 | 282 | this.inputLabel = label; 283 | } 284 | 285 | buildInput() { 286 | var thisTooltip = this; 287 | var input = document.createElement('INPUT'); 288 | input.type = 'text'; 289 | input.classList.add(this.op.inputClass); 290 | input.placeholder = this.op.inputPlaceholer; 291 | input.value = this.op.defaultValue && this.op.defaultValue.length > 0 ? 292 | this.op.defaultValue : 293 | ''; 294 | 295 | // Has the user added an event of his own to this tooltip? If so, it 296 | // will be called as a priority. 297 | if (this.op.onAction && typeof this.op.onAction === 'function') { 298 | input.addEventListener('keydown', e => { 299 | if (e.key === 'Enter') { 300 | this.op.onAction(input.value, e); 301 | if(thisTooltip.op.hideOnAction) thisTooltip.hide(); 302 | } 303 | }); 304 | } 305 | // Otherwise, the tooltip calls the default implementation. It is 306 | // understood that the user knows how this tooltip works, and has 307 | // configured it correctly. 308 | else { 309 | input.addEventListener('keydown', e => { 310 | if (e.key === 'Enter') { 311 | thisTooltip.insertEmbed(input.value , e); 312 | if(thisTooltip.op.hideOnAction) thisTooltip.hide(); 313 | } 314 | }); 315 | } 316 | 317 | this.input = input; 318 | } 319 | 320 | buildAction() { 321 | var thisTooltip = this; 322 | var linkAction = document.createElement('a'); 323 | linkAction.innerText = this.op.actionText; 324 | linkAction.classList.add(this.op.actionClass); 325 | 326 | // Has the user added an event of his own to this tooltip? If so, it 327 | // will be called as a priority. 328 | if (this.op.onAction && typeof this.op.onAction === 'function') { 329 | linkAction.addEventListener('click', e => { 330 | this.op.onAction(thisTooltip.input.value, e); 331 | if(thisTooltip.op.hideOnAction) thisTooltip.hide(); 332 | }); 333 | } 334 | // Otherwise, the tooltip calls the default implementation. It is 335 | // understood that the user knows how this tooltip works, and has 336 | // configured it correctly. 337 | else { 338 | linkAction.addEventListener('click', e => { 339 | thisTooltip.insertEmbed(thisTooltip.input.value , e); 340 | if(thisTooltip.op.hideOnAction) thisTooltip.hide(); 341 | }); 342 | } 343 | 344 | this.action = linkAction; 345 | } 346 | 347 | toolbarButtonPressed() { 348 | if (this.isVisible()) { 349 | this.hide(); 350 | return; 351 | } 352 | 353 | this.show(); 354 | } 355 | 356 | // Created for the convenience of client code. Not necessarily this needs to be utilized. 357 | setInputLabel(label) { 358 | if (!label || label.length <= 0) return; 359 | this.inputLabel.innerText = label; 360 | } 361 | 362 | // Created for the convenience of client code. Not necessarily this needs to be utilized. 363 | setActionLabel(label) { 364 | if (!label || label.length <= 0) return; 365 | this.action.innerText = label; 366 | } 367 | 368 | // Created for the convenience of client code. Not necessarily this needs to be utilized. 369 | setInputValue(value) { 370 | if (!value || value.length <= 0) return; 371 | this.input.value = value; 372 | } 373 | 374 | // Created for the convenience of client code. Not necessarily this needs to be utilized. 375 | setInputPlaceholder(placeholder) { 376 | if (!placeholder || placeholder.length <= 0) return; 377 | this.input.placeholder = placeholder; 378 | } 379 | 380 | // Created for the convenience of client code. Not necessarily this needs to be utilized. 381 | getInputValue() { 382 | return this.input.value; 383 | } 384 | 385 | show() { 386 | if(this.isVisible()) return; 387 | 388 | this.container.classList.remove('ql-hidden'); 389 | this.updatePosition(); 390 | 391 | if (this.op.onShow && typeof onShow === 'function') this.op.onShow(); 392 | } 393 | 394 | hide() { 395 | if(!this.isVisible()) return; 396 | 397 | this.container.classList.add('ql-hidden'); 398 | 399 | if(!this.op.defaultValue && this.op.clearAfterHide) this.input.value = ''; 400 | if (this.op.onHide && typeof onHide === 'function') this.op.onHide(); 401 | } 402 | 403 | isVisible() { 404 | return !hasClass(this.container, 'ql-hidden'); 405 | } 406 | 407 | updatePosition() { 408 | // quill.getBounds return a rectangle based on editor caret position. 409 | // This is where we can locate where the window will appear. The idea 410 | // here is to leave the horizontal center of the tooltip aligned with 411 | // the editor caret (range index). 412 | let range = this.quill.getSelection(); 413 | const bounds = this.quill.getBounds(range.index); 414 | 415 | // Tooltip left edge X. 416 | let x = bounds.left - this.container.offsetWidth / 2; 417 | let editorContainer = document.querySelector('.ql-container'); 418 | 419 | // See: http://javascript.info/coordinates 420 | let leftBorderLimit = editorContainer.getBoundingClientRect().left; 421 | let rightBorderLimit = editorContainer.getBoundingClientRect().right; 422 | 423 | // Corrects left edge. 424 | if ((x * -1) > leftBorderLimit) { 425 | x = x + ((x * -1) - leftBorderLimit); 426 | } 427 | 428 | // Tooltip right edge X. 429 | let widthX = x + this.container.offsetWidth + 2; 430 | 431 | // Corrects right edge. 432 | if (widthX > rightBorderLimit) { 433 | x = x - (widthX - rightBorderLimit); 434 | } 435 | 436 | this.container.style.top = 437 | bounds.top + // Y from upper left edge. 438 | bounds.height + // Caret Height (one line). 439 | 10 + // One more small space to not get too on top. 440 | 'px'; 441 | this.container.style.left = x + 'px'; 442 | } 443 | 444 | insertEmbed(value , e){ 445 | if(!value || value.length <= 0) return; 446 | 447 | var range = this.quill.getSelection(); 448 | if(!range) range = { 449 | index: getContentText().length - 1, 450 | length: 0 451 | }; 452 | 453 | // Unfortunately this line of code needs to be here. I don't understand 454 | // why it is necessary to format the URL when adding video as embed, as 455 | // it should already do this automatically ... 456 | if(this.format === 'video'){ 457 | value = extractVideoUrl(value); 458 | } 459 | 460 | this.quill.insertEmbed( 461 | range.index , 462 | this.format , 463 | value); 464 | } 465 | } 466 | 467 | // ################################################################################# 468 | // MAIN 469 | // ################################################################################# 470 | 471 | $(document).ready(function () { 472 | // No need to create a handler. 473 | var toolbarOptions = { 474 | container: 475 | [['bold', 'italic', 'underline', 'strike'], 476 | ['image', 'video', 'link'], 477 | ['clean']] 478 | }; 479 | 480 | var quill = new Quill('#editor', { 481 | theme: 'snow', 482 | modules: { 483 | 'toolbar': toolbarOptions 484 | } 485 | }); 486 | 487 | // All utility methods that use this global variable will only work with 488 | // the specific newly created instance of Quill. If other Quill instances 489 | // are created, they will continue to work only for the only instance 490 | // already specified. In order for utility methods to work with the new 491 | // instances, changes would need to be made. 492 | window.quill = quill; 493 | 494 | // Just pass the format name with the Quill reference. Of course, for 495 | // better use of this tool, the user can perform additional settings. 496 | // All configurations that can be made are commented in the class 497 | // documentation (up/above class declaration). 498 | var tooltip = new CustomizableTooltip('image' , quill , { 499 | inputLabel: 'Image:' , 500 | inputPlaceholer: 'Image URL...' , 501 | actionText: 'Insert', 502 | hideOnTyping: true, 503 | clearAfterHide: true 504 | }); 505 | 506 | // Open default tab. See: https://www.w3schools.com/howto/howto_js_tabs.asp 507 | const defualtTab = document.getElementById("default-tab-button"); 508 | defualtTab.click(); 509 | 510 | // Quill content alteration. 511 | quill.on('text-change', function (delta, oldDelta, source) { 512 | updateOpenTab(); 513 | }); 514 | }); -------------------------------------------------------------------------------- /Quill Project 004 - Customizable Tooltip/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 | 28 | 29 |
30 | 31 | 32 |
33 | 35 | 36 | 37 |
38 | 39 | 40 |
41 |

...

42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | 52 | 53 | -------------------------------------------------------------------------------- /Quill Project 004 - Customizable Tooltip/libs/highlight/styles/atelier-cave-dark.css: -------------------------------------------------------------------------------- 1 | /* Base16 Atelier Cave Dark - Theme */ 2 | /* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave) */ 3 | /* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ 4 | 5 | /* Atelier-Cave Comment */ 6 | .hljs-comment, 7 | .hljs-quote { 8 | color: #7e7887; 9 | } 10 | 11 | /* Atelier-Cave Red */ 12 | .hljs-variable, 13 | .hljs-template-variable, 14 | .hljs-attribute, 15 | .hljs-regexp, 16 | .hljs-link, 17 | .hljs-tag, 18 | .hljs-name, 19 | .hljs-selector-id, 20 | .hljs-selector-class { 21 | color: #d4b13e; 22 | } 23 | 24 | /* Atelier-Cave Orange */ 25 | .hljs-number, 26 | .hljs-meta, 27 | .hljs-built_in, 28 | .hljs-builtin-name, 29 | .hljs-literal, 30 | .hljs-type, 31 | .hljs-params { 32 | color: #aa573c; 33 | } 34 | 35 | /* Atelier-Cave Green */ 36 | .hljs-string, 37 | .hljs-symbol, 38 | .hljs-bullet { 39 | color: #2a9292; 40 | } 41 | 42 | /* Atelier-Cave Blue */ 43 | .hljs-title, 44 | .hljs-section { 45 | color: #576ddb; 46 | } 47 | 48 | /* Atelier-Cave Purple */ 49 | .hljs-keyword, 50 | .hljs-selector-tag { 51 | color: #955ae7; 52 | } 53 | 54 | .hljs-deletion, 55 | .hljs-addition { 56 | color: #19171c; 57 | display: inline-block; 58 | width: 100%; 59 | } 60 | 61 | .hljs-deletion { 62 | background-color: #be4678; 63 | } 64 | 65 | .hljs-addition { 66 | background-color: #2a9292; 67 | } 68 | 69 | .hljs { 70 | display: block; 71 | overflow-x: auto; 72 | background: #19171c; 73 | color: #8b8792; 74 | padding: 0.5em; 75 | } 76 | 77 | .hljs-emphasis { 78 | font-style: italic; 79 | } 80 | 81 | .hljs-strong { 82 | font-weight: bold; 83 | } 84 | -------------------------------------------------------------------------------- /Quill Project 004 - Customizable Tooltip/libs/quill/quill.core.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Quill Editor v1.3.6 3 | * https://quilljs.com/ 4 | * Copyright (c) 2014, Jason Chen 5 | * Copyright (c) 2013, salesforce.com 6 | */ 7 | .ql-container { 8 | box-sizing: border-box; 9 | font-family: Helvetica, Arial, sans-serif; 10 | font-size: 13px; 11 | height: 100%; 12 | margin: 0px; 13 | position: relative; 14 | } 15 | .ql-container.ql-disabled .ql-tooltip { 16 | visibility: hidden; 17 | } 18 | .ql-container.ql-disabled .ql-editor ul[data-checked] > li::before { 19 | pointer-events: none; 20 | } 21 | .ql-clipboard { 22 | left: -100000px; 23 | height: 1px; 24 | overflow-y: hidden; 25 | position: absolute; 26 | top: 50%; 27 | } 28 | .ql-clipboard p { 29 | margin: 0; 30 | padding: 0; 31 | } 32 | .ql-editor { 33 | box-sizing: border-box; 34 | line-height: 1.42; 35 | height: 100%; 36 | outline: none; 37 | overflow-y: auto; 38 | padding: 12px 15px; 39 | tab-size: 4; 40 | -moz-tab-size: 4; 41 | text-align: left; 42 | white-space: pre-wrap; 43 | word-wrap: break-word; 44 | } 45 | .ql-editor > * { 46 | cursor: text; 47 | } 48 | .ql-editor p, 49 | .ql-editor ol, 50 | .ql-editor ul, 51 | .ql-editor pre, 52 | .ql-editor blockquote, 53 | .ql-editor h1, 54 | .ql-editor h2, 55 | .ql-editor h3, 56 | .ql-editor h4, 57 | .ql-editor h5, 58 | .ql-editor h6 { 59 | margin: 0; 60 | padding: 0; 61 | counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 62 | } 63 | .ql-editor ol, 64 | .ql-editor ul { 65 | padding-left: 1.5em; 66 | } 67 | .ql-editor ol > li, 68 | .ql-editor ul > li { 69 | list-style-type: none; 70 | } 71 | .ql-editor ul > li::before { 72 | content: '\2022'; 73 | } 74 | .ql-editor ul[data-checked=true], 75 | .ql-editor ul[data-checked=false] { 76 | pointer-events: none; 77 | } 78 | .ql-editor ul[data-checked=true] > li *, 79 | .ql-editor ul[data-checked=false] > li * { 80 | pointer-events: all; 81 | } 82 | .ql-editor ul[data-checked=true] > li::before, 83 | .ql-editor ul[data-checked=false] > li::before { 84 | color: #777; 85 | cursor: pointer; 86 | pointer-events: all; 87 | } 88 | .ql-editor ul[data-checked=true] > li::before { 89 | content: '\2611'; 90 | } 91 | .ql-editor ul[data-checked=false] > li::before { 92 | content: '\2610'; 93 | } 94 | .ql-editor li::before { 95 | display: inline-block; 96 | white-space: nowrap; 97 | width: 1.2em; 98 | } 99 | .ql-editor li:not(.ql-direction-rtl)::before { 100 | margin-left: -1.5em; 101 | margin-right: 0.3em; 102 | text-align: right; 103 | } 104 | .ql-editor li.ql-direction-rtl::before { 105 | margin-left: 0.3em; 106 | margin-right: -1.5em; 107 | } 108 | .ql-editor ol li:not(.ql-direction-rtl), 109 | .ql-editor ul li:not(.ql-direction-rtl) { 110 | padding-left: 1.5em; 111 | } 112 | .ql-editor ol li.ql-direction-rtl, 113 | .ql-editor ul li.ql-direction-rtl { 114 | padding-right: 1.5em; 115 | } 116 | .ql-editor ol li { 117 | counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 118 | counter-increment: list-0; 119 | } 120 | .ql-editor ol li:before { 121 | content: counter(list-0, decimal) '. '; 122 | } 123 | .ql-editor ol li.ql-indent-1 { 124 | counter-increment: list-1; 125 | } 126 | .ql-editor ol li.ql-indent-1:before { 127 | content: counter(list-1, lower-alpha) '. '; 128 | } 129 | .ql-editor ol li.ql-indent-1 { 130 | counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; 131 | } 132 | .ql-editor ol li.ql-indent-2 { 133 | counter-increment: list-2; 134 | } 135 | .ql-editor ol li.ql-indent-2:before { 136 | content: counter(list-2, lower-roman) '. '; 137 | } 138 | .ql-editor ol li.ql-indent-2 { 139 | counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9; 140 | } 141 | .ql-editor ol li.ql-indent-3 { 142 | counter-increment: list-3; 143 | } 144 | .ql-editor ol li.ql-indent-3:before { 145 | content: counter(list-3, decimal) '. '; 146 | } 147 | .ql-editor ol li.ql-indent-3 { 148 | counter-reset: list-4 list-5 list-6 list-7 list-8 list-9; 149 | } 150 | .ql-editor ol li.ql-indent-4 { 151 | counter-increment: list-4; 152 | } 153 | .ql-editor ol li.ql-indent-4:before { 154 | content: counter(list-4, lower-alpha) '. '; 155 | } 156 | .ql-editor ol li.ql-indent-4 { 157 | counter-reset: list-5 list-6 list-7 list-8 list-9; 158 | } 159 | .ql-editor ol li.ql-indent-5 { 160 | counter-increment: list-5; 161 | } 162 | .ql-editor ol li.ql-indent-5:before { 163 | content: counter(list-5, lower-roman) '. '; 164 | } 165 | .ql-editor ol li.ql-indent-5 { 166 | counter-reset: list-6 list-7 list-8 list-9; 167 | } 168 | .ql-editor ol li.ql-indent-6 { 169 | counter-increment: list-6; 170 | } 171 | .ql-editor ol li.ql-indent-6:before { 172 | content: counter(list-6, decimal) '. '; 173 | } 174 | .ql-editor ol li.ql-indent-6 { 175 | counter-reset: list-7 list-8 list-9; 176 | } 177 | .ql-editor ol li.ql-indent-7 { 178 | counter-increment: list-7; 179 | } 180 | .ql-editor ol li.ql-indent-7:before { 181 | content: counter(list-7, lower-alpha) '. '; 182 | } 183 | .ql-editor ol li.ql-indent-7 { 184 | counter-reset: list-8 list-9; 185 | } 186 | .ql-editor ol li.ql-indent-8 { 187 | counter-increment: list-8; 188 | } 189 | .ql-editor ol li.ql-indent-8:before { 190 | content: counter(list-8, lower-roman) '. '; 191 | } 192 | .ql-editor ol li.ql-indent-8 { 193 | counter-reset: list-9; 194 | } 195 | .ql-editor ol li.ql-indent-9 { 196 | counter-increment: list-9; 197 | } 198 | .ql-editor ol li.ql-indent-9:before { 199 | content: counter(list-9, decimal) '. '; 200 | } 201 | .ql-editor .ql-indent-1:not(.ql-direction-rtl) { 202 | padding-left: 3em; 203 | } 204 | .ql-editor li.ql-indent-1:not(.ql-direction-rtl) { 205 | padding-left: 4.5em; 206 | } 207 | .ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right { 208 | padding-right: 3em; 209 | } 210 | .ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right { 211 | padding-right: 4.5em; 212 | } 213 | .ql-editor .ql-indent-2:not(.ql-direction-rtl) { 214 | padding-left: 6em; 215 | } 216 | .ql-editor li.ql-indent-2:not(.ql-direction-rtl) { 217 | padding-left: 7.5em; 218 | } 219 | .ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right { 220 | padding-right: 6em; 221 | } 222 | .ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right { 223 | padding-right: 7.5em; 224 | } 225 | .ql-editor .ql-indent-3:not(.ql-direction-rtl) { 226 | padding-left: 9em; 227 | } 228 | .ql-editor li.ql-indent-3:not(.ql-direction-rtl) { 229 | padding-left: 10.5em; 230 | } 231 | .ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right { 232 | padding-right: 9em; 233 | } 234 | .ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right { 235 | padding-right: 10.5em; 236 | } 237 | .ql-editor .ql-indent-4:not(.ql-direction-rtl) { 238 | padding-left: 12em; 239 | } 240 | .ql-editor li.ql-indent-4:not(.ql-direction-rtl) { 241 | padding-left: 13.5em; 242 | } 243 | .ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right { 244 | padding-right: 12em; 245 | } 246 | .ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right { 247 | padding-right: 13.5em; 248 | } 249 | .ql-editor .ql-indent-5:not(.ql-direction-rtl) { 250 | padding-left: 15em; 251 | } 252 | .ql-editor li.ql-indent-5:not(.ql-direction-rtl) { 253 | padding-left: 16.5em; 254 | } 255 | .ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right { 256 | padding-right: 15em; 257 | } 258 | .ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right { 259 | padding-right: 16.5em; 260 | } 261 | .ql-editor .ql-indent-6:not(.ql-direction-rtl) { 262 | padding-left: 18em; 263 | } 264 | .ql-editor li.ql-indent-6:not(.ql-direction-rtl) { 265 | padding-left: 19.5em; 266 | } 267 | .ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right { 268 | padding-right: 18em; 269 | } 270 | .ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right { 271 | padding-right: 19.5em; 272 | } 273 | .ql-editor .ql-indent-7:not(.ql-direction-rtl) { 274 | padding-left: 21em; 275 | } 276 | .ql-editor li.ql-indent-7:not(.ql-direction-rtl) { 277 | padding-left: 22.5em; 278 | } 279 | .ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right { 280 | padding-right: 21em; 281 | } 282 | .ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right { 283 | padding-right: 22.5em; 284 | } 285 | .ql-editor .ql-indent-8:not(.ql-direction-rtl) { 286 | padding-left: 24em; 287 | } 288 | .ql-editor li.ql-indent-8:not(.ql-direction-rtl) { 289 | padding-left: 25.5em; 290 | } 291 | .ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right { 292 | padding-right: 24em; 293 | } 294 | .ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right { 295 | padding-right: 25.5em; 296 | } 297 | .ql-editor .ql-indent-9:not(.ql-direction-rtl) { 298 | padding-left: 27em; 299 | } 300 | .ql-editor li.ql-indent-9:not(.ql-direction-rtl) { 301 | padding-left: 28.5em; 302 | } 303 | .ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right { 304 | padding-right: 27em; 305 | } 306 | .ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right { 307 | padding-right: 28.5em; 308 | } 309 | .ql-editor .ql-video { 310 | display: block; 311 | max-width: 100%; 312 | } 313 | .ql-editor .ql-video.ql-align-center { 314 | margin: 0 auto; 315 | } 316 | .ql-editor .ql-video.ql-align-right { 317 | margin: 0 0 0 auto; 318 | } 319 | .ql-editor .ql-bg-black { 320 | background-color: #000; 321 | } 322 | .ql-editor .ql-bg-red { 323 | background-color: #e60000; 324 | } 325 | .ql-editor .ql-bg-orange { 326 | background-color: #f90; 327 | } 328 | .ql-editor .ql-bg-yellow { 329 | background-color: #ff0; 330 | } 331 | .ql-editor .ql-bg-green { 332 | background-color: #008a00; 333 | } 334 | .ql-editor .ql-bg-blue { 335 | background-color: #06c; 336 | } 337 | .ql-editor .ql-bg-purple { 338 | background-color: #93f; 339 | } 340 | .ql-editor .ql-color-white { 341 | color: #fff; 342 | } 343 | .ql-editor .ql-color-red { 344 | color: #e60000; 345 | } 346 | .ql-editor .ql-color-orange { 347 | color: #f90; 348 | } 349 | .ql-editor .ql-color-yellow { 350 | color: #ff0; 351 | } 352 | .ql-editor .ql-color-green { 353 | color: #008a00; 354 | } 355 | .ql-editor .ql-color-blue { 356 | color: #06c; 357 | } 358 | .ql-editor .ql-color-purple { 359 | color: #93f; 360 | } 361 | .ql-editor .ql-font-serif { 362 | font-family: Georgia, Times New Roman, serif; 363 | } 364 | .ql-editor .ql-font-monospace { 365 | font-family: Monaco, Courier New, monospace; 366 | } 367 | .ql-editor .ql-size-small { 368 | font-size: 0.75em; 369 | } 370 | .ql-editor .ql-size-large { 371 | font-size: 1.5em; 372 | } 373 | .ql-editor .ql-size-huge { 374 | font-size: 2.5em; 375 | } 376 | .ql-editor .ql-direction-rtl { 377 | direction: rtl; 378 | text-align: inherit; 379 | } 380 | .ql-editor .ql-align-center { 381 | text-align: center; 382 | } 383 | .ql-editor .ql-align-justify { 384 | text-align: justify; 385 | } 386 | .ql-editor .ql-align-right { 387 | text-align: right; 388 | } 389 | .ql-editor.ql-blank::before { 390 | color: rgba(0,0,0,0.6); 391 | content: attr(data-placeholder); 392 | font-style: italic; 393 | left: 15px; 394 | pointer-events: none; 395 | position: absolute; 396 | right: 15px; 397 | } 398 | -------------------------------------------------------------------------------- /Quill Project 004 - Customizable Tooltip/styles.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0px; 3 | padding: 0px; 4 | } 5 | 6 | #all{ 7 | margin: 50px; 8 | } 9 | 10 | /* See: https://stackoverflow.com/a/9314458 */ 11 | .noselect { 12 | -webkit-touch-callout: none; /* iOS Safari */ 13 | -webkit-user-select: none; /* Safari */ 14 | -khtml-user-select: none; /* Konqueror HTML */ 15 | -moz-user-select: none; /* Firefox */ 16 | -ms-user-select: none; /* Internet Explorer/Edge */ 17 | user-select: none; /* Non-prefixed version, currently 18 | supported by Chrome and Opera */ 19 | } 20 | 21 | /* ################################################################################ */ 22 | /* TOOLTIP */ 23 | /* ################################################################################ */ 24 | 25 | .rs-tooltip-container { 26 | background-color:#fff; 27 | border: 1px solid#ccc; 28 | box-shadow: 0px 0px 5px#ddd; 29 | color:#444; 30 | padding: 5px 12px; 31 | white-space: nowrap; 32 | position: absolute; 33 | } 34 | 35 | .rs-tooltip-label { 36 | margin-right: 8px; 37 | } 38 | 39 | .rs-tooltip-input { 40 | padding: 3px 5px; 41 | font-size: 13px; 42 | height: 26px; 43 | width: 220px; 44 | } 45 | 46 | .rs-tooltip-action { 47 | margin-left: 8px; 48 | } 49 | 50 | /* ################################################################################ */ 51 | /* TABS */ 52 | /* ################################################################################ */ 53 | 54 | /* Style the tab */ 55 | .tab { 56 | overflow: hidden; 57 | border: 1px solid #ccc; 58 | background-color: #f1f1f1; 59 | } 60 | 61 | /* Style the buttons that are used to open the tab content */ 62 | .tab button { 63 | background-color: inherit; 64 | float: left; 65 | border: none; 66 | outline: none; 67 | cursor: pointer; 68 | padding: 14px 16px; 69 | transition: 0.3s; 70 | } 71 | 72 | /* Change background color of buttons on hover */ 73 | .tab button:hover { 74 | background-color: #ddd; 75 | } 76 | 77 | /* Create an active/current tablink class */ 78 | .tab button.active { 79 | background-color: #ccc; 80 | } 81 | 82 | /* Style the tab content */ 83 | .tab-content { 84 | display: none; 85 | padding: 6px 12px; 86 | border: 1px solid #ccc; 87 | border-top: none; 88 | } 89 | 90 | 91 | /*###################### */ 92 | /* DELTA, TEXT AND HTML */ 93 | /*###################### */ 94 | 95 | #tab-content-delta, 96 | #tab-content-html, 97 | #tab-content-text { 98 | padding: 0px; 99 | } 100 | 101 | pre{ 102 | white-space: normal; 103 | } 104 | 105 | code{ 106 | white-space: pre-wrap; 107 | } 108 | 109 | #tab-content-delta p{ 110 | font-family: Candara; 111 | } 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # INTRO 2 | 3 | This repository is designed to serve as an informational medium for anyone learning to use the rich text editor [Quill JS](https://quilljs.com/). Each existing folder represents a small project using Quill, all aimed at displaying a case study. A description of each one can be found below. All of them follow a very simple structure, where there are 3 common files: 4 | 5 | 1. index.html - Main page, and entry point. Open it to see the editor. 6 | 2. app.js - The JavaScript source code. 7 | 3. styles.css - CSS stylesheet for index.html page. 8 | 9 | To take advantage, each source code file is commented out. Therefore, in the desire to understand how something works, please try to read. 10 | 11 | #### CONTRIBUTING 12 | 13 | Seeing how some people have already accessed this repository, in order to have better information for everyone I humbly come to ask: [Could someone help me improve Project 001 - Highlight?](https://stackoverflow.com/questions/59437258/in-quill-how-can-i-use-bubble-themed-toolbar-in-read-only-mode) 14 | 15 | #### NOTE 16 | 17 | Not sure if I will be updating this forever. Therefore, do not expect future changes. This repository was created for display purposes only, to spread knowledge, and it was originated from a question I made in stackoverflow community: 18 | 19 | https://stackoverflow.com/q/59366868/2910546 20 | 21 | ### Quill Project 001 - Hightlight 22 | 23 | Using the bubble theme, we have here a toolbar with highlight controls. With this tool you can add/remove different highlight types in any selected text snippet. In this project, you will also discover how to: 24 | 25 | 1. Create a format. 26 | 2. Create a format that can take values (arguments). 27 | 3. Make the format behave differently depending on the received value. 28 | 29 | **Instructions:** 30 | 31 | 1. Select any portion of text to appear on the toolbar. 32 | 2. Use the options on the toolbar. 33 | 34 | ### Quill Project 002 - Centralized Video 35 | 36 | This project demonstrates how you can extend an existing blot to slightly change it's settings. To show how the process is done, Quill's native [video](https://github.com/quilljs/quill/blob/develop/formats/video.js) blot has been extended, where its horizontal positioning is centered, and height and width are set at the outset. 37 | 38 | **Instructions:** 39 | 40 | 1. Hover over the editor and click anywhere you want to add the video. 41 | 2. Click on the single visible toolbar button. 42 | 3. A small inbox will appear. Enter any desired video URL. 43 | 4. Press save and see the result. 44 | 45 | ### Quill Project 003 - Carousel 46 | 47 | This project shows how you can create a new module to add interesting features to Quill. Here we see how we can create a button in toolbar which displays a small tooltip that serves as means to create a carousel of images. Besides the user can choose which images will be used, he/she can also define some extra settings. 48 | 49 | For the implementation of the carousel of images, the [Slick JS](https://kenwheeler.github.io/slick/) library was used. For this reason, it is also possible to discover how to incorporate existing libraries/resources as new features to the editor. 50 | 51 | This project was deeply inspired by [quill-emoji](https://github.com/contentco/quill-emoji), which I am truly grateful for. 52 | 53 | **Instructions:** 54 | 55 | 1. A new button is present on Quill toolbar. Click on it and a small tooltip window will appear. This window is divided into a header, and two tabs with their contents. 56 | 2. Use the first tab to configure simple carousel settings. 57 | 3. Use the second tab to set the image URLs that will appear on the carousel. For convenience, testing and presentation, some images have already been separated. 58 | 4. When you are done, click the insert header button. 59 | 5. When the carousel is inserted, click the navigation buttons (the arrows), or click and drag the images to change its content. 60 | 61 | ### Quill Project 004 - Customizable Tooltip 62 | 63 | This project shows how it is possible to create a new simple tooltip that can insert images through URLs (simpler than presented in project 003 - Carousel). It looks almost the same as the native Quill tooltip. 64 | 65 | To make the developer user of this tool more comfortable, a number of configuration possibilities have been added, allowing the tooltip to be stylized, to have its text modified, and to be more comfortable to work with. The following is a complete list of configurable settings: 66 | 67 | - format: The format to be worked by tooltip. 68 | - inputLabel: Left label given to value input. 69 | - inputLabelClass: Overrides CSS class for value input label styling. 70 | - inputPlaceholder: Value input placeholder text (``). 71 | - inputClass: Overrides CSS class for value input styling. 72 | - actionText: Text for action "button" to the right of value input. 73 | - actionClass: Overrides CSS class for action text (the "button"). 74 | - containerClass: Replaces CSS class for element that contains all others. 75 | - hideOnTyping: If true, tooltip will be hidden when typing in Quill. 76 | - hideOnAction: If true, tooltip will be hidden by clicking action text. 77 | - clearAfterHide: If true, the value input has its text cleared after tooltip is hidden. 78 | - defaultValue: Defines a default value for value input. If set, clearAfterHide is always false. 79 | - onAction: Function called when action text is clicked by the user. Setting a value for this property makes the user responsible for the tooltip action. 80 | - onShow: Function called when tooltip is revealed. 81 | - onHide: Function called when tooltip is hidden. 82 | 83 | By allowing such settings, it is possible not only to override Quill's default image utility (format), but also video. 84 | 85 | **Instructions:** 86 | 87 | 1. Click on the image button. 88 | 2. Add the desired image URL. 89 | 3. Click on the Insert text. 90 | 91 | # QUILL FAQ 92 | 93 | Wishing to bring more information, I decided to create a FAQ section. I want to make it clear that the answers to all the questions listed were obtained from different locations over the internet. Its authors have not given me permission to exhibit here, nor have they denied me. If they wish so, I am open to remove any desired item. Likewise, the credit on them belongs to each one. 94 | 95 | **001 - How can I add a letter / word counter?** 96 | **001 - How can I add a module to Quill?** 97 | 98 | https://quilljs.com/guides/building-a-custom-module/ 99 | Also, take a look at [Quill Project 003 - Carousel](https://github.com/loagit/Quill-Examples-and-FAQ/tree/master/Quill%20Projeto%20003%20-%20Carousel). 100 | 101 | **002 - How can I perform CRUD operations through Quill API?** 102 | **002 - How can I insert or remove content?** 103 | 104 | https://quilljs.com/docs/api/#content 105 | 106 | **003 - How can I change the look of Quill?** 107 | **003 - How can I style the editor with CSS?** 108 | 109 | According to the documentation itself, you can see which classes are being used in Quill through the browser developer tool. Once these classes are discovered it is easy to add or override settings for them just by defining styles in CSS files. 110 | 111 | For example, to change the padding given to editor content: 112 | 113 | ```css 114 | .ql-editor{ 115 | padding: 0px; 116 | } 117 | ``` 118 | 119 | https://quilljs.com/docs/themes/#customization 120 | 121 | **004 - How can I use Delta API?** 122 | **004 - Where can I find more about Delta API?** 123 | 124 | https://github.com/quilljs/delta 125 | https://quilljs.com/docs/delta/ 126 | https://quilljs.com/guides/designing-the-delta-format/ 127 | 128 | **005 - How can I use Parchment API?** 129 | **005 - Where can I find more about Parchment API?** 130 | 131 | https://github.com/quilljs/parchment 132 | 133 | **006 - How can I work with Undo and Redo?** 134 | 135 | https://quilljs.com/docs/modules/history/ 136 | 137 | **007 - How can I use Syntax Highlight?** 138 | 139 | https://quilljs.com/docs/modules/syntax/ 140 | 141 | **008 - How can I set Quill in read mode only?** 142 | 143 | https://quilljs.com/docs/api/#enable 144 | 145 | **009 - How can I set the font of the selected text?** 146 | **009 - How can I add custom fonts to the toolbar?** 147 | 148 | https://quilljs.com/playground/#custom-fonts 149 | https://stackoverflow.com/questions/43728080/how-to-add-font-types-on-quill-js-with-toolbar-options 150 | 151 | **010 - How can I change text color and text background?** 152 | 153 | https://quilljs.com/playground/#class-vs-inline-style 154 | 155 | **011 - How can I implement autosave feature?** 156 | 157 | https://quilljs.com/playground/#autosave 158 | 159 | **012 - How can I set editor height but using a scroll bar?** 160 | 161 | https://quilljs.com/playground/#autogrow-height 162 | 163 | **013 - How can I find the full featured version of Quill?** 164 | **013 - Where can I find a exxample of Quill with all it's features?** 165 | 166 | https://quilljs.com/docs/formats/ 167 | 168 | **014 - How can I define a whitelist or blacklist of formats supported by Quill?** 169 | **014 - How can I filter content in Quill, excluding anything unwanted?** 170 | **014 - How can I prevent Quill from filtering content?** 171 | 172 | https://stackoverflow.com/questions/59397115/why-does-quill-filter-its-content 173 | 174 | **015 - How can I use Quill without the toolbar?** 175 | **015 - How can I remove Quill toolbar?** 176 | 177 | ```javascript 178 | var config = { 179 | "theme": "snow", 180 | "modules": { 181 | "toolbar": false 182 | } 183 | }; 184 | ``` 185 | 186 | https://stackoverflow.com/questions/39456273/how-do-i-create-a-quill-editor-without-a-toolbar 187 | 188 | **016 - How can I find a list of toolbar built with HTML?** 189 | **016 - How can I find a list of formats with their CSS names?** 190 | 191 | https://stackoverflow.com/questions/40347908/list-of-recognized-quill-toolbar-classes 192 | 193 | **017 - How can I create my own blot?** 194 | **017 - How can I create my own format?** 195 | **017 - How can I add new styles to Quill?** 196 | 197 | Try taking a look at the projects in this repository. Their source code is all commented. 198 | 199 | **018 - How can I set a toolbar like the one displayed on Quill page?** 200 | 201 | https://stackoverflow.com/questions/34734750/how-to-create-a-quilljs-toolbar-exactly-as-shown-in-samples# 202 | 203 | **019 - How can I extend an existing blot?** 204 | **019 - How can I create a blot from an existing one?** 205 | 206 | See [Project 002 - Centralized Video](https://github.com/loagit/Quill-Examples-and-FAQ/tree/master/Quill%20Project%20002%20-%20Centralized%20Video), in particular, the following line of code: 207 | 208 | https://github.com/loagit/Quill-Examples-and-FAQ/blob/master/Quill%20Project%20002%20-%20Centralized%20Video/app.js#L91 209 | 210 | **020 - How can I use the toolbar?** 211 | **020 - How can I define my own custom toolbar?** 212 | **020 - What are the existing ways to work with the toolbar module?** 213 | 214 | Quill's toolbar module allows the editor to have its toolbar configured in 3 different ways: 215 | 216 | 1. Quill default configuration. 217 | 2. Vector/Array of formats in JavaScript code. 218 | 3. HTML Elements with format CSS classes in HTML code. 219 | 220 | Out of curiosity, this can be seen at the beginning of the [toolbar module source code](https://github.com/quilljs/quill/blob/develop/modules/toolbar.js#L10). Where you can find: 221 | ```javascript 222 | if(Array.isArray(this.options.container){ // ... } 223 | else if(typeof this.options.container === 'string'){ // ... } 224 | else{ // ... } 225 | ``` 226 | Basically, according to the listed items above, in **Nº1** you use the toolbar with the standard Quill buttons. Here you do not have to do any configuration, but you will only have a portion of the Quill buttons, as not all are set by default. 227 | 228 | In **Nº2**, you define which buttons are present by passing a array of formats, like so: 229 | ```javascript 230 | // Example 1 231 | var toolbarOptions1 = [ 232 | ['bold', 'italic', 'underline', 'strike'], // toggled buttons 233 | ['blockquote', 'code-block'], 234 | 235 | [{ 'header': 1 }, { 'header': 2 }], // custom button values 236 | [{ 'list': 'ordered'}, { 'list': 'bullet' }], 237 | [{ 'script': 'sub'}, { 'script': 'super' }], // superscript/subscript 238 | [{ 'indent': '-1'}, { 'indent': '+1' }], // outdent/indent 239 | [{ 'direction': 'rtl' }], // text direction 240 | 241 | [{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown 242 | [{ 'header': [1, 2, 3, 4, 5, 6, false] }], 243 | 244 | [{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme 245 | [{ 'font': [] }], 246 | [{ 'align': [] }], 247 | 248 | ['clean'] // remove formatting button 249 | ]; 250 | 251 | // Example 2 252 | var toolbarOptions2 = ['bold', 'italic', 'underline', 'strike']; 253 | 254 | var quill = new Quill('#editor', { 255 | modules: { 256 | toolbar: toolbarOptions1 // For teaching use only 257 | } 258 | }); 259 | ``` 260 | **HINT / TIP:** To find all available native Quill formats, see questions 013 and 016. 261 | 262 | In **Nº3**, you pass an HTML element that will be used as a toolbar. In it, `