PageSourceSearch

https://gti-amuse.com/lib/spin.js/spin.js

js gti-amuse.com collected 2026-10-06 20:47:48 UTC 11,607 bytes, 377 lines download raw bytes

vendor: 11,607 bytes, lines 1-377
1/**
2 * Copyright (c) 2011-2014 Felix Gnass
3 * Licensed under the MIT license
4 * http://spin.js.org/
5 *
6 * Example:
7    var opts = {
8      lines: 12             // The number of lines to draw
9    , length: 7             // The length of each line
10    , width: 5              // The line thickness
11    , radius: 10            // The radius of the inner circle
12    , scale: 1.0            // Scales overall size of the spinner
13    , corners: 1            // Roundness (0..1)
14    , color: '#000'         // #rgb or #rrggbb
15    , opacity: 1/4          // Opacity of the lines
16    , rotate: 0             // Rotation offset
17    , direction: 1          // 1: clockwise, -1: counterclockwise
18    , speed: 1              // Rounds per second
19    , trail: 100            // Afterglow percentage
20    , fps: 20               // Frames per second when using setTimeout()
21    , zIndex: 2e9           // Use a high z-index by default
22    , className: 'spinner'  // CSS class to assign to the element
23    , top: '50%'            // center vertically
24    , left: '50%'           // center horizontally
25    , shadow: false         // Whether to render a shadow
26    , hwaccel: false        // Whether to use hardware acceleration (might be buggy)
27    , position: 'absolute'  // Element positioning
28    }
29    var target = document.getElementById('foo')
30    var spinner = new Spinner(opts).spin(target)
31 */
32;(function (root, factory) {
33
34  /* CommonJS */
35  if (typeof module == 'object' && module.exports) module.exports = factory()
36
37  /* AMD module */
38  else if (typeof define == 'function' && define.amd) define(factory)
39
40  /* Browser global */
41  else root.Spinner = factory()
42}(this, function () {
43  "use strict"
44
45  var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */
46    , animations = {} /* Animation rules keyed by their name */
47    , useCssAnimations /* Whether to use CSS animations or setTimeout */
48    , sheet /* A stylesheet to hold the @keyframe or VML rules. */
49
50  /**
51   * Utility function to create elements. If no tag name is given,
52   * a DIV is created. Optionally properties can be passed.
53   */
54  function createEl (tag, prop) {
55    var el = document.createElement(tag || 'div')
56      , n
57
58    for (n in prop) el[n] = prop[n]
59    return el
60  }
61
62  /**
63   * Appends children and returns the parent.
64   */
65  function ins (parent /* child1, child2, ...*/) {
66    for (var i = 1, n = arguments.length; i < n; i++) {
67      parent.appendChild(arguments[i])
68    }
69
70    return parent
71  }
72
73  /**
74   * Creates an opacity keyframe animation rule and returns its name.
75   * Since most mobile Webkits have timing issues with animation-delay,
76   * we create separate rules for each line/segment.
77   */
78  function addAnimation (alpha, trail, i, lines) {
79    var name = ['opacity', trail, ~~(alpha * 100), i, lines].join('-')
80      , start = 0.01 + i/lines * 100
81      , z = Math.max(1 - (1-alpha) / trail * (100-start), alpha)
82      , prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase()
83      , pre = prefix && '-' + prefix + '-' || ''
84
85    if (!animations[name]) {
86      sheet.insertRule(
87        '@' + pre + 'keyframes ' + name + '{' +
88        '0%{opacity:' + z + '}' +
89        start + '%{opacity:' + alpha + '}' +
90        (start+0.01) + '%{opacity:1}' +
91        (start+trail) % 100 + '%{opacity:' + alpha + '}' +
92        '100%{opacity:' + z + '}' +
93        '}', sheet.cssRules.length)
94
95      animations[name] = 1
96    }
97
98    return name
99  }
100
101  /**
102   * Tries various vendor prefixes and returns the first supported property.
103   */
104  function vendor (el, prop) {
105    var s = el.style
106      , pp
107      , i
108
109    prop = prop.charAt(0).toUpperCase() + prop.slice(1)
110    if (s[prop] !== undefined) return prop
111    for (i = 0; i < prefixes.length; i++) {
112      pp = prefixes[i]+prop
113      if (s[pp] !== undefined) return pp
114    }
115  }
116
117  /**
118   * Sets multiple style properties at once.
119   */
120  function css (el, prop) {
121    for (var n in prop) {
122      el.style[vendor(el, n) || n] = prop[n]
123    }
124
125    return el
126  }
127
128  /**
129   * Fills in default values.
130   */
131  function merge (obj) {
132    for (var i = 1; i < arguments.length; i++) {
133      var def = arguments[i]
134      for (var n in def) {
135        if (obj[n] === undefined) obj[n] = def[n]
136      }
137    }
138    return obj
139  }
140
141  /**
142   * Returns the line color from the given string or array.
143   */
144  function getColor (color, idx) {
145    return typeof color == 'string' ? color : color[idx % color.length]
146  }
147
148  // Built-in defaults
149
150  var defaults = {
151    lines: 12             // The number of lines to draw
152  , length: 7             // The length of each line
153  , width: 5              // The line thickness
154  , radius: 10            // The radius of the inner circle
155  , scale: 1.0            // Scales overall size of the spinner
156  , corners: 1            // Roundness (0..1)
157  , color: '#000'         // #rgb or #rrggbb
158  , opacity: 1/4          // Opacity of the lines
159  , rotate: 0             // Rotation offset
160  , direction: 1          // 1: clockwise, -1: counterclockwise
161  , speed: 1              // Rounds per second
162  , trail: 100            // Afterglow percentage
163  , fps: 20               // Frames per second when using setTimeout()
164  , zIndex: 2e9           // Use a high z-index by default
165  , className: 'spinner'  // CSS class to assign to the element
166  , top: '50%'            // center vertically
167  , left: '50%'           // center horizontally
168  , shadow: false         // Whether to render a shadow
169  , hwaccel: false        // Whether to use hardware acceleration (might be buggy)
170  , position: 'absolute'  // Element positioning
171  }
172
173  /** The constructor */
174  function Spinner (o) {
175    this.opts = merge(o || {}, Spinner.defaults, defaults)
176  }
177
178  // Global defaults that override the built-ins:
179  Spinner.defaults = {}
180
181  merge(Spinner.prototype, {
182    /**
183     * Adds the spinner to the given target element. If this instance is already
184     * spinning, it is automatically removed from its previous target b calling
185     * stop() internally.
186     */
187    spin: function (target) {
188      this.stop()
189
190      var self = this
191        , o = self.opts
192        , el = self.el = createEl(null, {className: o.className})
193
194      css(el, {
195        position: o.position
196      , width: 0
197      , zIndex: o.zIndex
198      , left: o.left
199      , top: o.top
200      })
201
202      if (target) {
203        target.insertBefore(el, target.firstChild || null)
204      }
205
206      el.setAttribute('role', 'progressbar')
207      self.lines(el, self.opts)
208
209      if (!useCssAnimations) {
210        // No CSS animation support, use setTimeout() instead
211        var i = 0
212          , start = (o.lines - 1) * (1 - o.direction) / 2
213          , alpha
214          , fps = o.fps
215          , f = fps / o.speed
216          , ostep = (1 - o.opacity) / (f * o.trail / 100)
217          , astep = f / o.lines
218
219        ;(function anim () {
220          i++
221          for (var j = 0; j < o.lines; j++) {
222            alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity)
223
224            self.opacity(el, j * o.direction + start, alpha, o)
225          }
226          self.timeout = self.el && setTimeout(anim, ~~(1000 / fps))
227        })()
228      }
229      return self
230    }
231
232    /**
233     * Stops and removes the Spinner.
234     */
235  , stop: function () {
236      var el = this.el
237      if (el) {
238        clearTimeout(this.timeout)
239        if (el.parentNode) el.parentNode.removeChild(el)
240        this.el = undefined
241      }
242      return this
243    }
244
245    /**
246     * Internal method that draws the individual lines. Will be overwritten
247     * in VML fallback mode below.
248     */
249  , lines: function (el, o) {
250      var i = 0
251        , start = (o.lines - 1) * (1 - o.direction) / 2
252        , seg
253
254      function fill (color, shadow) {
255        return css(createEl(), {
256          position: 'absolute'
257        , width: o.scale * (o.length + o.width) + 'px'
258        , height: o.scale * o.width + 'px'
259        , background: color
260        , boxShadow: shadow
261        , transformOrigin: 'left'
262        , transform: 'rotate(' + ~~(360/o.lines*i + o.rotate) + 'deg) translate(' + o.scale*o.radius + 'px' + ',0)'
263        , borderRadius: (o.corners * o.scale * o.width >> 1) + 'px'
264        })
265      }
266
267      for (; i < o.lines; i++) {
268        seg = css(createEl(), {
269          position: 'absolute'
270        , top: 1 + ~(o.scale * o.width / 2) + 'px'
271        , transform: o.hwaccel ? 'translate3d(0,0,0)' : ''
272        , opacity: o.opacity
273        , animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1 / o.speed + 's linear infinite'
274        })
275
276        if (o.shadow) ins(seg, css(fill('#000', '0 0 4px #000'), {top: '2px'}))
277        ins(el, ins(seg, fill(getColor(o.color, i), '0 0 1px rgba(0,0,0,.1)')))
278      }
279      return el
280    }
281
282    /**
283     * Internal method that adjusts the opacity of a single line.
284     * Will be overwritten in VML fallback mode below.
285     */
286  , opacity: function (el, i, val) {
287      if (i < el.childNodes.length) el.childNodes[i].style.opacity = val
288    }
289
290  })
291
292
293  function initVML () {
294
295    /* Utility function to create a VML tag */
296    function vml (tag, attr) {
297      return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr)
298    }
299
300    // No CSS transforms but VML support, add a CSS rule for VML elements:
301    sheet.addRule('.spin-vml', 'behavior:url(#default#VML)')
302
303    Spinner.prototype.lines = function (el, o) {
304      var r = o.scale * (o.length + o.width)
305        , s = o.scale * 2 * r
306
307      function grp () {
308        return css(
309          vml('group', {
310            coordsize: s + ' ' + s
311          , coordorigin: -r + ' ' + -r
312          })
313        , { width: s, height: s }
314        )
315      }
316
317      var margin = -(o.width + o.length) * o.scale * 2 + 'px'
318        , g = css(grp(), {position: 'absolute', top: margin, left: margin})
319        , i
320
321      function seg (i, dx, filter) {
322        ins(
323          g
324        , ins(
325            css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx})
326          , ins(
327              css(
328                vml('roundrect', {arcsize: o.corners})
329              , { width: r
330                , height: o.scale * o.width
331                , left: o.scale * o.radius
332                , top: -o.scale * o.width >> 1
333                , filter: filter
334                }
335              )
336            , vml('fill', {color: getColor(o.color, i), opacity: o.opacity})
337            , vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
338            )
339          )
340        )
341      }
342
343      if (o.shadow)
344        for (i = 1; i <= o.lines; i++) {
345          seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)')
346        }
347
348      for (i = 1; i <= o.lines; i++) seg(i)
349      return ins(el, g)
350    }
351
352    Spinner.prototype.opacity = function (el, i, val, o) {
353      var c = el.firstChild
354      o = o.shadow && o.lines || 0
355      if (c && i + o < c.childNodes.length) {
356        c = c.childNodes[i + o]; c = c && c.firstChild; c = c && c.firstChild
357        if (c) c.opacity = val
358      }
359    }
360  }
361
362  if (typeof document !== 'undefined') {
363    sheet = (function () {
364      var el = createEl('style', {type : 'text/css'})
365      ins(document.getElementsByTagName('head')[0], el)
366      return el.sheet || el.styleSheet
367    }())
368
369    var probe = css(createEl('group'), {behavior: 'url(#default#VML)'})
370
371    if (!vendor(probe, 'transform') && probe.adj) initVML()
372    else useCssAnimations = vendor(probe, 'animation')
373  }
374
375  return Spinner
376
377}));

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.