diff --git a/knockout.activity.js b/knockout.activity.js
index 34f5a26..a1c3d6a 100644
--- a/knockout.activity.js
+++ b/knockout.activity.js
@@ -1,382 +1,59 @@
-/*!
- * NETEYE Activity Indicator jQuery Plugin
- *
- * Copyright (c) 2010 NETEYE GmbH
- * Licensed under the MIT license
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- *
- * Author: Felix Gnass [fgnass at neteye dot de]
- * Version: @{VERSION}
- */
-
-/**
- * Plugin that renders a customisable activity indicator (spinner) using SVG or VML.
- */
-(function ($) {
-
- $.fn.activity = function (opts) {
- this.each(function () {
- var $this = $(this);
- var el = $this.data('activity');
- if (el) {
- clearInterval(el.data('interval'));
- el.remove();
- $this.removeData('activity');
- }
- if (opts !== false) {
- opts = $.extend({ color: $this.css('color') }, $.fn.activity.defaults, opts);
-
- el = render($this, opts).css('position', 'absolute').prependTo(opts.outside ? 'body' : $this);
- var h = $this.outerHeight() - el.height();
- var w = $this.outerWidth() - el.width();
- var margin = {
- top: opts.valign == 'top' ? opts.padding : opts.valign == 'bottom' ? h - opts.padding : Math.floor(h / 2),
- left: opts.align == 'left' ? opts.padding : opts.align == 'right' ? w - opts.padding : Math.floor(w / 2)
- };
- var offset = $this.offset();
- if (opts.outside) {
- el.css({ top: offset.top + 'px', left: offset.left + 'px' });
- }
- else {
- margin.top -= el.offset().top - offset.top;
- margin.left -= el.offset().left - offset.left;
- }
- el.css({ marginTop: margin.top + 'px', marginLeft: margin.left + 'px' });
- animate(el, opts.segments, Math.round(10 / opts.speed) / 10);
- $this.data('activity', el);
- }
- });
- return this;
- };
-
- $.fn.activity.defaults = {
- segments: 12,
- space: 3,
- length: 7,
- width: 4,
- speed: 1.2,
- align: 'center',
- valign: 'center',
- padding: 4
- };
-
- $.fn.activity.getOpacity = function (opts, i) {
- var steps = opts.steps || opts.segments - 1;
- var end = opts.opacity !== undefined ? opts.opacity : 1 / steps;
- return 1 - Math.min(i, steps) * (1 - end) / steps;
- };
-
- /**
- * Default rendering strategy. If neither SVG nor VML is available, a div with class-name 'busy'
- * is inserted, that can be styled with CSS to display an animated gif as fallback.
- */
- var render = function () {
- return $('
').addClass('busy');
- };
-
- /**
- * The default animation strategy does nothing as we expect an animated gif as fallback.
- */
- var animate = function () {
- };
-
- /**
- * Utility function to create elements in the SVG namespace.
- */
- function svg(tag, attr) {
- var el = document.createElementNS("http://www.w3.org/2000/svg", tag || 'svg');
- if (attr) {
- $.each(attr, function (k, v) {
- el.setAttributeNS(null, k, v);
- });
- }
- return $(el);
+// By: Hans Fjällemark and John Papa
+// Rewritten by Alex Cornejo
+// https://github.com/CodeSeven/KoLite
+//
+(function (factory) {
+ if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
+ factory(require("knockout"), exports);
+ } else if (typeof define === "function" && define["amd"]) {
+ define(["knockout", "exports"], factory);
+ } else {
+ factory(ko, ko);
}
-
- if (document.createElementNS && document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGRect) {
-
- // =======================================================================================
- // SVG Rendering
- // =======================================================================================
-
- /**
- * Rendering strategy that creates a SVG tree.
- */
- render = function (target, d) {
- var innerRadius = d.width * 2 + d.space;
- var r = (innerRadius + d.length + Math.ceil(d.width / 2) + 1);
-
- var el = svg().width(r * 2).height(r * 2);
-
- var g = svg('g', {
- 'stroke-width': d.width,
- 'stroke-linecap': 'round',
- stroke: d.color
- }).appendTo(svg('g', { transform: 'translate(' + r + ',' + r + ')' }).appendTo(el));
-
- for (var i = 0; i < d.segments; i++) {
- g.append(svg('line', {
- x1: 0,
- y1: innerRadius,
- x2: 0,
- y2: innerRadius + d.length,
- transform: 'rotate(' + (360 / d.segments * i) + ', 0, 0)',
- opacity: $.fn.activity.getOpacity(d, i)
- }));
- }
- return $('
').append(el).width(2 * r).height(2 * r);
- };
-
- // Check if Webkit CSS animations are available, as they work much better on the iPad
- // than setTimeout() based animations.
-
- if (document.createElement('div').style.WebkitAnimationName !== undefined) {
-
- var animations = {};
-
- /**
- * Animation strategy that uses dynamically created CSS animation rules.
- */
- animate = function (el, steps, duration) {
- if (!animations[steps]) {
- var name = 'spin' + steps;
- var rule = '@-webkit-keyframes ' + name + ' {';
- for (var i = 0; i < steps; i++) {
- var p1 = Math.round(100000 / steps * i) / 1000;
- var p2 = Math.round(100000 / steps * (i + 1) - 1) / 1000;
- var value = '% { -webkit-transform:rotate(' + Math.round(360 / steps * i) + 'deg); }\n';
- rule += p1 + value + p2 + value;
- }
- rule += '100% { -webkit-transform:rotate(100deg); }\n}';
- document.styleSheets[0].insertRule(rule, 0);
- animations[steps] = name;
- }
- el.css('-webkit-animation', animations[steps] + ' ' + duration + 's linear infinite');
- };
- }
- else {
-
- /**
- * Animation strategy that transforms a SVG element using setInterval().
- */
- animate = function (el, steps, duration) {
- var rotation = 0;
- var g = el.find('g g').get(0);
- el.data('interval', setInterval(function () {
- g.setAttributeNS(null, 'transform', 'rotate(' + (++rotation % steps * (360 / steps)) + ')');
- }, duration * 1000 / steps));
- };
- }
-
+}(function (ko, exports) {
+ if (typeof (ko) === undefined) {
+ throw 'Knockout is required, please ensure it is loaded before loading the dirty flag plug-in';
}
- else {
- // =======================================================================================
- // VML Rendering
- // =======================================================================================
-
- var s = $('').css('behavior', 'url(#default#VML)');
-
- $('body').append(s);
-
- if (s.get(0).adj) {
-
- // VML support detected. Insert CSS rules for group, shape and stroke.
- var sheet = document.createStyleSheet();
- $.each(['group', 'shape', 'stroke'], function () {
- sheet.addRule(this, "behavior:url(#default#VML);");
- });
-
- /**
- * Rendering strategy that creates a VML tree.
- */
- render = function (target, d) {
-
- var innerRadius = d.width * 2 + d.space;
- var r = (innerRadius + d.length + Math.ceil(d.width / 2) + 1);
- var s = r * 2;
- var o = -Math.ceil(s / 2);
-
- var el = $('', { coordsize: s + ' ' + s, coordorigin: o + ' ' + o }).css({ top: o, left: o, width: s, height: s });
- for (var i = 0; i < d.segments; i++) {
- el.append($('', { path: 'm ' + innerRadius + ',0 l ' + (innerRadius + d.length) + ',0' }).css({
- width: s,
- height: s,
- rotation: (360 / d.segments * i) + 'deg'
- }).append($('', { color: d.color, weight: d.width + 'px', endcap: 'round', opacity: $.fn.activity.getOpacity(d, i) })));
- }
- return $('', { coordsize: s + ' ' + s }).css({ width: s, height: s, overflow: 'hidden' }).append(el);
- };
-
- /**
- * Animation strategy that modifies the VML rotation property using setInterval().
- */
- animate = function (el, steps, duration) {
- var rotation = 0;
- var g = el.get(0);
- el.data('interval', setInterval(function () {
- g.style.rotation = ++rotation % steps * (360 / steps);
- }, duration * 1000 / steps));
- };
- }
- $(s).remove();
+ var defaultOptions = {
+ container: 'i',
+ activityClass: 'fa fa-spinner fa-spin',
+ inactiveClass: ''
+ };
+
+ function getOptions(poptions) {
+ var options = {};
+ for (var p in defaultOptions)
+ if (defaultOptions.hasOwnProperty(p))
+ if (poptions && poptions.hasOwnProperty(p))
+ options[p] = poptions[p];
+ else
+ options[p] = defaultOptions[p];
+ return options;
}
-})(jQuery);
-
-
-// By: Hans Fj�llemark and John Papa
-// https://github.com/CodeSeven/KoLite
-
-;(function($) {
- "use strict";
-
- /* ACTIVITY INDICATOR EXTENDED CLASS DEFINITION
- * ========================= */
- var Indicator = function($element) {
- this.$element = $element;
- this.onlyIcon = this.$element.contents().length === 1 && this.$element.children('i').length === 1;
- this.activityText = this.$element.data('activity-text');
- this.isIndicatorOnly = this.$element.is('i');
- this.icons = this.$element.children('i');
- };
-
- Indicator.prototype = {
- createTemporaryIcon: function() {
- if (this.onlyIcon)
- return;
- //this.temporaryIcon = $('');
- this.temporaryIcon = $('');
- this.$element.append(this.temporaryIcon);
- },
-
- hideExistingIcons: function() {
- if (this.onlyIcon)
- this.icons.css('visibility', 'hidden');
- },
-
- moveSpinnerToFront: function() {
- $('body > div, body > group').first().css('z-index', 9999);
- },
-
- removeTemporaryIcon: function() {
- if (!this.temporaryIcon)
- return;
-
- this.temporaryIcon.remove();
- this.temporaryIcon = null;
- },
-
- setText: function(state) {
- if (!this.activityText)
- return;
- var data = this.$element.data(),
- val = this.$element.is('input') ? 'val' : 'html';
- if (state === 'activity')
- this.$element.data('resetText', this.$element[val]());
- this.$element[val](data[state + 'Text']);
- },
-
- showExistingIcons: function() {
- this.icons.css('visibility', 'visible');
- },
-
- start: function() {
- this.isBusy = true;
- this.setText('activity');
- this.createTemporaryIcon();
- this.hideExistingIcons();
- if (this.$element.is('button'))
- this.$element.addClass('disabled').attr('disabled', 'disabled');
- this.$element.activity({
- align: this.onlyIcon || this.isIndicatorOnly ? 'center' : 'right',
- length: this.isIndicatorOnly ? 5 : 2,
- padding: 12,
- outside: true,
- segments: this.isIndicatorOnly ? 12 : 10,
- space: this.isIndicatorOnly ? 2 : 1,
- width: 1.5
- });
- this.moveSpinnerToFront();
- },
-
- stop: function() {
- this.removeTemporaryIcon();
- this.showExistingIcons();
- this.isBusy = false;
- this.setText('reset');
- this.$element.activity(false);
- this.$element.removeClass('disabled').removeAttr('disabled');
- },
-
- update: function(isLoading) {
- if (isLoading && !this.isBusy) {
- this.start();
- }
-
- if (!isLoading && this.isBusy) {
- this.stop();
- }
- }
- };
-
- /* ACTIVITY INDICATOR EXTENDED PLUGIN DEFINITION
- * ========================== */
-
- $.fn.activityEx = function(isLoading) {
- var activity = function($element) {
- if (!isLoading) {
- $element.activity(false);
- return;
- }
-
- var length = Math.round($element.height() / 4);
- var isInput = $element.is('input');
-
- $element.activity({
- align: $element.is('input') ? 'right' : 'center',
- length: length,
- padding: isInput ? length : 0,
- outside: true,
- segments: Math.max(10, 10 + (length - 5)),
- space: 1,
- width: 1.5
- });
- $('body > div').first().css('z-index', 9999);
- },
- buttonActivity = function($element) {
- var data = $element.data('activityEx');
- if (!data)
- $element.data('activityEx', (data = new Indicator($element)));
- data.update(isLoading);
- };
- return this.each(function() {
- $(this).is('button, input, a') ? buttonActivity($(this)) : activity($(this));
- });
- };
-})(jQuery);
-
-
-;(function ($, ko) {
ko.bindingHandlers.activity = {
- init: function (element) {
- ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
- $(element).activityEx(false);
- });
- },
-
- update: function (element, valueAccessor) {
+ init: function (element, valueAccessor, allBindingsAccessor) {
+ var options = getOptions(allBindingsAccessor().activityOptions);
+ var activity_indicator = document.createElement(options.container);
+ element._activity_indicator = activity_indicator;
+ element.insertBefore(activity_indicator, element.firstChild);
+ ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
+ element.removeChild(activity_indicator);
+ delete element._activity_indicator;
+ });
+ },
+
+ update: function (element, valueAccessor, allBindingsAccessor) {
+ var options = getOptions(allBindingsAccessor().activityOptions);
var value = ko.utils.unwrapObservable(valueAccessor());
- var activity = $.isFunction(value) ? value() : value;
- typeof activity !== 'boolean' || $(element).activityEx(activity);
+ var activity = typeof value === "function" ? value() : value;
+
+ if (activity)
+ element._activity_indicator.className = options.activityClass;
+ else
+ element._activity_indicator.className = options.inactiveClass;
}
};
-})(jQuery, ko);
+
+}));