/* Minification failed. Returning unminified contents.
(1660,17,1663,18): run-time error JS1314: Implicit property name must be identifier: isBelowTheFold(element, threshold){
                    var result = !_belowthefold(element, threshold);
                    return result;
                }
 */


var mobileApplicatoin = angular.module("barfootMobile", ['ngTouch', 'youtube-embed', 'ui.bootstrap']);
mobileApplicatoin.config(['$locationProvider', function ($locationProvider) {
    $locationProvider.html5Mode(true);
}]);








;
$("a").each(function () {
    if ($(this).attr('target') == undefined || $(this).attr('target') == '') {
        if ($(this).attr('href') != undefined && $(this).attr('href').indexOf('#') == -1 && $(this).attr('href') != '') {
            $(this).attr('target', '_self');
        }
    }
});;

if (!window['YT']) { var YT = { loading: 0, loaded: 0 }; } if (!window['YTConfig']) { var YTConfig = { 'host': 'http://www.youtube.com' }; } if (!YT.loading) { YT.loading = 1; (function () { var l = []; YT.ready = function (f) { if (YT.loaded) { f(); } else { l.push(f); } }; window.onYTReady = function () { YT.loaded = 1; for (var i = 0; i < l.length; i++) { try { l[i](); } catch (e) { } } }; YT.setConfig = function (c) { for (var k in c) { if (c.hasOwnProperty(k)) { YTConfig[k] = c[k]; } } }; var a = document.createElement('script'); a.type = 'text/javascript'; a.id = 'www-widgetapi-script'; a.src = 'https:' + '//s.ytimg.com/yts/jsbin/www-widgetapi-vflVl0AED/www-widgetapi.js'; a.async = true; var b = document.getElementsByTagName('script')[0]; b.parentNode.insertBefore(a, b); })(); };
/* global YT */
// https://github.com/brandly/angular-youtube-embed
angular.module('youtube-embed', ['ng'])
.service('youtubeEmbedUtils', ['$window', '$rootScope', function ($window, $rootScope) {
    var Service = {}

    // adapted from http://stackoverflow.com/a/5831191/1614967
    var youtubeRegexp = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\S*[^\w\s-])([\w-]{11})(?=[^\w-]|$)(?![?=&+%\w.-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig;
    var timeRegexp = /t=(\d+)[ms]?(\d+)?s?/;

    function contains(str, substr) {
        return (str.indexOf(substr) > -1);
    }

    Service.getIdFromURL = function getIdFromURL(url) {
        var id = url.replace(youtubeRegexp, '$1');

        if (contains(id, ';')) {
            var pieces = id.split(';');

            if (contains(pieces[1], '%')) {
                // links like this:
                // "http://www.youtube.com/attribution_link?a=pxa6goHqzaA&amp;u=%2Fwatch%3Fv%3DdPdgx30w9sU%26feature%3Dshare"
                // have the real query string URI encoded behind a ';'.
                // at this point, `id is 'pxa6goHqzaA;u=%2Fwatch%3Fv%3DdPdgx30w9sU%26feature%3Dshare'
                var uriComponent = decodeURIComponent(pieces[1]);
                id = ('http://youtube.com' + uriComponent)
                        .replace(youtubeRegexp, '$1');
            } else {
                // https://www.youtube.com/watch?v=VbNF9X1waSc&amp;feature=youtu.be
                // `id` looks like 'VbNF9X1waSc;feature=youtu.be' currently.
                // strip the ';feature=youtu.be'
                id = pieces[0];
            }
        } else if (contains(id, '#')) {
            // id might look like '93LvTKF_jW0#t=1'
            // and we want '93LvTKF_jW0'
            id = id.split('#')[0];
        }

        return id;
    };

    Service.getTimeFromURL = function getTimeFromURL(url) {
        url = url || '';

        // t=4m20s
        // returns ['t=4m20s', '4', '20']
        // t=46s
        // returns ['t=46s', '46']
        // t=46
        // returns ['t=46', '46']
        var times = url.match(timeRegexp);

        if (!times) {
            // zero seconds
            return 0;
        }

        // assume the first
        var full = times[0],
            minutes = times[1],
            seconds = times[2];

        // t=4m20s
        if (typeof seconds !== 'undefined') {
            seconds = parseInt(seconds, 10);
            minutes = parseInt(minutes, 10);

            // t=4m
        } else if (contains(full, 'm')) {
            minutes = parseInt(minutes, 10);
            seconds = 0;

            // t=4s
            // t=4
        } else {
            seconds = parseInt(minutes, 10);
            minutes = 0;
        }

        // in seconds
        return seconds + (minutes * 60);
    };

    Service.ready = false;

    function applyServiceIsReady() {
        $rootScope.$apply(function () {
            Service.ready = true;
        });
    };

    // If the library isn't here at all,
    if (typeof YT === "undefined") {
        // ...grab on to global callback, in case it's eventually loaded
        $window.onYouTubeIframeAPIReady = applyServiceIsReady;
    } else if (YT.loaded) {
        Service.ready = true;
    } else {
        YT.ready(applyServiceIsReady);
    }

    return Service;
}])
.directive('youtubeVideo', ['$window', 'youtubeEmbedUtils', function ($window, youtubeEmbedUtils) {
    var uniqId = 1;

    // from YT.PlayerState
    var stateNames = {
        '-1': 'unstarted',
        0: 'ended',
        1: 'playing',
        2: 'paused',
        3: 'buffering',
        5: 'queued'
    };

    var eventPrefix = 'youtube.player.';

    $window.YTConfig = {
        host: 'https://www.youtube.com'
    };

    return {
        restrict: 'EA',
        scope: {
            videoId: '=?',
            videoUrl: '=?',
            player: '=?',
            playerVars: '=?',
            playerHeight: '=?',
            playerWidth: '=?'
        },
        link: function (scope, element, attrs) {
            // allows us to $watch `ready`
            scope.utils = youtubeEmbedUtils;

            // player-id attr > id attr > directive-generated ID
            var playerId = attrs.playerId || element[0].id || 'unique-youtube-embed-id-' + uniqId++;
            element[0].id = playerId;

            // Attach to element
            scope.playerHeight = scope.playerHeight || 390;
            scope.playerWidth = scope.playerWidth || 640;
            scope.playerVars = scope.playerVars || {};

            // YT calls callbacks outside of digest cycle
            function applyBroadcast() {
                var args = Array.prototype.slice.call(arguments);
                scope.$apply(function () {
                    scope.$emit.apply(scope, args);
                });
            }

            function onPlayerStateChange(event) {
                var state = stateNames[event.data];
                if (typeof state !== 'undefined') {
                    applyBroadcast(eventPrefix + state, scope.player, event);
                }
                scope.$apply(function () {
                    scope.player.currentState = state;
                });
            }

            function onPlayerReady(event) {
                applyBroadcast(eventPrefix + 'ready', scope.player, event);
            }

            function onPlayerError(event) {
                applyBroadcast(eventPrefix + 'error', scope.player, event);
            }

            function createPlayer() {
                var playerVars = angular.copy(scope.playerVars);
                playerVars.start = playerVars.start || scope.urlStartTime;
                var player = new YT.Player(playerId, {
                    height: scope.playerHeight,
                    width: scope.playerWidth,
                    videoId: scope.videoId,
                    playerVars: playerVars,
                    events: {
                        onReady: onPlayerReady,
                        onStateChange: onPlayerStateChange,
                        onError: onPlayerError
                    }
                });

                player.id = playerId;
                return player;
            }

            function loadPlayer() {
                if (scope.videoId || scope.playerVars.list) {
                    if (scope.player && typeof scope.player.destroy === 'function') {
                        scope.player.destroy();
                    }

                    scope.player = createPlayer();
                }
            };

            var stopWatchingReady = scope.$watch(
                function () {
                    return scope.utils.ready
                        // Wait until one of them is defined...
                        && (typeof scope.videoUrl !== 'undefined'
                        || typeof scope.videoId !== 'undefined'
                        || typeof scope.playerVars.list !== 'undefined');
                },
                function (ready) {
                    if (ready) {
                        stopWatchingReady();

                        // URL takes first priority
                        if (typeof scope.videoUrl !== 'undefined') {
                            scope.$watch('videoUrl', function (url) {
                                scope.videoId = scope.utils.getIdFromURL(url);
                                scope.urlStartTime = scope.utils.getTimeFromURL(url);

                                loadPlayer();
                            });

                            // then, a video ID
                        } else if (typeof scope.videoId !== 'undefined') {
                            scope.$watch('videoId', function () {
                                scope.urlStartTime = null;
                                loadPlayer();
                            });

                            // finally, a list
                        } else {
                            scope.$watch('playerVars.list', function () {
                                scope.urlStartTime = null;
                                loadPlayer();
                            });
                        }
                    }
                });

            scope.$watchCollection(['playerHeight', 'playerWidth'], function () {
                if (scope.player) {
                    scope.player.setSize(scope.playerWidth, scope.playerHeight);
                }
            });

            scope.$on('$destroy', function () {
                scope.player && scope.player.destroy();
            });
        }
    };
}]);;
/**
 * @license AngularJS v1.5.0
 * (c) 2010-2016 Google, Inc. http://angularjs.org
 * License: MIT
 */
(function (window, angular, undefined) {
    'use strict';

    /* global ngTouchClickDirectiveFactory: false,
     */

    /**
     * @ngdoc module
     * @name ngTouch
     * @description
     *
     * # ngTouch
     *
     * The `ngTouch` module provides touch events and other helpers for touch-enabled devices.
     * The implementation is based on jQuery Mobile touch event handling
     * ([jquerymobile.com](http://jquerymobile.com/)).
     *
     *
     * See {@link ngTouch.$swipe `$swipe`} for usage.
     *
     * <div doc-module-components="ngTouch"></div>
     *
     */

    // define ngTouch module
    /* global -ngTouch */
    var ngTouch = angular.module('ngTouch', []);

    ngTouch.provider('$touch', $TouchProvider);

    function nodeName_(element) {
        return angular.lowercase(element.nodeName || (element[0] && element[0].nodeName));
    }

    /**
     * @ngdoc provider
     * @name $touchProvider
     *
     * @description
     * The `$touchProvider` allows enabling / disabling {@link ngTouch.ngClick ngTouch's ngClick directive}.
     */
    $TouchProvider.$inject = ['$provide', '$compileProvider'];
    function $TouchProvider($provide, $compileProvider) {

        /**
         * @ngdoc method
         * @name  $touchProvider#ngClickOverrideEnabled
         *
         * @param {boolean=} enabled update the ngClickOverrideEnabled state if provided, otherwise just return the
         * current ngClickOverrideEnabled state
         * @returns {*} current value if used as getter or itself (chaining) if used as setter
         *
         * @kind function
         *
         * @description
         * Call this method to enable/disable {@link ngTouch.ngClick ngTouch's ngClick directive}. If enabled,
         * the default ngClick directive will be replaced by a version that eliminates the 300ms delay for
         * click events on browser for touch-devices.
         *
         * The default is `false`.
         *
         */
        var ngClickOverrideEnabled = false;
        var ngClickDirectiveAdded = false;
        this.ngClickOverrideEnabled = function (enabled) {
            if (angular.isDefined(enabled)) {

                if (enabled && !ngClickDirectiveAdded) {
                    ngClickDirectiveAdded = true;

                    // Use this to identify the correct directive in the delegate
                    ngTouchClickDirectiveFactory.$$moduleName = 'ngTouch';
                    $compileProvider.directive('ngClick', ngTouchClickDirectiveFactory);

                    $provide.decorator('ngClickDirective', ['$delegate', function ($delegate) {
                        if (ngClickOverrideEnabled) {
                            // drop the default ngClick directive
                            $delegate.shift();
                        } else {
                            // drop the ngTouch ngClick directive if the override has been re-disabled (because
                            // we cannot de-register added directives)
                            var i = $delegate.length - 1;
                            while (i >= 0) {
                                if ($delegate[i].$$moduleName === 'ngTouch') {
                                    $delegate.splice(i, 1);
                                    break;
                                }
                                i--;
                            }
                        }

                        return $delegate;
                    }]);
                }

                ngClickOverrideEnabled = enabled;
                return this;
            }

            return ngClickOverrideEnabled;
        };

        /**
        * @ngdoc service
        * @name $touch
        * @kind object
        *
        * @description
        * Provides the {@link ngTouch.$touch#ngClickOverrideEnabled `ngClickOverrideEnabled`} method.
        *
        */
        this.$get = function () {
            return {
                /**
                 * @ngdoc method
                 * @name  $touch#ngClickOverrideEnabled
                 *
                 * @returns {*} current value of `ngClickOverrideEnabled` set in the {@link ngTouch.$touchProvider $touchProvider},
                 * i.e. if {@link ngTouch.ngClick ngTouch's ngClick} directive is enabled.
                 *
                 * @kind function
                 */
                ngClickOverrideEnabled: function () {
                    return ngClickOverrideEnabled;
                }
            };
        };

    }

    /* global ngTouch: false */

    /**
     * @ngdoc service
     * @name $swipe
     *
     * @description
     * The `$swipe` service is a service that abstracts the messier details of hold-and-drag swipe
     * behavior, to make implementing swipe-related directives more convenient.
     *
     * Requires the {@link ngTouch `ngTouch`} module to be installed.
     *
     * `$swipe` is used by the `ngSwipeLeft` and `ngSwipeRight` directives in `ngTouch`.
     *
     * # Usage
     * The `$swipe` service is an object with a single method: `bind`. `bind` takes an element
     * which is to be watched for swipes, and an object with four handler functions. See the
     * documentation for `bind` below.
     */

    ngTouch.factory('$swipe', [function () {
        // The total distance in any direction before we make the call on swipe vs. scroll.
        var MOVE_BUFFER_RADIUS = 10;

        var POINTER_EVENTS = {
            'mouse': {
                start: 'mousedown',
                move: 'mousemove',
                end: 'mouseup'
            },
            'touch': {
                start: 'touchstart',
                move: 'touchmove',
                end: 'touchend',
                cancel: 'touchcancel'
            }
        };

        function getCoordinates(event) {
            var originalEvent = event.originalEvent || event;
            var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent];
            var e = (originalEvent.changedTouches && originalEvent.changedTouches[0]) || touches[0];

            return {
                x: e.clientX,
                y: e.clientY
            };
        }

        function getEvents(pointerTypes, eventType) {
            var res = [];
            angular.forEach(pointerTypes, function (pointerType) {
                var eventName = POINTER_EVENTS[pointerType][eventType];
                if (eventName) {
                    res.push(eventName);
                }
            });
            return res.join(' ');
        }

        return {
            /**
             * @ngdoc method
             * @name $swipe#bind
             *
             * @description
             * The main method of `$swipe`. It takes an element to be watched for swipe motions, and an
             * object containing event handlers.
             * The pointer types that should be used can be specified via the optional
             * third argument, which is an array of strings `'mouse'` and `'touch'`. By default,
             * `$swipe` will listen for `mouse` and `touch` events.
             *
             * The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end`
             * receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }` and the raw
             * `event`. `cancel` receives the raw `event` as its single parameter.
             *
             * `start` is called on either `mousedown` or `touchstart`. After this event, `$swipe` is
             * watching for `touchmove` or `mousemove` events. These events are ignored until the total
             * distance moved in either dimension exceeds a small threshold.
             *
             * Once this threshold is exceeded, either the horizontal or vertical delta is greater.
             * - If the horizontal distance is greater, this is a swipe and `move` and `end` events follow.
             * - If the vertical distance is greater, this is a scroll, and we let the browser take over.
             *   A `cancel` event is sent.
             *
             * `move` is called on `mousemove` and `touchmove` after the above logic has determined that
             * a swipe is in progress.
             *
             * `end` is called when a swipe is successfully completed with a `touchend` or `mouseup`.
             *
             * `cancel` is called either on a `touchcancel` from the browser, or when we begin scrolling
             * as described above.
             *
             */
            bind: function (element, eventHandlers, pointerTypes) {
                // Absolute total movement, used to control swipe vs. scroll.
                var totalX, totalY;
                // Coordinates of the start position.
                var startCoords;
                // Last event's position.
                var lastPos;
                // Whether a swipe is active.
                var active = false;

                pointerTypes = pointerTypes || ['mouse', 'touch'];
                element.on(getEvents(pointerTypes, 'start'), function (event) {
                    startCoords = getCoordinates(event);
                    active = true;
                    totalX = 0;
                    totalY = 0;
                    lastPos = startCoords;
                    eventHandlers['start'] && eventHandlers['start'](startCoords, event);
                });
                var events = getEvents(pointerTypes, 'cancel');
                if (events) {
                    element.on(events, function (event) {
                        active = false;
                        eventHandlers['cancel'] && eventHandlers['cancel'](event);
                    });
                }

                element.on(getEvents(pointerTypes, 'move'), function (event) {
                    if (!active) return;

                    // Android will send a touchcancel if it thinks we're starting to scroll.
                    // So when the total distance (+ or - or both) exceeds 10px in either direction,
                    // we either:
                    // - On totalX > totalY, we send preventDefault() and treat this as a swipe.
                    // - On totalY > totalX, we let the browser handle it as a scroll.

                    if (!startCoords) return;
                    var coords = getCoordinates(event);

                    totalX += Math.abs(coords.x - lastPos.x);
                    totalY += Math.abs(coords.y - lastPos.y);

                    lastPos = coords;

                    if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) {
                        return;
                    }

                    // One of totalX or totalY has exceeded the buffer, so decide on swipe vs. scroll.
                    if (totalY > totalX) {
                        // Allow native scrolling to take over.
                        active = false;
                        eventHandlers['cancel'] && eventHandlers['cancel'](event);
                        return;
                    } else {
                        // Prevent the browser from scrolling.
                        event.preventDefault();
                        eventHandlers['move'] && eventHandlers['move'](coords, event);
                    }
                });

                element.on(getEvents(pointerTypes, 'end'), function (event) {
                    if (!active) return;
                    active = false;
                    eventHandlers['end'] && eventHandlers['end'](getCoordinates(event), event);
                });
            }
        };
    }]);

    /* global ngTouch: false,
      nodeName_: false
    */

    /**
     * @ngdoc directive
     * @name ngClick
     * @deprecated
     *
     * @description
     * <div class="alert alert-danger">
     * **DEPRECATION NOTICE**: Beginning with Angular 1.5, this directive is deprecated and by default **disabled**.
     * The directive will receive no further support and might be removed from future releases.
     * If you need the directive, you can enable it with the {@link ngTouch.$touchProvider $touchProvider#ngClickOverrideEnabled}
     * function. We also recommend that you migrate to [FastClick](https://github.com/ftlabs/fastclick).
     * To learn more about the 300ms delay, this [Telerik article](http://developer.telerik.com/featured/300-ms-click-delay-ios-8/)
     * gives a good overview.
     * </div>
     * A more powerful replacement for the default ngClick designed to be used on touchscreen
     * devices. Most mobile browsers wait about 300ms after a tap-and-release before sending
     * the click event. This version handles them immediately, and then prevents the
     * following click event from propagating.
     *
     * Requires the {@link ngTouch `ngTouch`} module to be installed.
     *
     * This directive can fall back to using an ordinary click event, and so works on desktop
     * browsers as well as mobile.
     *
     * This directive also sets the CSS class `ng-click-active` while the element is being held
     * down (by a mouse click or touch) so you can restyle the depressed element if you wish.
     *
     * @element ANY
     * @param {expression} ngClick {@link guide/expression Expression} to evaluate
     * upon tap. (Event object is available as `$event`)
     *
     * @example
        <example module="ngClickExample" deps="angular-touch.js">
          <file name="index.html">
            <button ng-click="count = count + 1" ng-init="count=0">
              Increment
            </button>
            count: {{ count }}
          </file>
          <file name="script.js">
            angular.module('ngClickExample', ['ngTouch']);
          </file>
        </example>
     */

    var ngTouchClickDirectiveFactory = ['$parse', '$timeout', '$rootElement',
        function ($parse, $timeout, $rootElement) {
            var TAP_DURATION = 750; // Shorter than 750ms is a tap, longer is a taphold or drag.
            var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers.
            var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click
            var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks.

            var ACTIVE_CLASS_NAME = 'ng-click-active';
            var lastPreventedTime;
            var touchCoordinates;
            var lastLabelClickCoordinates;


            // TAP EVENTS AND GHOST CLICKS
            //
            // Why tap events?
            // Mobile browsers detect a tap, then wait a moment (usually ~300ms) to see if you're
            // double-tapping, and then fire a click event.
            //
            // This delay sucks and makes mobile apps feel unresponsive.
            // So we detect touchstart, touchcancel and touchend ourselves and determine when
            // the user has tapped on something.
            //
            // What happens when the browser then generates a click event?
            // The browser, of course, also detects the tap and fires a click after a delay. This results in
            // tapping/clicking twice. We do "clickbusting" to prevent it.
            //
            // How does it work?
            // We attach global touchstart and click handlers, that run during the capture (early) phase.
            // So the sequence for a tap is:
            // - global touchstart: Sets an "allowable region" at the point touched.
            // - element's touchstart: Starts a touch
            // (- touchcancel ends the touch, no click follows)
            // - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold
            //   too long) and fires the user's tap handler. The touchend also calls preventGhostClick().
            // - preventGhostClick() removes the allowable region the global touchstart created.
            // - The browser generates a click event.
            // - The global click handler catches the click, and checks whether it was in an allowable region.
            //     - If preventGhostClick was called, the region will have been removed, the click is busted.
            //     - If the region is still there, the click proceeds normally. Therefore clicks on links and
            //       other elements without ngTap on them work normally.
            //
            // This is an ugly, terrible hack!
            // Yeah, tell me about it. The alternatives are using the slow click events, or making our users
            // deal with the ghost clicks, so I consider this the least of evils. Fortunately Angular
            // encapsulates this ugly logic away from the user.
            //
            // Why not just put click handlers on the element?
            // We do that too, just to be sure. If the tap event caused the DOM to change,
            // it is possible another element is now in that position. To take account for these possibly
            // distinct elements, the handlers are global and care only about coordinates.

            // Checks if the coordinates are close enough to be within the region.
            function hit(x1, y1, x2, y2) {
                return Math.abs(x1 - x2) < CLICKBUSTER_THRESHOLD && Math.abs(y1 - y2) < CLICKBUSTER_THRESHOLD;
            }

            // Checks a list of allowable regions against a click location.
            // Returns true if the click should be allowed.
            // Splices out the allowable region from the list after it has been used.
            function checkAllowableRegions(touchCoordinates, x, y) {
                for (var i = 0; i < touchCoordinates.length; i += 2) {
                    if (hit(touchCoordinates[i], touchCoordinates[i + 1], x, y)) {
                        touchCoordinates.splice(i, i + 2);
                        return true; // allowable region
                    }
                }
                return false; // No allowable region; bust it.
            }

            // Global click handler that prevents the click if it's in a bustable zone and preventGhostClick
            // was called recently.
            function onClick(event) {
                if (Date.now() - lastPreventedTime > PREVENT_DURATION) {
                    return; // Too old.
                }

                var touches = event.touches && event.touches.length ? event.touches : [event];
                var x = touches[0].clientX;
                var y = touches[0].clientY;
                // Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label
                // and on the input element). Depending on the exact browser, this second click we don't want
                // to bust has either (0,0), negative coordinates, or coordinates equal to triggering label
                // click event
                if (x < 1 && y < 1) {
                    return; // offscreen
                }
                if (lastLabelClickCoordinates &&
                    lastLabelClickCoordinates[0] === x && lastLabelClickCoordinates[1] === y) {
                    return; // input click triggered by label click
                }
                // reset label click coordinates on first subsequent click
                if (lastLabelClickCoordinates) {
                    lastLabelClickCoordinates = null;
                }
                // remember label click coordinates to prevent click busting of trigger click event on input
                if (nodeName_(event.target) === 'label') {
                    lastLabelClickCoordinates = [x, y];
                }

                // Look for an allowable region containing this click.
                // If we find one, that means it was created by touchstart and not removed by
                // preventGhostClick, so we don't bust it.
                if (checkAllowableRegions(touchCoordinates, x, y)) {
                    return;
                }

                // If we didn't find an allowable region, bust the click.
                event.stopPropagation();
                event.preventDefault();

                // Blur focused form elements
                event.target && event.target.blur && event.target.blur();
            }


            // Global touchstart handler that creates an allowable region for a click event.
            // This allowable region can be removed by preventGhostClick if we want to bust it.
            function onTouchStart(event) {
                var touches = event.touches && event.touches.length ? event.touches : [event];
                var x = touches[0].clientX;
                var y = touches[0].clientY;
                touchCoordinates.push(x, y);

                $timeout(function () {
                    // Remove the allowable region.
                    for (var i = 0; i < touchCoordinates.length; i += 2) {
                        if (touchCoordinates[i] == x && touchCoordinates[i + 1] == y) {
                            touchCoordinates.splice(i, i + 2);
                            return;
                        }
                    }
                }, PREVENT_DURATION, false);
            }

            // On the first call, attaches some event handlers. Then whenever it gets called, it creates a
            // zone around the touchstart where clicks will get busted.
            function preventGhostClick(x, y) {
                if (!touchCoordinates) {
                    $rootElement[0].addEventListener('click', onClick, true);
                    $rootElement[0].addEventListener('touchstart', onTouchStart, true);
                    touchCoordinates = [];
                }

                lastPreventedTime = Date.now();

                checkAllowableRegions(touchCoordinates, x, y);
            }

            // Actual linking function.
            return function (scope, element, attr) {
                var clickHandler = $parse(attr.ngClick),
                    tapping = false,
                    tapElement,  // Used to blur the element after a tap.
                    startTime,   // Used to check if the tap was held too long.
                    touchStartX,
                    touchStartY;

                function resetState() {
                    tapping = false;
                    element.removeClass(ACTIVE_CLASS_NAME);
                }

                element.on('touchstart', function (event) {
                    tapping = true;
                    tapElement = event.target ? event.target : event.srcElement; // IE uses srcElement.
                    // Hack for Safari, which can target text nodes instead of containers.
                    if (tapElement.nodeType == 3) {
                        tapElement = tapElement.parentNode;
                    }

                    element.addClass(ACTIVE_CLASS_NAME);

                    startTime = Date.now();

                    // Use jQuery originalEvent
                    var originalEvent = event.originalEvent || event;
                    var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent];
                    var e = touches[0];
                    touchStartX = e.clientX;
                    touchStartY = e.clientY;
                });

                element.on('touchcancel', function (event) {
                    resetState();
                });

                element.on('touchend', function (event) {
                    var diff = Date.now() - startTime;

                    // Use jQuery originalEvent
                    var originalEvent = event.originalEvent || event;
                    var touches = (originalEvent.changedTouches && originalEvent.changedTouches.length) ?
                        originalEvent.changedTouches :
                        ((originalEvent.touches && originalEvent.touches.length) ? originalEvent.touches : [originalEvent]);
                    var e = touches[0];
                    var x = e.clientX;
                    var y = e.clientY;
                    var dist = Math.sqrt(Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2));

                    if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) {
                        // Call preventGhostClick so the clickbuster will catch the corresponding click.
                        preventGhostClick(x, y);

                        // Blur the focused element (the button, probably) before firing the callback.
                        // This doesn't work perfectly on Android Chrome, but seems to work elsewhere.
                        // I couldn't get anything to work reliably on Android Chrome.
                        if (tapElement) {
                            tapElement.blur();
                        }

                        if (!angular.isDefined(attr.disabled) || attr.disabled === false) {
                            element.triggerHandler('click', [event]);
                        }
                    }

                    resetState();
                });

                // Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click
                // something else nearby.
                element.onclick = function (event) { };

                // Actual click handler.
                // There are three different kinds of clicks, only two of which reach this point.
                // - On desktop browsers without touch events, their clicks will always come here.
                // - On mobile browsers, the simulated "fast" click will call this.
                // - But the browser's follow-up slow click will be "busted" before it reaches this handler.
                // Therefore it's safe to use this directive on both mobile and desktop.
                element.on('click', function (event, touchend) {
                    scope.$apply(function () {
                        clickHandler(scope, { $event: (touchend || event) });
                    });
                });

                element.on('mousedown', function (event) {
                    element.addClass(ACTIVE_CLASS_NAME);
                });

                element.on('mousemove mouseup', function (event) {
                    element.removeClass(ACTIVE_CLASS_NAME);
                });

            };
        }];

    /* global ngTouch: false */

    /**
     * @ngdoc directive
     * @name ngSwipeLeft
     *
     * @description
     * Specify custom behavior when an element is swiped to the left on a touchscreen device.
     * A leftward swipe is a quick, right-to-left slide of the finger.
     * Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag
     * too.
     *
     * To disable the mouse click and drag functionality, add `ng-swipe-disable-mouse` to
     * the `ng-swipe-left` or `ng-swipe-right` DOM Element.
     *
     * Requires the {@link ngTouch `ngTouch`} module to be installed.
     *
     * @element ANY
     * @param {expression} ngSwipeLeft {@link guide/expression Expression} to evaluate
     * upon left swipe. (Event object is available as `$event`)
     *
     * @example
        <example module="ngSwipeLeftExample" deps="angular-touch.js">
          <file name="index.html">
            <div ng-show="!showActions" ng-swipe-left="showActions = true">
              Some list content, like an email in the inbox
            </div>
            <div ng-show="showActions" ng-swipe-right="showActions = false">
              <button ng-click="reply()">Reply</button>
              <button ng-click="delete()">Delete</button>
            </div>
          </file>
          <file name="script.js">
            angular.module('ngSwipeLeftExample', ['ngTouch']);
          </file>
        </example>
     */

    /**
     * @ngdoc directive
     * @name ngSwipeRight
     *
     * @description
     * Specify custom behavior when an element is swiped to the right on a touchscreen device.
     * A rightward swipe is a quick, left-to-right slide of the finger.
     * Though ngSwipeRight is designed for touch-based devices, it will work with a mouse click and drag
     * too.
     *
     * Requires the {@link ngTouch `ngTouch`} module to be installed.
     *
     * @element ANY
     * @param {expression} ngSwipeRight {@link guide/expression Expression} to evaluate
     * upon right swipe. (Event object is available as `$event`)
     *
     * @example
        <example module="ngSwipeRightExample" deps="angular-touch.js">
          <file name="index.html">
            <div ng-show="!showActions" ng-swipe-left="showActions = true">
              Some list content, like an email in the inbox
            </div>
            <div ng-show="showActions" ng-swipe-right="showActions = false">
              <button ng-click="reply()">Reply</button>
              <button ng-click="delete()">Delete</button>
            </div>
          </file>
          <file name="script.js">
            angular.module('ngSwipeRightExample', ['ngTouch']);
          </file>
        </example>
     */

    function makeSwipeDirective(directiveName, direction, eventName) {
        ngTouch.directive(directiveName, ['$parse', '$swipe', function ($parse, $swipe) {
            // The maximum vertical delta for a swipe should be less than 75px.
            var MAX_VERTICAL_DISTANCE = 75;
            // Vertical distance should not be more than a fraction of the horizontal distance.
            var MAX_VERTICAL_RATIO = 0.3;
            // At least a 30px lateral motion is necessary for a swipe.
            var MIN_HORIZONTAL_DISTANCE = 30;

            return function (scope, element, attr) {
                var swipeHandler = $parse(attr[directiveName]);

                var startCoords, valid;

                function validSwipe(coords) {
                    // Check that it's within the coordinates.
                    // Absolute vertical distance must be within tolerances.
                    // Horizontal distance, we take the current X - the starting X.
                    // This is negative for leftward swipes and positive for rightward swipes.
                    // After multiplying by the direction (-1 for left, +1 for right), legal swipes
                    // (ie. same direction as the directive wants) will have a positive delta and
                    // illegal ones a negative delta.
                    // Therefore this delta must be positive, and larger than the minimum.
                    if (!startCoords) return false;
                    var deltaY = Math.abs(coords.y - startCoords.y);
                    var deltaX = (coords.x - startCoords.x) * direction;
                    return valid && // Short circuit for already-invalidated swipes.
                        deltaY < MAX_VERTICAL_DISTANCE &&
                        deltaX > 0 &&
                        deltaX > MIN_HORIZONTAL_DISTANCE &&
                        deltaY / deltaX < MAX_VERTICAL_RATIO;
                }

                var pointerTypes = ['touch'];
                if (!angular.isDefined(attr['ngSwipeDisableMouse'])) {
                    pointerTypes.push('mouse');
                }
                $swipe.bind(element, {
                    'start': function (coords, event) {
                        startCoords = coords;
                        valid = true;
                    },
                    'cancel': function (event) {
                        valid = false;
                    },
                    'end': function (coords, event) {
                        if (validSwipe(coords)) {
                            scope.$apply(function () {
                                element.triggerHandler(eventName);
                                swipeHandler(scope, { $event: event });
                            });
                        }
                    }
                }, pointerTypes);
            };
        }]);
    }

    // Left is negative X-coordinate, right is positive.
    makeSwipeDirective('ngSwipeLeft', -1, 'swipeleft');
    makeSwipeDirective('ngSwipeRight', 1, 'swiperight');



})(window, window.angular);;
/*
 * angular-ui-bootstrap
 * http://angular-ui.github.io/bootstrap/

 * Version: 2.2.0 - 2016-10-10
 * License: MIT
 */angular.module("ui.bootstrap",["ui.bootstrap.modal","ui.bootstrap.stackedMap","ui.bootstrap.position"]),angular.module("ui.bootstrap.modal",["ui.bootstrap.stackedMap","ui.bootstrap.position"]).factory("$$multiMap",function(){return{createNew:function(){var e={};return{entries:function(){return Object.keys(e).map(function(t){return{key:t,value:e[t]}})},get:function(t){return e[t]},hasKey:function(t){return!!e[t]},keys:function(){return Object.keys(e)},put:function(t,o){e[t]||(e[t]=[]),e[t].push(o)},remove:function(t,o){var n=e[t];if(n){var r=n.indexOf(o);-1!==r&&n.splice(r,1),n.length||delete e[t]}}}}}}).provider("$uibResolve",function(){var e=this;this.resolver=null,this.setResolver=function(e){this.resolver=e},this.$get=["$injector","$q",function(t,o){var n=e.resolver?t.get(e.resolver):null;return{resolve:function(e,r,i,a){if(n)return n.resolve(e,r,i,a);var l=[];return angular.forEach(e,function(e){l.push(angular.isFunction(e)||angular.isArray(e)?o.resolve(t.invoke(e)):angular.isString(e)?o.resolve(t.get(e)):o.resolve(e))}),o.all(l).then(function(t){var o={},n=0;return angular.forEach(e,function(e,r){o[r]=t[n++]}),o})}}}]}).directive("uibModalBackdrop",["$animate","$injector","$uibModalStack",function(e,t,o){function n(t,n,r){r.modalInClass&&(e.addClass(n,r.modalInClass),t.$on(o.NOW_CLOSING_EVENT,function(o,i){var a=i();t.modalOptions.animation?e.removeClass(n,r.modalInClass).then(a):a()}))}return{restrict:"A",compile:function(e,t){return e.addClass(t.backdropClass),n}}}]).directive("uibModalWindow",["$uibModalStack","$q","$animateCss","$document",function(e,t,o,n){return{scope:{index:"@"},restrict:"A",transclude:!0,templateUrl:function(e,t){return t.templateUrl||"uib/template/modal/window.html"},link:function(r,i,a){i.addClass(a.windowTopClass||""),r.size=a.size,r.close=function(t){var o=e.getTop();o&&o.value.backdrop&&"static"!==o.value.backdrop&&t.target===t.currentTarget&&(t.preventDefault(),t.stopPropagation(),e.dismiss(o.key,"backdrop click"))},i.on("click",r.close),r.$isRendered=!0;var l=t.defer();r.$$postDigest(function(){l.resolve()}),l.promise.then(function(){var l=null;a.modalInClass&&(l=o(i,{addClass:a.modalInClass}).start(),r.$on(e.NOW_CLOSING_EVENT,function(e,t){var n=t();o(i,{removeClass:a.modalInClass}).start().then(n)})),t.when(l).then(function(){var t=e.getTop();if(t&&e.modalRendered(t.key),!n[0].activeElement||!i[0].contains(n[0].activeElement)){var o=i[0].querySelector("[autofocus]");o?o.focus():i[0].focus()}})})}}}]).directive("uibModalAnimationClass",function(){return{compile:function(e,t){t.modalAnimation&&e.addClass(t.uibModalAnimationClass)}}}).directive("uibModalTransclude",["$animate",function(e){return{link:function(t,o,n,r,i){i(t.$parent,function(t){o.empty(),e.enter(t,o)})}}}]).factory("$uibModalStack",["$animate","$animateCss","$document","$compile","$rootScope","$q","$$multiMap","$$stackedMap","$uibPosition",function(e,t,o,n,r,i,a,l,s){function d(e){var t="-";return e.replace(D,function(e,o){return(o?t:"")+e.toLowerCase()})}function u(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)}function c(){for(var e=-1,t=C.keys(),o=0;o<t.length;o++)C.get(t[o]).value.backdrop&&(e=o);return e>-1&&M>e&&(e=M),e}function p(e,t){var o=C.get(e).value,n=o.appendTo;C.remove(e),T=C.top(),T&&(M=parseInt(T.value.modalDomEl.attr("index"),10)),m(o.modalDomEl,o.modalScope,function(){var t=o.openedClass||k;E.remove(t,e);var r=E.hasKey(t);n.toggleClass(t,r),!r&&y&&y.heightOverflow&&y.scrollbarWidth&&(n.css(y.originalRight?{paddingRight:y.originalRight+"px"}:{paddingRight:""}),y=null),f(!0)},o.closedDeferred),h(),t&&t.focus?t.focus():n.focus&&n.focus()}function f(e){var t;C.length()>0&&(t=C.top().value,t.modalDomEl.toggleClass(t.windowTopClass||"",e))}function h(){if(w&&-1===c()){var e=$;m(w,$,function(){e=null}),w=void 0,$=void 0}}function m(t,o,n,r){function a(){a.done||(a.done=!0,e.leave(t).then(function(){n&&n(),t.remove(),r&&r.resolve()}),o.$destroy())}var l,s=null,d=function(){return l||(l=i.defer(),s=l.promise),function(){l.resolve()}};return o.$broadcast(S.NOW_CLOSING_EVENT,d),i.when(s).then(a)}function g(e){if(e.isDefaultPrevented())return e;var t=C.top();if(t)switch(e.which){case 27:t.value.keyboard&&(e.preventDefault(),r.$apply(function(){S.dismiss(t.key,"escape key press")}));break;case 9:var o=S.loadFocusElementList(t),n=!1;e.shiftKey?(S.isFocusInFirstItem(e,o)||S.isModalFocused(e,t))&&(n=S.focusLastFocusableElement(o)):S.isFocusInLastItem(e,o)&&(n=S.focusFirstFocusableElement(o)),n&&(e.preventDefault(),e.stopPropagation())}}function v(e,t,o){return!e.value.modalScope.$broadcast("modal.closing",t,o).defaultPrevented}function b(){Array.prototype.forEach.call(document.querySelectorAll("["+x+"]"),function(e){var t=parseInt(e.getAttribute(x),10),o=t-1;e.setAttribute(x,o),o||(e.removeAttribute(x),e.removeAttribute("aria-hidden"))})}var w,$,y,k="modal-open",C=l.createNew(),E=a.createNew(),S={NOW_CLOSING_EVENT:"modal.stack.now-closing"},M=0,T=null,x="data-bootstrap-modal-aria-hidden-count",N="a[href], area[href], input:not([disabled]):not([tabindex='-1']), button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']), textarea:not([disabled]):not([tabindex='-1']), iframe, object, embed, *[tabindex]:not([tabindex='-1']), *[contenteditable=true]",D=/[A-Z]/g;return r.$watch(c,function(e){$&&($.index=e)}),o.on("keydown",g),r.$on("$destroy",function(){o.off("keydown",g)}),S.open=function(t,i){function a(e){function t(e){var t=e.parent()?e.parent().children():[];return Array.prototype.filter.call(t,function(t){return t!==e[0]})}if(e&&"BODY"!==e[0].tagName)return t(e).forEach(function(e){var t="true"===e.getAttribute("aria-hidden"),o=parseInt(e.getAttribute(x),10);o||(o=t?1:0),e.setAttribute(x,o+1),e.setAttribute("aria-hidden","true")}),a(e.parent())}var l=o[0].activeElement,u=i.openedClass||k;f(!1),T=C.top(),C.add(t,{deferred:i.deferred,renderDeferred:i.renderDeferred,closedDeferred:i.closedDeferred,modalScope:i.scope,backdrop:i.backdrop,keyboard:i.keyboard,openedClass:i.openedClass,windowTopClass:i.windowTopClass,animation:i.animation,appendTo:i.appendTo}),E.put(u,t);var p=i.appendTo,h=c();if(!p.length)throw new Error("appendTo element not found. Make sure that the element passed is in DOM.");h>=0&&!w&&($=r.$new(!0),$.modalOptions=i,$.index=h,w=angular.element('<div uib-modal-backdrop="modal-backdrop"></div>'),w.attr({"class":"modal-backdrop","ng-style":"{'z-index': 1040 + (index && 1 || 0) + index*10}","uib-modal-animation-class":"fade","modal-in-class":"in"}),i.backdropClass&&w.addClass(i.backdropClass),i.animation&&w.attr("modal-animation","true"),n(w)($),e.enter(w,p),s.isScrollable(p)&&(y=s.scrollbarPadding(p),y.heightOverflow&&y.scrollbarWidth&&p.css({paddingRight:y.right+"px"})));var m;i.component?(m=document.createElement(d(i.component.name)),m=angular.element(m),m.attr({resolve:"$resolve","modal-instance":"$uibModalInstance",close:"$close($value)",dismiss:"$dismiss($value)"})):m=i.content,M=T?parseInt(T.value.modalDomEl.attr("index"),10)+1:0;var g=angular.element('<div uib-modal-window="modal-window"></div>');g.attr({"class":"modal","template-url":i.windowTemplateUrl,"window-top-class":i.windowTopClass,role:"dialog","aria-labelledby":i.ariaLabelledBy,"aria-describedby":i.ariaDescribedBy,size:i.size,index:M,animate:"animate","ng-style":"{'z-index': 1050 + $$topModalIndex*10, display: 'block'}",tabindex:-1,"uib-modal-animation-class":"fade","modal-in-class":"in"}).append(m),i.windowClass&&g.addClass(i.windowClass),i.animation&&g.attr("modal-animation","true"),p.addClass(u),i.scope&&(i.scope.$$topModalIndex=M),e.enter(n(g)(i.scope),p),C.top().value.modalDomEl=g,C.top().value.modalOpener=l,a(g)},S.close=function(e,t){var o=C.get(e);return b(),o&&v(o,t,!0)?(o.value.modalScope.$$uibDestructionScheduled=!0,o.value.deferred.resolve(t),p(e,o.value.modalOpener),!0):!o},S.dismiss=function(e,t){var o=C.get(e);return b(),o&&v(o,t,!1)?(o.value.modalScope.$$uibDestructionScheduled=!0,o.value.deferred.reject(t),p(e,o.value.modalOpener),!0):!o},S.dismissAll=function(e){for(var t=this.getTop();t&&this.dismiss(t.key,e);)t=this.getTop()},S.getTop=function(){return C.top()},S.modalRendered=function(e){var t=C.get(e);S.focusFirstFocusableElement(S.loadFocusElementList(t)),t&&t.value.renderDeferred.resolve()},S.focusFirstFocusableElement=function(e){return e.length>0?(e[0].focus(),!0):!1},S.focusLastFocusableElement=function(e){return e.length>0?(e[e.length-1].focus(),!0):!1},S.isModalFocused=function(e,t){if(e&&t){var o=t.value.modalDomEl;if(o&&o.length)return(e.target||e.srcElement)===o[0]}return!1},S.isFocusInFirstItem=function(e,t){return t.length>0?(e.target||e.srcElement)===t[0]:!1},S.isFocusInLastItem=function(e,t){return t.length>0?(e.target||e.srcElement)===t[t.length-1]:!1},S.loadFocusElementList=function(e){if(e){var t=e.value.modalDomEl;if(t&&t.length){var o=t[0].querySelectorAll(N);return o?Array.prototype.filter.call(o,function(e){return u(e)}):o}}},S}]).provider("$uibModal",function(){var e={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$rootScope","$q","$document","$templateRequest","$controller","$uibResolve","$uibModalStack",function(t,o,n,r,i,a,l){function s(e){return e.template?o.when(e.template):r(angular.isFunction(e.templateUrl)?e.templateUrl():e.templateUrl)}var d={},u=null;return d.getPromiseChain=function(){return u},d.open=function(r){function d(){return g}var c=o.defer(),p=o.defer(),f=o.defer(),h=o.defer(),m={result:c.promise,opened:p.promise,closed:f.promise,rendered:h.promise,close:function(e){return l.close(m,e)},dismiss:function(e){return l.dismiss(m,e)}};if(r=angular.extend({},e.options,r),r.resolve=r.resolve||{},r.appendTo=r.appendTo||n.find("body").eq(0),!r.component&&!r.template&&!r.templateUrl)throw new Error("One of component or template or templateUrl options is required.");var g;g=r.component?o.when(a.resolve(r.resolve,{},null,null)):o.all([s(r),a.resolve(r.resolve,{},null,null)]);var v;return v=u=o.all([u]).then(d,d).then(function(e){function o(t,o,n,r){t.$scope=a,t.$scope.$resolve={},n?t.$scope.$uibModalInstance=m:t.$uibModalInstance=m;var i=o?e[1]:e;angular.forEach(i,function(e,o){r&&(t[o]=e),t.$scope.$resolve[o]=e})}var n=r.scope||t,a=n.$new();a.$close=m.close,a.$dismiss=m.dismiss,a.$on("$destroy",function(){a.$$uibDestructionScheduled||a.$dismiss("$uibUnscheduledDestruction")});var s,d,u={scope:a,deferred:c,renderDeferred:h,closedDeferred:f,animation:r.animation,backdrop:r.backdrop,keyboard:r.keyboard,backdropClass:r.backdropClass,windowTopClass:r.windowTopClass,windowClass:r.windowClass,windowTemplateUrl:r.windowTemplateUrl,ariaLabelledBy:r.ariaLabelledBy,ariaDescribedBy:r.ariaDescribedBy,size:r.size,openedClass:r.openedClass,appendTo:r.appendTo},g={},v={};r.component?(o(g,!1,!0,!1),g.name=r.component,u.component=g):r.controller&&(o(v,!0,!1,!0),d=i(r.controller,v,!0,r.controllerAs),r.controllerAs&&r.bindToController&&(s=d.instance,s.$close=a.$close,s.$dismiss=a.$dismiss,angular.extend(s,{$resolve:v.$scope.$resolve},n)),s=d(),angular.isFunction(s.$onInit)&&s.$onInit()),r.component||(u.content=e[0]),l.open(m,u),p.resolve(!0)},function(e){p.reject(e),c.reject(e)})["finally"](function(){u===v&&(u=null)}),m},d}]};return e}),angular.module("ui.bootstrap.stackedMap",[]).factory("$$stackedMap",function(){return{createNew:function(){var e=[];return{add:function(t,o){e.push({key:t,value:o})},get:function(t){for(var o=0;o<e.length;o++)if(t===e[o].key)return e[o]},keys:function(){for(var t=[],o=0;o<e.length;o++)t.push(e[o].key);return t},top:function(){return e[e.length-1]},remove:function(t){for(var o=-1,n=0;n<e.length;n++)if(t===e[n].key){o=n;break}return e.splice(o,1)[0]},removeTop:function(){return e.pop()},length:function(){return e.length}}}}}),angular.module("ui.bootstrap.position",[]).factory("$uibPosition",["$document","$window",function(e,t){var o,n,r={normal:/(auto|scroll)/,hidden:/(auto|scroll|hidden)/},i={auto:/\s?auto?\s?/i,primary:/^(top|bottom|left|right)$/,secondary:/^(top|bottom|left|right|center)$/,vertical:/^(top|bottom)$/},a=/(HTML|BODY)/;return{getRawNode:function(e){return e.nodeName?e:e[0]||e},parseStyle:function(e){return e=parseFloat(e),isFinite(e)?e:0},offsetParent:function(o){function n(e){return"static"===(t.getComputedStyle(e).position||"static")}o=this.getRawNode(o);for(var r=o.offsetParent||e[0].documentElement;r&&r!==e[0].documentElement&&n(r);)r=r.offsetParent;return r||e[0].documentElement},scrollbarWidth:function(r){if(r){if(angular.isUndefined(n)){var i=e.find("body");i.addClass("uib-position-body-scrollbar-measure"),n=t.innerWidth-i[0].clientWidth,n=isFinite(n)?n:0,i.removeClass("uib-position-body-scrollbar-measure")}return n}if(angular.isUndefined(o)){var a=angular.element('<div class="uib-position-scrollbar-measure"></div>');e.find("body").append(a),o=a[0].offsetWidth-a[0].clientWidth,o=isFinite(o)?o:0,a.remove()}return o},scrollbarPadding:function(e){e=this.getRawNode(e);var o=t.getComputedStyle(e),n=this.parseStyle(o.paddingRight),r=this.parseStyle(o.paddingBottom),i=this.scrollParent(e,!1,!0),l=this.scrollbarWidth(a.test(i.tagName));return{scrollbarWidth:l,widthOverflow:i.scrollWidth>i.clientWidth,right:n+l,originalRight:n,heightOverflow:i.scrollHeight>i.clientHeight,bottom:r+l,originalBottom:r}},isScrollable:function(e,o){e=this.getRawNode(e);var n=o?r.hidden:r.normal,i=t.getComputedStyle(e);return n.test(i.overflow+i.overflowY+i.overflowX)},scrollParent:function(o,n,i){o=this.getRawNode(o);var a=n?r.hidden:r.normal,l=e[0].documentElement,s=t.getComputedStyle(o);if(i&&a.test(s.overflow+s.overflowY+s.overflowX))return o;var d="absolute"===s.position,u=o.parentElement||l;if(u===l||"fixed"===s.position)return l;for(;u.parentElement&&u!==l;){var c=t.getComputedStyle(u);if(d&&"static"!==c.position&&(d=!1),!d&&a.test(c.overflow+c.overflowY+c.overflowX))break;u=u.parentElement}return u},position:function(o,n){o=this.getRawNode(o);var r=this.offset(o);if(n){var i=t.getComputedStyle(o);r.top-=this.parseStyle(i.marginTop),r.left-=this.parseStyle(i.marginLeft)}var a=this.offsetParent(o),l={top:0,left:0};return a!==e[0].documentElement&&(l=this.offset(a),l.top+=a.clientTop-a.scrollTop,l.left+=a.clientLeft-a.scrollLeft),{width:Math.round(angular.isNumber(r.width)?r.width:o.offsetWidth),height:Math.round(angular.isNumber(r.height)?r.height:o.offsetHeight),top:Math.round(r.top-l.top),left:Math.round(r.left-l.left)}},offset:function(o){o=this.getRawNode(o);var n=o.getBoundingClientRect();return{width:Math.round(angular.isNumber(n.width)?n.width:o.offsetWidth),height:Math.round(angular.isNumber(n.height)?n.height:o.offsetHeight),top:Math.round(n.top+(t.pageYOffset||e[0].documentElement.scrollTop)),left:Math.round(n.left+(t.pageXOffset||e[0].documentElement.scrollLeft))}},viewportOffset:function(o,n,r){o=this.getRawNode(o),r=r!==!1?!0:!1;var i=o.getBoundingClientRect(),a={top:0,left:0,bottom:0,right:0},l=n?e[0].documentElement:this.scrollParent(o),s=l.getBoundingClientRect();if(a.top=s.top+l.clientTop,a.left=s.left+l.clientLeft,l===e[0].documentElement&&(a.top+=t.pageYOffset,a.left+=t.pageXOffset),a.bottom=a.top+l.clientHeight,a.right=a.left+l.clientWidth,r){var d=t.getComputedStyle(l);a.top+=this.parseStyle(d.paddingTop),a.bottom-=this.parseStyle(d.paddingBottom),a.left+=this.parseStyle(d.paddingLeft),a.right-=this.parseStyle(d.paddingRight)}return{top:Math.round(i.top-a.top),bottom:Math.round(a.bottom-i.bottom),left:Math.round(i.left-a.left),right:Math.round(a.right-i.right)}},parsePlacement:function(e){var t=i.auto.test(e);return t&&(e=e.replace(i.auto,"")),e=e.split("-"),e[0]=e[0]||"top",i.primary.test(e[0])||(e[0]="top"),e[1]=e[1]||"center",i.secondary.test(e[1])||(e[1]="center"),e[2]=t?!0:!1,e},positionElements:function(e,o,n,r){e=this.getRawNode(e),o=this.getRawNode(o);var a=angular.isDefined(o.offsetWidth)?o.offsetWidth:o.prop("offsetWidth"),l=angular.isDefined(o.offsetHeight)?o.offsetHeight:o.prop("offsetHeight");n=this.parsePlacement(n);var s=r?this.offset(e):this.position(e),d={top:0,left:0,placement:""};if(n[2]){var u=this.viewportOffset(e,r),c=t.getComputedStyle(o),p={width:a+Math.round(Math.abs(this.parseStyle(c.marginLeft)+this.parseStyle(c.marginRight))),height:l+Math.round(Math.abs(this.parseStyle(c.marginTop)+this.parseStyle(c.marginBottom)))};if(n[0]="top"===n[0]&&p.height>u.top&&p.height<=u.bottom?"bottom":"bottom"===n[0]&&p.height>u.bottom&&p.height<=u.top?"top":"left"===n[0]&&p.width>u.left&&p.width<=u.right?"right":"right"===n[0]&&p.width>u.right&&p.width<=u.left?"left":n[0],n[1]="top"===n[1]&&p.height-s.height>u.bottom&&p.height-s.height<=u.top?"bottom":"bottom"===n[1]&&p.height-s.height>u.top&&p.height-s.height<=u.bottom?"top":"left"===n[1]&&p.width-s.width>u.right&&p.width-s.width<=u.left?"right":"right"===n[1]&&p.width-s.width>u.left&&p.width-s.width<=u.right?"left":n[1],"center"===n[1])if(i.vertical.test(n[0])){var f=s.width/2-a/2;u.left+f<0&&p.width-s.width<=u.right?n[1]="left":u.right+f<0&&p.width-s.width<=u.left&&(n[1]="right")}else{var h=s.height/2-p.height/2;u.top+h<0&&p.height-s.height<=u.bottom?n[1]="top":u.bottom+h<0&&p.height-s.height<=u.top&&(n[1]="bottom")}}switch(n[0]){case"top":d.top=s.top-l;break;case"bottom":d.top=s.top+s.height;break;case"left":d.left=s.left-a;break;case"right":d.left=s.left+s.width}switch(n[1]){case"top":d.top=s.top;break;case"bottom":d.top=s.top+s.height-l;break;case"left":d.left=s.left;break;case"right":d.left=s.left+s.width-a;break;case"center":i.vertical.test(n[0])?d.left=s.left+s.width/2-a/2:d.top=s.top+s.height/2-l/2}return d.top=Math.round(d.top),d.left=Math.round(d.left),d.placement="center"===n[1]?n[0]:n[0]+"-"+n[1],d},adjustTop:function(e,t,o,n){return-1!==e.indexOf("top")&&o!==n?{top:t.top-n+"px"}:void 0},positionArrow:function(e,o){e=this.getRawNode(e);var n=e.querySelector(".tooltip-inner, .popover-inner");if(n){var r=angular.element(n).hasClass("tooltip-inner"),a=e.querySelector(r?".tooltip-arrow":".arrow");if(a){var l={top:"",bottom:"",left:"",right:""};if(o=this.parsePlacement(o),"center"===o[1])return void angular.element(a).css(l);var s="border-"+o[0]+"-width",d=t.getComputedStyle(a)[s],u="border-";u+=i.vertical.test(o[0])?o[0]+"-"+o[1]:o[1]+"-"+o[0],u+="-radius";var c=t.getComputedStyle(r?n:e)[u];switch(o[0]){case"top":l.bottom=r?"0":"-"+d;break;case"bottom":l.top=r?"0":"-"+d;break;case"left":l.right=r?"0":"-"+d;break;case"right":l.left=r?"0":"-"+d}l[o[1]]=c,angular.element(a).css(l)}}}}}]),angular.module("ui.bootstrap.position").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibPositionCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'),angular.$$uibPositionCss=!0});;
/*
 * angular-ui-bootstrap
 * http://angular-ui.github.io/bootstrap/

 * Version: 2.2.0 - 2016-10-10
 * License: MIT
 */angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.modal","ui.bootstrap.stackedMap","ui.bootstrap.position"]),angular.module("ui.bootstrap.tpls",["uib/template/modal/window.html"]),angular.module("ui.bootstrap.modal",["ui.bootstrap.stackedMap","ui.bootstrap.position"]).factory("$$multiMap",function(){return{createNew:function(){var t={};return{entries:function(){return Object.keys(t).map(function(e){return{key:e,value:t[e]}})},get:function(e){return t[e]},hasKey:function(e){return!!t[e]},keys:function(){return Object.keys(t)},put:function(e,o){t[e]||(t[e]=[]),t[e].push(o)},remove:function(e,o){var n=t[e];if(n){var r=n.indexOf(o);-1!==r&&n.splice(r,1),n.length||delete t[e]}}}}}}).provider("$uibResolve",function(){var t=this;this.resolver=null,this.setResolver=function(t){this.resolver=t},this.$get=["$injector","$q",function(e,o){var n=t.resolver?e.get(t.resolver):null;return{resolve:function(t,r,i,a){if(n)return n.resolve(t,r,i,a);var l=[];return angular.forEach(t,function(t){l.push(angular.isFunction(t)||angular.isArray(t)?o.resolve(e.invoke(t)):angular.isString(t)?o.resolve(e.get(t)):o.resolve(t))}),o.all(l).then(function(e){var o={},n=0;return angular.forEach(t,function(t,r){o[r]=e[n++]}),o})}}}]}).directive("uibModalBackdrop",["$animate","$injector","$uibModalStack",function(t,e,o){function n(e,n,r){r.modalInClass&&(t.addClass(n,r.modalInClass),e.$on(o.NOW_CLOSING_EVENT,function(o,i){var a=i();e.modalOptions.animation?t.removeClass(n,r.modalInClass).then(a):a()}))}return{restrict:"A",compile:function(t,e){return t.addClass(e.backdropClass),n}}}]).directive("uibModalWindow",["$uibModalStack","$q","$animateCss","$document",function(t,e,o,n){return{scope:{index:"@"},restrict:"A",transclude:!0,templateUrl:function(t,e){return e.templateUrl||"uib/template/modal/window.html"},link:function(r,i,a){i.addClass(a.windowTopClass||""),r.size=a.size,r.close=function(e){var o=t.getTop();o&&o.value.backdrop&&"static"!==o.value.backdrop&&e.target===e.currentTarget&&(e.preventDefault(),e.stopPropagation(),t.dismiss(o.key,"backdrop click"))},i.on("click",r.close),r.$isRendered=!0;var l=e.defer();r.$$postDigest(function(){l.resolve()}),l.promise.then(function(){var l=null;a.modalInClass&&(l=o(i,{addClass:a.modalInClass}).start(),r.$on(t.NOW_CLOSING_EVENT,function(t,e){var n=e();o(i,{removeClass:a.modalInClass}).start().then(n)})),e.when(l).then(function(){var e=t.getTop();if(e&&t.modalRendered(e.key),!n[0].activeElement||!i[0].contains(n[0].activeElement)){var o=i[0].querySelector("[autofocus]");o?o.focus():i[0].focus()}})})}}}]).directive("uibModalAnimationClass",function(){return{compile:function(t,e){e.modalAnimation&&t.addClass(e.uibModalAnimationClass)}}}).directive("uibModalTransclude",["$animate",function(t){return{link:function(e,o,n,r,i){i(e.$parent,function(e){o.empty(),t.enter(e,o)})}}}]).factory("$uibModalStack",["$animate","$animateCss","$document","$compile","$rootScope","$q","$$multiMap","$$stackedMap","$uibPosition",function(t,e,o,n,r,i,a,l,s){function d(t){var e="-";return t.replace(D,function(t,o){return(o?e:"")+t.toLowerCase()})}function u(t){return!!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)}function c(){for(var t=-1,e=C.keys(),o=0;o<e.length;o++)C.get(e[o]).value.backdrop&&(t=o);return t>-1&&M>t&&(t=M),t}function p(t,e){var o=C.get(t).value,n=o.appendTo;C.remove(t),T=C.top(),T&&(M=parseInt(T.value.modalDomEl.attr("index"),10)),h(o.modalDomEl,o.modalScope,function(){var e=o.openedClass||k;E.remove(e,t);var r=E.hasKey(e);n.toggleClass(e,r),!r&&y&&y.heightOverflow&&y.scrollbarWidth&&(n.css(y.originalRight?{paddingRight:y.originalRight+"px"}:{paddingRight:""}),y=null),f(!0)},o.closedDeferred),m(),e&&e.focus?e.focus():n.focus&&n.focus()}function f(t){var e;C.length()>0&&(e=C.top().value,e.modalDomEl.toggleClass(e.windowTopClass||"",t))}function m(){if(w&&-1===c()){var t=$;h(w,$,function(){t=null}),w=void 0,$=void 0}}function h(e,o,n,r){function a(){a.done||(a.done=!0,t.leave(e).then(function(){n&&n(),e.remove(),r&&r.resolve()}),o.$destroy())}var l,s=null,d=function(){return l||(l=i.defer(),s=l.promise),function(){l.resolve()}};return o.$broadcast(S.NOW_CLOSING_EVENT,d),i.when(s).then(a)}function g(t){if(t.isDefaultPrevented())return t;var e=C.top();if(e)switch(t.which){case 27:e.value.keyboard&&(t.preventDefault(),r.$apply(function(){S.dismiss(e.key,"escape key press")}));break;case 9:var o=S.loadFocusElementList(e),n=!1;t.shiftKey?(S.isFocusInFirstItem(t,o)||S.isModalFocused(t,e))&&(n=S.focusLastFocusableElement(o)):S.isFocusInLastItem(t,o)&&(n=S.focusFirstFocusableElement(o)),n&&(t.preventDefault(),t.stopPropagation())}}function v(t,e,o){return!t.value.modalScope.$broadcast("modal.closing",e,o).defaultPrevented}function b(){Array.prototype.forEach.call(document.querySelectorAll("["+x+"]"),function(t){var e=parseInt(t.getAttribute(x),10),o=e-1;t.setAttribute(x,o),o||(t.removeAttribute(x),t.removeAttribute("aria-hidden"))})}var w,$,y,k="modal-open",C=l.createNew(),E=a.createNew(),S={NOW_CLOSING_EVENT:"modal.stack.now-closing"},M=0,T=null,x="data-bootstrap-modal-aria-hidden-count",N="a[href], area[href], input:not([disabled]):not([tabindex='-1']), button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']), textarea:not([disabled]):not([tabindex='-1']), iframe, object, embed, *[tabindex]:not([tabindex='-1']), *[contenteditable=true]",D=/[A-Z]/g;return r.$watch(c,function(t){$&&($.index=t)}),o.on("keydown",g),r.$on("$destroy",function(){o.off("keydown",g)}),S.open=function(e,i){function a(t){function e(t){var e=t.parent()?t.parent().children():[];return Array.prototype.filter.call(e,function(e){return e!==t[0]})}if(t&&"BODY"!==t[0].tagName)return e(t).forEach(function(t){var e="true"===t.getAttribute("aria-hidden"),o=parseInt(t.getAttribute(x),10);o||(o=e?1:0),t.setAttribute(x,o+1),t.setAttribute("aria-hidden","true")}),a(t.parent())}var l=o[0].activeElement,u=i.openedClass||k;f(!1),T=C.top(),C.add(e,{deferred:i.deferred,renderDeferred:i.renderDeferred,closedDeferred:i.closedDeferred,modalScope:i.scope,backdrop:i.backdrop,keyboard:i.keyboard,openedClass:i.openedClass,windowTopClass:i.windowTopClass,animation:i.animation,appendTo:i.appendTo}),E.put(u,e);var p=i.appendTo,m=c();if(!p.length)throw new Error("appendTo element not found. Make sure that the element passed is in DOM.");m>=0&&!w&&($=r.$new(!0),$.modalOptions=i,$.index=m,w=angular.element('<div uib-modal-backdrop="modal-backdrop"></div>'),w.attr({"class":"modal-backdrop","ng-style":"{'z-index': 1040 + (index && 1 || 0) + index*10}","uib-modal-animation-class":"fade","modal-in-class":"in"}),i.backdropClass&&w.addClass(i.backdropClass),i.animation&&w.attr("modal-animation","true"),n(w)($),t.enter(w,p),s.isScrollable(p)&&(y=s.scrollbarPadding(p),y.heightOverflow&&y.scrollbarWidth&&p.css({paddingRight:y.right+"px"})));var h;i.component?(h=document.createElement(d(i.component.name)),h=angular.element(h),h.attr({resolve:"$resolve","modal-instance":"$uibModalInstance",close:"$close($value)",dismiss:"$dismiss($value)"})):h=i.content,M=T?parseInt(T.value.modalDomEl.attr("index"),10)+1:0;var g=angular.element('<div uib-modal-window="modal-window"></div>');g.attr({"class":"modal","template-url":i.windowTemplateUrl,"window-top-class":i.windowTopClass,role:"dialog","aria-labelledby":i.ariaLabelledBy,"aria-describedby":i.ariaDescribedBy,size:i.size,index:M,animate:"animate","ng-style":"{'z-index': 1050 + $$topModalIndex*10, display: 'block'}",tabindex:-1,"uib-modal-animation-class":"fade","modal-in-class":"in"}).append(h),i.windowClass&&g.addClass(i.windowClass),i.animation&&g.attr("modal-animation","true"),p.addClass(u),i.scope&&(i.scope.$$topModalIndex=M),t.enter(n(g)(i.scope),p),C.top().value.modalDomEl=g,C.top().value.modalOpener=l,a(g)},S.close=function(t,e){var o=C.get(t);return b(),o&&v(o,e,!0)?(o.value.modalScope.$$uibDestructionScheduled=!0,o.value.deferred.resolve(e),p(t,o.value.modalOpener),!0):!o},S.dismiss=function(t,e){var o=C.get(t);return b(),o&&v(o,e,!1)?(o.value.modalScope.$$uibDestructionScheduled=!0,o.value.deferred.reject(e),p(t,o.value.modalOpener),!0):!o},S.dismissAll=function(t){for(var e=this.getTop();e&&this.dismiss(e.key,t);)e=this.getTop()},S.getTop=function(){return C.top()},S.modalRendered=function(t){var e=C.get(t);S.focusFirstFocusableElement(S.loadFocusElementList(e)),e&&e.value.renderDeferred.resolve()},S.focusFirstFocusableElement=function(t){return t.length>0?(t[0].focus(),!0):!1},S.focusLastFocusableElement=function(t){return t.length>0?(t[t.length-1].focus(),!0):!1},S.isModalFocused=function(t,e){if(t&&e){var o=e.value.modalDomEl;if(o&&o.length)return(t.target||t.srcElement)===o[0]}return!1},S.isFocusInFirstItem=function(t,e){return e.length>0?(t.target||t.srcElement)===e[0]:!1},S.isFocusInLastItem=function(t,e){return e.length>0?(t.target||t.srcElement)===e[e.length-1]:!1},S.loadFocusElementList=function(t){if(t){var e=t.value.modalDomEl;if(e&&e.length){var o=e[0].querySelectorAll(N);return o?Array.prototype.filter.call(o,function(t){return u(t)}):o}}},S}]).provider("$uibModal",function(){var t={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$rootScope","$q","$document","$templateRequest","$controller","$uibResolve","$uibModalStack",function(e,o,n,r,i,a,l){function s(t){return t.template?o.when(t.template):r(angular.isFunction(t.templateUrl)?t.templateUrl():t.templateUrl)}var d={},u=null;return d.getPromiseChain=function(){return u},d.open=function(r){function d(){return g}var c=o.defer(),p=o.defer(),f=o.defer(),m=o.defer(),h={result:c.promise,opened:p.promise,closed:f.promise,rendered:m.promise,close:function(t){return l.close(h,t)},dismiss:function(t){return l.dismiss(h,t)}};if(r=angular.extend({},t.options,r),r.resolve=r.resolve||{},r.appendTo=r.appendTo||n.find("body").eq(0),!r.component&&!r.template&&!r.templateUrl)throw new Error("One of component or template or templateUrl options is required.");var g;g=r.component?o.when(a.resolve(r.resolve,{},null,null)):o.all([s(r),a.resolve(r.resolve,{},null,null)]);var v;return v=u=o.all([u]).then(d,d).then(function(t){function o(e,o,n,r){e.$scope=a,e.$scope.$resolve={},n?e.$scope.$uibModalInstance=h:e.$uibModalInstance=h;var i=o?t[1]:t;angular.forEach(i,function(t,o){r&&(e[o]=t),e.$scope.$resolve[o]=t})}var n=r.scope||e,a=n.$new();a.$close=h.close,a.$dismiss=h.dismiss,a.$on("$destroy",function(){a.$$uibDestructionScheduled||a.$dismiss("$uibUnscheduledDestruction")});var s,d,u={scope:a,deferred:c,renderDeferred:m,closedDeferred:f,animation:r.animation,backdrop:r.backdrop,keyboard:r.keyboard,backdropClass:r.backdropClass,windowTopClass:r.windowTopClass,windowClass:r.windowClass,windowTemplateUrl:r.windowTemplateUrl,ariaLabelledBy:r.ariaLabelledBy,ariaDescribedBy:r.ariaDescribedBy,size:r.size,openedClass:r.openedClass,appendTo:r.appendTo},g={},v={};r.component?(o(g,!1,!0,!1),g.name=r.component,u.component=g):r.controller&&(o(v,!0,!1,!0),d=i(r.controller,v,!0,r.controllerAs),r.controllerAs&&r.bindToController&&(s=d.instance,s.$close=a.$close,s.$dismiss=a.$dismiss,angular.extend(s,{$resolve:v.$scope.$resolve},n)),s=d(),angular.isFunction(s.$onInit)&&s.$onInit()),r.component||(u.content=t[0]),l.open(h,u),p.resolve(!0)},function(t){p.reject(t),c.reject(t)})["finally"](function(){u===v&&(u=null)}),h},d}]};return t}),angular.module("ui.bootstrap.stackedMap",[]).factory("$$stackedMap",function(){return{createNew:function(){var t=[];return{add:function(e,o){t.push({key:e,value:o})},get:function(e){for(var o=0;o<t.length;o++)if(e===t[o].key)return t[o]},keys:function(){for(var e=[],o=0;o<t.length;o++)e.push(t[o].key);return e},top:function(){return t[t.length-1]},remove:function(e){for(var o=-1,n=0;n<t.length;n++)if(e===t[n].key){o=n;break}return t.splice(o,1)[0]},removeTop:function(){return t.pop()},length:function(){return t.length}}}}}),angular.module("ui.bootstrap.position",[]).factory("$uibPosition",["$document","$window",function(t,e){var o,n,r={normal:/(auto|scroll)/,hidden:/(auto|scroll|hidden)/},i={auto:/\s?auto?\s?/i,primary:/^(top|bottom|left|right)$/,secondary:/^(top|bottom|left|right|center)$/,vertical:/^(top|bottom)$/},a=/(HTML|BODY)/;return{getRawNode:function(t){return t.nodeName?t:t[0]||t},parseStyle:function(t){return t=parseFloat(t),isFinite(t)?t:0},offsetParent:function(o){function n(t){return"static"===(e.getComputedStyle(t).position||"static")}o=this.getRawNode(o);for(var r=o.offsetParent||t[0].documentElement;r&&r!==t[0].documentElement&&n(r);)r=r.offsetParent;return r||t[0].documentElement},scrollbarWidth:function(r){if(r){if(angular.isUndefined(n)){var i=t.find("body");i.addClass("uib-position-body-scrollbar-measure"),n=e.innerWidth-i[0].clientWidth,n=isFinite(n)?n:0,i.removeClass("uib-position-body-scrollbar-measure")}return n}if(angular.isUndefined(o)){var a=angular.element('<div class="uib-position-scrollbar-measure"></div>');t.find("body").append(a),o=a[0].offsetWidth-a[0].clientWidth,o=isFinite(o)?o:0,a.remove()}return o},scrollbarPadding:function(t){t=this.getRawNode(t);var o=e.getComputedStyle(t),n=this.parseStyle(o.paddingRight),r=this.parseStyle(o.paddingBottom),i=this.scrollParent(t,!1,!0),l=this.scrollbarWidth(a.test(i.tagName));return{scrollbarWidth:l,widthOverflow:i.scrollWidth>i.clientWidth,right:n+l,originalRight:n,heightOverflow:i.scrollHeight>i.clientHeight,bottom:r+l,originalBottom:r}},isScrollable:function(t,o){t=this.getRawNode(t);var n=o?r.hidden:r.normal,i=e.getComputedStyle(t);return n.test(i.overflow+i.overflowY+i.overflowX)},scrollParent:function(o,n,i){o=this.getRawNode(o);var a=n?r.hidden:r.normal,l=t[0].documentElement,s=e.getComputedStyle(o);if(i&&a.test(s.overflow+s.overflowY+s.overflowX))return o;var d="absolute"===s.position,u=o.parentElement||l;if(u===l||"fixed"===s.position)return l;for(;u.parentElement&&u!==l;){var c=e.getComputedStyle(u);if(d&&"static"!==c.position&&(d=!1),!d&&a.test(c.overflow+c.overflowY+c.overflowX))break;u=u.parentElement}return u},position:function(o,n){o=this.getRawNode(o);var r=this.offset(o);if(n){var i=e.getComputedStyle(o);r.top-=this.parseStyle(i.marginTop),r.left-=this.parseStyle(i.marginLeft)}var a=this.offsetParent(o),l={top:0,left:0};return a!==t[0].documentElement&&(l=this.offset(a),l.top+=a.clientTop-a.scrollTop,l.left+=a.clientLeft-a.scrollLeft),{width:Math.round(angular.isNumber(r.width)?r.width:o.offsetWidth),height:Math.round(angular.isNumber(r.height)?r.height:o.offsetHeight),top:Math.round(r.top-l.top),left:Math.round(r.left-l.left)}},offset:function(o){o=this.getRawNode(o);var n=o.getBoundingClientRect();return{width:Math.round(angular.isNumber(n.width)?n.width:o.offsetWidth),height:Math.round(angular.isNumber(n.height)?n.height:o.offsetHeight),top:Math.round(n.top+(e.pageYOffset||t[0].documentElement.scrollTop)),left:Math.round(n.left+(e.pageXOffset||t[0].documentElement.scrollLeft))}},viewportOffset:function(o,n,r){o=this.getRawNode(o),r=r!==!1?!0:!1;var i=o.getBoundingClientRect(),a={top:0,left:0,bottom:0,right:0},l=n?t[0].documentElement:this.scrollParent(o),s=l.getBoundingClientRect();if(a.top=s.top+l.clientTop,a.left=s.left+l.clientLeft,l===t[0].documentElement&&(a.top+=e.pageYOffset,a.left+=e.pageXOffset),a.bottom=a.top+l.clientHeight,a.right=a.left+l.clientWidth,r){var d=e.getComputedStyle(l);a.top+=this.parseStyle(d.paddingTop),a.bottom-=this.parseStyle(d.paddingBottom),a.left+=this.parseStyle(d.paddingLeft),a.right-=this.parseStyle(d.paddingRight)}return{top:Math.round(i.top-a.top),bottom:Math.round(a.bottom-i.bottom),left:Math.round(i.left-a.left),right:Math.round(a.right-i.right)}},parsePlacement:function(t){var e=i.auto.test(t);return e&&(t=t.replace(i.auto,"")),t=t.split("-"),t[0]=t[0]||"top",i.primary.test(t[0])||(t[0]="top"),t[1]=t[1]||"center",i.secondary.test(t[1])||(t[1]="center"),t[2]=e?!0:!1,t},positionElements:function(t,o,n,r){t=this.getRawNode(t),o=this.getRawNode(o);var a=angular.isDefined(o.offsetWidth)?o.offsetWidth:o.prop("offsetWidth"),l=angular.isDefined(o.offsetHeight)?o.offsetHeight:o.prop("offsetHeight");n=this.parsePlacement(n);var s=r?this.offset(t):this.position(t),d={top:0,left:0,placement:""};if(n[2]){var u=this.viewportOffset(t,r),c=e.getComputedStyle(o),p={width:a+Math.round(Math.abs(this.parseStyle(c.marginLeft)+this.parseStyle(c.marginRight))),height:l+Math.round(Math.abs(this.parseStyle(c.marginTop)+this.parseStyle(c.marginBottom)))};if(n[0]="top"===n[0]&&p.height>u.top&&p.height<=u.bottom?"bottom":"bottom"===n[0]&&p.height>u.bottom&&p.height<=u.top?"top":"left"===n[0]&&p.width>u.left&&p.width<=u.right?"right":"right"===n[0]&&p.width>u.right&&p.width<=u.left?"left":n[0],n[1]="top"===n[1]&&p.height-s.height>u.bottom&&p.height-s.height<=u.top?"bottom":"bottom"===n[1]&&p.height-s.height>u.top&&p.height-s.height<=u.bottom?"top":"left"===n[1]&&p.width-s.width>u.right&&p.width-s.width<=u.left?"right":"right"===n[1]&&p.width-s.width>u.left&&p.width-s.width<=u.right?"left":n[1],"center"===n[1])if(i.vertical.test(n[0])){var f=s.width/2-a/2;u.left+f<0&&p.width-s.width<=u.right?n[1]="left":u.right+f<0&&p.width-s.width<=u.left&&(n[1]="right")}else{var m=s.height/2-p.height/2;u.top+m<0&&p.height-s.height<=u.bottom?n[1]="top":u.bottom+m<0&&p.height-s.height<=u.top&&(n[1]="bottom")}}switch(n[0]){case"top":d.top=s.top-l;break;case"bottom":d.top=s.top+s.height;break;case"left":d.left=s.left-a;break;case"right":d.left=s.left+s.width}switch(n[1]){case"top":d.top=s.top;break;case"bottom":d.top=s.top+s.height-l;break;case"left":d.left=s.left;break;case"right":d.left=s.left+s.width-a;break;case"center":i.vertical.test(n[0])?d.left=s.left+s.width/2-a/2:d.top=s.top+s.height/2-l/2}return d.top=Math.round(d.top),d.left=Math.round(d.left),d.placement="center"===n[1]?n[0]:n[0]+"-"+n[1],d},adjustTop:function(t,e,o,n){return-1!==t.indexOf("top")&&o!==n?{top:e.top-n+"px"}:void 0},positionArrow:function(t,o){t=this.getRawNode(t);var n=t.querySelector(".tooltip-inner, .popover-inner");if(n){var r=angular.element(n).hasClass("tooltip-inner"),a=t.querySelector(r?".tooltip-arrow":".arrow");if(a){var l={top:"",bottom:"",left:"",right:""};if(o=this.parsePlacement(o),"center"===o[1])return void angular.element(a).css(l);var s="border-"+o[0]+"-width",d=e.getComputedStyle(a)[s],u="border-";u+=i.vertical.test(o[0])?o[0]+"-"+o[1]:o[1]+"-"+o[0],u+="-radius";var c=e.getComputedStyle(r?n:t)[u];switch(o[0]){case"top":l.bottom=r?"0":"-"+d;break;case"bottom":l.top=r?"0":"-"+d;break;case"left":l.right=r?"0":"-"+d;break;case"right":l.left=r?"0":"-"+d}l[o[1]]=c,angular.element(a).css(l)}}}}}]),angular.module("uib/template/modal/window.html",[]).run(["$templateCache",function(t){t.put("uib/template/modal/window.html","<div class=\"modal-dialog {{size ? 'modal-' + size : ''}}\"><div class=\"modal-content\" uib-modal-transclude></div></div>\n")}]),angular.module("ui.bootstrap.position").run(function(){!angular.$$csp().noInlineStyle&&!angular.$$uibPositionCss&&angular.element(document).find("head").prepend('<style type="text/css">.uib-position-measure{display:block !important;visibility:hidden !important;position:absolute !important;top:-9999px !important;left:-9999px !important;}.uib-position-scrollbar-measure{position:absolute !important;top:-9999px !important;width:50px !important;height:50px !important;overflow:scroll !important;}.uib-position-body-scrollbar-measure{overflow:scroll !important;}</style>'),angular.$$uibPositionCss=!0});;
angular.module("barfootMobile")
    .service('autocompleteService', ['$http', '$log', 'webProxy', function ($http, $log, webProxy) {
        return function (mode, query) {
            var searchMode;
            switch (mode) {
                case "Rural":
                    searchMode = 'U';
                    break;
                case "Rental":
                    searchMode = "P";
                    break;
                case "Commercial":
                    searchMode = "C";
                    break;
                case "Global":
                    searchMode = "G";
                    break;
                case "Residential":
                    searchMode = "R";
                    break;
                default:
                    searchMode = "R";
            }

            //Rural - "U"
            //Rental - "P"
            //Commercial - "C"
            //Global - "G":
            //Residential - "R"

            var param = {
                _returnTypes: [],
                Mode: searchMode,
                Query: query,
                Results: [],
                ReturnTypes: [],
                MaxResults: 7
            }

            return webProxy('autocomplete', param).then(function (data) {
                //chain promise back to he target
                return data;
            });
        };
    }]);;
angular.module("barfootMobile")
    .service('btAccounts', ["webProxy", function (webProxy) {
        return function () {
            return {
                showLogin: function () {
                    webProxy('add-pending-task', {
                        Url: window.location.href,
                        Task: "RedirectToUrl"
                    });
                    window.location.href = '/oauthauthentication.aspx';
                },
                userIsAuthenticated: function () {
                    return webProxy('user-isauthenicated-mobile');
                },
                addRedirectToUrl: function () {
                    return webProxy('add-pending-task', {
                        Url: window.location.href,
                        Task: "RedirectToUrl"
                    });
                },
                addSaveSearchPendingTask: function () {
                    return webProxy('add-pending-task', {
                        Url: window.location.href + "#savesearch",
                        Task: "RedirectToUrl"
                    });
                },
                addFavouritesPendingTask: function (listingSourceId) {
                    webProxy('add-pending-task', {
                        ListingSourceID: listingSourceId,
                        Task: "AddFavourite"
                    });

                    webProxy('add-pending-task', {
                        Url: window.location.href,
                        Task: "RedirectToUrl"
                    });

                },
                processPendingTask: function () {
                    return webProxy('process-pending-task');
                }

            };
        };
    }]);;
angular.module("barfootMobile")
   .service('btFavouritesService', [
       '$location',
       'webProxy',
 function (
     $location,
     webProxy) {
     return {
         addToFavourites: function (listingNo) {
             return webProxy("favorites-add", {
                 ListingNo: listingNo,
                 State: 'Requesting'
             });
         },
         deleteFavourite:function(listingNo) {
             return webProxy("favorites-delete", {
                 ListingNo: listingNo,
                 State: 'Deleting'
             });
         },
         getFavouritesCount:function() {
             return webProxy("get-favourites-count");
         },
         isPropertyFavourite: function (listingId) {
             return webProxy("is-property-favorite", {
                 ListingID: listingId
             });
         }
     }

 }]);
;
angular.module("barfootMobile")
    .service('btLockscrolling', ["webProxy", function (webProxy) {
        return function () {
            return {
                lockPage: function() {
                    $('body').addClass('disable-bgScroll');
                },
                unlockPage: function() {
                    $('body').removeClass('disable-bgScroll');
                }

            };
        };
    }]);;
angular.module("barfootMobile")
    .factory('btUrl', ['$location',
  function ($location) {
      var self = {

          _generateHashList: function(hashArray){
              var returnResult ='';
              angular.forEach(hashArray, function(val){
                  if(returnResult.length <= 0) {
                    returnResult = val[0] + '=' + val[1]
                  } else {
                    returnResult = returnResult + ',' + val[0] + '=' + val[1]
                  }
              })
              return returnResult;
          },

          addHash: function(key,value) {

            if($location.hash().indexOf(key)  !=  -1) {
              this.removeHash(key);
            }


            if($location.hash().length > 0) {
              $location.hash($location.hash() + ','+ key + '=' + value);  
            } else {
              $location.hash(key + '=' + value);
            }
            
          },

          
          removeHash: function(key) {
            var hashArray = $location.hash().split(',');
            var removedItem = undefined;

            angular.forEach(hashArray, function(val){
              if(val.split('=')[0] == key) {
                  removedItem = val;
              }
            });

            var disposedItem = hashArray.pop(removedItem);

            $location.hash(this._generateHashList(hashArray))
          },

          addOrUpdateQueryString: function(key, value) {
              return self._updateQueryStringParameter(window.location.href, key, value);
          },
          _updateQueryStringParameter: function(uri, key, value) {
              var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
              var separator = uri.indexOf('?') !== -1 ? "&" : "?";
              if (uri.match(re)) {
                  return uri.replace(re, '$1' + key + "=" + value + '$2');
              } else {
                  return uri + separator + key + "=" + value;
              }
          }
      }

      return self;

  }]);

;
angular.module("barfootMobile")
    .service('btValidateCaptchaService', [
        '$http', '$log', 'webProxy', function ($http, $log, webProxy) {
            
            return function (captchaFieldResponse) {
                var param = {
                    captchaFieldResponse: captchaFieldResponse
                }

                return webProxy('validate-captcha', param).then(function(data) {
                    return data;
                });
            };
        }
    ]);

;
angular.module('barfootMobile')
    .service('cssHelperService', [function () {

        var addClass = function(el, className) {
            if (el.classList) el.classList.add(className);
            else if (!hasClass(el, className)) el.className += ' ' + className;
        };

        var removeClass = function(el, className) {
            if (el.classList) el.classList.remove(className);
            else el.className = el.className.replace(new RegExp('\\b'+ className+'\\b', 'g'), '');
        }

        function hasClass(el, className ) {
            return (' ' + el.className + ' ' ).indexOf( ' '+ className + ' ' ) > -1;
        }

        function setClass(el, className) {
            el.className = className;
        }

        return {
            addClass: addClass,
            removeClass: removeClass,
            hasClass: hasClass,
            setClass: setClass
        };
    }]);
;
angular.module("barfootMobile")
    .service("featureProperties", [
    "$http", "$log", "webProxy", "$timeout", function($http, $log, webProxy, $timeout) {
        return function (mode, cacheId, cacheDuration) {

            if (cacheId == undefined) {
                cacheId = '';
            }

            if (cacheDuration == undefined) {
                cacheDuration = 0;
            }
            var options = {
                Mode: mode,
                FeatureProperties: [],
                CacheId: cacheId,
                CacheDuration: cacheDuration
            }
            return webProxy("get-feature-properties", options);
        };
    }
]);;
angular.module("barfootMobile")
    .service('folioService', ['$http', function ($http) {

        var update = function (folio) {
            return $http({
                method: 'POST',
                url: '/api/folio/update',
                data: folio,
                headers: {
                    'Content-Type': 'application/json'
                },
                responseType: 'json'
            });
        };

        var deleteFolio = function (folio) {
            return $http({
                method: 'POST',
                url: '/api/folio/delete',
                data: folio,
                headers: {
                    'Content-Type': 'application/json'
                },
                responseType: 'json'
            });
        };

        var reName = function (folio) {
            return $http({
                method: 'POST',
                url: '/api/folio/rename',
                data: folio,
                headers: {
                    'Content-Type': 'application/json'
                },
                responseType: 'json'
            });
        };

        var suggestedName = function(queryString) {

            var req = {
                method: 'GET',
                url: '/api/folio/suggestedname?queryString=' + queryString,
                responseType: 'json'
            }

            return $http(req);
        }

        var get = function () {

            var req = {
                method: 'GET',
                url: '/api/folio/getall',
                responseType: 'json'
            }

            return $http(req);
        }

        return {
            update: update,
            delete: deleteFolio,
            reName: reName,
            suggestedName: suggestedName,
            get: get
        }
    }]);;
/*

 IPageOptionModel interface :
 {
     name:string,               : options name
     hasChildren:boolean,       : flag for having children
     isSelected:boolean,        : flag for being already selected.
     value:obj,                 : value returned when selected
     parent:obj                 : parent page is exists.
 }

IPageModel interface :
 {
     name:string,               : page name
     options:IPageOptionModel[],: page selectable options
     slideOut: boolean          : true if you want the page to slide in.
 }

 config :
        optionsItems:IPageOptionModel[] (required)                          : the options to display on the first page.
        model:obj (required)                                                : returned ngModel / selected Items.
        onSelectionPage : function(pageOptionsModel):IPageOptionModel[]     : called when a page is selected, will return the next page's
        onSelectionComplete: function(ngModel):void                         : function called once the done button is clicked.
        onSelectionCancelled: function():void                               : function called once the cancel button is clicked.
        defaultListName: string                                             : title display at the top of single page lists.


 */



angular.module("barfootMobile")
.service('fullScreenListDialog', ['$http', '$log', function($http, $log) {
	return function() {
		return {
			open: function(config) {
				var listScope = angular.element('bt-fullscreen-list').first().scope();
				
				//Make sure the model has been set
				if (config.model == undefined) {
					$log.error('Model must be present in the config object passed to the fullScreenListDialog service')
					return;
				}
				
				// make sure the optionsItems var is present.
				if (config.optionsItems == undefined) {
					$log.error("optionsItems must be present in the fullScreenListDialog service config")
					return;
				}
				
				// Also make sure there are actual items in the options. Or there is nothing to display in the list.
				if (config.optionsItems.length <= 0) {
					$log.error("optionsItems must be populated in the fullScreenListDialog service.")
					return;
				}
				
				// Setup start up page. IPageModel
				var pages = [
				{
					name: '',
					options: config.optionsItems,
					slideOut: false
				}
				]
				
				listScope.open(config.model, pages);
				
				//Setup call backs.
				listScope.onSelectionPage = config.onSelectionPage;
				listScope.onSelectionComplete = config.onSelectionComplete;
				listScope.onSelectionCancelled = config.onSelectionCancelled;
				listScope.onSelectionChange = config.onSelectionChange;
				listScope.defaultListName = config.defaultListName;
			
			
			
			},
			close: function() {
				var listScope = angular.element('bt-fullscreen-list').first().scope();
				listScope.closeList();
			},
			addPage: function(IPageModel) {
				var listScope = angular.element('bt-fullscreen-list').first().scope();
				listScope.pages.push(IPageModel);
			}
		};
	}
	;
}
]);
;
angular.module("barfootMobile").service("listingDetailService", [
    "$http", "$log", "webProxy", "$timeout", function($http, $log, webProxy, $timeout) {
        return function(listingID) {

            var request = {
                ListingID: listingID
            }
            return webProxy("get-listing-model", request).then(function (listingModel) {
                return listingModel;
            });

        };
    }
]);;
angular.module("barfootMobile")
    .service('priceService', ['$http','$log', function ($http,$log) {
        return function () {
            return {
                getResidentialPrices:function() {
                    return [
                        ,['25000','$25,000']
                        ,['50000','$50,000']
                        ,['100000','$100,000']
                        ,['150000','$200,000']
                        ,['250000','$250,000']
                        ,['300000','$300,000']
                        ,['400000','$400,000']
                        ,['500000','$500,000']
                        ,['600000','$600,000']
                        ,['700000','$700,000']
                        ,['800000','$800,000']
                        ,['900000','$900,000']
                        ,['1000000','$1m']
                        ,['1200000','$1.2m']
                        ,['1400000','$1.4m']
                        ,['1600000','$1.6m']
                        ,['1800000','$1.8m']
                        ,['2000000','$2m']
                        ,['2500000','$2.5m']
                        ,['3500000','$3.5m']
                        ,['5000000','$5m']
                        ,['7500000','$7.5m']
                        ,['10000000','$10m']
                    ]
                }
            };
        };
    }]);;
angular.module("barfootMobile")
    .service('screenService', ['$window',function ($window) {
        return function () {
			genScreen =  {
				availWidth:$window.outerWidth > 0 ? $window.outerWidth : $window.innerWidth,
				availHeight: $window.outerHeight > 0 ? $window.outerHeight : $window.innerHeight
			}	
			return genScreen;
        };
    }]);;

// This services is responsible for calling the listingIndex call.
// This should be used for lazy-loading listings on the page.

angular.module("barfootMobile")
    .service('searchService', [function () {
        return function () {
            return {
                redirectToSearch: function (mode) {
                    //Set te default of residential if there is no mode provided.
                    if (mode == undefined) {
                        mode = "Residential";
                    }

                    // get all hidden fields for this mode of search
                    var allHiddenFields = angular.element('[ng-mode=' + mode + '] [type=hidden]');

                    var queryString = '';

                    angular.forEach(allHiddenFields, function (hiddenField) {
                        //Check to see if the hidden field has a value
                        if ($(hiddenField).attr('value') != '') {

                            //we have a value , so we should add it to the query string
                            // note that the '#' is required in angular. as it'll not read query string that are not precessed by a '#'
                            // https://github.com/angular/angular.js/issues/7239
                            if (queryString.indexOf('?') == -1) {
                                queryString += '#?' + $(hiddenField).attr('query-name') + '=' + $(hiddenField).attr('value')
                            } else {
                                queryString += '&' + $(hiddenField).attr('query-name') + '=' + $(hiddenField).attr('value')
                            }
                        }
                    });

                    // we have completed building the query string based off the controls on the page.
                    // we need to now redirect the browser to the search page and append the query to the url
                    // from there the search page will be able to populate the service again.
                    // and search for the listings.

                    window.location.href = '/search' + queryString;
                }
            }
        };
    }]);
;
/*
Documenation : http://confluence.barfoot.co.nz:8090/display/IT/Select+List+Dialog
*/



angular.module("barfootMobile")
.service('selectListDialog', ['$http', '$log', function($http, $log) {
	return function() {
		return {
			open: function(config) {
				var listScope = angular.element('bt-fullscreen-list').first().scope();
				
				//Make sure the model has been set
				if (config.model == undefined) {
					$log.error('Model must be present in the config object passed to the selectListDialog service')
					return;
				}
				
				// make sure the optionsItems var is present.
				if (config.pages == undefined) {
					$log.error("pages must be present in the selectListDialog service config")
					return;
				}
				
				// Also make sure there are actual items in the options. Or there is nothing to display in the list.
				if (config.pages.length <= 0) {
					$log.error("pages must be populated in the selectListDialog service.")
					return;
				}
				
				
				listScope.open(config.model, config.pages);
				
				//Setup call backs.
				listScope.onSelectionPage = config.onSelectionPage;
				listScope.onSelectionComplete = config.onSelectionComplete;
				listScope.onSelectionCancelled = config.onSelectionCancelled;
				listScope.onSelectionChange = config.onSelectionChange;
			
			
			
			},
			close: function() {
				var listScope = angular.element('bt-fullscreen-list').first().scope();
				listScope.closeList();
			},
			addPage: function(IPageModel) {
				var listScope = angular.element('bt-fullscreen-list').first().scope();
				listScope.addPage(IPageModel);
				
			}
		};
	}
	;
}
]);
;

angular.module("barfootMobile")
    .service('viewport', [function () {
        return function () {
            var _getTopFold = function() {
                return $(window).height() + $(window).scrollTop();
            };
            var _getTop = function() {
                return $(window).scrollTop();
            };

            var _getRightFold = function() {
                return $(window).width() + $(window).scrollLeft();
            };
            var _getLeftFold = function() {
                return $(window).scrollLeft();
            }

            var _belowthefold = function (element, threshold) {
                var fold = $(window).height() + $(window).scrollTop();
                return fold <= $(element).offset().top - threshold;
               
            };

            var _abovethetop = function (element, threshold) {
                return _getTop() >= $(element).offset().top + $(element).height() - threshold;
            };

            var _rightofscreen = function (element, threshold) {
                return _getRightFold() <= $(element).offset().left - threshold;
            };

            var _leftofscreen = function (element, threshold) {
                return _getLeftFold() >= $(element).offset().left + $(element).width() - threshold;
            };
            return {
               
               
                isInViewport: function(element) {
                    return this.isInThreshold(element, 0);
                },
                isInThreshold: function (element, threshold) {
                    return  //    !_rightofscreen(element, threshold) 
                            //&&  !_leftofscreen(element, threshold) 
                            !_belowthefold(element, threshold) 
                            &&  !_abovethetop(element, threshold);
                },
                isBelowTheFold(element, threshold){
                    var result = !_belowthefold(element, threshold);
                    return result;
                }

            }
        };
    }]);;
angular.module('barfootMobile').
    service('webProxy', [
        '$http', '$log', '$q', function($http, $log, $q) {
            return function(apiString, params) {
                var defer = $q.defer();
                webproxy.Execute(apiString, params,
                    function(data) {

                        var returnedObject = JSON.parse(data.d);
                        defer.resolve(returnedObject);

                    }, function (e) {
                        $log.error('Query = ', apiString);
                        $log.error('Web proxy Failure', e);
                        defer.reject(e);
                    });

                // return the promise
                return defer.promise;
            };
        }
    ]);;
angular.module("barfootMobile")
    .filter('stringsplit', function() {
        return function (input, splitChar, splitIndex) {
            var splitstring = input.split(splitChar);


            if (splitstring.length>= splitIndex + 1) {
               
                return input.split(splitChar)[splitIndex];
            } else {
               
                return input;
            }
        }
    });;
angular.module("barfootMobile").
    controller("btEmailConfirmationModal",
    [
        '$scope',
        '$uibModalInstance',
        'agents',
        'senderName',
        'branchName',
        function (
            $scope,
            $uibModalInstance,
            agents,
            senderName,
            branchName
            ) {
            $scope.branchName = branchName;
            $scope.agents = agents;
            $scope.senderName = senderName;
            $scope.close = function () {
                $uibModalInstance.close(this);
                btEvents.trigger(btEventType.EmailConfirmationModalClosed);
            }
        }
    ]);;

angular.module("barfootMobile").controller("btFormsTextController", [
    "$scope", "$element", "$log", "$timeout", function ($scope, $element, $log, $timeout) {


        // private fields
        var _clientValidation = false;
        var _isLoading = true;
        var _enterFunctionType = 'focus';
        var _enterSelector = '';

        //Setup scope parameters
        $scope.showIsRequiredMessage = false;
        $scope.btIsvalid = undefined;
        $scope.IsFocused = undefined;
        $scope.hasValue = undefined;
        
        // private functions
       
        var _resetValues = function () {
            // reset all the values you require here. 
            $scope.showIsRequiredMessage = false;
            $scope.btIsvalid = undefined;
            $scope.IsFocused = undefined;
            $scope.hasValue = undefined;
            _enterFunctionType = 'focus';
            _enterSelector = $element.find("input").attr('bt-enter-selector');
            _clientValidation = $element.attr('bt-clientsideValidation').toLowerCase() == 'true';

            
        }

        var _checkHiddenFieldForViewState = function() {

            // Will query the internal hidden field for a value. because the view state would be self-managed by the asp hidden field.
            // That way we don't need to write any custom viewstate logic.

            var hiddenField = $element.find('input[type=hidden]').first();
            
            if (hiddenField != undefined) {
                if (hiddenField.val() != undefined) {
                    if (hiddenField.val().length > 0 && hiddenField.val() != '{{ngModel}}') {
                        $scope.hasValue = true;
                        $scope.IsFocused = true;
                        $scope.ngModel = hiddenField.val();
                    }
                }
            }
           
        }
       

        //scope functions 
        $scope.onFocus = function () {
            $element.find("input").focus();
            $scope.IsFocused = true;
        }

        $scope.$watch('ngModel', function(val) {
            var hiddenField = $element.find('input[type=hidden]').first();
            if (hiddenField != undefined) {
                hiddenField.val(val);
            }
        });

        //this is done like this because emails will now fire onchange event until the test is a valid email.
        $element.find('input').bind("keydown keypress", function (val) {

            if (_isLoading == false) {
                if (val.key != 'Enter') {
                    var value = angular.element(val.target).val();
                    var ind = val.key == 'Backspace' ? 0 : 1;
                    var answer = value.length + ind > 0;
                    $scope.isFocused = answer;
                    $scope.hasValue = answer;
                } else {
                    val.preventDefault();
                    $(_enterSelector).focus();
                }
               
            }

            
           
        });

        var _init = function() {
            _resetValues();
            _checkHiddenFieldForViewState();

            _isLoading = false;
        }
        _init();
    }
]);
;
angular.module("barfootMobile").
    controller("btListingDocuments",
    [
        '$scope',
       "btAccounts",
        function (
            $scope,
            btAccounts
            ) {
            $scope.login = function () {
                btAccounts().addRedirectToUrl();
                btAccounts().showLogin();
            };
        }
    ]);;

(function (angular) {
    angular.module('barfootMobile').controller(
        'btPageHeaderController',
        [
            '$scope',
            'btAccounts',
            'cssHelperService',
            '$element',
            function (
                $scope,
                btAccounts,
                cssHelperService,
                $element
            ) {
                //Fields
                $scope.filterCount = 0;
                $scope.searchTagCount = 0;
                $scope.savedPropertiesCnt = 0;
                $scope.savedSearchesCount = 0;
                var subItems;
                var savedPropertyBadge = angular.element('#favourites-tip');
                var savedSearchBadge = angular.element('#searches-tip');
                var classNames = ['block-link', 'col-md-1 icon icon-person', 'login-button'];

                // Private Functions
                var _onPropertySaveOfUnsave = function (val) {

                    switch (val.Operation) {
                        case 'save':
                            $scope.savedPropertiesCnt++;
                            break;
                        case 'unsave':
                            $scope.savedPropertiesCnt--;
                            break;
                    }


                    // Toggle display upon new calculation.
                    if ($scope.savedPropertiesCnt <= 0) {
                        savedPropertyBadge.removeClass('active');
                    } else {
                        savedPropertyBadge.addClass('active');
                    }


                    // Update the display
                    savedPropertyBadge.text($scope.savedPropertiesCnt);
                };

                var onSearchSaved = function () {
                    $scope.savedSearchCount++;
                    savedSearchBadge.addClass('active');
                    savedSearchBadge.text($scope.savedSearchCount);
                };

                var onSearchDelete = function () {
                    $scope.savedSearchCount--;
                    if ($scope.savedSearchCount <= 0) {
                        savedSearchBadge.removeClass('active');
                    }
                    savedSearchBadge.text($scope.savedSearchCount);
                };

                var disableScroll = function (disable) {
                    var sUsrAg = navigator.userAgent;
                    if (sUsrAg.indexOf('Safari') > -1) {
                        if (disable)
                            cssHelperService.addClass(document.body, 'no-scroll');
                        else
                            cssHelperService.removeClass(document.body, 'no-scroll');
                    } else {
                        if (disable)
                            document.body.style.overflowY = 'hidden';
                        else
                            document.body.style.overflowY = 'scroll';
                    }
                };

                // public functions
                $scope.menuClick = function () {
                    $scope.showMenu = true;
                    disableScroll($scope.showMenu);
                    angular.element('.main-navigation').toggleClass('active');
                    $scope.activeClose = !$scope.activeClose;
                };

                $scope.cancelNavigation = function () {
                    angular.element('.main-navigation').toggleClass('active');
                    $scope.activeClose = !$scope.activeClose;
                    $scope.option = -1;
                    $scope.subOption = -1;
                    $scope.optionLabel = '';
                    disableScroll(!$scope.showMenu);
                    $scope.showMenu = false;
                    subItems.removeClass('slide-sub-item');
                };

                $scope.login = function () {
                    btAccounts().addRedirectToUrl();
                    btAccounts().showLogin();
                };

                $scope.select = function (option, label) {
                    $scope.optionLabel = label;
                    subItems.removeClass('slide-sub-item');
                    $element.find('#sub-item-' + option).addClass('slide-sub-item');
                };

                $scope.subSelect = function (subOption) {
                    if ($scope.subOption === subOption) {
                        //deselect current
                        $scope.subOption = -1;
                    } else {
                        $scope.subOption = subOption;
                    }
                };

                $scope.return = function () {
                    subItems.removeClass('slide-sub-item');
                    $scope.optionLabel = '';
                };

                $scope.showAccountModalMenu = function (event) {
                    $scope.accountsMenuOpen = !$scope.accountsMenuOpen;
                    event.stopPropagation();
                };

                $scope.init = function (savedSearchCount, savedPropertyCount) {

                    // Init function that should be run on load
                    $scope.accountsMenuOpen = false;
                    $scope.activeClose = false;
                    $scope.option = -1;
                    $scope.subOption = -1;
                    $scope.optionLabel = '';
                    $scope.showMenu = false;
                    $scope.initializeCounter = 0;
                    subItems = $element.find('.sub-item');

                    // Save property count should be pre-populated by the server. So we should just base our count off that. 
                    $scope.savedPropertiesCnt = savedPropertyBadge.text() * 1;
                    if ($scope.savedPropertiesCnt === 0) $scope.savedPropertiesCnt = savedPropertyCount;
                    $scope.savedSearchCount = savedSearchBadge.text() * 1;
                    if ($scope.savedSearchCount === 0) $scope.savedSearchCount = savedSearchCount;
                    // Wire up event listeners 
                    btEvents.addListener(btEventType.searchHasBeenDelete, function (e, val) {
                        onSearchDelete();
                    });

                    btEvents.addListener(btEventType.searchHasBeenSaved, function (e, val) {
                        onSearchSaved();
                    });
                    // Wire up event listeners
                    btEvents.addListener(btEventType.onPropertySaveOrUnsave, function (e, val) {
                        _onPropertySaveOfUnsave(val);
                    });
                    btEvents.addListener(btEventType.onFilterCountChange, function (e, val) {
                        $scope.filterCount = val;
                    });

                    document.body.addEventListener('click', function (e) {
                        if (classNames.indexOf(e.target.className) === -1 && $scope.accountsMenuOpen) {
                            $scope.accountsMenuOpen = false;
                            $scope.$apply();
                        }
                    });

                    document.body.addEventListener('touchend', function (e) {
                        if (classNames.indexOf(e.target.className) === -1 && $scope.accountsMenuOpen) {
                            $scope.accountsMenuOpen = false;
                            $scope.$apply();
                        }
                    });

                };

            }
        ]);

})(window.angular);;
angular.module("barfootMobile").controller("btSavedSearchTile",
    [
        'folioService', "$scope", '$element', '$timeout',
        function (folioService, $scope, $element, $timeout) {
            $scope.savedSearchCnt = '';
            $scope.showEmptySavedSearchPage = false;

            var _removeTile = function (folioId) {
                $('[data-folidid=' + folioId + ']').addClass('remove-tile');
                $timeout(function () {
                    var sepElement = $('[data-folidid=' + folioId + ']').prev('.tileSeperator').first();
                    $('[data-folidid=' + folioId + ']').remove();
                    sepElement.remove();
                    $scope.savedSearchCnt--;
                }, 200);
            }

            var _collapseDetailsPanel = function (folioId) {
                var collapsePanel = $('[data-folidid=' + folioId + ']').find('.collapse');
                $(collapsePanel).removeClass('in');
                var showDetailsBtn = $('#ShowSavedSearchDetail' + '_' + folioId);
                $(showDetailsBtn).text('SHOW DETAILS');
            }

            $scope.switchLabelText = function (folioId) {
                var showDetailsBtn = $('#ShowSavedSearchDetail' + '_' + folioId);
                // risk of getting out of sycn with the collapse panel's state, but will leave for now.
                if (showDetailsBtn.text() === 'SHOW DETAILS') {
                    showDetailsBtn.text('HIDE DETAILS');
                    
                } else {
                    showDetailsBtn.text('SHOW DETAILS');
                }
            }

            $scope.deleteIcon = 'icon icon-cross';
            $scope.deleteSavedSearch = function (event, folioId) {
                var folio = {
                    FolioId: folioId
                }
                folioService.delete(folio).then(function (response) {
                    if (response.data.Success) {
                        _removeTile(folioId);
                        $timeout(function () {
                            btEvents.trigger(btEventType.searchHasBeenDelete, { FolioId: folioId });
                        }, 100);
                    }
                });
            }

            $scope.editSearchName = function (event, folioId) {
                $('.bt-fullscreen-dialog').css('top', '0');
                btEvents.trigger(btEventType.dialogRequest, folioId);
            }

            $scope.showConfirmationState = function (e,folioId) {
                $('[data-folidid=' + folioId + ']').addClass('confirmation-stat');
                _collapseDetailsPanel(folioId);
               
            }

            $scope.hideConfirmationState = function (e, folioId) {
                $('[data-folidid=' + folioId + ']').removeClass('confirmation-stat');
            }
            var init = function () {
                $scope.$watch('savedSearchCnt',
                    function(val) {
                        if (val > 0) {
                            $scope.showEmptySavedSearchPage = false;
                        } else {
                            $scope.showEmptySavedSearchPage = true;
                        }
                    });
                
            }
            init();

        }
    ]);;
angular.module("barfootMobile").
    controller("btSlideable", [
        '$scope', '$element', '$timeout', '$window', function ($scope, $element, $timeout, $window) {
            $timeout(function () {

                var _reculcalateScreen = function() {
                    var parentWidth = $element.parent().outerWidth();
                    var parentHeight = $element.parent().outerHeight();
                    var hozDiv = $element;
                    var cssClass = {
                        'width': parentWidth,
                        'height': parentHeight + 10,
                        'overflow-y': 'hidden',
                        'overflow-x': 'scroll'
                    }
                    hozDiv.css(cssClass);
                }
                

                var _init = function() {
                    _reculcalateScreen();
                   
                    window.addEventListener('orientationchange', function () {
                        _reculcalateScreen();
                    });
                }
                _init();

            }, 0);

        }
    ]);

;
angular.module("barfootMobile").controller("savedSearchDialog",
    [
        'folioService', "$scope", '$element', '$log', '$timeout', function (folioService, $scope, $element, $log, $timeout) {

            // this is the name of the dialog.
            $scope.dialogName = "save-search-dialog";
            $scope.isOpenHomeEmail = true;
            $scope.frequency = 'Weekly';
            // if the save dialog is opened, we what the focus to be set on the name input form. 
            btEvents.addListener(btEventType.dialogRequest, function (e, dialogName) {
                $scope.isActive = $scope.dialogName == dialogName;
                if ($scope.isActive == true) {
                    $scope.forceTextFocus = true;

                }
            });

            // We don't want the open homes check box to be active if the never option is selected. 
            // so lets watch for the change and disabled when it's never. 
            $scope.onFreqChange = function (newFreq) {
                if (newFreq == 'Never') {
                    $scope.disableOpenHome = true;
                } else {
                    // check bos should be active.
                    $scope.disableOpenHome = false;
                }
            }
            $scope.pressedEnterOnSearchName = function () {

                $element.find('input[type=text]').blur();
            }

            $scope.cancelSave = function (e) {
                e.preventDefault();
                btEvents.trigger(btEventType.dialogCancel, $scope.dialogName);
            }

            $scope.cancelEdit = function (e, folioId) {
                e.preventDefault();
                btEvents.trigger(btEventType.dialogCancel, folioId);
            }
            $scope.SaveBtnClass = "SaveSearch btn btn-blue";
            $scope.SaveSearchBtnText = "Save search";
            $scope.SaveBtnDisabled = false;

            $scope.editSavedSearchName = function (e, savedSearchName, folioId) {
                e.preventDefault();
                if (savedSearchName == undefined || savedSearchName == '') {
                    $log.error('name can not be null or empty');
                    return;
                }
                var folio = {
                    FolioId: folioId,
                    Name: savedSearchName
                }
                folioService.reName(folio).then(function (response) {
                    if (response.data.Success) {
                        btEvents.trigger(btEventType.dialogCancel, folioId);
                        var nameField = $('[data-searchName=' + folioId + ']');
                        if (nameField != null) {
                            nameField.html(savedSearchName);
                        }
                    }
                });
            }

        }
    ]);;

(function (angular) {
    angular.module("barfootMobile").controller(
        "btListingImageCarousel",
        ['$scope', '$log', '$window', '$element', '$timeout', '$compile', 'btLockscrolling',
            function ($scope, $log, $window, $element) {

                var _getActiveItem = function () {
                    var result = undefined;
                    angular.forEach($scope.listingImages, function (item) {
                        if (item.isActive != undefined) {
                            if (item.isActive === true) {
                                result = item;
                            }
                        }
                    });

                    //Set the default to be the first image if nothing is found active.
                    if (result == undefined) {
                        result = $scope.listingImages[0];
                    }
                    return result;
                }


                var _getLastItem = function () {
                    return $scope.listingImages[$scope.listingImages.length - 1];
                }

                var _getActiveItemIndex = function () {
                    return $scope.listingImages.indexOf(_getActiveItem());
                }

                var _getSlidePanelElement = function () {
                    return $element.find('.slide-panel').first();
                }

                var _getNextSibling = function (item) {
                    var index = item.idx;
                    if ((index + 1) != $scope.listingImages.length && index != -1) {

                        return $scope.listingImages[index + 1];
                    }
                    return undefined;
                }

                var _calculateYellowBarSize = function (indexOfActiveItem) {
                    var totalItems = $scope.listingImages.length;
                    $scope.viewPercentage = (indexOfActiveItem + 1) / totalItems * 100;

                    if ($scope.viewPercentage == 0) {
                        $scope.viewPercentage = 100;
                    }
                }

                var _getPrevSibling = function (item) {
                    if (item.idx - 1 != -1 && item.idx != -1) {
                        return $scope.listingImages[item.idx -1];
                    }
                    return undefined;
                }

               
                
                var _getElementFromIndex = function(idx) {
                    return $element.find('.slide-panel > div')[idx];
                }

                var _loadItemImages = function(item) {
                    var element = _getElementFromIndex(item.idx);
                    var obj = {
                        "background-image": 'url("' + item.url + '")'
                    }
                    $(element).find('>div').css(obj);
                }

                var _lazyLoadSiblingItems = function (activeItem) {
                    angular.forEach($scope.listingImages, function(item) {
                        _loadItemImages(item);
                    });

                }

                var _resetSlides = function (element) {

                    $(element).find('.slide-in-right').removeClass('slide-in-right');
                    $(element).find('.slide-in-left').removeClass('slide-in-left');
                    $(element).find('.slide-out-left').removeClass('slide-out-left');
                    $(element).find('.slide-out-right').removeClass('slide-out-right');
                }
                var _slideOutLeft = function (item) {
                    
                    var element = _getElementFromIndex(item.idx);
                    _resetSlides(element);
                    $(element).find('.item').addClass('slide-out-left').removeClass('active');
                }

                var _slideInRight = function (item) {
                    var element = _getElementFromIndex(item.idx);
                    _resetSlides(element);

                    $(element).find('.item').addClass('active slide-in-right');
                }

                var _slideOutRight = function (item) {
                    var element = _getElementFromIndex(item.idx);
                    _resetSlides(element);
                    $(element).find('.item').addClass('slide-out-right').removeClass('active');
                }

                var _slideInLeft = function (item) {
                    var element = _getElementFromIndex(item.idx);
                    _resetSlides(element);
                    $(element).find('.item').addClass('active slide-in-left');
                }

                
                

               

                var _getICarouselItemsFromHtml = function() {
                    var result = [];

                    angular.forEach($element.find('.slide-panel > div'), function (item) {
                        
                        result.push({
                            url: $(item).attr('data-url'),
                            isLink: false,
                            idx: $(item).attr('data-idx') * 1,
                            isActive: $(item).attr('data-isactive') == "true"
                        });
                    });
                    
                    return result;
                }

                $scope.swipeLeft = function (activeItem) {
                    if ($scope.listingImages.length > 1) {
                        
                        var nextItem = _getNextSibling(activeItem);

                        if (nextItem == undefined) {
                            nextItem = $scope.listingImages[0];
                        }
                        _slideOutLeft(activeItem);
                        _slideInRight(nextItem);
                        _calculateYellowBarSize(nextItem.idx);
                        
                    }

                }

               

               
                $scope.swipeRight = function (activeItem) {
                    if ($scope.listingImages.length > 1) {
                        var prevItem = _getPrevSibling(activeItem);
                        
                        if (prevItem == undefined) {
                            prevItem = _getLastItem();
                        }

                        _slideOutRight(activeItem);
                        _slideInLeft(prevItem);
                        _calculateYellowBarSize(prevItem.idx);
                        
                    }


                }

                var _calculateItemSizes = function () {
                    angular.forEach($scope.listingImages, function (item) {
                        item.width = $window.outerWidth;
                    });
                    var height = $window.outerHeight > 0 ? $window.outerHeight : $window.innerHeight;
                    var width = $window.outerWidth > 0 ? $window.outerWidth : $window.innerWidth;

                    var slidePanel = _getSlidePanelElement();
                    slidePanel.css('width', width * $scope.listingImages.length + 'px');
                    slidePanel.css('height', height);

                    if ($scope.btGaleryviewEnabled == true) {
                        if ($scope.galleryViewActive == true) {
                            $scope.activeGalleryStyle = 'width:' + width + 'px;height:' + height + 'px;bottom:-' + (height / 2) + 'px;';
                        }
                    } else {
                        $scope.activeGalleryStyle = '';
                    }



                }

               

                var _init = function () {

                    
                    $scope.listingImages = _getICarouselItemsFromHtml();
                    
                    _calculateItemSizes();
                    _calculateYellowBarSize(_getActiveItemIndex());
                    angular.element($window).on('resize', function () {
                        _calculateItemSizes();
                    })

                    _lazyLoadSiblingItems();
                }
                _init();
            }
        ]);

})(window.angular);;
angular.module("barfootMobile")
.directive("btEmailAlerts", function () {
    return {
        restrict: 'E',
        transclude: true,
        templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-email-alerts.html",
        scope: {
            btLabel: '=',
            btName: '=',
            ngModel: '=',
            ngChange: '=',
            btIsvalid: '=',
            btIsrequired: '=',
            btIsrequiredmessage: '=',
            onEnterpress: '=',
            isCommercialOrRental: '=',
            btFrequency: '=',
            isOpenHomeEmail: '=',
            folioId: '=',
            searchName:'='
        },
        controller: ['$scope', 'folioService', function ($scope, folioService) {
            $scope.onChange = function () {
                if ($scope.ngModel == $scope.btLabel) {
                    if ($scope.ngChange != undefined) {
                        $scope.ngChange($scope.ngModel);
                    }
                }
            }
            $scope.UpdateSavedSearch = function (folioId) {
                var folio = {
                    FolioId: $scope.folioId,
                    Name: $scope.searchName,
                    SendOpenHomeNotifications: $scope.isOpenHomeEmail,
                    SendPropertyNotifications: $scope.btFrequency === 'Never' ? false : true,
                    PropertyNotificationSchedule: $scope.btFrequency
                }
                folioService.update(folio).then(function (response) {
                    if (response.data.Success) {
                       
                    }
                });
            }

            $scope.checkBoxStatus=function() {
            }
        }]
    }
});
;
angular.module("barfootMobile")
    .directive('btEnterKeypress', function () {
        return function (scope, element, attrs) {
            element.bind("keydown keypress", function (event) {
                var keyCode = event.which || event.keyCode;
                // If enter key is pressed
                if (keyCode === 13) {
                    scope.$eval(attrs.btEnterKeypress);
                    event.preventDefault();
                }
            });
        };
    });;
angular.module("barfootMobile")
    .directive("btFavouritePropertyStar", [
        function() {
            return {
                restrict: "A",
                scope: {
                    btListingid: "=",
                    btListingrefnumber: "=",
                    btOnloadState: "=",
                    btLoggedin: "="
                },
                controller: [
                    "$scope",
                    "btAccounts",
                    "btFavouritesService",
                    "$element",
                    function(
                        $scope,
                        btAccounts,
                        btFavouritesService,
                        $element
                    ) {
                        $scope.IsFavourite = $scope.btOnloadState == "True"; 
                        loggedIn = $scope.btLoggedin == "True";
                        $element.on("click", function(e) {
                            // Stop any other click actions from happening
                            e.preventDefault();
                            e.stopPropagation();

                            // Check the user is signed in.
                            if (loggedIn) {
                                if ($scope.IsFavourite == false) {

                                    // The user wants to add this to the favourites.
                                    btFavouritesService.addToFavourites($scope.btListingid).then(function (result) {

                                        // Trigger event to allow header icons to update etc.
                                        btEvents.trigger(btEventType.onPropertySaveOrUnsave, { Operation: "save" });
                                        $scope.IsFavourite = true;
                                        $element.addClass("active");

                                    });
                                } else {

                                    // The user wants to remove this from their favourites.
                                    btFavouritesService.deleteFavourite($scope.btListingid).then(function (result) {
                                        // Trigger event to update the header icons etc.
                                        btEvents.trigger(btEventType.onPropertySaveOrUnsave, { Operation: "unsave" });
                                        $scope.IsFavourite = false;
                                        $element.removeClass("active");

                                    });
                                }
                            } else {
                                btAccounts().addFavouritesPendingTask($scope.btListingid);
                                btAccounts().showLogin();
                            }

                        });
                    }
                ]

            };
        }
    ]);;
angular.module("barfootMobile")
    .directive("btFavouriteProperty", function () {
        return {
            restrict: "E",
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-favourite-property.html",
            scope: {
                btListingid: '=',
                btListingrefnumber: '='
            },
            controller: [
                '$scope',
                '$timeout',
                'btAccounts',
                'btFavouritesService',
'listingDetailService',
                function (
                    $scope,
                    $timeout,
                    btAccounts,
                    btFavouritesService, 
listingDetailService
                    ) {

                    $scope.$watch('btListingid', 'btListingrefnumber', function () {
                        if ($scope.btListingid == undefined && $scope.btListingrefnumber == undefined) {
                            $scope.listingLoaded = false;
                        } else
                            $scope.listingLoaded = true;

                    });
                    $scope.ListingRefNumber = $scope.btListingrefnumber;
                    $scope.class = "favourite icon icon-star";
                    $scope.starAnimationClass = "favourite icon icon-star animatation";
                    var isPropertyFavourite = function () {
                        btAccounts().userIsAuthenticated().then(function (data) {
                            if (data === "True") {
                                btFavouritesService.isPropertyFavourite($scope.btListingid).then(function (data) {
                                    if (data === "True") {
                                        $scope.class = "favourite icon icon-star active";
                                    }
                                    else
                                        $scope.class = "favourite icon icon-star";
                                });

                            } else {
                                $scope.class = "favourite icon icon-star";
                            }
                        });

                    }
                    isPropertyFavourite();
                    $scope.onFavouriteClick = function (e) {



                        e.stopPropagation();
                        //For adding or deleting a property from favourites use Listing Source ID
                        if ($scope.class === "favourite icon icon-star") {
                            btAccounts().userIsAuthenticated().then(function (data) {
                                if (data === "True") {
                                    ///logic if user is authenticated

                                    btFavouritesService.addToFavourites($scope.btListingid).then(function (result) {
                                        btEvents.trigger(btEventType.onPropertySaveOrUnsave, {Operation: 'save', ListingNo: $scope.btListingid });
                                        $scope.class = "favourite icon icon-star active";
                                        $scope.starAnimationClass = "favourite icon icon-star animatation show";
                                    });
                                } else {
                                    btAccounts().addFavouritesPendingTask($scope.btListingid); ///For add to favourtes pending task Listing ID should be the parameter
                                    btAccounts().showLogin();
                                    ///logic if user is not authenticated
                                }

                            });
                        }
                        else if ($scope.class === "favourite icon icon-star active") {
                            btFavouritesService.deleteFavourite($scope.btListingid).then(function (result) {
                                btEvents.trigger(btEventType.onPropertySaveOrUnsave, { Operation: 'unsave', ListingNo: $scope.btListingid });
                                $scope.class = "favourite icon icon-star";
                                $scope.starAnimationClass = "favourite icon icon-star animatation";
                            });
                        }


                    }
                    $scope.listingModel = undefined;
                    var init = function () {
                        if ($scope.ListingRefNumber == undefined || $scope.ListingRefNumber === "") {
                            listingDetailService($scope.btListingid).then(function (listingModel) {
                                $scope.listingModel = listingModel;
                                $scope.ListingRefNumber = $scope.listingModel.Listing_Ref_No;

                            });
                        }

                    }
                    init();
                }]

        };
    });;
angular.module("barfootMobile")
    .directive('btFocusWhen', ['$timeout','$parse',function ($timeout, $parse) {
    return {
        //scope: true,   // optionally create a child scope
        link: function (scope, element, attrs) {
            var model = $parse(attrs.btFocusWhen);
            scope.$watch(model, function (value) {
                if (value === true) { 
                    $timeout(function () {
                        element[0].focus();
                    });
                }
            });
            // to address @blesh's comment, set attribute value to 'false'
            // on blur event:
            element.bind('blur', function () {

            });
        }
    }
}]);;
angular.module("barfootMobile")
    .directive("btFormsCheckbox", function () {
        return {
            restrict: "E",
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-forms-checkbox.html",
            scope: {
                btLabel: "=",
                ngModel: "=",
                btDisable: "=",
                btDisplaylabel: "=",
                ngChange: "=",
                btDisableanduncheck:'='

            }, 
            controller: [
                "$scope", "$location", "$element", function ($scope, $location, $element) {
                    $scope.initialState = undefined;
                    $scope.model = "false";
                    var _init = function () {
                        $scope.initialState = $scope.ngModel;
                         $scope.$watch('ngModel', function (newVal) {
                            $scope.model = newVal == true ? "true" : "false";
                        })
                        $scope.$watch('btDisableanduncheck', function(val) {
                            if (val == true) {
                                $scope.model = 'false';
                            }
                        })
                        $scope.$watch('model', function (modelValue) {
                            $scope.ngModel = modelValue == 'true';
                            
                        })
                    }
                    _init();
                }
            ]

        };
    });;
angular.module("barfootMobile")
    .directive("btFormsInput", function () {
        return {
            restrict: "E",
            transclude: true,
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-forms-input.html",
            scope: {
                btLabel: "=",
                ngModel: "=",
                ngChange: "=",
                btIsvalid: "=",
                btIsrequired: "=",
                btIsrequiredmessage: "=",
                onEnterpress: "=",
                onFocusevent: '=',
                onBlurevent: '=',
                btPresetvalue: "=",
                btFocus: '=',
                btShowValidationMsg: '=',
                btType: '=',
                btBackgroungColor: '='

            },
            controller: [
                "$scope", "$element", "$log", "$timeout", function ($scope, $element, $log, $timeout) {

                    var _reset = function () {
                        if ($scope.btShowValidationMsg === undefined || $scope.btShowValidationMsg === false)
                            $scope.showIsRequiredMessage = false;
                        else
                            $scope.showIsRequiredMessage = $scope.btShowValidationMsg;

                        // if there is a preset value , set the model to be that. 
                        if ($scope.btPresetvalue != undefined) {
                            $scope.ngModel = $scope.btPresetvalue;
                        }
                    };
                    var _init = function () {
                        _reset();
                    };
                    $scope.$watch('btShowValidationMsg', function (newVal) {

                        $scope.showIsRequiredMessage = $scope.btShowValidationMsg;

                    });

                    var _checkForRequiredValidation = function () {
                        if ($scope.btIsrequired == true) {
                            if ($scope.ngModel === "" || $scope.ngModel == undefined) {
                                $scope.showIsRequiredMessage = true;
                            } else {
                                $scope.showIsRequiredMessage = false;
                            }
                        } else {
                            $scope.showIsRequiredMessage = false;
                        }
                    }
                    var focusAnimation = function () {
                        $element.find('.bt-forms-email').addClass('focused');
                    }

                    $scope.addFocus = function (event) {
                        // overload for this focus event.

                        if ($scope.onFocusevent != undefined) {
                            $scope.onFocusevent(event);
                        }
                        focusAnimation();
                    }
                    $scope.$watch('btFocus', function (newVal) {
                        $timeout(function () {
                            if (newVal == true) {
                                $element.find('input[type=text]').focus();
                            }
                        }, 0);

                    });

                    $scope.enterIsPressed = function () {
                        if ($scope.onEnterpress != undefined && ($scope.ngModel != "" || $scope.ngModel != undefined)) {
                            $scope.onEnterpress();
                        }
                    };

                    var blurAnimation = function () {
                        $element.find('.bt-forms-email').removeClass('focused');
                        _checkForRequiredValidation();
                    }
                    $scope.removeFocus = function (event) {
                        // overload for this blue event.
                        if ($scope.onBlurevent != undefined) {
                            $scope.onBlurevent(event)
                        }
                        blurAnimation();
                    }
                    $scope.hasValue = function (hasValue) {
                        var container = $element.find(".bt-forms-text");
                        hasValue ? container.addClass("has-value") : container.removeClass("has-value");
                    };

                    $element.find('input').bind("keydown keypress", function (val) {
                        var value = angular.element(val.target).val();

                        if (value.length + 1 > 0) {
                            $scope.hasValue(true);
                            focusAnimation();
                        } else {
                            $scope.hasValue(false);
                            blurAnimation();
                        }

                    });

                    // ngChange will only fire on type=email inputs when it's valid. 
                    // so if the email is not valid, it'll not reach here
                    $scope.onChange = function () {
                        if ($scope.ngChange != undefined) {
                            $scope.ngChange();
                        }

                        if ($scope.ngModel != undefined) {
                            if ($scope.ngModel.length > 0) {
                                $scope.hasValue(true);
                                $scope.addFocus();
                            } else {
                                $scope.hasValue(false);
                            }
                        }
                    };
                    if ($scope.ngModel != undefined) {
                        if ($scope.ngModel.length > 0) {
                            hasValue(true);
                        }
                    }

                    $scope.onFocus = function () {

                        $element.find("input").focus();
                        $scope.addFocus();

                    };
                    btEvents.addListener(btEventType.EmailConfirmationModalClosed, function () {
                        $scope.hasValue(false);
                        blurAnimation();
                    });
                    _init();
                }
            ]
        };
    });;
angular.module("barfootMobile")
.directive("btFormsRadio", function () {
    return {
        restrict: 'E',
        transclude: true,
        templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-forms-radio.html",
        scope: {
            btLabel: '=',
            btName: '=',
            ngModel: '=',
            ngChange: '=',
            btIsvalid: '=',
            btIsrequired: '=',
            btIsrequiredmessage: '=',
            onEnterpress: '='



        },
        controller: ['$scope', '$element', function ($scope, $element) {
            $scope.onChange = function () {
                if ($scope.ngModel == $scope.btLabel) {
                    if ($scope.ngChange != undefined) {
                        $scope.ngChange($scope.ngModel);
                    }
                }
            }
        }]
    }
});
;
angular.module("barfootMobile")
    .directive("btFormsTextarea", function () {
        return {
            restrict: "E",
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-forms-textarea.html",
            scope: {
                btLabel: "=",
                ngModel: "=",
                ngChange: "=",
                btIsvalid: "=",
                btIsrequired: "=",
                btIsrequiredmessage: "=",
                onEnterpress: "=",
                onFocusevent: '=',
                onBlurevent: '=',
                btPresetvalue: "=",
                btFocus: '=',
                btShowValidationMsg: '=',
                btBackgroungColor: '='
            },
            controller: [
                "$scope", "$element", "$log", "$timeout", function ($scope, $element, $log, $timeout) {

                    var _reset = function () {
                        if ($scope.btShowValidationMsg === undefined || $scope.btShowValidationMsg === false)
                            $scope.showIsRequiredMessage = false;
                        else
                            $scope.showIsRequiredMessage = $scope.btShowValidationMsg;

                        // if there is a preset value , set the model to be that. 
                        if ($scope.btPresetvalue != undefined) {
                            $scope.ngModel = $scope.btPresetvalue;
                        }
                    };

                    var _init = function () {
                        _reset();
                    };

                    $scope.$watch('btShowValidationMsg', function (newVal) {
                        $scope.showIsRequiredMessage = $scope.btShowValidationMsg;
                    });

                    var _checkForRequiredValidation = function () {
                        if ($scope.btIsrequired == true) {
                            if ($scope.ngModel === "" || $scope.ngModel == undefined) {
                                $scope.showIsRequiredMessage = true;
                            } else {
                                $scope.showIsRequiredMessage = false;
                            }
                        } else {
                            $scope.showIsRequiredMessage = false;
                        }
                    }

                    var focusAnimation = function () {
                        $element.find('.bt-forms-email').addClass('focused');
                    }

                    $scope.addFocus = function (event) {
                        // overload for this focus event.

                        if ($scope.onFocusevent != undefined) {
                            $scope.onFocusevent(event);
                        }
                        focusAnimation();
                    }

                    $scope.$watch('btFocus', function (newVal) {
                        $timeout(function () {
                            if (newVal == true) {
                                $element.find('textarea').focus();
                            }
                        }, 0);

                    });

                    $scope.enterIsPressed = function () {
                        if ($scope.onEnterpress != undefined && ($scope.ngModel != "" || $scope.ngModel != undefined)) {
                            $scope.onEnterpress();
                        }
                    };

                    var blurAnimation = function () {
                        $element.find('.bt-forms-email').removeClass('focused');
                        _checkForRequiredValidation();
                    }

                    $scope.removeFocus = function (event) {
                        // overload for this blue event.
                        if ($scope.onBlurevent != undefined) {
                            $scope.onBlurevent(event)
                        }
                        blurAnimation();
                    }

                    $scope.hasValue = function (hasValue) {
                        var container = $element.find(".bt-forms-text");
                        hasValue ? container.addClass("has-value") : container.removeClass("has-value");
                    };

                    $element.find('textarea').bind("keydown keypress", function (val) {
                        var value = angular.element(val.target).val();

                        if (value.length + 1 > 0) {
                            $scope.hasValue(true);
                            focusAnimation();
                        } else {
                            $scope.hasValue(false);
                            blurAnimation();
                        }

                    });

                    // ngChange will only fire on type=email inputs when it's valid. 
                    // so if the email is not valid, it'll not reach here
                    $scope.onChange = function () {
                        if ($scope.ngChange != undefined) {
                            $scope.ngChange();
                        }

                        if ($scope.ngModel != undefined) {
                            if ($scope.ngModel.length > 0) {
                                $scope.hasValue(true);
                                $scope.addFocus();
                            } else {
                                $scope.hasValue(false);
                            }
                        }
                    };

                    if ($scope.ngModel != undefined) {
                        if ($scope.ngModel.length > 0) {
                            hasValue(true);
                        }
                    }

                    $scope.onFocus = function () {

                        $element.find("textarea").focus();
                        $scope.addFocus();

                    };

                    btEvents.addListener(btEventType.EmailConfirmationModalClosed, function () {
                        $scope.hasValue(false);
                        blurAnimation();
                    });

                    _init();
                }
            ]
        };
    });;
angular.module("barfootMobile")
    .directive("btFullscreenDialog", function () {
        return {
            restrict: 'E',
            transclude: true,
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-fullscreen-dialog.html",
            scope: {
                btName: '='
               , isActive: '='
            },
            controller: ['$scope',
                'btLockscrolling',
                '$location',
                function (
                    $scope,
                    btLockscrolling,
                    $location) {

                    $scope.active = $scope.isActive;

                    var init = function () {

                        // when this global event is fired. 
                        // the full screen dialog will check to make sure the names passed in by the event is it's own. 
                        // if so, it will make this one active, If not it will assume that is much become in-active. 
                        btEvents.addListener(btEventType.dialogRequest, function (e, dialogName) {
                            if ($scope.btName == dialogName)
                                $scope.active = true;
                            btLockscrolling().lockPage();

                        });


                        btEvents.addListener(btEventType.dialogCancel, function (e, dialogName) {
                            if ($scope.btName === dialogName)
                                $scope.active = false;
                            btLockscrolling().unlockPage();

                        });
                    }
                    init();

                    var showSaveSearchDialog = function () {
                        var hashValue = $location.hash();
                        if (hashValue === "savesearch") {
                            $scope.active = true;
                            btLockscrolling().lockPage();
                            // window.location.hash = "";
                            $location.hash("");
                        }

                    }
                    showSaveSearchDialog();
                }]
        }
    });;
angular.module("barfootMobile")
.directive("btHiddenfieldValue", function () {
    return {
        restrict: 'A',
        scope: {
            btHiddenfieldValue:'='
        },
        controller: ['$scope', '$element', function ($scope, $element) {
            $scope.$watch('btHiddenfieldValue', function (newVal) {
                $element.attr('value', newVal);
            })
        }]
    }
});
;

angular.module("barfootMobile")
.directive("btImageCarousel", [function () {
    return {
        restrict: 'E',
        templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-image-carousel.html",
        scope: {
            btImagelist: '=',
            btGaleryviewEnabled: '=',
            onFavourite: '=',
            onPlayvideo: '=',
            btStaticIcons: '=',
            btListingid: '=',
            btListingref: '='
        },
        controller: ['$scope', '$log', '$window', '$element', '$timeout', '$compile', 'btLockscrolling', function ($scope, $log, $window, $element, $timeout, $compile, btLockscrolling) {
            var _getActiveItem = function () {
                var result = undefined;
                angular.forEach($scope.btImagelist, function (item) {
                    if (item.isActive != undefined) {
                        if (item.isActive === true) {
                            result = item;
                        }
                    }
                });
                return result;
            }

            $scope.activeGalleryStyle = '';
            $scope.galleryViewActive = false;
            $scope.staticBeds = 0;
            $scope.staticBaths = 0;
            $scope.staticParks = 0;
            $scope.staticSold = false;


            var _getLastItem = function () {
                return $scope.btImagelist[$scope.btImagelist.length - 1];
            }

            var _getActiveItemIndex = function () {
                return $scope.btImagelist.indexOf(_getActiveItem());
            }

            var _getSlidePanelElement = function () {
                return $element.find('.slide-panel').first()
            }

            var _getNextSibling = function (item) {
                var index = $scope.btImagelist.indexOf(item);
                if ((index + 1) != $scope.btImagelist.length && index != -1) {

                    return $scope.btImagelist[index + 1];
                }
                return undefined;
            }

            var _calculateYellowBarSize = function () {
                var indexOfActiveItem = _getActiveItemIndex() + 1;
                var totalItems = $scope.btImagelist.length;
                $scope.viewPercentage = indexOfActiveItem / totalItems * 100;

                if ($scope.viewPercentage == 0) {
                    $scope.viewPercentage = 100;
                }
            }

            var _getPrevSibling = function (item) {
                var index = $scope.btImagelist.indexOf(item)
                if (index - 1 != -1 && index != -1) {
                    return $scope.btImagelist[index - 1];
                }
                return undefined;
            }

            var _setActiveItem = function (item) {
                angular.forEach($scope.btImagelist, function (val) {
                    val.isActive = false;
                    if (val == item) {
                        val.isActive = true;
                    }
                });
                _lazyLoadSiblingItems();
                _calculateYellowBarSize();
            }


            var _lazyLoadSiblingItems = function (initLoad) {

                // confirm the active item is loaded ( just in case of jumping to item)
                // note : Items could be image , video or link ( listings are links. )
                // Load delay will only be respected on the initload 
                if ($scope.btImagelist.length > 0) {


                    var activeItem = _getActiveItem();
                    if (activeItem == undefined) {
                        activeItem = $scope.btImagelist[0];
                        activeItem.load = true;
                    }
                    else
                        activeItem.load = true;

                    var nextItem = _getNextSibling(activeItem);
                    if (nextItem == undefined) {
                        nextItem = $scope.btImagelist[0];
                    }


                    if (nextItem.loadDelay != undefined && initLoad == true) {
                        $timeout(function () {
                            nextItem.load = true;
                        }, nextItem.loadDelay);
                    } else {
                        nextItem.load = true;
                    }
                    

                    var prevItem = _getPrevSibling(activeItem);
                    if (prevItem == undefined) {
                        prevItem = _getLastItem();
                    }


                    if (prevItem.loadDelay != undefined && initLoad == true) {
                        $timeout(function () {
                            prevItem.load = true;
                        }, prevItem.loadDelay);
                    } else {
                        prevItem.load = true;
                        
                    }
                }



            }

            var _resetSlides = function (item) {

                item.slideOutLeft = false;
                item.slideInLeft = false;
                item.slideInRight = false;
                item.slideOutRight = false;
            }
            var _slideOutLeft = function (item) {
                _resetSlides(item);
                angular.forEach($scope.btImagelist, function (val) {
                    val.slideOutLeft = false;
                })
                item.slideOutLeft = true;
            }

            var _slideInRight = function (item) {
                _resetSlides(item);
                angular.forEach($scope.btImagelist, function (val) {
                    val.slideInRight = false;
                })
                item.slideInRight = true;
            }

            var _slideOutRight = function (item) {
                _resetSlides(item);
                angular.forEach($scope.btImagelist, function (val) {
                    val.slideOutRight = false;
                })
                item.slideOutRight = true;
            }

            var _slideInLeft = function (item) {
                _resetSlides(item);
                angular.forEach($scope.btImagelist, function (val) {
                    val.slideInLeft = false;
                })
                item.slideInLeft = true;
            }

            var _getAllVideoItems = function () {
                var results = [];
                angular.forEach($scope.btImagelist, function (item) {
                    if (item.isVideo == true) {
                        results.push(item)
                    }
                })

                return results;
            }

            var _cleanUpVideos = function () {
                $element.find('iframe').remove();
                angular.forEach($scope.btImagelist, function (item) {
                    if (item.isVideo == true) {
                        item.playVideo = false;
                    }
                })
            }

            var _loadIframeVideo = function (item) {

                if (item.isVideo == true && item.videoCancelled != true) {
                    item.playVideo = true;

                    $scope.$on('youtube.player.ended', function ($event, player) {
                        angular.forEach($scope.btImagelist, function (item) {
                            if (item.isVideo == true) {
                                item.playVideo = false;
                            }
                        });
                        _cleanUpVideos();
                    });

                    $scope.$on('youtube.player.ready', function ($event, player) {
                        player.playVideo();
                    });
                    if ($scope.galleryViewActive == true) {
                        $timeout(function () {
                            $element.find('.youtube-player').attr('style', 'height:' + ($window.innerHeight - 30) + 'px !important;');

                            $compile($element.find('.youtube-player'));
                            // videoPlayer.playVideo();
                        }, 300);
                    }


                }
            }



            $scope.swipeLeft = function (item) {
                if ($scope.btImagelist.length > 1) {
                    var activeItem = _getActiveItem();
                    var nextItem = _getNextSibling(activeItem);

                    if (nextItem == undefined) {
                        nextItem = $scope.btImagelist[0];
                    }

                    _slideOutLeft(activeItem);
                    _slideInRight(nextItem);
                    _setActiveItem(nextItem)
                    _cleanUpVideos();
                }

            }

         
            $scope.cancelVideo = function (item) {
                if (item == undefined) {
                    item = _getAllVideoItems()[0];

                }
                if (item != undefined) {
                    item.playVideo = false;
                }


                _cleanUpVideos();
            }



            $scope.itemClicked = function (item) {

                if ($scope.btGaleryviewEnabled == true) {

                    if (item.isVideo == true && $scope.galleryViewActive == true) {
                        _loadIframeVideo(item);
                    }

                    if ($scope.galleryViewActive == false) {
                        $scope.galleryViewActive = true;
                        _calculateItemSizes();
                    }


                } else {
                    $scope.galleryViewActive = false;
                    if (item.isLink == true) {
                        window.location.href = item.linkUrl;
                    }

                    if (item.isVideo == true && item.videoCancelled != true) {
                        _loadIframeVideo(item);
                    }

                    if (item.videoCancelled == true) {
                        item.videoCancelled = false;
                    }
                }
            }

            //$scope.onFavouriteClick = function(item){
            //	if($scope.onFavourite != undefined){
            //		$scope.onFavourite(item);
            //	}
            //}

            $scope.swipeRight = function (item) {
                if ($scope.btImagelist.length > 1) {
                    var activeItem = _getActiveItem();
                    var prevItem = _getPrevSibling(activeItem);

                    if (prevItem == undefined) {
                        prevItem = _getLastItem();
                    }

                    _slideOutRight(activeItem);
                    _slideInLeft(prevItem);
                    _setActiveItem(prevItem)
                    _cleanUpVideos();
                }


            }

            var _calculateItemSizes = function () {
                angular.forEach($scope.btImagelist, function (item) {
                    item.width = $window.outerWidth;
                });
                var height = $window.outerHeight > 0 ? $window.outerHeight : $window.innerHeight;
                var width = $window.outerWidth > 0 ? $window.outerWidth : $window.innerWidth;

                var slidePanel = _getSlidePanelElement();
                slidePanel.css('width', width * $scope.btImagelist.length + 'px');
                slidePanel.css('height', height);

                if ($scope.btGaleryviewEnabled == true) {
                    if ($scope.galleryViewActive == true) {
                        $scope.activeGalleryStyle = 'width:' + width + 'px;height:' + height + 'px;bottom:-' + (height / 2) + 'px;';
                    }
                } else {
                    $scope.activeGalleryStyle = '';
                }



            }

            var _addUrlQualityExtention = function(querystring) {
                angular.forEach($scope.btImagelist, function(item) {
                    item.url = item.url + querystring;
                });
            }

            var _init = function () {

                // Add append image quality query to the end of all url's
                _addUrlQualityExtention("?width=1000&height=688&mode=crop&quality=70");


                if ($scope.btImagelist == undefined) {
                    $scope.btImagelist = [];
                }

                // if there are no images in the carousel. Then it might be loading async in another controller. 
                // So if this ever updated and has items in it. Lets re-initialize the carousel.
                if ($scope.btImagelist.length == 0) {
                    var cancelEvent = $scope.$watch('btImagelist', function(val) {
                        if ($scope.btImagelist != undefined) {
                            if ($scope.btImagelist.length > 0) {
                                _init();
                                cancelEvent();
                            }
                        }

                    });
                }

                $scope.$watch('galleryViewActive', function (val) {

                    angular.element('bt-image-carousel').hide();
                    $($element).show();


                    if (val == true) {

                        btLockscrolling().lockPage();

                    } else {

                        angular.element('bt-image-carousel').show();
                        btLockscrolling().unlockPage();
                    }
                });
                
                // Get the active Item. If there is none, default to the first item in the list. 
                var activeItem = _getActiveItem();
                if (activeItem == undefined && $scope.btImagelist.length > 0) {
                    $scope.btImagelist[0].isActive = true;
                }

                // check to see if the video has a placeholder image. If not have a look at youtube to find one. 
                var videoItems = _getAllVideoItems();
                angular.forEach(videoItems, function(videoItem) {

                    if (videoItem.linkUrl == undefined) {
                        $log.error('Carousel item has been marked as a video, yet the videoItem.linkUrl is undefined.');
                    }
                    var youtubeId = videoItem.linkUrl.split('?v=')[1];
                    if (youtubeId == undefined) {
                        //example url : www.youtube.com/embed/w9VGu9i4mGw?rel=0
                        youtubeId = videoItem.linkUrl.split('embed/')[1].replace('?rel=0', '');
                    }

                    if (videoItem.url == '' || videoItem.url == undefined) {
                        videoItem.url = 'http://img.youtube.com/vi/' + youtubeId + '/hqdefault.jpg';
                    }
                    videoItem.youtubeID = youtubeId;
                });


                if ($scope.btStaticIcons == true) {
                    if ($scope.btImagelist != undefined) {
                        var firstItem = $scope.btImagelist[0];
                        if (firstItem != undefined) {
                            $scope.staticBeds = firstItem.beds;
                            $scope.staticBaths = firstItem.baths;
                            $scope.staticParks = firstItem.parks;
                            $scope.staticSold = firstItem.isSold;
                        }
                    }

                }

                _calculateItemSizes();
                _calculateYellowBarSize();
                angular.element($window).on('resize', function () {
                    _calculateItemSizes();
                })
                _lazyLoadSiblingItems(true);


               }
            _init();

        }]


    }
}]);

;
angular.module("barfootMobile")
    .directive("btInfoSlidePage", function() {
        return {
            restrict: 'E',
            transclude:true,
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-info-slide-page.html",
            scope:{
            	btHeight:'=',
            	btWidth:'='
            },
            controller:['$scope','$timeout','$element',function($scope,$timeout,$element){
            }]
        }
    });;
angular.module("barfootMobile")
    .directive("btInfoSlide", function() {
        return {
            restrict: 'E',
            transclude:true,
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-info-slide.html",
            scope:{
            	btHeight:'=',
            	btWidth:'=',
            	btTime:'='
            },
            controller:['$scope','$timeout','$element','$interval',function($scope,$timeout,$element,$interval){
				$scope.swipeWidth = 0;
				$scope.innerContainer = $element.find('.inner');
				$scope.childItems = $element.find('.inner > *');
				$scope.element = $element;
            	$timeout(function(){
            		$scope.element.find('.image-counter').html('');
					$scope.innerContainer.css('height',$scope.btHeight);
					$scope.childItems = $element.find('.inner > *');
					$scope.element.find('.image-counter').css('width', 18 * $element.find('.inner > *').length + 6)
					for(i = 0; i < $element.find('.inner > *').length ; i++) {
						$scope.element.find('.image-counter').append('<div></div>');
					}
					$scope.element.find('.image-counter > div').removeClass('active');

					$scope.swipeWidth = $scope.btWidth;
					$element.find('.bt-info-slide-page').css('width',$scope.element.parent().outerWidth());

            	},100)
				
				if($scope.btTime != undefined) {
					var counter = 0;
					angular.element(angular.element('.bt-info-slide-page')[counter]).addClass('active');
					angular.element($scope.element.find('.image-counter > div')[counter]).addClass('active');
					$interval(function(){
						counter++;
						if(counter == angular.element('.bt-info-slide-page').length) {
							counter = 0;
						}
						angular.element('.bt-info-slide-page').removeClass('active');
						angular.element(angular.element('.bt-info-slide-page')[counter]).addClass('active');
						$scope.element.find('.image-counter > div').removeClass('active');
						angular.element($scope.element.find('.image-counter > div')[counter]).addClass('active');

					},$scope.btTime * 1);
				}
            }]
        }
    });;
angular.module("barfootMobile")
    .directive("btLineBreak", function () {
        return {
            restrict: 'E',
            transclude: true,
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-line-break.html",
            scope: {},
            controller: ['$scope', '$element', '$log', function ($scope, $element, $log) {
               

            }]
        }
    });;
angular.module("barfootMobile").directive("btReadMore", function() {
	return {
		restrict: 'E',
		transclude: true,
		templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-read-more.html",
		scope: {
			btStartHeight: '='
		},
		controller: ['$scope', '$element', '$timeout', function($scope, $element, $timeout) {
			$scope.isFullHeight = false;
			var _init = function() {
				$element.find('.content').css('height', $scope.btStartHeight - 30 + 'px');
			}
			_init();

			$scope.readMoreClick = function(){
				if($scope.isFullHeight == false) {
					$element.find('.content').css('height', 'auto');
					$scope.isFullHeight = true;
				} else  {
					$element.find('.content').css('height', $scope.btStartHeight - 30 + 'px');
					$scope.isFullHeight = false;
				}
			}
		}
		]
	}
});
;
angular.module("barfootMobile")
    .directive("btRecentArticles", function() {
        return {
            restrict: 'E',
            transclude:true,
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-recent-articles.html",
            controller:['$scope','$element','$timeout', function($scope,$element,$timeout){
            	$scope.articles = [
            		{title:'Market report in 2016', content:'LOrim Ipsum dolor sit amet, consectetur adipiscing eli'},
            		{title:'Market report in 2017', content:'LOrim Ipsum dolor sit amet, consectetur adipiscing eli'},
            		{title:'Market report in 2018', content:'LOrim Ipsum dolor sit amet, consectetur adipiscing eli'},
            	]
				$timeout(function(){
					var listContainer = $element.find('.bt-recent-articles')
            		var listItem = $element.find('.bt-recent-articles li');
            		$element.find('.bt-recent-articles').css('width',((angular.element(listItem[0]).outerWidth(true))* listItem.length) + 32)	
				},0)
            	
            	
            }]
        }
    });;
angular.module("barfootMobile")
    .directive("btShakePanel", function() {
        return {
            restrict: 'E',
            transclude:true,
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-shake-panel.html",
            scope: {
              	btShake:'='
            }
           
        }
    });;
function makeSwipeDirective(directiveName, direction, eventName) {
    angular.module("barfootMobile").directive(directiveName, ['$parse', '$swipe', function ($parse, $swipe) {
        // The maximum vertical delta for a swipe should be less than 75px.
        var MAX_VERTICAL_DISTANCE = 150;
        // Vertical distance should not be more than a fraction of the horizontal distance.
        var MAX_VERTICAL_RATIO = 0.3;
        // At least a 30px lateral motion is necessary for a swipe.
        var MIN_HORIZONTAL_DISTANCE = 30;

        return function (scope, element, attr) {
            var swipeHandler = $parse(attr[directiveName]);

            var startCoords, valid;

            function validSwipe(coords) {
                // Check that it's within the coordinates.
                // Absolute vertical distance must be within tolerances.
                // Horizontal distance, we take the current X - the starting X.
                // This is negative for leftward swipes and positive for rightward swipes.
                // After multiplying by the direction (-1 for left, +1 for right), legal swipes
                // (ie. same direction as the directive wants) will have a positive delta and
                // illegal ones a negative delta.
                // Therefore this delta must be positive, and larger than the minimum.
                if (!startCoords) return false;
                var deltaY = Math.abs(coords.y - startCoords.y);
                var deltaX = (coords.x - startCoords.x) * direction;
                return valid && // Short circuit for already-invalidated swipes.
                     deltaY < MAX_VERTICAL_DISTANCE &&
                    deltaX > 0 &&
                    deltaX > MIN_HORIZONTAL_DISTANCE; //&&
                // deltaY / deltaX < MAX_VERTICAL_RATIO;
            }

            var pointerTypes = ['touch'];
            if (!angular.isDefined(attr['ngSwipeDisableMouse'])) {
                pointerTypes.push('mouse');
            }
            $swipe.bind(element, {
                'start': function (coords, event) {
                    startCoords = coords;
                    valid = true;
                },
                'cancel': function (event) {
                    valid = false;
                },
                'end': function (coords, event) {
                    if (validSwipe(coords)) {
                        scope.$apply(function () {
                            element.triggerHandler(eventName);
                            swipeHandler(scope, { $event: event });
                        });
                    }
                }
            }, pointerTypes);
        };
    }]);
}

// Left is negative X-coordinate, right is positive.
makeSwipeDirective('btSwipeLeft', -1, 'swipeleft');
makeSwipeDirective('btSwipeRight', 1, 'swiperight');

;
angular.module("barfootMobile")
    .directive("btTab", function() {
        return {
            restrict: 'E',
            transclude:true,
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-tab.html",
            scope: {
              	btLabel:'='
            },
            controller:['$scope','$element','$log',function($scope,$element,$log){
					$scope.isActive = false;
            		$scope.$on('label-change',function($event, labelName){
						$scope.isActive = $scope.btLabel == labelName;
            		})
            		var init = function(){
						// find the parent tab control. and get it's scope. 
						// once we have that, ass the label provided by this tab. 

						var parentTab = $element.parents('.bt-tabs').first();
						
						if(parentTab.length == 0) {
							$log.error('a bt-tab directives must be within a bt-tabs directive');
						}

						if($scope.btLabel == '' || $scope.btLabel == undefined) {
							$log.error('bt-label attribute can not be undefined on empty for a bt-tab')
						}

						var parentScope = parentTab.scope();

						if (parentScope != undefined) {
							parentScope.addLabel($scope.btLabel);
						} else {
							$log.error('parent tab scope was not located')
						}
            		}
            		init();


            		
            }]
        }
    });;
angular.module("barfootMobile")
    .directive("btTabs", function() {
        return {
            restrict: 'E',
            transclude:true,
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-tabs.html",
            scope:{},
            controller:['$scope','$timeout',function($scope,$timeout){

            	$scope.labels = [];
				$scope.firstPageSetActive = false;
				$scope.addLabel = function(labelName){

					$scope.labels.push(labelName);
					if($scope.firstPageSetActive == false){
						$scope.firstPageSetActive = true;
						$scope.$broadcast('label-change',labelName);
					}
					

				}

				$scope.switchTo = function(labelName){
					$scope.$broadcast('label-change',labelName);
				}

				
            }]
        }
    });;
angular.module("barfootMobile")
    .directive("btTestDir", function () {
        return {
            restrict: 'E',
            transclude:true,
            scope: {
                btLabel: '=',
                btMode: '='
            },
            templateUrl: "/assets/js/version2-webforms/angularjs/templates/bt-test-dir.html"

        }
    });;
