<commit_before>(function () {

    var root = this;

    var defaults = {
        chart: {
            animations: true,
            // by default take the size of the parent container
            defaultWidth: 400,
            // height = width * ratio
            defaultAspect: 1 / 1.61803398875,
            // calculated at render time based on the options & container
            width: undefined,
            // if defined, height takes precedence over aspect
            height: undefined,
            // margin between the container and the chart (ie labels or axis title)
            margin: {
                top: 0,
                right: 0,
                bottom: 0,
                left: 0
            },
            // padding between the chart area and the inner plot area */
            padding: {
                top: 0,
                right: 0,
                bottom: 0,
                left: 0
            },
            // with in pixels of the plot area (area inside the axis if any). This gets calculated on render
            plotWidth: undefined,
            // height in pixels of the plot area (area inside the axis if any). This gets calculated on render
            plotHeight: undefined,
            // top edge in pixels (from the edge of the svg) of the plot area (area inside the axis if any). This gets calculated on render
            plotTop: undefined,
            // left edge in pixels (from the edge of the svg) of the plot area (area inside the axis if any). This gets calculated on render
            plotLeft: undefined,
        },

        xAxis: {
        },

        yAxis: {
        },

        tooltip: {
        }
    };

    /**
    * Create a set of related visualizations by calling the Narwhal visualization constructor. This creates a Narwhal instance, based on the core Narwhal object.
    *
    *   * Pass the constructor any configuration options in the *options* parameter. Make sure the `el` option contains the selector of the container in which the Narwhal instance will be rendered.
    *   * Set the frame for this Narwhal instance (e.g. `.cartesian()`).
    *   * Add one or more specific visualizations to this Narwhal instance (e.g. `.scatter()`, `.trend-line()`). Pass each visualization constructor the data it displays.
    *   * Invoke an action for this Narwhal instance (e.g. `.render()`).
    *
    * ### Example:
    *
    *     new Narwhal({el: 'myChart'})
    *       .cartesian()
    *       .line([1,3,2,5])
    *       .render()
    *
    *
    * @class Narwhal() visualizations object
    * @param {object} options The global options object
    * @see {@link config}
    *
    */
    function Narwhal (options) {
        this.init(options);

        return this;
    }

    /**
    * Adds a new kind of visualization to the core Narwhal object.
    * The *renderer* function will be called when you add this visualization to instances of Narwhal.
    *
    * ### Example:
    *
    *     Narwhal.export("exampleVisualization", function(data, layer) {
    *           //function body to create exampleVisualization
    *           //for example using SVG and/or D3
    *     });
    *
    *     //to include the visualization into a specific Narwhal instance
    *     new Narwhal(options)
    *           .exampleVisualization(data)
    *           .render()
    *
    * @param {String} ctorName Name of the visualization, used as a constructor name.
    * @param {Function} renderer Function called when this visualization is added to a Narwhal instance. This function receives the data that is passed in to the constructor.
    * @see options
    */
    Narwhal.export = function (ctorName, renderer) {

        if (typeof renderer !== 'function') throw new Error('Invalid render function for ' + ctorName + ' visualization');

        function sortSeries(data) {
            if(!data || !data.length) return [];

            if(data[0].data) {
                _.each(data, sortSeries);
            }

            var shouldSort = _.isObject(data[0]) && _.isDate(data[0].x);
            var sortFunc = function (a, b) { return a.x - b.x; };
            if(shouldSort) {
                data.sort(sortFunc);
            }

            return data;
        }

        Narwhal.prototype[ctorName] = function (data, options) {
            var categories = this.options ? this.options.xAxis ? this.options.xAxis.categories : undefined : undefined;
            var opt =  _.extend({}, this.options[ctorName], options);
            var vis;

            data = data || [];
            sortSeries(data);
            vis = new Narwhal.VisualizationContainer(_.nw.normalizeSeries(data, categories), opt, ctorName, renderer, this);
            this._visualizations.push(vis);

            return this;
        };
    };

    /**
    * Exposes functionality to the core Narwhal object.
    * Use this to add *functionality* that will be available for any new visualizations created with `.export()`.
    *
    * ###Example:
    *
    *     Narwhal.expose("example", function () {
    *         // return a new instance of the functionality we want to expose
    *         // to the narwhal instance...
    *         return {
    *              // when included in the instance, the function `.transformData` is available the visualizations
    *             transformData: function(data) { .... }
    *         };
    *     });
    *
    *     Narwhal.export("visualizationThatUsesTransformDataFunction", function(data, layer) {
    *           //function body including call to this.transformData(data)
    *     });
    *
    *     // to include the functionality into a specific instance
    *     new Narwhal(options)
    *           .example()
    *           .visualizationThatUsesTransformDataFunction()
    *           .render()
    */
    Narwhal.expose = function (ctorName, functionalityConstructor) {
        var ctor = function () {
            var functionality = typeof functionalityConstructor === 'function' ? new functionalityConstructor() : functionalityConstructor;
            // extend the --instance-- we don't want all charts to be overriden...
            _.extend(this, _.omit(functionality, 'init'));

            if(functionality.init) functionality.init.call(this, this.options);

            return this;
        };

        Narwhal.prototype[ctorName] = ctor;

        return this;
    };

    Narwhal.prototype = _.extend(Narwhal.prototype, {
        _visualizations: [],

        // Initializes the instance of Narwhal
        init: function (options) {
            // for now, just  store this options here...
            // the final set of options will be composed before rendering
            // after all components/visualizations have been added
            this.options = options || {};

            this._visualizations.length = 0;

            return this;
        },

        calculateWidth: function () {
            var width = _.nw.getStyle(this.options.el, 'width');
            return this.options.el ? (parseInt(width, 10) || this.options.chart.defaultWidth) : this.options.chart.defaultWidth;
        },

        calculateHeight: function () {
            var height = _.nw.getStyle(this.options.el, 'height');
            var containerHeight = this.options.el ? parseInt(height, 10) : undefined;
            var calcWidth = this.options.chart.width;
            var ratio = this.options.chart.aspect || this.options.chart.defaultAspect;

            return !!containerHeight ?  containerHeight : Math.round(calcWidth * ratio);
        },

        calcMetrics: function () {
            var options = this.options;

            this.adjustPadding();

            this.adjustTitlePadding();

            options.chart.width = options.chart.width || this.calculateWidth();
            options.chart.height = options.chart.height || this.calculateHeight();

            this.options = _.merge(options, {
                chart: {
                    plotWidth: options.chart.width - options.chart.margin.left - options.chart.margin.right - options.chart.padding.left - options.chart.padding.right,
                    plotHeight: options.chart.height - options.chart.margin.top - options.chart.margin.bottom - options.chart.padding.top - options.chart.padding.bottom,
                    plotLeft: options.chart.margin.left + options.chart.padding.left,
                    plotTop: options.chart.margin.top + options.chart.padding.top
                }
            });
        },

        adjustPadding: function () {
            // overriden by components that need to adjust padding
            return this;
        },

        adjustTitlePadding: function () {
            // overriden by components that need to adjust padding
            return this;
        },

        composeOptions: function () {
            var allDefaults = _.merge({}, defaults);
            var mergeDefaults = function (vis) { _.merge(allDefaults, vis.renderer.defaults); };

            _.each(this._visualizations, mergeDefaults);

            // compose the final list of options right before start rendering
            this.options = _.merge({}, allDefaults, this.options);
        },

        baseRender: function () {
            this.plotArea();

            return this;
        },

        /**
        * Renders this Narwhal instance and all its visualizations into the DOM.
        *
        * Example:
        *
        *     new Narwhal({ el:'.myChart' })
        *           .pie([1,2,3])
        *           .render()
        *
        * @function .render
        *
        */
        render: function () {
            this.composeOptions();

            this.calcMetrics();

            this.baseRender();

            this.renderVisualizations();

            return this;
        },

        update: function () {
            this.calcMetrics();
            return this;
        },

        plotArea: function () {

            var chartOpt = this.options.chart;

            this.container = d3.select(this.options.el);

            if(!this.svg) {
                this.svg = this.container
                    .append('svg')
                    .attr('viewBox', '0 0 ' + chartOpt.width + ' ' + chartOpt.height)
                    .attr('preserveAspectRatio', 'xMinYMin')
                    .attr('class', 'narwhal-chart')
                    .attr('height', chartOpt.height)
                    .append('g')
                        .attr('transform', 'translate(' + chartOpt.margin.left + ',' + chartOpt.margin.top + ')');
            }

            return this;
        },

        createVisualizationLayer: function (vis, id) {
            return this.svg.append('g')
                .attr('vis-id', id)
                .attr('vis-type', vis.type)
                .attr('transform', 'translate(' + this.options.chart.padding.left + ',' + this.options.chart.padding.top + ')');
        },

        renderVisualizations: function () {

            _.each(this._visualizations, function (visualization, index) {
                var id = index + 1;
                var layer = visualization.layer || this.createVisualizationLayer(visualization, id);
                var opt = _.merge({}, this.options, visualization.options);
                visualization.layer = layer;
                visualization.parent = this;
                visualization.render(layer, opt, this);
            }, this);

            return this;
        },

        getVisualization: function (index) {
            return this._visualizations[index];
        },

        compose: function(ctorName, funcArray) {
            // compose differnt functional objects into this instance...
            // this way we can do something like new Narwhal().BarChart(...) and it includes
            // cartesia, xAxis, yAxis, tooltip, highliter, etc...
        },

        // place holder function for now
        data: function () {

        }
    });

    // export to our context
    root.Narwhal = Narwhal;

})();
<commit_msg>Added global setData to narwhal and rename getVisualization to select<commit_after>(function () {

    var root = this;

    var defaults = {
        chart: {
            animations: true,
            // by default take the size of the parent container
            defaultWidth: 400,
            // height = width * ratio
            defaultAspect: 1 / 1.61803398875,
            // calculated at render time based on the options & container
            width: undefined,
            // if defined, height takes precedence over aspect
            height: undefined,
            // margin between the container and the chart (ie labels or axis title)
            margin: {
                top: 0,
                right: 0,
                bottom: 0,
                left: 0
            },
            // padding between the chart area and the inner plot area */
            padding: {
                top: 0,
                right: 0,
                bottom: 0,
                left: 0
            },
            // with in pixels of the plot area (area inside the axis if any). This gets calculated on render
            plotWidth: undefined,
            // height in pixels of the plot area (area inside the axis if any). This gets calculated on render
            plotHeight: undefined,
            // top edge in pixels (from the edge of the svg) of the plot area (area inside the axis if any). This gets calculated on render
            plotTop: undefined,
            // left edge in pixels (from the edge of the svg) of the plot area (area inside the axis if any). This gets calculated on render
            plotLeft: undefined,
        },

        xAxis: {
        },

        yAxis: {
        },

        tooltip: {
        }
    };

    /**
    * Create a set of related visualizations by calling the Narwhal visualization constructor. This creates a Narwhal instance, based on the core Narwhal object.
    *
    *   * Pass the constructor any configuration options in the *options* parameter. Make sure the `el` option contains the selector of the container in which the Narwhal instance will be rendered.
    *   * Set the frame for this Narwhal instance (e.g. `.cartesian()`).
    *   * Add one or more specific visualizations to this Narwhal instance (e.g. `.scatter()`, `.trend-line()`). Pass each visualization constructor the data it displays.
    *   * Invoke an action for this Narwhal instance (e.g. `.render()`).
    *
    * ### Example:
    *
    *     new Narwhal({el: 'myChart'})
    *       .cartesian()
    *       .line([1,3,2,5])
    *       .render()
    *
    *
    * @class Narwhal() visualizations object
    * @param {object} options The global options object
    * @see {@link config}
    *
    */
    function Narwhal (options) {
        this.init(options);

        return this;
    }

    /**
    * Adds a new kind of visualization to the core Narwhal object.
    * The *renderer* function will be called when you add this visualization to instances of Narwhal.
    *
    * ### Example:
    *
    *     Narwhal.export("exampleVisualization", function(data, layer) {
    *           //function body to create exampleVisualization
    *           //for example using SVG and/or D3
    *     });
    *
    *     //to include the visualization into a specific Narwhal instance
    *     new Narwhal(options)
    *           .exampleVisualization(data)
    *           .render()
    *
    * @param {String} ctorName Name of the visualization, used as a constructor name.
    * @param {Function} renderer Function called when this visualization is added to a Narwhal instance. This function receives the data that is passed in to the constructor.
    * @see options
    */
    Narwhal.export = function (ctorName, renderer) {

        if (typeof renderer !== 'function') throw new Error('Invalid render function for ' + ctorName + ' visualization');

        function sortSeries(data) {
            if(!data || !data.length) return [];

            if(data[0].data) {
                _.each(data, sortSeries);
            }

            var shouldSort = _.isObject(data[0]) && _.isDate(data[0].x);
            var sortFunc = function (a, b) { return a.x - b.x; };
            if(shouldSort) {
                data.sort(sortFunc);
            }

            return data;
        }

        Narwhal.prototype[ctorName] = function (data, options) {
            var categories = this.options ? this.options.xAxis ? this.options.xAxis.categories : undefined : undefined;
            var opt =  _.extend({}, this.options[ctorName], options);
            var vis;

            data = data || [];
            sortSeries(data);
            vis = new Narwhal.VisualizationContainer(_.nw.normalizeSeries(data, categories), opt, ctorName, renderer, this);
            this._visualizations.push(vis);

            return this;
        };
    };

    /**
    * Exposes functionality to the core Narwhal object.
    * Use this to add *functionality* that will be available for any new visualizations created with `.export()`.
    *
    * ###Example:
    *
    *     Narwhal.expose("example", function () {
    *         // return a new instance of the functionality we want to expose
    *         // to the narwhal instance...
    *         return {
    *              // when included in the instance, the function `.transformData` is available the visualizations
    *             transformData: function(data) { .... }
    *         };
    *     });
    *
    *     Narwhal.export("visualizationThatUsesTransformDataFunction", function(data, layer) {
    *           //function body including call to this.transformData(data)
    *     });
    *
    *     // to include the functionality into a specific instance
    *     new Narwhal(options)
    *           .example()
    *           .visualizationThatUsesTransformDataFunction()
    *           .render()
    */
    Narwhal.expose = function (ctorName, functionalityConstructor) {
        var ctor = function () {
            var functionality = typeof functionalityConstructor === 'function' ? new functionalityConstructor() : functionalityConstructor;
            // extend the --instance-- we don't want all charts to be overriden...
            _.extend(this, _.omit(functionality, 'init'));

            if(functionality.init) functionality.init.call(this, this.options);

            return this;
        };

        Narwhal.prototype[ctorName] = ctor;

        return this;
    };

    Narwhal.prototype = _.extend(Narwhal.prototype, {
        _visualizations: [],

        // Initializes the instance of Narwhal
        init: function (options) {
            // for now, just  store this options here...
            // the final set of options will be composed before rendering
            // after all components/visualizations have been added
            this.options = options || {};

            this._visualizations.length = 0;

            return this;
        },

        calculateWidth: function () {
            var width = _.nw.getStyle(this.options.el, 'width');
            return this.options.el ? (parseInt(width, 10) || this.options.chart.defaultWidth) : this.options.chart.defaultWidth;
        },

        calculateHeight: function () {
            var height = _.nw.getStyle(this.options.el, 'height');
            var containerHeight = this.options.el ? parseInt(height, 10) : undefined;
            var calcWidth = this.options.chart.width;
            var ratio = this.options.chart.aspect || this.options.chart.defaultAspect;

            return !!containerHeight ?  containerHeight : Math.round(calcWidth * ratio);
        },

        calcMetrics: function () {
            var options = this.options;

            this.adjustPadding();

            this.adjustTitlePadding();

            options.chart.width = options.chart.width || this.calculateWidth();
            options.chart.height = options.chart.height || this.calculateHeight();

            this.options = _.merge(options, {
                chart: {
                    plotWidth: options.chart.width - options.chart.margin.left - options.chart.margin.right - options.chart.padding.left - options.chart.padding.right,
                    plotHeight: options.chart.height - options.chart.margin.top - options.chart.margin.bottom - options.chart.padding.top - options.chart.padding.bottom,
                    plotLeft: options.chart.margin.left + options.chart.padding.left,
                    plotTop: options.chart.margin.top + options.chart.padding.top
                }
            });
        },

        adjustPadding: function () {
            // overriden by components that need to adjust padding
            return this;
        },

        adjustTitlePadding: function () {
            // overriden by components that need to adjust padding
            return this;
        },

        composeOptions: function () {
            var allDefaults = _.merge({}, defaults);
            var mergeDefaults = function (vis) { _.merge(allDefaults, vis.renderer.defaults); };

            _.each(this._visualizations, mergeDefaults);

            // compose the final list of options right before start rendering
            this.options = _.merge({}, allDefaults, this.options);
        },

        baseRender: function () {
            this.plotArea();

            return this;
        },

        /**
        * Renders this Narwhal instance and all its visualizations into the DOM.
        *
        * Example:
        *
        *     new Narwhal({ el:'.myChart' })
        *           .pie([1,2,3])
        *           .render()
        *
        * @function .render
        *
        */
        render: function () {
            this.composeOptions();

            this.calcMetrics();

            this.baseRender();

            this.renderVisualizations();

            return this;
        },

        update: function () {
            this.calcMetrics();
            return this;
        },

        plotArea: function () {

            var chartOpt = this.options.chart;

            this.container = d3.select(this.options.el);

            if(!this.svg) {
                this.svg = this.container
                    .append('svg')
                    .attr('viewBox', '0 0 ' + chartOpt.width + ' ' + chartOpt.height)
                    .attr('preserveAspectRatio', 'xMinYMin')
                    .attr('class', 'narwhal-chart')
                    .attr('height', chartOpt.height)
                    .append('g')
                        .attr('transform', 'translate(' + chartOpt.margin.left + ',' + chartOpt.margin.top + ')');
            }

            return this;
        },

        createVisualizationLayer: function (vis, id) {
            return this.svg.append('g')
                .attr('vis-id', id)
                .attr('vis-type', vis.type)
                .attr('transform', 'translate(' + this.options.chart.padding.left + ',' + this.options.chart.padding.top + ')');
        },

        renderVisualizations: function () {

            _.each(this._visualizations, function (visualization, index) {
                var id = index + 1;
                var layer = visualization.layer || this.createVisualizationLayer(visualization, id);
                var opt = _.merge({}, this.options, visualization.options);
                visualization.layer = layer;
                visualization.parent = this;
                visualization.render(layer, opt, this);
            }, this);

            return this;
        },

        /**
        * Set's the same data set into all visualizations for an instance
        *
        * Example:
        *
        *     var data = [1,2,3,4,5];
        *     var chart = new Narwhal({ el:'.myChart' })
        *           .scatter(data)
        *           .trendLine(data);
        *
        *     data.push(10);
        *     chart.setData(data)
        *           .render();
        *
        * @function .setData
        *
        */
        setData: function (data) {
            _.invoke(this._visualizations, 'setData', data);

            return this;
        },

        /**
        * Returns a VisualizationContainer object for the visualization at a given index (0-based)
        *
        * Example:
        *
        *     var chart = new Narwhal({ el:'.myChart' })
        *           .pie([1,2,3])
        *           .render()
        *
        *     var myPie = chart.select(0)
        *
        *     // do something with the visualization like updateing its data set
        *     myPie.setData([6,7,8,9]).render()
        *
        * @function .select
        *
        */
        select: function (index) {
            return this._visualizations[index];
        },

        // place holder function for now
        data: function () {

        }
    });

    // export to our context
    root.Narwhal = Narwhal;

})();
<|endoftext|>


