https://subart.si/wp-content/plugins/breakdance/subplugins/breakda…/animated-heading.js?bd_ver=2.8.1
1(function () { 2 const { mergeObjects } = BreakdanceFrontend.utils; 3 4 class BreakdanceAnimatedHeading { 5 defaultOptions = { 6 content: { 7 changing_text: [ 8 { 9 text: "awesome", 10 }, 11 { 12 text: "great", 13 }, 14 { 15 text: "cool", 16 }, 17 ], 18 }, 19 design: { 20 effect: { 21 type: "rotating", 22 typing: { 23 type_speed: { number: 100, unit: 'ms' }, 24 start_delay: { number: 0, unit: 'ms' }, 25 back_speed: { number: 100, unit: 'ms' }, 26 back_delay: { number: 100, unit: 'ms' }, 27 shuffle: false, 28 disable_loop: false, 29 hide_cursor: false, 30 cursor: "|", 31 }, 32 rotating: { 33 duration: { number: 700, unit: 'ms' }, 34 delay: { number: 200, unit: 'ms' }, 35 easing_in: "easeOutSine", 36 easing_out: "easeInExpo", 37 transform_origin: { 38 x: 50, 39 y: 50, 40 }, 41 opacity_in: [0, 1], 42 opacity_out: 0, 43 effect: "flipX", 44 }, 45 }, 46 }, 47 }; 48 49 constructor(selector, options) { 50 this.selector = selector; 51 this.element = document.querySelector( 52 `${this.selector} .bde-animated-heading__text` 53 ); 54 this.options = mergeObjects(this.defaultOptions, options); 55 this.init(); 56 } 57 58 getDuration(value) { 59 if (typeof value === "number") return; 60 if (!value) return value; 61 if (value.unit === "ms") return value.number; 62 return value.number * 1000; // Convert S to MS 63 } 64 65 // Init anime.js 66 initAnime() { 67 const { design } = this.options; 68 this.words = this.createWords(); 69 70 this.animeTimeline = anime.timeline({ 71 loop: true, 72 }); 73 74 this.animateWords(design.effect.rotating.effect, this.words); 75 } 76 77 createWords() { 78 let wordsArray = []; 79 this.wordsWrapper = document.querySelector( 80 `${this.selector} .bde-animated-heading__wrapper` 81 ); 82 83 this.options.content.changing_text.forEach((item) => { 84 if (item.text && item.text.length > 0) { 85 const span = document.createElement("span"); 86 span.setAttribute("class", "bde-animated-heading__word"); 87 span.innerText = item.text.trim(); 88 this.wordsWrapper.appendChild(span); 89 wordsArray.push(span); 90 } 91 }); 92 93 return wordsArray; 94 } 95 96 // Destroy anime.js 97 destroyAnime() { 98 if (!this.animeTimeline) return; 99 // Clean up the timeline 100 this.animeTimeline.remove(this.words); 101 this.animeTimeline = null; 102 this.wordsWrapper = null; 103 this.words.forEach((word) => word.remove()); 104 } 105 106 _anime(element, effectIn, effectOut) { 107 const effect = this.options.design.effect.rotating; 108 109 this.animeTimeline 110 .add({ 111 ...effectIn, 112 targets: element, 113 opacity: effect.opacity_in, 114 duration: this.getDuration(effect.duration), 115 easing: effect.easing_in, 116 changeBegin: () => { 117 const newWidth = element.clientWidth; 118 this.wordsWrapper.style.width = newWidth + "px"; 119 }, 120 }) 121 .add({ 122 ...effectOut, 123 targets: element, 124 opacity: effect.opacity_out, 125 duration: this.getDuration(effect.duration), 126 easing: effect.easing_out, 127 delay: this.getDuration(effect.delay), 128 }); 129 } 130 131 animateWords(effectName, words) { 132 switch (effectName) { 133 case "slideDown": 134 words.forEach((element) => { 135 this._anime( 136 element, 137 { translateY: ["-150%", 0] }, 138 { translateY: "150%" } 139 ); 140 }); 141 break; 142 case "slideRight": 143 words.forEach((element) => { 144 this._anime( 145 element, 146 { translateX: ["-100%", 0] }, 147 { translateX: "100%" } 148 ); 149 }); 150 break; 151 case "slideUp": 152 words.forEach((element) => { 153 this._anime( 154 element, 155 { translateY: ["150%", 0] }, 156 { translateY: "-150%" } 157 ); 158 }); 159 break; 160 case "slideLeft": 161 words.forEach((element) => { 162 this._anime( 163 element, 164 { translateX: ["100%", 0] }, 165 { translateX: "-100%" } 166 ); 167 }); 168 break; 169 case "rotate": 170 words.forEach((element) => { 171 this._anime(element, { rotate: [45, 0] }, { rotate: [0, -45] }); 172 }); 173 break; 174 case "flipX": 175 words.forEach((element) => { 176 this._anime(element, { rotateX: [-90, 0] }, { rotateX: [0, -90] }); 177 }); 178 break; 179 case "flipY": 180 words.forEach((element) => { 181 this._anime(element, { rotateY: [-90, 0] }, { rotateY: [0, -90] }); 182 }); 183 break; 184 case "zoomIn": 185 words.forEach((element) => { 186 this._anime(element, { scale: [0, 1] }, { scale: [1, 2] }); 187 }); 188 break; 189 case "zoomOut": 190 words.forEach((element) => { 191 this._anime(element, { scale: [2, 1] }, { scale: [1, 0] }); 192 }); 193 break; 194 default: 195 console.warn(`Animated Heading: ${effectName} effect not found.`); 196 } 197 } 198 199 // Init Typed.js 200 initTyped() { 201 const settings = this.options.design.effect.typing; 202 const text = this.options.content.changing_text; 203 const strings = text.map((word) => word.text); 204 this.typedElement = document.querySelector( 205 `${this.selector} .js-eeah-typed` 206 ); 207 208 this.typedElement.innerHTML = ""; 209 210 this.typed = new Typed(this.typedElement, {
211 strings: strings, 212 smartBackspace: true, 213 typeSpeed: this.getDuration(settings.type_speed), 214 startDelay: this.getDuration(settings.start_delay), 215 backSpeed: this.getDuration(settings.back_speed), 216 backDelay: this.getDuration(settings.back_delay), 217 shuffle: !!settings.shuffle, 218 fadeOut: false, 219 showCursor: !settings.hide_cursor, 220 loop: !settings.disable_loop, 221 cursorChar: settings.cursor, 222 }); 223 224 this.typed.start(); 225 } 226 227 // Destroy typed.js 228 destroyTyped() { 229 if (!this.typed) return; 230 this.typed.destroy(); 231 this.typedElement.innerHTML = ""; 232 this.typed = null; 233 } 234 235 // Update plugin 236 update(options = {}) { 237 this.options = mergeObjects(this.defaultOptions, options); 238 this.destroy(); 239 this.init(); 240 } 241 242 // Destory plugin 243 destroy() { 244 const { type } = this.options.design.effect; 245 switch (type) { 246 case "rotating": 247 this.destroyAnime(); 248 break; 249 case "typing": 250 this.destroyTyped(); 251 break; 252 default: 253 console.warn( 254 `Animated Heading: ${type} animation could not be destroyed.` 255 ); 256 } 257 } 258 259 // Init plugin 260 init() { 261 const { type } = this.options.design.effect; 262 switch (type) { 263 case "rotating": 264 this.initAnime(); 265 break; 266 case "typing": 267 this.initTyped(); 268 break; 269 default: 270 console.warn(`Animated Heading: ${type} animation not initialised.`); 271 } 272 } 273 } 274 window.BreakdanceAnimatedHeading = BreakdanceAnimatedHeading; 275})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.