<commit_before>'use strict';
/* Controllers */

function listGistCtrl($scope, $http) {
    $http.get('http://localhost:3000/gists')
            .success(function(data) {
        for (var item in data) {
            data[item].tags = data[item].description ? data[item].description.match(/(#[A-Za-z0-9\-\_]+)/g) : [];
        }
        $scope.gists = data;
    });
}

function singleGistCtrl($scope, $routeParams, $http) {
    $http.get('http://localhost:3000/gists/' + $routeParams.gistId)
            .success(function(data) {
        $scope.single = data;
        $scope.tags = data.description ? data.description.match(/(#[A-Za-z0-9\-\_]+)/g) : [];

        $scope.enableEdit = function() {
            $scope.edit = true;
            $('.edit').slideDown('slow');
        };
        $scope.disableEdit = function() {
            $scope.edit = false;
        };

        << << << < HEAD
                $scope.warnDeleteGist = function() {
            $('.delete').slideDown('slow');
        };
        $scope.cancelDeleteGist = function() {
            $('.delete').slideUp('slow');
        };

        $scope.del = function($event) {
            if ($event) {
                $event.preventDefault();
            }
            var data = {
                id: $scope.single.id
            };
            $http.delete('http://localhost:3000/gists/:id', data)
                    .success(function(response) {
                if (response.status === 'ok') {
                    $('.warn').slideDown('slow');
                    $('.warn span').text('Gist saved');
                    $scope.single.history = response.data.history;
                    setTimeout(function() {
                        $('.warn').slideUp();
                    }, 2500);
                }
            });
        };

        $scope.addFile = function() {
            var fileName = 'newFile' + Object.keys($scope.single.files).length + '.txt';
            $scope.single.files[fileName] = {
                content: '',
                filename: fileName,
                language: 'text'
            };
        };

        $scope.dragStart = function(e) {
            e.stopPropagation();
            e.preventDefault();
            $('.edit').slideDown('slow');
            $('.main section').addClass('dragarea');
            $('.edit span').text('Drag detected - now drop!');
            console.log('dragging start');
        };

        $scope.drop = function(e) {
            e.stopPropagation();
            e.preventDefault();
            var data = event.dataTransfer;
            for (var i = 0; i < data.files.length; i++) { // For each dropped file
                var file = data.files[i];
                var reader = new FileReader();

                reader.onloadend = (function(filename) {
                    return function(event) {
                        $scope.single.files[filename] = {
                            filename: filename,
                            content: event.target.result,
                            language: 'html'
                        };
                        $scope.$digest();
                    }
                })(file.name);

                reader.readAsText(file);
                $('.edit').slideUp('slow');
                $('.ok').slideDown('slow');
                $('.main section').removeClass('dragarea');
                $('.ok span').html('Dropped: ' + file.name + '');
                reader.onloadend = (function(filename) {
                    return function(event) {
                        $scope.single.files[filename] = {
                            filename: filename,
                            content: event.target.result,
                            language: 'html'
                        };
                        $scope.$digest();
                    }
                })(file.name);

                reader.readAsText(file);

            }
        };

        $scope.dragEnd = function(e) {
            e.stopPropagation();
            e.preventDefault();
            console.log('drag end');
        };

        $scope.save = function($event) {
            $('.loading span').text('Saving...');
            $('.edit').slideUp();
            if ($event) {
                $event.preventDefault();
            }

            var data = {
                description: $scope.single.description,
                id: $scope.single.id,
                files: {}
            };

            for (var file in $scope.single.files) {
                data.files[file] = {
                    content: $scope.single.files[file].content,
                    filename: $scope.single.files[file].filename
                };
            }

            $http.post('http://localhost:3000/gists/edit', data)
                    .success(function(response) {
                if (response.status === 'ok') {
                    $('.ok').slideDown('slow');
                    $('.ok span').text('Gist saved');
                    $scope.edit = false;
                    $scope.single.history = response.data.history;
                    setTimeout(function() {
                        $('.ok').slideUp();
                    }, 2500);
                }
            });

        };

    });
}

function commentsGistCtrl($scope, $routeParams, $http) {
    $http.get('http://localhost:3000/gists/comments/' + $routeParams.gistId)
            .success(function(data) {
        $scope.comments = data;
    });
}

function createGistCtrl($scope, $routeParams, $http) {
    $scope.description = '';
    $scope.isPublic = false;
    $scope.files = [
        {
            filename: '',
            content: ''
        }
    ];

    $scope.addFile = function() {
        console.log('add file');
        console.log($scope);
        $scope.files.push({
            content: '',
            filename: '',
            language: 'html'
        });
    };

    $scope.save = function($event) {

        if ($event) {
            $event.preventDefault();
        }

        var data = {
            description: $scope.description,
            "public": $scope.isPublic,
            files: {}
        };

        for (var file in $scope.files) {
            data.files[$scope.files[file].filename] = {
                content: $scope.files[file].content
            };
        }

        $http.post('http://localhost:3000/gists/create', data)
                .success(function(response) {
            if (response.status === 'ok') {
                $('.ok').slideDown('slow');
                $('.ok span').text('Gist saved');
                window.location.href = "#/gist/" + response.data.id
            }
        });
    }
}
<commit_msg>Conflicts resolve oops.<commit_after>'use strict';
/* Controllers */

function listGistCtrl($scope, $http) {
    $http.get('http://localhost:3000/gists')
            .success(function(data) {
        for (var item in data) {
            data[item].tags = data[item].description ? data[item].description.match(/(#[A-Za-z0-9\-\_]+)/g) : [];
        }
        $scope.gists = data;
    });
}

function singleGistCtrl($scope, $routeParams, $http) {
    $http.get('http://localhost:3000/gists/' + $routeParams.gistId)
            .success(function(data) {
        $scope.single = data;
        $scope.tags = data.description ? data.description.match(/(#[A-Za-z0-9\-\_]+)/g) : [];

        $scope.enableEdit = function() {
            $scope.edit = true;
            $('.edit').slideDown('slow');
        };
        $scope.disableEdit = function() {
            $scope.edit = false;
        };

        $scope.warnDeleteGist = function() {
            $('.delete').slideDown('slow');
        };
        $scope.cancelDeleteGist = function() {
            $('.delete').slideUp('slow');
        };

        $scope.del = function($event) {
            if ($event) {
                $event.preventDefault();
            }
            var data = {
                id: $scope.single.id
            };
            $http.delete('http://localhost:3000/gists/:id', data)
                    .success(function(response) {
                if (response.status === 'ok') {
                    $('.warn').slideDown('slow');
                    $('.warn span').text('Gist saved');
                    $scope.single.history = response.data.history;
                    setTimeout(function() {
                        $('.warn').slideUp();
                    }, 2500);
                }
            });
        };

        $scope.addFile = function() {
            var fileName = 'newFile' + Object.keys($scope.single.files).length + '.txt';
            $scope.single.files[fileName] = {
                content: '',
                filename: fileName,
                language: 'text'
            };
        };

        $scope.dragStart = function(e) {
            e.stopPropagation();
            e.preventDefault();
            $('.edit').slideDown('slow');
            $('.main section').addClass('dragarea');
            $('.edit span').text('Drag detected - now drop!');
            console.log('dragging start');
        };

        $scope.drop = function(e) {
            e.stopPropagation();
            e.preventDefault();
            var data = event.dataTransfer;
            for (var i = 0; i < data.files.length; i++) { // For each dropped file
                var file = data.files[i];
                var reader = new FileReader();

                reader.onloadend = (function(filename) {
                    return function(event) {
                        $scope.single.files[filename] = {
                            filename: filename,
                            content: event.target.result,
                            language: 'html'
                        };
                        $scope.$digest();
                    }
                })(file.name);

                reader.readAsText(file);
                $('.edit').slideUp('slow');
                $('.ok').slideDown('slow');
                $('.main section').removeClass('dragarea');
                $('.ok span').html('Dropped: ' + file.name + '');
                reader.onloadend = (function(filename) {
                    return function(event) {
                        $scope.single.files[filename] = {
                            filename: filename,
                            content: event.target.result,
                            language: 'html'
                        };
                        $scope.$digest();
                    }
                })(file.name);

                reader.readAsText(file);

            }
        };

        $scope.dragEnd = function(e) {
            e.stopPropagation();
            e.preventDefault();
            console.log('drag end');
        };

        $scope.save = function($event) {
            $('.loading span').text('Saving...');
            $('.edit').slideUp();
            if ($event) {
                $event.preventDefault();
            }

            var data = {
                description: $scope.single.description,
                id: $scope.single.id,
                files: {}
            };

            for (var file in $scope.single.files) {
                data.files[file] = {
                    content: $scope.single.files[file].content,
                    filename: $scope.single.files[file].filename
                };
            }

            $http.post('http://localhost:3000/gists/edit', data)
                    .success(function(response) {
                if (response.status === 'ok') {
                    $('.ok').slideDown('slow');
                    $('.ok span').text('Gist saved');
                    $scope.edit = false;
                    $scope.single.history = response.data.history;
                    setTimeout(function() {
                        $('.ok').slideUp();
                    }, 2500);
                }
            });

        };

    });
}

function commentsGistCtrl($scope, $routeParams, $http) {
    $http.get('http://localhost:3000/gists/comments/' + $routeParams.gistId)
            .success(function(data) {
        $scope.comments = data;
    });
}

function createGistCtrl($scope, $routeParams, $http) {
    $scope.description = '';
    $scope.isPublic = false;
    $scope.files = [
        {
            filename: '',
            content: ''
        }
    ];

    $scope.addFile = function() {
        console.log('add file');
        console.log($scope);
        $scope.files.push({
            content: '',
            filename: '',
            language: 'html'
        });
    };

    $scope.save = function($event) {

        if ($event) {
            $event.preventDefault();
        }

        var data = {
            description: $scope.description,
            "public": $scope.isPublic,
            files: {}
        };

        for (var file in $scope.files) {
            data.files[$scope.files[file].filename] = {
                content: $scope.files[file].content
            };
        }

        $http.post('http://localhost:3000/gists/create', data)
                .success(function(response) {
            if (response.status === 'ok') {
                $('.ok').slideDown('slow');
                $('.ok span').text('Gist saved');
                window.location.href = "#/gist/" + response.data.id
            }
        });
    }
}
<|endoftext|>


<commit_before>/*
 * jQuery UI Menu @VERSION
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Menu
 *
 * Depends:
 *	jquery.ui.core.js
 *  jquery.ui.widget.js
 */
(function($) {

$.widget("ui.menu", {
	_create: function() {
		var self = this;
		this.element
			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
			.attr({
				role: "listbox",
				"aria-activedescendant": "ui-active-menuitem"
			})
			.click(function( event ) {
				if (self.options.disabled) {
					return false;
				}
				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
					return;
				}
				// temporary
				event.preventDefault();
				self.select( event );
			});
		this.refresh();

		if (!this.options.input) {
			this.options.input = this.element.attr("tabindex", 0);
		}
		this.options.input.bind("keydown.menu", function(event) {
			if (self.options.disabled) {
				return;
			}
			switch (event.keyCode) {
			case $.ui.keyCode.PAGE_UP:
				self.previousPage();
				event.preventDefault();
				event.stopImmediatePropagation();
				break;
			case $.ui.keyCode.PAGE_DOWN:
				self.nextPage();
				event.preventDefault();
				event.stopImmediatePropagation();
				break;
			case $.ui.keyCode.UP:
				self.previous();
				event.preventDefault();
				event.stopImmediatePropagation();
				break;
			case $.ui.keyCode.DOWN:
				self.next();
				event.preventDefault();
				event.stopImmediatePropagation();
				break;
			case $.ui.keyCode.ENTER:
				self.select();
				event.preventDefault();
				event.stopImmediatePropagation();
				break;
			}
		});
	},

	destroy: function() {
		$.Widget.prototype.destroy.apply(this, arguments);

		this.element
			.removeClass("ui-menu ui-widget ui-widget-content ui-corner-all")
			.removeAttr("tabindex")
			.removeAttr("role")
			.removeAttr("aria-activedescendant");

		this.element.children(".ui-menu-item")
			.removeClass("ui-menu-item")
			.removeAttr("role")
			.children("a")
			.removeClass("ui-corner-all")
			.removeAttr("tabindex")
			.unbind(".menu");
	},

	refresh: function() {
		var self = this;

		// don't refresh list items that are already adapted
		var items = this.element.children("li:not(.ui-menu-item):has(a)")
			.addClass("ui-menu-item")
			.attr("role", "menuitem");

		items.children("a")
			.addClass("ui-corner-all")
			.attr("tabindex", -1)
			// mouseenter doesn't work with event delegation
			.bind("mouseenter.menu", function( event ) {
				if (self.options.disabled) {
					return;
				}
				self.activate( event, $(this).parent() );
			})
			.bind("mouseleave.menu", function() {
				if (self.options.disabled) {
					return;
				}
				self.deactivate();
			});
	},

	activate: function( event, item ) {
		this.deactivate();
		if (this.hasScroll()) {
			var offset = item.offset().top - this.element.offset().top,
				scroll = this.element.attr("scrollTop"),
				elementHeight = this.element.height();
			if (offset < 0) {
				this.element.attr("scrollTop", scroll + offset);
			} else if (offset > elementHeight) {
				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
			}
		}
		this.active = item.eq(0)
			.children("a")
				.addClass("ui-state-hover")
				.attr("id", "ui-active-menuitem")
			.end();
		this._trigger("focus", event, { item: item });
	},

	deactivate: function() {
		if (!this.active) { return; }

		this.active.children("a")
			.removeClass("ui-state-hover")
			.removeAttr("id");
		this._trigger("blur");
		this.active = null;
	},

	next: function(event) {
		this.move("next", ".ui-menu-item:first", event);
	},

	previous: function(event) {
		this.move("prev", ".ui-menu-item:last", event);
	},

	first: function() {
		return this.active && !this.active.prev().length;
	},

	last: function() {
		return this.active && !this.active.next().length;
	},

	move: function(direction, edge, event) {
		if (!this.active) {
			this.activate(event, this.element.children(edge));
			return;
		}
		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
		if (next.length) {
			this.activate(event, next);
		} else {
			this.activate(event, this.element.children(edge));
		}
	},

	// TODO merge with previousPage
	nextPage: function(event) {
		if (this.hasScroll()) {
			// TODO merge with no-scroll-else
			if (!this.active || this.last()) {
				this.activate(event, this.element.children(":first"));
				return;
			}
			var base = this.active.offset().top,
				height = this.element.height(),
				result = this.element.children("li").filter(function() {
					var close = $(this).offset().top - base - height + $(this).height();
					// TODO improve approximation
					return close < 10 && close > -10;
				});

			// TODO try to catch this earlier when scrollTop indicates the last page anyway
			if (!result.length) {
				result = this.element.children(":last");
			}
			this.activate(event, result);
		} else {
			this.activate(event, this.element.children(!this.active || this.last() ? ":first" : ":last"));
		}
	},

	// TODO merge with nextPage
	previousPage: function(event) {
		if (this.hasScroll()) {
			// TODO merge with no-scroll-else
			if (!this.active || this.first()) {
				this.activate(event, this.element.children(":last"));
				return;
			}

			var base = this.active.offset().top,
				height = this.element.height();
				result = this.element.children("li").filter(function() {
					var close = $(this).offset().top - base + height - $(this).height();
					// TODO improve approximation
					return close < 10 && close > -10;
				});

			// TODO try to catch this earlier when scrollTop indicates the last page anyway
			if (!result.length) {
				result = this.element.children(":first");
			}
			this.activate(event, result);
		} else {
			this.activate(event, this.element.children(!this.active || this.first() ? ":last" : ":first"));
		}
	},

	hasScroll: function() {
		return this.element.height() < this.element.attr("scrollHeight");
	},

	select: function( event ) {
		this._trigger("select", event, { item: this.active });
	}
});

}(jQuery));
<commit_msg>Menu: Fixes for destroy method completeness<commit_after>/*
 * jQuery UI Menu @VERSION
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Menu
 *
 * Depends:
 *	jquery.ui.core.js
 *  jquery.ui.widget.js
 */
(function($) {

$.widget("ui.menu", {
	_create: function() {
		var self = this;
		this.element
			.addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
			.attr({
				role: "listbox",
				"aria-activedescendant": "ui-active-menuitem"
			})
			.bind("click.menu", function( event ) {
				if (self.options.disabled) {
					return false;
				}
				if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
					return;
				}
				// temporary
				event.preventDefault();
				self.select( event );
			});
		this.refresh();

		if (!this.options.input) {
			this.options.input = this.element.attr("tabIndex", 0);
		}
		this.options.input.bind("keydown.menu", function(event) {
			if (self.options.disabled) {
				return;
			}
			switch (event.keyCode) {
			case $.ui.keyCode.PAGE_UP:
				self.previousPage();
				event.preventDefault();
				event.stopImmediatePropagation();
				break;
			case $.ui.keyCode.PAGE_DOWN:
				self.nextPage();
				event.preventDefault();
				event.stopImmediatePropagation();
				break;
			case $.ui.keyCode.UP:
				self.previous();
				event.preventDefault();
				event.stopImmediatePropagation();
				break;
			case $.ui.keyCode.DOWN:
				self.next();
				event.preventDefault();
				event.stopImmediatePropagation();
				break;
			case $.ui.keyCode.ENTER:
				self.select();
				event.preventDefault();
				event.stopImmediatePropagation();
				break;
			}
		});
	},

	destroy: function() {
		$.Widget.prototype.destroy.apply(this, arguments);

		this.element
			.removeClass("ui-menu ui-widget ui-widget-content ui-corner-all")
			.removeAttr("tabIndex")
			.removeAttr("role")
			.removeAttr("aria-activedescendant");

		this.element.children(".ui-menu-item")
			.removeClass("ui-menu-item")
			.removeAttr("role")
			.children("a")
			.removeClass("ui-corner-all")
			.removeAttr("tabIndex")
			.unbind(".menu");
	},

	refresh: function() {
		var self = this;

		// don't refresh list items that are already adapted
		var items = this.element.children("li:not(.ui-menu-item):has(a)")
			.addClass("ui-menu-item")
			.attr("role", "menuitem");

		items.children("a")
			.addClass("ui-corner-all")
			.attr("tabIndex", -1)
			// mouseenter doesn't work with event delegation
			.bind("mouseenter.menu", function( event ) {
				if (self.options.disabled) {
					return;
				}
				self.activate( event, $(this).parent() );
			})
			.bind("mouseleave.menu", function() {
				if (self.options.disabled) {
					return;
				}
				self.deactivate();
			});
	},

	activate: function( event, item ) {
		this.deactivate();
		if (this.hasScroll()) {
			var offset = item.offset().top - this.element.offset().top,
				scroll = this.element.attr("scrollTop"),
				elementHeight = this.element.height();
			if (offset < 0) {
				this.element.attr("scrollTop", scroll + offset);
			} else if (offset > elementHeight) {
				this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
			}
		}
		this.active = item.eq(0)
			.children("a")
				.addClass("ui-state-hover")
				.attr("id", "ui-active-menuitem")
			.end();
		this._trigger("focus", event, { item: item });
	},

	deactivate: function() {
		if (!this.active) { return; }

		this.active.children("a")
			.removeClass("ui-state-hover")
			.removeAttr("id");
		this._trigger("blur");
		this.active = null;
	},

	next: function(event) {
		this.move("next", ".ui-menu-item:first", event);
	},

	previous: function(event) {
		this.move("prev", ".ui-menu-item:last", event);
	},

	first: function() {
		return this.active && !this.active.prev().length;
	},

	last: function() {
		return this.active && !this.active.next().length;
	},

	move: function(direction, edge, event) {
		if (!this.active) {
			this.activate(event, this.element.children(edge));
			return;
		}
		var next = this.active[direction + "All"](".ui-menu-item").eq(0);
		if (next.length) {
			this.activate(event, next);
		} else {
			this.activate(event, this.element.children(edge));
		}
	},

	// TODO merge with previousPage
	nextPage: function(event) {
		if (this.hasScroll()) {
			// TODO merge with no-scroll-else
			if (!this.active || this.last()) {
				this.activate(event, this.element.children(":first"));
				return;
			}
			var base = this.active.offset().top,
				height = this.element.height(),
				result = this.element.children("li").filter(function() {
					var close = $(this).offset().top - base - height + $(this).height();
					// TODO improve approximation
					return close < 10 && close > -10;
				});

			// TODO try to catch this earlier when scrollTop indicates the last page anyway
			if (!result.length) {
				result = this.element.children(":last");
			}
			this.activate(event, result);
		} else {
			this.activate(event, this.element.children(!this.active || this.last() ? ":first" : ":last"));
		}
	},

	// TODO merge with nextPage
	previousPage: function(event) {
		if (this.hasScroll()) {
			// TODO merge with no-scroll-else
			if (!this.active || this.first()) {
				this.activate(event, this.element.children(":last"));
				return;
			}

			var base = this.active.offset().top,
				height = this.element.height();
				result = this.element.children("li").filter(function() {
					var close = $(this).offset().top - base + height - $(this).height();
					// TODO improve approximation
					return close < 10 && close > -10;
				});

			// TODO try to catch this earlier when scrollTop indicates the last page anyway
			if (!result.length) {
				result = this.element.children(":first");
			}
			this.activate(event, result);
		} else {
			this.activate(event, this.element.children(!this.active || this.first() ? ":last" : ":first"));
		}
	},

	hasScroll: function() {
		return this.element.height() < this.element.attr("scrollHeight");
	},

	select: function( event ) {
		this._trigger("select", event, { item: this.active });
	}
});

}(jQuery));
<|endoftext|>


<commit_before>/*
 * Copyright 2014 WebFilings, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define(function(require) {
    'use strict';

    var requestAnimFrame = require('wf-js-common/requestAnimationFrame');
    var EventTypes = require('wf-js-uicomponents/awesome_map/EventTypes');

    /**
     * Creates a new ScrollBar with the given ScrollList and options.
     *
     * @classdesc
     *
     * A ScrollBar provides a UI based on the traditional browser scrollbar
     * for users to scroll the ScrollList.
     *
     * @name ScrollBar
     * @constructor
     *
     * @param {ScrollList} scrollList
     *        The ScrollList that the ScrollBar is constructed for
     *
     * @param {HTMLElement} parent
     *        The parent element for the ScrollBar to be created within
     *
     * @param {Object} options
     *        An object with optional classes and ids to be placed on the
     *        scrollbarEL and scrollbarContainerEL.
     *
     * @param {number} options.minHeight
     *        The minimum height, in pixels, of the ScrollBar
     *        If not provided, the minHeight will default to 16
     *
     *
     * @example
     *
     * var parent = getElementById('parent');
     * var options = {};
     *
     * options.scrollbarId = "scrollbar";
     * options.scrollbarClass = "scrollbar";
     * options.scrollbarContainerId = "scrollbar-container";
     * options.scrollbarContainerClass = "scrollbar-container";
     * options.minHeight = 8;
     *
     * scrollBar = new ScrollBar(scrollList, parent, options);
     */

    var ScrollBar = function(scrollList, parent, options) {
        var offset;
        var that = this;

        if (!scrollList) {
            throw new Error('ScrollBar#ScrollBar: scrollList is required');
        }
        else {
            this._scrollList = scrollList;
        }

        if (!parent) {
            throw new Error('ScrollBar#ScrollBar: parent is required.');
        }
        else {
            this._parent = parent;
        }

        this._options = options;

        this._layout = scrollList.getLayout();

        this._TOTAL_ITEMS = scrollList.getItemSizeCollection ? scrollList.getItemSizeCollection()._items.length :
                            scrollList.getItemMetadata().length;

        this._viewportHeight = this._layout.getVisiblePosition().bottom - this._layout.getVisiblePosition().top;

        this._virtualHeight = this._layout.getSize().height - this._viewportHeight;

        this._scrollableVirtualHeight = this._layout.getSize().height;

        this._listMap = this._scrollList.getListMap();

        this._setUpDOM();

        this._availableScrollbarHeight = this._viewportHeight - this._scrollbarHeight;

        // Set scrollbarScrolling to initially false
        this._scrollbarScrolling = false;

        this._clickOffset = null;

        // Set the initial scale
        this._scale = this._scrollList.getScale();

        // Get the initial position, in case it's not at 0, and set the scrollbar position
        requestAnimFrame(function() {
            that._placeScrollBar(that, that._elements.scrollbar);
        });

        // Match the scroll bar positioning to the users scrolling
        this._listMap.onTranslationChanged(function() {
            if (that._scrollbarScrolling) {
                return;
            }
            requestAnimFrame(function() {
                that._placeScrollBar();
            });
        });

        // Make necessary adjustments when the users zooms in or out
        this._listMap.onScaleChanged(function() {
            that._adjustScale();
            that._placeScrollBar();
        });

        this._scrollList.onItemsInserted(function() {
            that._TOTAL_ITEMS = scrollList.getItemSizeCollection()._items.length;
            that._adjustScale();
            that._placeScrollBar();
        });

        // Make adjustments when the scrollList is resized
        this._scrollList.onInteraction(function(scrollList, args) {
            if (args.event.type === EventTypes.RESIZE) {
                that._resize = true;
            }

            if (args.event.type === EventTypes.RELEASE && that._resize === true) {
                that._adjustScale();
                that._resize = false;
            }
        });

        // Attach handlers for scrolling the ScrollBar
        this._elements.scrollbar.addEventListener('mousedown', function(event) {
            offset = that._elements.scrollbar.offsetTop + that._elements.scrollbarContainer.offsetTop;
            that._clickOffset = event.clientY - offset + that._elements.scrollbarContainer.offsetTop;
            that._scrollbarScrolling = true;

            that._mouseupHandler = function() {
                that._stopUpdatingScrollbar();
            };

            that._mousemoveHandler = function(e) {
                that._updateScrollBar(e, that._clickOffset);
            };

            document.addEventListener('mousemove', that._mousemoveHandler);

            document.addEventListener('mouseup', that._mouseupHandler);
        });

    };

    ScrollBar.prototype = {

        //---------------------------------------------------------
        // Public methods
        //---------------------------------------------------------

        /**
         * Destruct the ScrollBar created HTML elements
         * @method ScrollBar#dispose
         */
        dispose: function() {
            this._elements.scrollbarContainer.removeChild(this._elements.scrollbar);
            this._parent.removeChild(this._elements.scrollbarContainer);
        },

        //---------------------------------------------------------
        // Private methods
        //---------------------------------------------------------

        /**
         * Initialize the HTML elements used by this instance of ScrollBar
         * @private
         */
        _setUpDOM: function() {
            // Create the scrollbar's container
            var scrollbarContainerEL = document.createElement('div');
            var scrollbarEL = document.createElement('div');

            // Set the given classes and ids scrollbar and it's container
            if (this._options.scrollbarId) {
                scrollbarEL.setAttribute('id', this._options.scrollbarId);
            }
            if (this._options.scrollbarClass) {
                scrollbarEL.className += ' ' + this._options.scrollbarClass;
            }
            if (this._options.scrollbarContainerId) {
                scrollbarContainerEL.setAttribute('id', this._options.scrollbarContainerId);
            }
            if (this._options.scrollbarContainerClass) {
                scrollbarContainerEL.className += ' ' + this._options.scrollbarContainerClass;
            }

            // Append the scrollbar and it's parent container to the given parent element
            scrollbarContainerEL.appendChild(scrollbarEL);
            this._parent.appendChild(scrollbarContainerEL);

            this._elements = {scrollbar: scrollbarEL, scrollbarContainer: scrollbarContainerEL};

            this._adjustScale();

            // Set the container height to the viewport height
            scrollbarContainerEL.style.height = this._layout.getViewportSize().height + 'px';
            // Set the scrollbar height
            scrollbarEL.style.height = this._scrollbarHeight + 'px';
        },

        /**
         * Position the scrollbar based on the current position of the ScrollList
         */
        _placeScrollBar: function() {
            var currentPosition = this._layout.getVisiblePosition().top;
            var translatedPosition = this._availableScrollbarHeight / this._virtualHeight * currentPosition;
            this._elements.scrollbar.style.top = translatedPosition + 'px';
        },

        /**
         * Position the scrollbar based on the position of a click event
         */
        _updateScrollBar: function(event, clickOffset) {
            // Don't go past the window bounds
            var scrollbarPos = Math.max(0, event.clientY - clickOffset);
            scrollbarPos = Math.min(scrollbarPos, this._viewportHeight - this._scrollbarHeight);
            this._elements.scrollbar.style.top = scrollbarPos + 'px';

            // Use the ratio of scrollbar position inside the scrolling area to calculate
            // the current item we should be interested in.
            var positionOfInterest = ((scrollbarPos) / (this._viewportHeight - this._scrollbarHeight)) * (this._virtualHeight);

            // Ensure that positionOfInterest isn't undefined.
            if (!positionOfInterest) {
                positionOfInterest = 0;
            }

            var x = this._listMap.getCurrentTransformState().translateX;

            this._listMap.transform({
                x: x,
                y: -positionOfInterest,
                scale: 1
            });
            this._scrollList.render();
        },

        /**
         * Remove the event listeners that update the scrollbar from the document
         */
        _stopUpdatingScrollbar: function() {
            this._clickOffset = undefined;
            document.removeEventListener('mousemove', this._mousemoveHandler);
            this._scrollbarScrolling = false;
            this._removeDocumentEventWatching(this);
        },

        /**
         * Remove the mouseup listener from the document
         */
        _removeDocumentEventWatching: function() {
            document.removeEventListener('mouseup', this._mouseupHandler);
        },

        /**
         * Calculate the scroll bar height based on the viewport height and the scaled virtual height
         */
        _calculateScrollBarHeight: function() {
            // Calculate the size of the scrollbar depending on the virtual height
            // The scrollbar shouldn't be shorter than MIN_HEIGHT
            var MIN_HEIGHT = this._options.minHeight || 8;
            var height = Math.max(MIN_HEIGHT, (this._viewportHeight / this._scrollableVirtualHeight) * this._layout.getViewportSize().height);

            return height;
        },

        /**
         * Scale the virtual height and re-calculate the scroll bar height
         */
        _adjustScale: function() {
            this._scale = this._scrollList.getScale();
            this._viewportHeight = this._layout.getVisiblePosition().bottom - this._layout.getVisiblePosition().top;
            this._virtualHeight = this._layout.getSize().height - this._viewportHeight;
            this._scrollableVirtualHeight = this._layout.getSize().height;
            this._scrollbarHeight = this._calculateScrollBarHeight();
            this._elements.scrollbar.style.height = this._scrollbarHeight + 'px';
            this._elements.scrollbarContainer.style.height = this._layout.getViewportSize().height + 'px';
            this._availableScrollbarHeight = this._viewportHeight - this._scrollbarHeight;
        }

    };

    return ScrollBar;

});
<commit_msg>Fix some scaling difficulties occuring upon wheel scrolling<commit_after>/*
 * Copyright 2014 WebFilings, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define(function(require) {
    'use strict';

    var requestAnimFrame = require('wf-js-common/requestAnimationFrame');
    var EventTypes = require('wf-js-uicomponents/awesome_map/EventTypes');

    /**
     * Creates a new ScrollBar with the given ScrollList and options.
     *
     * @classdesc
     *
     * A ScrollBar provides a UI based on the traditional browser scrollbar
     * for users to scroll the ScrollList.
     *
     * @name ScrollBar
     * @constructor
     *
     * @param {ScrollList} scrollList
     *        The ScrollList that the ScrollBar is constructed for
     *
     * @param {HTMLElement} parent
     *        The parent element for the ScrollBar to be created within
     *
     * @param {Object} options
     *        An object with optional classes and ids to be placed on the
     *        scrollbarEL and scrollbarContainerEL.
     *
     * @param {number} options.minHeight
     *        The minimum height, in pixels, of the ScrollBar
     *        If not provided, the minHeight will default to 16
     *
     *
     * @example
     *
     * var parent = getElementById('parent');
     * var options = {};
     *
     * options.scrollbarId = "scrollbar";
     * options.scrollbarClass = "scrollbar";
     * options.scrollbarContainerId = "scrollbar-container";
     * options.scrollbarContainerClass = "scrollbar-container";
     * options.minHeight = 8;
     *
     * scrollBar = new ScrollBar(scrollList, parent, options);
     */

    var ScrollBar = function(scrollList, parent, options) {
        var offset;
        var that = this;

        if (!scrollList) {
            throw new Error('ScrollBar#ScrollBar: scrollList is required');
        }
        else {
            this._scrollList = scrollList;
        }

        if (!parent) {
            throw new Error('ScrollBar#ScrollBar: parent is required.');
        }
        else {
            this._parent = parent;
        }

        this._options = options;

        this._layout = scrollList.getLayout();

        this._TOTAL_ITEMS = scrollList.getItemSizeCollection ? scrollList.getItemSizeCollection()._items.length :
                            scrollList.getItemMetadata().length;

        this._viewportHeight = this._layout.getVisiblePosition().bottom - this._layout.getVisiblePosition().top;

        this._virtualHeight = this._layout.getSize().height - this._viewportHeight;

        this._scrollableVirtualHeight = this._layout.getSize().height;

        this._listMap = this._scrollList.getListMap();

        this._setUpDOM();

        this._availableScrollbarHeight = this._viewportHeight - this._scrollbarHeight;

        // Set scrollbarScrolling to initially false
        this._scrollbarScrolling = false;

        this._clickOffset = null;

        // Set the initial scale
        this._scale = this._listMap.getCurrentTransformState().scale;

        // Get the initial position, in case it's not at 0, and set the scrollbar position
        requestAnimFrame(function() {
            that._placeScrollBar(that, that._elements.scrollbar);
        });

        // Match the scroll bar positioning to the users scrolling
        this._listMap.onTranslationChanged(function() {
            if (that._scrollbarScrolling) {
                return;
            }
            requestAnimFrame(function() {
                that._placeScrollBar();
            });
        });

        // Make necessary adjustments when the users zooms in or out
        this._listMap.onScaleChanged(function() {
            that._adjustScale();
            that._placeScrollBar();
        });

        this._scrollList.onItemsInserted(function() {
            that._TOTAL_ITEMS = scrollList.getItemSizeCollection()._items.length;
            that._adjustScale();
            that._placeScrollBar();
        });

        // Make adjustments when the scrollList is resized
        this._scrollList.onInteraction(function(scrollList, args) {
            if (args.event.type === EventTypes.RESIZE) {
                that._resize = true;
            }

            if (args.event.type === EventTypes.RELEASE && that._resize === true) {
                that._adjustScale();
                that._resize = false;
            }
        });

        // Attach handlers for scrolling the ScrollBar
        this._elements.scrollbar.addEventListener('mousedown', function(event) {
            offset = that._elements.scrollbar.offsetTop + that._elements.scrollbarContainer.offsetTop;
            that._clickOffset = event.clientY - offset + that._elements.scrollbarContainer.offsetTop;
            that._scrollbarScrolling = true;

            that._mouseupHandler = function() {
                that._stopUpdatingScrollbar();
            };

            that._mousemoveHandler = function(e) {
                that._updateScrollBar(e, that._clickOffset);
            };

            document.addEventListener('mousemove', that._mousemoveHandler);

            document.addEventListener('mouseup', that._mouseupHandler);
        });

    };

    ScrollBar.prototype = {

        //---------------------------------------------------------
        // Public methods
        //---------------------------------------------------------

        /**
         * Destruct the ScrollBar created HTML elements
         * @method ScrollBar#dispose
         */
        dispose: function() {
            this._elements.scrollbarContainer.removeChild(this._elements.scrollbar);
            this._parent.removeChild(this._elements.scrollbarContainer);
        },

        //---------------------------------------------------------
        // Private methods
        //---------------------------------------------------------

        /**
         * Initialize the HTML elements used by this instance of ScrollBar
         * @private
         */
        _setUpDOM: function() {
            // Create the scrollbar's container
            var scrollbarContainerEL = document.createElement('div');
            var scrollbarEL = document.createElement('div');

            // Set the given classes and ids scrollbar and it's container
            if (this._options.scrollbarId) {
                scrollbarEL.setAttribute('id', this._options.scrollbarId);
            }
            if (this._options.scrollbarClass) {
                scrollbarEL.className += ' ' + this._options.scrollbarClass;
            }
            if (this._options.scrollbarContainerId) {
                scrollbarContainerEL.setAttribute('id', this._options.scrollbarContainerId);
            }
            if (this._options.scrollbarContainerClass) {
                scrollbarContainerEL.className += ' ' + this._options.scrollbarContainerClass;
            }

            // Append the scrollbar and it's parent container to the given parent element
            scrollbarContainerEL.appendChild(scrollbarEL);
            this._parent.appendChild(scrollbarContainerEL);

            this._elements = { scrollbar: scrollbarEL, scrollbarContainer: scrollbarContainerEL };

            this._adjustScale();

            // Set the container height to the viewport height
            scrollbarContainerEL.style.height = this._layout.getViewportSize().height + 'px';
            // Set the scrollbar height
            scrollbarEL.style.height = this._scrollbarHeight + 'px';
        },

        /**
         * Position the scrollbar based on the current position of the ScrollList
         */
        _placeScrollBar: function() {
            var currentPosition = this._layout.getVisiblePosition().top;
            var translatedPosition = this._availableScrollbarHeight / this._virtualHeight * currentPosition;
            this._elements.scrollbar.style.top = translatedPosition + 'px';
        },

        /**
         * Position the scrollbar based on the position of a click event
         */
        _updateScrollBar: function(event, clickOffset) {
            // Don't go past the window bounds
            var scrollbarPos = Math.max(0, event.clientY - clickOffset);
            scrollbarPos = Math.min(scrollbarPos, this._availableScrollbarHeight);
            this._elements.scrollbar.style.top = scrollbarPos + 'px';

            // Use the ratio of scrollbar position inside the scrolling area to calculate
            // the current item we should be interested in.
            var positionOfInterest = (scrollbarPos / (this._viewportHeight - this._scrollbarHeight)) * (this._virtualHeight * this._scale);

            // Ensure that positionOfInterest isn't undefined.
            if (!positionOfInterest) {
                positionOfInterest = 0;
            }

            var currentState = this._listMap.getCurrentTransformState();
            var x = currentState.translateX;

            this._listMap.transform({
                x: x,
                y: -positionOfInterest,
                scale: this._scale
            });

            this._scrollList.render();
        },

        /**
         * Remove the event listeners that update the scrollbar from the document
         */
        _stopUpdatingScrollbar: function() {
            this._clickOffset = undefined;
            document.removeEventListener('mousemove', this._mousemoveHandler);
            this._scrollbarScrolling = false;
            this._removeDocumentEventWatching(this);
        },

        /**
         * Remove the mouseup listener from the document
         */
        _removeDocumentEventWatching: function() {
            document.removeEventListener('mouseup', this._mouseupHandler);
        },

        /**
         * Calculate the scroll bar height based on the viewport height and the scaled virtual height
         */
        _calculateScrollBarHeight: function() {
            // Calculate the size of the scrollbar depending on the virtual height
            // The scrollbar shouldn't be shorter than MIN_HEIGHT
            var MIN_HEIGHT = this._options.minHeight || 8;
            var height = Math.max(MIN_HEIGHT, (this._viewportHeight / this._scrollableVirtualHeight) * this._layout.getViewportSize().height);

            return height;
        },

        /**
         * Scale the virtual height and re-calculate the scroll bar height
         */
        _adjustScale: function() {
            this._scale = this._listMap.getCurrentTransformState().scale;
            this._viewportHeight = this._layout.getVisiblePosition().bottom - this._layout.getVisiblePosition().top;
            this._virtualHeight = this._layout.getSize().height - this._viewportHeight;
            this._scrollableVirtualHeight = this._layout.getSize().height;
            this._scrollbarHeight = this._calculateScrollBarHeight();
            this._elements.scrollbar.style.height = this._scrollbarHeight + 'px';
            this._elements.scrollbarContainer.style.height = this._layout.getViewportSize().height + 'px';
            this._availableScrollbarHeight = this._layout.getViewportSize().height - this._scrollbarHeight;
        }

    };

    return ScrollBar;

});
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
(function(cloudStack) {
  cloudStack.sections.events = {
    title: 'label.menu.events',
    id: 'events',
    sectionSelect: {
      preFilter: function(args) {
        if(isAdmin())
          return ["events", "alerts"];
        else
          return ["events"];
      },
      label: 'label.select-view'
    },
    sections: {
      events: {
        type: 'select',
        title: 'label.menu.events',
        listView: {
          id: 'events',
          label: 'label.menu.events',
          fields: {
            description: { label: 'label.description' },
            domain: { label: 'label.domain' },
						account: { label: 'label.account' },
            created: { label: 'label.date', converter: cloudStack.converters.toLocalDate }
          },
          dataProvider: function(args) {
						var array1 = [];
						if(args.filterBy != null) {
							if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) {
								switch(args.filterBy.search.by) {
								case "name":
									if(args.filterBy.search.value.length > 0)
										array1.push("&keyword=" + args.filterBy.search.value);
									break;
								}
							}
						}

            $.ajax({
              url: createURL("listEvents&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
              dataType: "json",
              async: true,
              success: function(json) {
                var items = json.listeventsresponse.event;
                args.response.success({data:items});
              }
            });
          },
					detailView: {
            name: 'label.details',
            tabs: {
              details: {
                title: 'label.details',
                fields: [
                  {
									  description: { label: 'label.description' },
										state: { label: 'label.state' },
									  level: { label: 'label.level' },
                    type: { label: 'label.type' },
										domain: { label: 'label.domain' },
										account: { label: 'label.account' },
										username: { label: 'label.initiated.by' },
                    created: { label: 'label.date', converter: cloudStack.converters.toLocalDate },
										id: { label: 'label.id' }
                  }
                ],
                dataProvider: function(args) {
									$.ajax({
										url: createURL("listEvents&id=" + args.context.events[0].id),
										dataType: "json",
										async: true,
										success: function(json) {
											var item = json.listeventsresponse.event[0];
											args.response.success({data: item});
										}
									});
								}
              }
            }
          }
        }
      },
      alerts: {
        type: 'select',
        title: 'label.menu.alerts',
        listView: {
          id: 'alerts',
          label: 'label.menu.alerts',
          fields: {
            description: { label: 'label.description' },
            sent: { label: 'label.date', converter: cloudStack.converters.toLocalDate }
          },
          dataProvider: function(args) {
					  var array1 = [];
						if(args.filterBy != null) {
							if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) {
								switch(args.filterBy.search.by) {
								case "name":
									if(args.filterBy.search.value.length > 0)
										array1.push("&keyword=" + args.filterBy.search.value);
									break;
								}
							}
						}
            $.ajax({
              url: createURL("listAlerts&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
              dataType: "json",
              async: true,
              success: function(json) {
                var items = json.listalertsresponse.alert;
                args.response.success({data:items});
              }
            });
          },
          detailView: {
            name: 'Alert details',
            tabs: {
              details: {
                title: 'label.details',
                fields: [
                  {
                    id: { label: 'ID' },
                    description: { label: 'label.description' },
                    sent: { label: 'label.date', converter: cloudStack.converters.toLocalDate }
                  }
                ],
                dataProvider: function(args) {
									$.ajax({
										url: createURL("listAlerts&id=" + args.context.alerts[0].id),
										dataType: "json",
										async: true,
										success: function(json) {
											var item = json.listalertsresponse.alert[0];
											args.response.success({data: item});
										}
									});
								}
              }
            }
          }
        }
      }
    }
  };
})(cloudStack);
<commit_msg>cloudstack UI - add advanced search on Event page.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
(function(cloudStack) {
  cloudStack.sections.events = {
    title: 'label.menu.events',
    id: 'events',
    sectionSelect: {
      preFilter: function(args) {
        if(isAdmin())
          return ["events", "alerts"];
        else
          return ["events"];
      },
      label: 'label.select-view'
    },
    sections: {
      events: {
        type: 'select',
        title: 'label.menu.events',
        listView: {
          id: 'events',
          label: 'label.menu.events',
          fields: {
            description: { label: 'label.description' },
						level: { label: 'label.level' },
            domain: { label: 'label.domain' },
						account: { label: 'label.account' },
            created: { label: 'label.date', converter: cloudStack.converters.toLocalDate }
          },

					advSearchFields: {
            level: {
						  label: 'label.level',
							select: function(args) {
							  args.response.success({
									data: [
									  {id: '', description: ''},
									  {id: 'INFO', description: 'INFO'},
										{id: 'WARN', description: 'WARN'},
										{id: 'ERROR', description: 'ERROR'}
									]
								});
							}
						},
						domainid: {
							label: 'Domain',
							select: function(args) {
								$.ajax({
									url: createURL('listDomains'),
									data: {
										listAll: true,
										details: 'min'
									},
									success: function(json) {
										var array1 = [{id: '', description: ''}];
										var domains = json.listdomainsresponse.domain;
										if(domains != null && domains.length > 0) {
											for(var i = 0; i < domains.length; i++) {
												array1.push({id: domains[i].id, description: domains[i].path});
											}
										}
										args.response.success({
											data: array1
										});
									}
								});
							},
							isHidden: function(args) {
								if(isAdmin() || isDomainAdmin())
									return false;
								else
									return true;
							}
						},
						account: {
							label: 'Account',
							isHidden: function(args) {
								if(isAdmin() || isDomainAdmin())
									return false;
								else
									return true;
							}
						}
					},

          dataProvider: function(args) {
						var data = {};
						listViewDataProvider(args, data);

            $.ajax({
              url: createURL('listEvents'),
              data: data,
              success: function(json) {
                var items = json.listeventsresponse.event;
                args.response.success({data:items});
              }
            });
          },
					detailView: {
            name: 'label.details',
            tabs: {
              details: {
                title: 'label.details',
                fields: [
                  {
									  description: { label: 'label.description' },
										state: { label: 'label.state' },
									  level: { label: 'label.level' },
                    type: { label: 'label.type' },
										domain: { label: 'label.domain' },
										account: { label: 'label.account' },
										username: { label: 'label.initiated.by' },
                    created: { label: 'label.date', converter: cloudStack.converters.toLocalDate },
										id: { label: 'label.id' }
                  }
                ],
                dataProvider: function(args) {
									$.ajax({
										url: createURL("listEvents&id=" + args.context.events[0].id),
										dataType: "json",
										async: true,
										success: function(json) {
											var item = json.listeventsresponse.event[0];
											args.response.success({data: item});
										}
									});
								}
              }
            }
          }
        }
      },
      alerts: {
        type: 'select',
        title: 'label.menu.alerts',
        listView: {
          id: 'alerts',
          label: 'label.menu.alerts',
          fields: {
            description: { label: 'label.description' },
            sent: { label: 'label.date', converter: cloudStack.converters.toLocalDate }
          },
          dataProvider: function(args) {
					  var array1 = [];
						if(args.filterBy != null) {
							if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) {
								switch(args.filterBy.search.by) {
								case "name":
									if(args.filterBy.search.value.length > 0)
										array1.push("&keyword=" + args.filterBy.search.value);
									break;
								}
							}
						}
            $.ajax({
              url: createURL("listAlerts&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
              dataType: "json",
              async: true,
              success: function(json) {
                var items = json.listalertsresponse.alert;
                args.response.success({data:items});
              }
            });
          },
          detailView: {
            name: 'Alert details',
            tabs: {
              details: {
                title: 'label.details',
                fields: [
                  {
                    id: { label: 'ID' },
                    description: { label: 'label.description' },
                    sent: { label: 'label.date', converter: cloudStack.converters.toLocalDate }
                  }
                ],
                dataProvider: function(args) {
									$.ajax({
										url: createURL("listAlerts&id=" + args.context.alerts[0].id),
										dataType: "json",
										async: true,
										success: function(json) {
											var item = json.listalertsresponse.alert[0];
											args.response.success({data: item});
										}
									});
								}
              }
            }
          }
        }
      }
    }
  };
})(cloudStack);
<|endoftext|>


<commit_before>'use strict';

angular.module('baikalApp.controllers', ['ngRoute'])

.controller('HeaderCtrl', ['$scope', '$translate', '$routeParams', function($scope, $translate, $routeParams) {
	if ($translate.use() == 'ru') {
    	$scope.other_lang = 'en';
    } else {
    	$scope.other_lang = 'ru';
    }
	$scope.languageChange = function () {
	    $translate.use($scope.other_lang);
	    if ($scope.other_lang == 'ru') {
	    	$scope.other_lang = 'en';
	    } else {
	    	$scope.other_lang = 'ru';
	    }
	};
}])

.controller('MusicCtrl', ['$scope', 'Music', function($scope, Music) {
	$scope.music = Music;
	$scope.music_state = Music.state;
	$scope.music_current = Music.current;
	$scope.$watchCollection(function() { return [Music.state, Music.current]; }, function (newVal, oldVal) {
		console.log(newVal);
		if(newVal) {
			$scope.music_state = newVal[0];
			$scope.music_current = newVal[1];
		}
	});
	$scope.logState = function() {
		console.log(Music.state);
		Music.state = "test";
	}
}])

.controller('PostlistCtrl', ['$scope', '$routeParams', '$translate', 'Post', 'Category', function($scope, $routeParams, $translate, Post, Category) {
	$scope.categories = Category.get(function(categories) {
		$scope.category = categories[$routeParams.category+'_'+$translate.use()];
	});
	Post.query({pid: $routeParams.category, cid: $routeParams.category}, function(posts) {
		for (var i = posts.length - 1; i >= 0; i--) {
			if (!posts[i].link) {
				posts[i].link = "#/post/"+$routeParams.category+"/"+posts[i].id;
			}
		};
		$scope.posts = posts;
	});
}])

.controller('PostviewCtrl', ['$scope', '$routeParams', 'Post', function($scope, $routeParams, Post) {
	$scope.post = Post.get({pid: $routeParams.pid, cid: $routeParams.cid});
}])

.controller('ContactsCtrl', ['$scope', 'Post', '$translate', function($scope, Post, $translate) {

}])

.controller('LeagueCtrl', ['$scope', 'Post', function($scope, Post) {
  $scope.post = Post.get({pid: "league", cid: "league"});
}])

.controller('RecordsCtrl', ['$scope', '$routeParams', 'Media', function($scope, $routeParams, Media) {
	$scope.medias = Media.query({pid: "records"});
	$scope.title = "RECORDS";
}])

.controller('VolunteersCtrl', ['$scope', 'Post', function($scope, Post) {
  $scope.post = Post.get({pid: "volunteers", cid: "volunteers"});
}]);<commit_msg>music<commit_after>'use strict';

angular.module('baikalApp.controllers', ['ngRoute'])

.controller('HeaderCtrl', ['$scope', '$translate', '$routeParams', function($scope, $translate, $routeParams) {
	if ($translate.use() == 'ru') {
    	$scope.other_lang = 'en';
    } else {
    	$scope.other_lang = 'ru';
    }
	$scope.languageChange = function () {
	    $translate.use($scope.other_lang);
	    if ($scope.other_lang == 'ru') {
	    	$scope.other_lang = 'en';
	    } else {
	    	$scope.other_lang = 'ru';
	    }
	};
}])

.controller('MusicCtrl', ['$scope', 'Music', function($scope, Music) {
	$scope.music = Music;
	$scope.music_state = Music.state;
	$scope.music_current = Music.current;
	$scope.$watchCollection(function() { return [Music.state, Music.current]; }, function (newVal, oldVal) {
		console.log(oldVal);
		if(newVal) {
			$scope.music_state = newVal[0];
			$scope.music_current = newVal[1];
		}
	});
	$scope.logState = function() {
		console.log(Music.state);
		Music.state = "test";
	}
}])

.controller('PostlistCtrl', ['$scope', '$routeParams', '$translate', 'Post', 'Category', function($scope, $routeParams, $translate, Post, Category) {
	$scope.categories = Category.get(function(categories) {
		$scope.category = categories[$routeParams.category+'_'+$translate.use()];
	});
	Post.query({pid: $routeParams.category, cid: $routeParams.category}, function(posts) {
		for (var i = posts.length - 1; i >= 0; i--) {
			if (!posts[i].link) {
				posts[i].link = "#/post/"+$routeParams.category+"/"+posts[i].id;
			}
		};
		$scope.posts = posts;
	});
}])

.controller('PostviewCtrl', ['$scope', '$routeParams', 'Post', function($scope, $routeParams, Post) {
	$scope.post = Post.get({pid: $routeParams.pid, cid: $routeParams.cid});
}])

.controller('ContactsCtrl', ['$scope', 'Post', '$translate', function($scope, Post, $translate) {

}])

.controller('LeagueCtrl', ['$scope', 'Post', function($scope, Post) {
  $scope.post = Post.get({pid: "league", cid: "league"});
}])

.controller('RecordsCtrl', ['$scope', '$routeParams', 'Media', function($scope, $routeParams, Media) {
	$scope.medias = Media.query({pid: "records"});
	$scope.title = "RECORDS";
}])

.controller('VolunteersCtrl', ['$scope', 'Post', function($scope, Post) {
  $scope.post = Post.get({pid: "volunteers", cid: "volunteers"});
}]);<|endoftext|>