<commit_before>import { getExternalResources } from '../../../core/util/resource';
import VectorLayer from '../../../layer/VectorLayer';
import OverlayLayerCanvasRenderer from './OverlayLayerCanvasRenderer';
import PointExtent from '../../../geo/PointExtent';
import * as vec3 from '../../../core/util/vec3';
import { now } from '../../../core/util/common';
const TEMP_EXTENT = new PointExtent();
const TEMP_VEC3 = [];
const TEMP_FIXEDEXTENT = new PointExtent();
const PLACEMENT_CENTER = 'center';

/**
 * @classdesc
 * Renderer class based on HTML5 Canvas2D for VectorLayers
 * @protected
 * @memberOf renderer
 * @name VectorLayerCanvasRenderer
 * @extends renderer.OverlaylayerCanvasRenderer
 * @param {VectorLayer} layer - layer to render
 */
class VectorLayerRenderer extends OverlayLayerCanvasRenderer {

    getImageData() {
        //如果不开启geometry event 或者 渲染频率很高 不要取缓存了，因为getImageData是个很昂贵的操作
        if (!this.layer.options['geometryEvents'] || (!this._lastRenderTime) || (now() - this._lastRenderTime) < 32) {
            return null;
        }
        if (!this._imageData) {
            const { width, height } = this.context.canvas;
            this._imageData = this.context.getImageData(0, 0, width, height);
        }
        return this._imageData;
    }

    clearImageData() {
        //每次渲染完成清除缓存的imageData
        delete this._imageData;
        this._lastRenderTime = now();
    }

    checkResources() {
        const resources = super.checkResources.apply(this, arguments);
        let style = this.layer.getStyle();
        if (style) {
            if (!Array.isArray(style)) {
                style = [style];
            }
            style.forEach(s => {
                const res = getExternalResources(s['symbol'], true);
                for (let i = 0, l = res.length; i < l; i++) {
                    if (!this.resources.isResourceLoaded(res[i])) {
                        resources.push(res[i]);
                    }
                }
            });
        }
        return resources;
    }

    needToRedraw() {
        const map = this.getMap();
        if (map.isInteracting() && this.layer.options['enableAltitude']) {
            return true;
        }
        // don't redraw when map is zooming without pitch and layer doesn't have any point symbolizer.
        if (map.isZooming() && !map.isRotating() && !map.getPitch() && !this._hasPoint && this.layer.constructor === VectorLayer) {
            return false;
        }
        return super.needToRedraw();
    }

    /**
     * render layer
     * @param  {Geometry[]} geometries   geometries to render
     * @param  {Boolean} ignorePromise   whether escape step of promise
     */
    draw() {
        if (!this.getMap()) {
            return;
        }
        if (!this.layer.isVisible() || this.layer.isEmpty()) {
            this.clearCanvas();
            this.completeRender();
            return;
        }

        this.prepareCanvas();

        this.drawGeos();

        this.completeRender();
    }

    isBlank() {
        if (!this.context) {
            return false;
        }
        return !this.context.canvas._drawn;
    }

    drawOnInteracting() {
        if (!this._geosToDraw) {
            return;
        }
        this._updateMapStateCache();
        this._updateDisplayExtent();
        const map = this.getMap();
        //refresh geometries on zooming
        const count = this.layer.getCount();
        const res = this.mapStateCache.resolution;
        if (map.isZooming() &&
            map.options['seamlessZoom'] && this._drawnRes !== undefined && res > this._drawnRes * 1.5 &&
            this._geosToDraw.length < count || map.isMoving() || map.isInteracting()) {
            this.prepareToDraw();
            this._batchConversionMarkers(this.mapStateCache.glZoom);
            if (!this._onlyHasPoint) {
                this.forEachGeo(this.checkGeo, this);
            }
            this._drawnRes = res;
        }
        this._sortByDistanceToCamera(map.cameraPosition);
        for (let i = 0, l = this._geosToDraw.length; i < l; i++) {
            const geo = this._geosToDraw[i];
            if (!geo._isCheck) {
                if (!geo.isVisible()) {
                    delete geo._cPoint;
                    delete geo._inCurrentView;
                    continue;
                }
            }
            geo._paint(this._displayExtent);
            // https://richardartoul.github.io/jekyll/update/2015/04/26/hidden-classes.html
            // https://juejin.cn/post/6972702293636415519
            this._geosToDraw[i]._cPoint = undefined;
            this._geosToDraw[i]._inCurrentView = undefined;
        }
        this.clearImageData();
    }

    /**
     * Show and render
     * @override
     */
    show() {
        this.layer.forEach(function (geo) {
            geo._repaint();
        });
        super.show.apply(this, arguments);
    }

    forEachGeo(fn, context) {
        this.layer.forEach(fn, context);
    }

    drawGeos() {
        this._updateMapStateCache();
        this._drawnRes = this.mapStateCache.resolution;
        this._updateDisplayExtent();
        this.prepareToDraw();
        this._batchConversionMarkers(this.mapStateCache.glZoom);
        if (!this._onlyHasPoint) {
            this.forEachGeo(this.checkGeo, this);
        }
        this._sortByDistanceToCamera(this.getMap().cameraPosition);
        for (let i = 0, len = this._geosToDraw.length; i < len; i++) {
            this._geosToDraw[i]._paint();
            this._geosToDraw[i]._cPoint = undefined;
            this._geosToDraw[i]._inCurrentView = undefined;
        }
        this.clearImageData();
    }

    prepareToDraw() {
        this._hasPoint = false;
        this._geosToDraw = [];
    }

    checkGeo(geo) {
        //点的话已经在批量处理里判断过了
        if (geo.type === 'Point') {
            if (geo._inCurrentView) {
                this._hasPoint = true;
                geo._isCheck = true;
                this._geosToDraw.push(geo);
            }
            return;
        }
        // LineString ,Polygon,Circle etc
        geo._isCheck = false;
        if (!geo || !geo.isVisible() || !geo.getMap() ||
            !geo.getLayer() || (!geo.getLayer().isCanvasRender())) {
            return;
        }

        const painter = geo._getPainter();
        let inCurrentView = true;
        if (geo._inCurrentView) {
            inCurrentView = true;
        } else if (geo._inCurrentView === false) {
            inCurrentView = false;
        } else {
            const extent2D = painter.get2DExtent(this.resources, TEMP_EXTENT);
            if (!extent2D || !extent2D.intersects(this._displayExtent)) {
                inCurrentView = false;
            }
        }
        if (!inCurrentView) {
            return;
        }
        if (painter.hasPoint()) {
            this._hasPoint = true;
        }
        geo._isCheck = true;
        this._geosToDraw.push(geo);
    }

    onZoomEnd() {
        delete this.canvasExtent2D;
        super.onZoomEnd.apply(this, arguments);
    }

    onRemove() {
        this.forEachGeo(function (g) {
            g.onHide();
        });
        delete this._geosToDraw;
    }

    onGeometryPropertiesChange(param) {
        if (param) {
            this.layer._styleGeometry(param['target']);
        }
        super.onGeometryPropertiesChange(param);
    }

    _updateDisplayExtent() {
        let extent2D = this.canvasExtent2D;
        if (this._maskExtent) {
            if (!this._maskExtent.intersects(extent2D)) {
                this.completeRender();
                return;
            }
            extent2D = extent2D.intersection(this._maskExtent);
        }
        this._displayExtent = extent2D;
    }

    identifyAtPoint(point, options = {}) {
        const geometries = this._geosToDraw;
        if (!geometries) {
            return [];
        }
        return this.layer._hitGeos(geometries, point, options);
    }

    _updateMapStateCache() {
        const map = this.getMap();
        const offset = map._pointToContainerPoint(this.southWest)._add(0, -map.height);
        const resolution = map.getResolution();
        const pitch = map.getPitch();
        const bearing = map.getBearing();
        const glScale = map.getGLScale();
        const glZoom = map.getGLZoom();
        const containerExtent = map.getContainerExtent();
        const _2DExtent = map._get2DExtent();
        const glExtent = map._get2DExtent(glZoom);
        this.mapStateCache = {
            resolution,
            pitch,
            bearing,
            glScale,
            glZoom,
            _2DExtent,
            glExtent,
            containerExtent,
            offset
        };
        return this;
    }

    // Better performance of batch coordinate conversion
    // 优化前 11fps
    // 优化后 15fps
    _batchConversionMarkers(glZoom) {
        const cPoints = [];
        const markers = [];
        const altitudes = [];
        const altitudeCache = {};
        const layer = this.layer;
        const layerOpts = layer.options;
        const layerAltitude = layer.getAltitude ? layer.getAltitude() : 0;
        const isCanvasRender = layer.isCanvasRender();
        this._onlyHasPoint = true;
        //Traverse all Geo
        let idx = 0;
        for (let i = 0, len = this.layer._geoList.length; i < len; i++) {
            const geo = this.layer._geoList[i];
            const type = geo.getType();
            if (type === 'Point') {
                let painter = geo._painter;
                if (!painter) {
                    painter = geo._getPainter();
                }
                const point = painter.getRenderPoints(PLACEMENT_CENTER)[0][0];
                const altitude = layerOpts['enableAltitude'] ? geo.getAltitude() : layerAltitude;
                //减少方法的调用
                if (altitudeCache[altitude] === undefined) {
                    altitudeCache[altitude] = painter.getAltitude();
                }
                cPoints[idx] = point;
                altitudes[idx] = altitudeCache[altitude];
                markers[idx] = geo;
                idx++;
            } else {
                this._onlyHasPoint = false;
            }
        }
        if (idx === 0) {
            return [];
        }
        const map = this.getMap();
        const pts = map._pointsToContainerPoints(cPoints, glZoom, altitudes);
        const containerExtent = map.getContainerExtent();
        const { xmax, ymax, xmin, ymin } = containerExtent;
        const extentCache = {};
        for (let i = 0, len = markers.length; i < len; i++) {
            const geo = markers[i];
            geo._cPoint = pts[i];
            const { x, y } = pts[i];
            //Is the point in view
            geo._inCurrentView = (x >= xmin && y >= ymin && x <= xmax && y <= ymax);
            //不在视野内的，再用fixedExtent 精确判断下
            if (!geo._inCurrentView) {
                const symbolkey = geo._symbolHash;
                let fixedExtent;
                if (symbolkey) {
                    //相同的symbol 不要重复计算
                    fixedExtent = extentCache[symbolkey] = (extentCache[symbolkey] || geo._painter.getFixedExtent());
                } else {
                    fixedExtent = geo._painter.getFixedExtent();
                }
                TEMP_FIXEDEXTENT.set(fixedExtent.xmin, fixedExtent.ymin, fixedExtent.xmax, fixedExtent.ymax);
                TEMP_FIXEDEXTENT._add(pts[i]);
                geo._inCurrentView = TEMP_FIXEDEXTENT.intersects(containerExtent);
            }
            if (geo._inCurrentView) {
                if (!geo.isVisible() || !isCanvasRender) {
                    geo._inCurrentView = false;
                }
                //如果当前图层上只有点，整个checkGeo都不用执行了,这里已经把所有的点都判断了
                if (this._onlyHasPoint && geo._inCurrentView) {
                    this._hasPoint = true;
                    geo._isCheck = true;
                    this._geosToDraw.push(geo);
                }
            }
        }
        return pts;
    }

    _sortByDistanceToCamera(cameraPosition) {
        if (!this.layer.options['sortByDistanceToCamera']) {
            return;
        }
        if (!this._geosToDraw.length) {
            return;
        }
        const map = this.getMap();
        const p = map.distanceToPoint(1000, 0, map.getGLScale()).x;
        const meterScale = p / 1000;
        const placement = 'center';
        this._geosToDraw.sort((a, b) => {
            const type0 = a.getType();
            const type1 = b.getType();
            if (type0 !== 'Point' || type1 !== 'Point') {
                return 0;
            }
            const painter0 = a._painter;
            const painter1 = b._painter;
            if (!painter0 || !painter1) {
                return 0;
            }
            const point0 = painter0.getRenderPoints(placement)[0][0];
            const point1 = painter1.getRenderPoints(placement)[0][0];
            const alt0 = painter0.getAltitude() * meterScale;
            const alt1 = painter1.getAltitude() * meterScale;
            vec3.set(TEMP_VEC3, point0.x, point0.y, alt0);
            const dist0 = vec3.distance(TEMP_VEC3, cameraPosition);
            vec3.set(TEMP_VEC3, point1.x, point1.y, alt1);
            const dist1 = vec3.distance(TEMP_VEC3, cameraPosition);
            return dist1 - dist0;
        });
    }
}

VectorLayer.registerRenderer('canvas', VectorLayerRenderer);

export default VectorLayerRenderer;
<commit_msg>restore forEachGeo in VectorLayerCanvasRenderer (#1442)<commit_after>import { getExternalResources } from '../../../core/util/resource';
import VectorLayer from '../../../layer/VectorLayer';
import OverlayLayerCanvasRenderer from './OverlayLayerCanvasRenderer';
import PointExtent from '../../../geo/PointExtent';
import * as vec3 from '../../../core/util/vec3';
import { now } from '../../../core/util/common';
const TEMP_EXTENT = new PointExtent();
const TEMP_VEC3 = [];
const TEMP_FIXEDEXTENT = new PointExtent();
const PLACEMENT_CENTER = 'center';

/**
 * @classdesc
 * Renderer class based on HTML5 Canvas2D for VectorLayers
 * @protected
 * @memberOf renderer
 * @name VectorLayerCanvasRenderer
 * @extends renderer.OverlaylayerCanvasRenderer
 * @param {VectorLayer} layer - layer to render
 */
class VectorLayerRenderer extends OverlayLayerCanvasRenderer {

    getImageData() {
        //如果不开启geometry event 或者 渲染频率很高 不要取缓存了，因为getImageData是个很昂贵的操作
        if (!this.layer.options['geometryEvents'] || (!this._lastRenderTime) || (now() - this._lastRenderTime) < 32) {
            return null;
        }
        if (!this._imageData) {
            const { width, height } = this.context.canvas;
            this._imageData = this.context.getImageData(0, 0, width, height);
        }
        return this._imageData;
    }

    clearImageData() {
        //每次渲染完成清除缓存的imageData
        delete this._imageData;
        this._lastRenderTime = now();
    }

    checkResources() {
        const resources = super.checkResources.apply(this, arguments);
        let style = this.layer.getStyle();
        if (style) {
            if (!Array.isArray(style)) {
                style = [style];
            }
            style.forEach(s => {
                const res = getExternalResources(s['symbol'], true);
                for (let i = 0, l = res.length; i < l; i++) {
                    if (!this.resources.isResourceLoaded(res[i])) {
                        resources.push(res[i]);
                    }
                }
            });
        }
        return resources;
    }

    needToRedraw() {
        const map = this.getMap();
        if (map.isInteracting() && this.layer.options['enableAltitude']) {
            return true;
        }
        // don't redraw when map is zooming without pitch and layer doesn't have any point symbolizer.
        if (map.isZooming() && !map.isRotating() && !map.getPitch() && !this._hasPoint && this.layer.constructor === VectorLayer) {
            return false;
        }
        return super.needToRedraw();
    }

    /**
     * render layer
     * @param  {Geometry[]} geometries   geometries to render
     * @param  {Boolean} ignorePromise   whether escape step of promise
     */
    draw() {
        if (!this.getMap()) {
            return;
        }
        if (!this.layer.isVisible() || this.layer.isEmpty()) {
            this.clearCanvas();
            this.completeRender();
            return;
        }

        this.prepareCanvas();

        this.drawGeos();

        this.completeRender();
    }

    isBlank() {
        if (!this.context) {
            return false;
        }
        return !this.context.canvas._drawn;
    }

    drawOnInteracting() {
        if (!this._geosToDraw) {
            return;
        }
        this._updateMapStateCache();
        this._updateDisplayExtent();
        const map = this.getMap();
        //refresh geometries on zooming
        const count = this.layer.getCount();
        const res = this.mapStateCache.resolution;
        if (map.isZooming() &&
            map.options['seamlessZoom'] && this._drawnRes !== undefined && res > this._drawnRes * 1.5 &&
            this._geosToDraw.length < count || map.isMoving() || map.isInteracting()) {
            this.prepareToDraw();
            this._batchConversionMarkers(this.mapStateCache.glZoom);
            this.forEachGeo(this.checkGeo, this);
            this._drawnRes = res;
        }
        this._sortByDistanceToCamera(map.cameraPosition);
        for (let i = 0, l = this._geosToDraw.length; i < l; i++) {
            const geo = this._geosToDraw[i];
            if (!geo._isCheck) {
                if (!geo.isVisible()) {
                    delete geo._cPoint;
                    delete geo._inCurrentView;
                    continue;
                }
            }
            geo._paint(this._displayExtent);
            // https://richardartoul.github.io/jekyll/update/2015/04/26/hidden-classes.html
            // https://juejin.cn/post/6972702293636415519
            this._geosToDraw[i]._cPoint = undefined;
            this._geosToDraw[i]._inCurrentView = undefined;
        }
        this.clearImageData();
    }

    /**
     * Show and render
     * @override
     */
    show() {
        this.layer.forEach(function (geo) {
            geo._repaint();
        });
        super.show.apply(this, arguments);
    }

    forEachGeo(fn, context) {
        this.layer.forEach(fn, context);
    }

    drawGeos() {
        this._updateMapStateCache();
        this._drawnRes = this.mapStateCache.resolution;
        this._updateDisplayExtent();
        this.prepareToDraw();
        this._batchConversionMarkers(this.mapStateCache.glZoom);
        this.forEachGeo(this.checkGeo, this);
        this._sortByDistanceToCamera(this.getMap().cameraPosition);
        for (let i = 0, len = this._geosToDraw.length; i < len; i++) {
            this._geosToDraw[i]._paint();
            this._geosToDraw[i]._cPoint = undefined;
            this._geosToDraw[i]._inCurrentView = undefined;
        }
        this.clearImageData();
    }

    prepareToDraw() {
        this._hasPoint = false;
        this._geosToDraw = [];
    }

    checkGeo(geo) {
        //点的话已经在批量处理里判断过了
        if (geo.type === 'Point') {
            if (geo._inCurrentView) {
                this._hasPoint = true;
                geo._isCheck = true;
                this._geosToDraw.push(geo);
            }
            return;
        }
        // LineString ,Polygon,Circle etc
        geo._isCheck = false;
        if (!geo || !geo.isVisible() || !geo.getMap() ||
            !geo.getLayer() || (!geo.getLayer().isCanvasRender())) {
            return;
        }

        const painter = geo._getPainter();
        let inCurrentView = true;
        if (geo._inCurrentView) {
            inCurrentView = true;
        } else if (geo._inCurrentView === false) {
            inCurrentView = false;
        } else {
            const extent2D = painter.get2DExtent(this.resources, TEMP_EXTENT);
            if (!extent2D || !extent2D.intersects(this._displayExtent)) {
                inCurrentView = false;
            }
        }
        if (!inCurrentView) {
            return;
        }
        if (painter.hasPoint()) {
            this._hasPoint = true;
        }
        geo._isCheck = true;
        this._geosToDraw.push(geo);
    }

    onZoomEnd() {
        delete this.canvasExtent2D;
        super.onZoomEnd.apply(this, arguments);
    }

    onRemove() {
        this.forEachGeo(function (g) {
            g.onHide();
        });
        delete this._geosToDraw;
    }

    onGeometryPropertiesChange(param) {
        if (param) {
            this.layer._styleGeometry(param['target']);
        }
        super.onGeometryPropertiesChange(param);
    }

    _updateDisplayExtent() {
        let extent2D = this.canvasExtent2D;
        if (this._maskExtent) {
            if (!this._maskExtent.intersects(extent2D)) {
                this.completeRender();
                return;
            }
            extent2D = extent2D.intersection(this._maskExtent);
        }
        this._displayExtent = extent2D;
    }

    identifyAtPoint(point, options = {}) {
        const geometries = this._geosToDraw;
        if (!geometries) {
            return [];
        }
        return this.layer._hitGeos(geometries, point, options);
    }

    _updateMapStateCache() {
        const map = this.getMap();
        const offset = map._pointToContainerPoint(this.southWest)._add(0, -map.height);
        const resolution = map.getResolution();
        const pitch = map.getPitch();
        const bearing = map.getBearing();
        const glScale = map.getGLScale();
        const glZoom = map.getGLZoom();
        const containerExtent = map.getContainerExtent();
        const _2DExtent = map._get2DExtent();
        const glExtent = map._get2DExtent(glZoom);
        this.mapStateCache = {
            resolution,
            pitch,
            bearing,
            glScale,
            glZoom,
            _2DExtent,
            glExtent,
            containerExtent,
            offset
        };
        return this;
    }

    // Better performance of batch coordinate conversion
    // 优化前 11fps
    // 优化后 15fps
    _batchConversionMarkers(glZoom) {
        const cPoints = [];
        const markers = [];
        const altitudes = [];
        const altitudeCache = {};
        const layer = this.layer;
        const layerOpts = layer.options;
        const layerAltitude = layer.getAltitude ? layer.getAltitude() : 0;
        const isCanvasRender = layer.isCanvasRender();
        this._onlyHasPoint = true;
        //Traverse all Geo
        let idx = 0;
        for (let i = 0, len = this.layer._geoList.length; i < len; i++) {
            const geo = this.layer._geoList[i];
            const type = geo.getType();
            if (type === 'Point') {
                let painter = geo._painter;
                if (!painter) {
                    painter = geo._getPainter();
                }
                const point = painter.getRenderPoints(PLACEMENT_CENTER)[0][0];
                const altitude = layerOpts['enableAltitude'] ? geo.getAltitude() : layerAltitude;
                //减少方法的调用
                if (altitudeCache[altitude] === undefined) {
                    altitudeCache[altitude] = painter.getAltitude();
                }
                cPoints[idx] = point;
                altitudes[idx] = altitudeCache[altitude];
                markers[idx] = geo;
                idx++;
            } else {
                this._onlyHasPoint = false;
            }
        }
        if (idx === 0) {
            return [];
        }
        const map = this.getMap();
        const pts = map._pointsToContainerPoints(cPoints, glZoom, altitudes);
        const containerExtent = map.getContainerExtent();
        const { xmax, ymax, xmin, ymin } = containerExtent;
        const extentCache = {};
        for (let i = 0, len = markers.length; i < len; i++) {
            const geo = markers[i];
            geo._cPoint = pts[i];
            const { x, y } = pts[i];
            //Is the point in view
            geo._inCurrentView = (x >= xmin && y >= ymin && x <= xmax && y <= ymax);
            //不在视野内的，再用fixedExtent 精确判断下
            if (!geo._inCurrentView) {
                const symbolkey = geo._symbolHash;
                let fixedExtent;
                if (symbolkey) {
                    //相同的symbol 不要重复计算
                    fixedExtent = extentCache[symbolkey] = (extentCache[symbolkey] || geo._painter.getFixedExtent());
                } else {
                    fixedExtent = geo._painter.getFixedExtent();
                }
                TEMP_FIXEDEXTENT.set(fixedExtent.xmin, fixedExtent.ymin, fixedExtent.xmax, fixedExtent.ymax);
                TEMP_FIXEDEXTENT._add(pts[i]);
                geo._inCurrentView = TEMP_FIXEDEXTENT.intersects(containerExtent);
            }
            if (geo._inCurrentView) {
                if (!geo.isVisible() || !isCanvasRender) {
                    geo._inCurrentView = false;
                }
            }
        }
        return pts;
    }

    _sortByDistanceToCamera(cameraPosition) {
        if (!this.layer.options['sortByDistanceToCamera']) {
            return;
        }
        if (!this._geosToDraw.length) {
            return;
        }
        const map = this.getMap();
        const p = map.distanceToPoint(1000, 0, map.getGLScale()).x;
        const meterScale = p / 1000;
        const placement = 'center';
        this._geosToDraw.sort((a, b) => {
            const type0 = a.getType();
            const type1 = b.getType();
            if (type0 !== 'Point' || type1 !== 'Point') {
                return 0;
            }
            const painter0 = a._painter;
            const painter1 = b._painter;
            if (!painter0 || !painter1) {
                return 0;
            }
            const point0 = painter0.getRenderPoints(placement)[0][0];
            const point1 = painter1.getRenderPoints(placement)[0][0];
            const alt0 = painter0.getAltitude() * meterScale;
            const alt1 = painter1.getAltitude() * meterScale;
            vec3.set(TEMP_VEC3, point0.x, point0.y, alt0);
            const dist0 = vec3.distance(TEMP_VEC3, cameraPosition);
            vec3.set(TEMP_VEC3, point1.x, point1.y, alt1);
            const dist1 = vec3.distance(TEMP_VEC3, cameraPosition);
            return dist1 - dist0;
        });
    }
}

VectorLayer.registerRenderer('canvas', VectorLayerRenderer);

export default VectorLayerRenderer;
<|endoftext|>


<commit_before>'use strict';

angular.module('doc.client', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/client', {
    templateUrl: 'client/client.html',
    controller: 'ClientCtrl'
  });
  $routeProvider.when('/', {
    templateUrl: 'client/client.html',
    controller: 'ClientCtrl'
  });
}])

.controller('ClientCtrl', ["$scope", "queue", "search", "playback", function($scope, queue, search, playback) {

	/* Definitions */

	$scope.queue = [];
	$scope.currentlyPlaying = null;
	$scope.chk = {
		recent: false,
		related: false,
		relatedToRecent: false
	}
	$scope.showControls = false;
	$scope.playbackState = false;
	$scope.magicModeState = false;
	$scope.playbackStateIcon = "fa fa-play fa-2x";
	$scope.playbackStateMessage = "Resume Playback";
	$scope.playbackMaxLengthState = true;
	$scope.magicModeState = false;

	/* Queue */

	$scope.updateQueue = function (){
		queue.get(function(response){
			$scope.queue = response.queue;
			$scope.currentlyPlaying = response.current;
		});
	}

	/* Skip Current Song */
	$scope.skipSong = function(){
		playback.skip();
	}

	/* Related */

	$scope.relatedCheckboxClicked = function(){
		playback.setRelated($scope.chk.related, function(resp){
			$scope.chk.related = resp.state;
		});
	}

	$scope.updateRelatedCheckbox = function(){
		playback.getRelated(function(resp){
			$scope.chk.related = resp.state;
		})
	}

	$scope.clearRecent = function(){
		playback.clearRecentList();
	}

	/* Related To Recent */

	$scope.relatedToRecentCheckboxClicked = function(){
		playback.setRelatedToRecent($scope.chk.relatedToRecent, function(resp){
			$scope.chk.relatedToRecent = resp.state;
		});
	}

	$scope.updateRelatedToRecentCheckbox = function(){
		playback.getRelatedToRecent(function(resp){
			$scope.chk.relatedToRecent = resp.state;
		});
	};

	/* Recent */

	$scope.recentCheckboxClicked = function(){
		playback.setRecent($scope.chk.recent, function(resp){
			$scope.recentCheckbox = resp.state;
		});
	};

	$scope.updateRecentCheckbox = function(){
		playback.getRecent(function(resp){
			$scope.chk.recent = resp.state;
		});
	};

	/* Playback State */

	$scope.playbackStateButtonClicked = function(){
		$scope.playbackState = !$scope.playbackState
		playback.setState($scope.playbackState, function(resp){
			$scope.playbackState = resp.state;

			if($scope.playbackState){
				$scope.playbackStateIcon = "fa fa-pause fa-2x";
				$scope.playbackStateMessage = "Pause Playback";
			}
			else{
				$scope.playbackStateIcon = "fa fa-play fa-2x";
				$scope.playbackStateMessage = "Resume Playback";
			}
		});
	};

	$scope.updatePlaybackState = function(){
		if($scope.showControls){
			playback.getState(function(resp){
				$scope.playbackState = resp.state;

				if($scope.playbackState){
					$scope.playbackStateIcon = "fa fa-pause fa-2x";
					$scope.playbackStateMessage = "Pause Playback fa-2x";
				}
				else{
					$scope.playbackStateIcon = "fa fa-play";
					$scope.playbackStateMessage = "Resume Playback";
				}
			})
		}
	};

	/* Search Song */

	$scope.searchSong = function(){
		search($scope.url, function(results){
			$scope.searchResults = results;
		})
	};

	$scope.requestSong = function(ytid){
		for(var i=0; i < $scope.searchResults.length; i++){
			if($scope.searchResults[i].yt === ytid){
				var song = $scope.searchResults[i];
				queue.add({
					url: song.url,
					yt: song.yt,
					title: song.title,
					uploader: song.uploader,
					description: song.description,
					thumbnail: song.thumbnail
				}, function(res){
					updateQueue();
				});
				alert("Song Requested\n" + song.title);
				break;
			}
		}
	};

	/* Hide/Show Controls */

	$scope.toggleControls = function(){
		$scope.showControls = !$scope.showControls;
	};

	/* Magic Mode */
	$scope.toggleMagicMode = function(){
		$scope.chk.related = !$scope.chk.related;
		$scope.chk.relatedToRecent = !$scope.chk.relatedToRecent;
		$scope.relatedCheckboxClicked();
		$scope.relatedToRecentCheckboxClicked();
		$scope.magicModeState = !$scope.magicModeState;
	}

	$scope.updateMagicModeState = function(){
		$scope.magicModeState =($scope.chk.related && $scope.chk.relatedToRecent);
	}

	/* Easter Eggs */
	$scope.easterEgg = function(){
		alert("It looked unbalanced without the one on the left...");
	}

	var egg = new Egg("up,up,down,down,left,right,left,right,b,a", function() {
		playback.toggleMaxLengthState(function(resp){
			$scope.playbackMaxLengthState = resp.state;
		});
	}).listen();

	$scope.updateMaxLength = function(){
		playback.getMaxLengthState(function(resp){
			$scope.playbackMaxLengthState = resp.state;
		});
	};

	/* UI REST Data Update Timer */

	$scope.restUpdate = function(){
		$scope.updateQueue();
		$scope.updateRelatedCheckbox();
		$scope.updateRelatedToRecentCheckbox();
		$scope.updateRecentCheckbox();
		$scope.updatePlaybackState();
		$scope.updateMaxLength();
		$scope.updateMagicModeState();
	};

	$scope.restUpdate();
	$scope.updateTimer = setInterval($scope.restUpdate, 10000);

}]);
<commit_msg>fix magic mode update issue<commit_after>'use strict';

angular.module('doc.client', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/client', {
    templateUrl: 'client/client.html',
    controller: 'ClientCtrl'
  });
  $routeProvider.when('/', {
    templateUrl: 'client/client.html',
    controller: 'ClientCtrl'
  });
}])

.controller('ClientCtrl', ["$scope", "queue", "search", "playback", function($scope, queue, search, playback) {

	/* Definitions */

	$scope.queue = [];
	$scope.currentlyPlaying = null;
	$scope.chk = {
		recent: false,
		related: false,
		relatedToRecent: false
	}
	$scope.showControls = false;
	$scope.playbackState = false;
	$scope.magicModeState = false;
	$scope.playbackStateIcon = "fa fa-play fa-2x";
	$scope.playbackStateMessage = "Resume Playback";
	$scope.playbackMaxLengthState = true;
	$scope.magicModeState = false;

	/* Queue */

	$scope.updateQueue = function (){
		queue.get(function(response){
			$scope.queue = response.queue;
			$scope.currentlyPlaying = response.current;
		});
	}

	/* Skip Current Song */
	$scope.skipSong = function(){
		playback.skip();
	}

	/* Related */

	$scope.relatedCheckboxClicked = function(){
		playback.setRelated($scope.chk.related, function(resp){
			$scope.chk.related = resp.state;
			$scope.updateMagicModeState();
		});
	}

	$scope.updateRelatedCheckbox = function(){
		playback.getRelated(function(resp){
			$scope.chk.related = resp.state;
		})
	}

	$scope.clearRecent = function(){
		playback.clearRecentList();
	}

	/* Related To Recent */

	$scope.relatedToRecentCheckboxClicked = function(){
		playback.setRelatedToRecent($scope.chk.relatedToRecent, function(resp){
			$scope.chk.relatedToRecent = resp.state;
			$scope.updateMagicModeState();
		});
	}

	$scope.updateRelatedToRecentCheckbox = function(){
		playback.getRelatedToRecent(function(resp){
			$scope.chk.relatedToRecent = resp.state;
		});
	};

	/* Recent */

	$scope.recentCheckboxClicked = function(){
		playback.setRecent($scope.chk.recent, function(resp){
			$scope.recentCheckbox = resp.state;
		});
	};

	$scope.updateRecentCheckbox = function(){
		playback.getRecent(function(resp){
			$scope.chk.recent = resp.state;
		});
	};

	/* Playback State */

	$scope.playbackStateButtonClicked = function(){
		$scope.playbackState = !$scope.playbackState
		playback.setState($scope.playbackState, function(resp){
			$scope.playbackState = resp.state;

			if($scope.playbackState){
				$scope.playbackStateIcon = "fa fa-pause fa-2x";
				$scope.playbackStateMessage = "Pause Playback";
			}
			else{
				$scope.playbackStateIcon = "fa fa-play fa-2x";
				$scope.playbackStateMessage = "Resume Playback";
			}
		});
	};

	$scope.updatePlaybackState = function(){
		if($scope.showControls){
			playback.getState(function(resp){
				$scope.playbackState = resp.state;

				if($scope.playbackState){
					$scope.playbackStateIcon = "fa fa-pause fa-2x";
					$scope.playbackStateMessage = "Pause Playback fa-2x";
				}
				else{
					$scope.playbackStateIcon = "fa fa-play";
					$scope.playbackStateMessage = "Resume Playback";
				}
			})
		}
	};

	/* Search Song */

	$scope.searchSong = function(){
		search($scope.url, function(results){
			$scope.searchResults = results;
		})
	};

	$scope.requestSong = function(ytid){
		for(var i=0; i < $scope.searchResults.length; i++){
			if($scope.searchResults[i].yt === ytid){
				var song = $scope.searchResults[i];
				queue.add({
					url: song.url,
					yt: song.yt,
					title: song.title,
					uploader: song.uploader,
					description: song.description,
					thumbnail: song.thumbnail
				}, function(res){
					updateQueue();
				});
				alert("Song Requested\n" + song.title);
				break;
			}
		}
	};

	/* Hide/Show Controls */

	$scope.toggleControls = function(){
		$scope.showControls = !$scope.showControls;
	};

	/* Magic Mode */
	$scope.toggleMagicMode = function(){
		$scope.chk.related = !$scope.chk.related;
		$scope.chk.relatedToRecent = !$scope.chk.relatedToRecent;
		$scope.relatedCheckboxClicked();
		$scope.relatedToRecentCheckboxClicked();
		$scope.magicModeState = !$scope.magicModeState;
	}

	$scope.updateMagicModeState = function(){
		$scope.magicModeState =($scope.chk.related && $scope.chk.relatedToRecent);
	}

	/* Easter Eggs */
	$scope.easterEgg = function(){
		alert("It looked unbalanced without the one on the left...");
	}

	var egg = new Egg("up,up,down,down,left,right,left,right,b,a", function() {
		playback.toggleMaxLengthState(function(resp){
			$scope.playbackMaxLengthState = resp.state;
		});
	}).listen();

	$scope.updateMaxLength = function(){
		playback.getMaxLengthState(function(resp){
			$scope.playbackMaxLengthState = resp.state;
		});
	};

	/* UI REST Data Update Timer */

	$scope.restUpdate = function(){
		$scope.updateQueue();
		$scope.updateRelatedCheckbox();
		$scope.updateRelatedToRecentCheckbox();
		$scope.updateRecentCheckbox();
		$scope.updatePlaybackState();
		$scope.updateMaxLength();
		$scope.updateMagicModeState();
	};

	$scope.restUpdate();
	$scope.updateTimer = setInterval($scope.restUpdate, 10000);

}]);
<|endoftext|>


<commit_before>$(document).ready(function () {

	var owl = $("#owl-demo");

    owl.owlCarousel({
      items : 4, //10 items above 1000px browser width
      itemsDesktop : [1000,5], //5 items between 1000px and 901px
      itemsDesktopSmall : [900,3], // betweem 900px and 601px
      itemsTablet: [600,2], //2 items between 600 and 0
      itemsMobile : false // itemsMobile disabled - inherit from itemsTablet option
    });

    owl.trigger('owl.play',1500); //owl.play event accept autoPlay speed as second parameter

});<commit_msg>0.0.5 Signed-off-by: yegorsss <yegorsss@yandex.ru><commit_after>$(document).ready(function () {

	var owl = $("#owl-demo");

    owl.owlCarousel({
      items : 4, //10 items above 1000px browser width
      itemsDesktop : [1000,5], //5 items between 1000px and 901px
      itemsDesktopSmall : [900,3], // betweem 900px and 601px
      itemsTablet: [600,2], //2 items between 600 and 0
      itemsMobile : false // itemsMobile disabled - inherit from itemsTablet option
    });

    owl.trigger('owl.play',1500); //owl.play event accept autoPlay speed as second parameter
});<|endoftext|>


<commit_before>import Tile from './tile';

export default class Board {
    constructor(el) {
        this.tiles = [];
        this.containers = [];
        this.el = el;
        this.width = 200;
        this.height = 200;
        this.tilesPerRow = 4;
        this.tilesPerCol = 4;
        this.dragTarget = null;
        this.prevTop = 0;
        this.prevLeft = 0;
        this.startX = 0;
        this.startY = 0;
    }

    generateTiles() {
        const tileWidth = this.width / this.tilesPerRow;
        const tileHeight = this.height / this.tilesPerCol;
        for (let row = 0; row < this.tilesPerRow; row++) {
            for (let col = 0; col < this.tilesPerCol; col++) {
                const tile = new Tile(
                    this,
                    col * tileHeight,
                    row * tileWidth,
                    this.width,
                    this.height,
                    col * 20,
                    row * 20,
                    row === 0,
                    row === this.tilesPerRow - 1,
                    col === 0,
                    col === this.tilesPerCol - 1);
                this.tiles.push(tile);
                this.containers.push(tile.container);
            }
        }
    }

    startDrag = (e, container) => {
        e.preventDefault();
        this.dragTarget = container;
        this.startX = e.clientX;
        this.startY = e.clientY;
        this.prevTop = parseInt(this.dragTarget.el.style.top, 10);
        this.prevLeft = parseInt(this.dragTarget.el.style.left, 10);
        this.el.addEventListener('mousemove', this.handleMousemove);
        document.body.addEventListener('mouseleave', this.cancelDrag);
    };

    handleMousemove = (e) => {
        if (this.dragTarget !== null) {
            const newTop = Math.min(Math.max(0, (e.clientY - this.startY) + this.prevTop), this.el.clientHeight - 10);
            const newLeft = Math.min(Math.max(0, (e.clientX - this.startX) + this.prevLeft), this.el.clientWidth - 10);
            this.dragTarget.el.style.top = `${newTop}px`;
            this.dragTarget.el.style.left = `${newLeft}px`;
        }
    };

    cancelDrag = () => {
        this.dragTarget = null;
        this.el.removeEventListener('mousemove', this.handleMousemove);
        document.body.removeEventListener('mouseleave', this.cancelDrag);
    }
}
<commit_msg>Added change to z-index on drag.<commit_after>import Tile from './tile';

export default class Board {
    constructor(el) {
        this.tiles = [];
        this.containers = [];
        this.el = el;
        this.width = 200;
        this.height = 200;
        this.tilesPerRow = 4;
        this.tilesPerCol = 4;
        this.dragTarget = null;
        this.prevTop = 0;
        this.prevLeft = 0;
        this.startX = 0;
        this.startY = 0;
        this.zIndexMax = 0;
    }

    generateTiles() {
        const tileWidth = this.width / this.tilesPerRow;
        const tileHeight = this.height / this.tilesPerCol;
        for (let row = 0; row < this.tilesPerRow; row++) {
            for (let col = 0; col < this.tilesPerCol; col++) {
                const tile = new Tile(
                    this,
                    col * tileHeight,
                    row * tileWidth,
                    this.width,
                    this.height,
                    col * 20,
                    row * 20,
                    row === 0,
                    row === this.tilesPerRow - 1,
                    col === 0,
                    col === this.tilesPerCol - 1);
                this.tiles.push(tile);
                this.containers.push(tile.container);
            }
        }
    }

    startDrag = (e, container) => {
        e.preventDefault();
        this.dragTarget = container;
        this.startX = e.clientX;
        this.startY = e.clientY;
        this.prevTop = parseInt(this.dragTarget.el.style.top, 10);
        this.prevLeft = parseInt(this.dragTarget.el.style.left, 10);
        if (this.zIndexMax === 0 || this.dragTarget.el.style.zIndex < this.zIndexMax) {
            this.zIndexMax += 1;
            this.dragTarget.el.style.zIndex = this.zIndexMax;
        }
        this.el.addEventListener('mousemove', this.handleMousemove);
        document.body.addEventListener('mouseleave', this.cancelDrag);
    };

    handleMousemove = (e) => {
        if (this.dragTarget !== null) {
            const newTop = Math.min(Math.max(0, (e.clientY - this.startY) + this.prevTop), this.el.clientHeight - 10);
            const newLeft = Math.min(Math.max(0, (e.clientX - this.startX) + this.prevLeft), this.el.clientWidth - 10);
            this.dragTarget.el.style.top = `${newTop}px`;
            this.dragTarget.el.style.left = `${newLeft}px`;
        }
    };

    cancelDrag = () => {
        this.dragTarget = null;
        this.el.removeEventListener('mousemove', this.handleMousemove);
        document.body.removeEventListener('mouseleave', this.cancelDrag);
    }
}
<|endoftext|>


<commit_before>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	url = require('url'),
	config = require('@v4fire/core/config/default'),
	concatUrls = require('urlconcat').concat,
	o = require('uniconf/options').option;

module.exports = config.createConfig({dirs: [__dirname, 'client']}, {
	__proto__: config,

	apiURL() {
		return this.api.proxy ? concatUrls(this.api.pathname(), 'api') : this.api.url;
	},

	api: {
		proxy: true,

		url: o('api-url', {
			env: true
		}),

		port: o('port', {
			env: true,
			type: 'number',
			default: 3333,
			validate(value) {
				return Number.isFinite(value) && (value > 0) && (value < 65536);
			}
		}),

		host() {
			return o('host-url', {
				env: true,
				default: `http://localhost:${this.port}/`
			});
		},

		pathname() {
			return o('base-path', {
				env: true,
				default: url.parse(this.host()).pathname || '/'
			});
		},

		schema: {

		}
	},

	build: {
		single: o('single-build', {
			env: true
		}),

		entries: o('entries', {
			env: true,
			short: 'e',
			coerce: (v) => v ? v.split(',') : []
		}),

		fast() {
			const v = o('fast-build', {
				env: true,
				type: 'boolean'
			});

			return v != null ? v : isProd;
		},

		buildGraphFromCache: o('build-graph-from-cache', {
			env: true,
			type: 'boolean'
		})
	},

	webpack: {
		externals: {
			'collection.js': '$C',
			'eventemitter2': 'EventEmitter2',
			'localforage': 'localforage',
			'sugar': 'Sugar',
			'vue': 'Vue',
			'chart.js': 'Chart',
			'ion-sound': 'ion',
			'socket.io-client': 'io',
			'setimmediate': 'setImmediate'
		},

		fatHTML: false,
		devtool: false,

		hashLength() {
			return !isProd || this.fatHTML ? false : 15;
		},

		dataURILimit() {
			return this.fatHTML ? false : 4096;
		},

		output(params) {
			const
				res = this.fatHTML ? '[name]' : '[hash]_[name]';

			if (params) {
				return res.replace(/\[(.*?)]/g, (str, key) => {
					if (params[key] != null) {
						return params[key];
					}

					return '';
				});
			}

			return res;
		},

		assetsJSON() {
			return 'assets.json';
		}
	},

	imageOpts: {
		mozjpeg: {
			progressive: true,
			quality: 65
		},

		optipng: {
			enabled: false,
		},

		pngquant: {
			quality: '65-90',
			speed: 4
		},

		gifsicle: {
			interlaced: false,
		},

		webp: {
			quality: 75
		},

		svgo: {

		}
	},

	html: {
		useShortDoctype: true,
		conservativeCollapse: true,
		removeAttributeQuotes: true,
		removeComments: isProd,
		collapseWhitespace: isProd
	},

	postcss: {

	},

	autoprefixer: {

	},

	uglify: {

	},

	monic() {
		return {
			stylus: {
				flags: {
					'+:*': true
				}
			}
		};
	},

	favicons() {
		return {
			appName: this.appName,
			path: this.src.assets('favicons'),
			background: '#FFF',
			display: 'standalone',
			orientation: 'portrait',
			version: 1.0,
			logging: false
		};
	},

	snakeskin() {
		function ignore(target) {
			target.ignore = true;
			return function () {
				return target.apply(this, arguments);
			};
		}

		const {
			webpack,
			src
		} = this;

		return {
			client: this.extend(super.snakeskin(), {
				adapter: 'ss2vue',
				adapterOptions: {transpiler: true},
				tagFilter: 'tagFilter',
				tagNameFilter: 'tagNameFilter',
				bemFilter: 'bemFilter',
				vars: {
					ignore
				}
			}),

			server: this.extend(super.snakeskin(), {
				vars: {
					fatHTML: webpack.fatHTML,
					hashLength: webpack.hashLength(),
					fileName: webpack.output,
					root: src.cwd(),
					output: src.clientOutput(),
					favicons: this.favicons().path,
					assets: src.assets(),
					lib: src.lib()
				}
			})
		};
	},

	typescript() {
		return {
			client: super.typescript(),
			worker: super.typescript(),
			server: super.typescript()
		};
	},

	css() {
		return {
			minimize: Boolean(isProd || Number(process.env.MINIFY_CSS))
		};
	},

	stylus() {
		return {
			preferPathResolver: 'webpack'
		};
	}
});
<commit_msg>fileName -> outputPattern<commit_after>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	url = require('url'),
	config = require('@v4fire/core/config/default'),
	concatUrls = require('urlconcat').concat,
	o = require('uniconf/options').option;

module.exports = config.createConfig({dirs: [__dirname, 'client']}, {
	__proto__: config,

	apiURL() {
		return this.api.proxy ? concatUrls(this.api.pathname(), 'api') : this.api.url;
	},

	api: {
		proxy: true,

		url: o('api-url', {
			env: true
		}),

		port: o('port', {
			env: true,
			type: 'number',
			default: 3333,
			validate(value) {
				return Number.isFinite(value) && (value > 0) && (value < 65536);
			}
		}),

		host() {
			return o('host-url', {
				env: true,
				default: `http://localhost:${this.port}/`
			});
		},

		pathname() {
			return o('base-path', {
				env: true,
				default: url.parse(this.host()).pathname || '/'
			});
		},

		schema: {

		}
	},

	build: {
		single: o('single-build', {
			env: true
		}),

		entries: o('entries', {
			env: true,
			short: 'e',
			coerce: (v) => v ? v.split(',') : []
		}),

		fast() {
			const v = o('fast-build', {
				env: true,
				type: 'boolean'
			});

			return v != null ? v : isProd;
		},

		buildGraphFromCache: o('build-graph-from-cache', {
			env: true,
			type: 'boolean'
		})
	},

	webpack: {
		externals: {
			'collection.js': '$C',
			'eventemitter2': 'EventEmitter2',
			'localforage': 'localforage',
			'sugar': 'Sugar',
			'vue': 'Vue',
			'chart.js': 'Chart',
			'ion-sound': 'ion',
			'socket.io-client': 'io',
			'setimmediate': 'setImmediate'
		},

		fatHTML: false,
		devtool: false,

		hashLength() {
			return !isProd || this.fatHTML ? false : 15;
		},

		dataURILimit() {
			return this.fatHTML ? false : 4096;
		},

		output(params) {
			const
				res = this.fatHTML ? '[name]' : '[hash]_[name]';

			if (params) {
				return res.replace(/\[(.*?)]/g, (str, key) => {
					if (params[key] != null) {
						return params[key];
					}

					return '';
				});
			}

			return res;
		},

		assetsJSON() {
			return 'assets.json';
		}
	},

	imageOpts: {
		mozjpeg: {
			progressive: true,
			quality: 65
		},

		optipng: {
			enabled: false,
		},

		pngquant: {
			quality: '65-90',
			speed: 4
		},

		gifsicle: {
			interlaced: false,
		},

		webp: {
			quality: 75
		},

		svgo: {

		}
	},

	html: {
		useShortDoctype: true,
		conservativeCollapse: true,
		removeAttributeQuotes: true,
		removeComments: isProd,
		collapseWhitespace: isProd
	},

	postcss: {

	},

	autoprefixer: {

	},

	uglify: {

	},

	monic() {
		return {
			stylus: {
				flags: {
					'+:*': true
				}
			}
		};
	},

	favicons() {
		return {
			appName: this.appName,
			path: this.src.assets('favicons'),
			background: '#FFF',
			display: 'standalone',
			orientation: 'portrait',
			version: 1.0,
			logging: false
		};
	},

	snakeskin() {
		function ignore(target) {
			target.ignore = true;
			return function () {
				return target.apply(this, arguments);
			};
		}

		const {
			webpack,
			src
		} = this;

		return {
			client: this.extend(super.snakeskin(), {
				adapter: 'ss2vue',
				adapterOptions: {transpiler: true},
				tagFilter: 'tagFilter',
				tagNameFilter: 'tagNameFilter',
				bemFilter: 'bemFilter',
				vars: {
					ignore
				}
			}),

			server: this.extend(super.snakeskin(), {
				vars: {
					fatHTML: webpack.fatHTML,
					hashLength: webpack.hashLength(),
					root: src.cwd(),
					outputPattern: webpack.output,
					output: src.clientOutput(),
					favicons: this.favicons().path,
					assets: src.assets(),
					lib: src.lib()
				}
			})
		};
	},

	typescript() {
		return {
			client: super.typescript(),
			worker: super.typescript(),
			server: super.typescript()
		};
	},

	css() {
		return {
			minimize: Boolean(isProd || Number(process.env.MINIFY_CSS))
		};
	},

	stylus() {
		return {
			preferPathResolver: 'webpack'
		};
	}
});
<|endoftext|>


<commit_before>var tree = Arboreal.parse(survey200, 'children');

//the h and w values should be locked at a 1:2 ratio of h to w
var h = 450;
var w = 900;

function setupVis(){

//create svg, appended to a div with the id #visualization_div, w and h values to be computed by jquery later
//to connect viz to responsive layout if desired
var visualization = d3.select('#visualization_div').append('svg')
              .attr('width', w)
              .attr('height', h)
              .attr('class', 'visualization');

// setup overlays
(function() {

    //add four directional arrows, scalable on resize of parent container which must be a square to preserve dimensions of viz.
    visualization.append('line')
            .attr('x1', w*.5)
            .attr('y1', h*.25)
            .attr('x2', w*.5)
            .attr('y2', 15)
            .attr('id', 'toparrow')
            .attr('marker-end', "url(#Triangle)");
    visualization.append('line')
            .attr('x1', w*.75)
            .attr('y1', h*.5)
            .attr('x2', w-15)
            .attr('y2', h*.5)
            .attr('id', 'rightarrow')
            .attr('marker-end', "url(#Triangle)");
    visualization.append('line')
            .attr('x1', w*.25)
            .attr('y1', h*.5)
            .attr('x2', 15)
            .attr('y2', h*.5)
            .attr('id', 'leftarrow')
            .attr('marker-end', "url(#Triangle)");
    visualization.append('line')
            .attr('x1', w*.5)
            .attr('y1', h*.75)
            .attr('x2', w*.5)
            .attr('y2', h-15)
            .attr('id', 'bottomarrow')
            .attr('marker-end', "url(#Triangle)");
    // add the center circle
    visualization.append('circle')
            .attr('cx', w*.5)
            .attr('cy', h*.5)
            .attr('r', 7)
            .attr('id', 'centercircle');
    // add four hover circles on lines
    visualization.append('circle')
            .attr('cx', w*.5)
            .attr('cy', h*.1)
            .attr('r', 10)
            .attr('id', 'top_circle');
    visualization.append('circle')
            .attr('cx', w*.9)
            .attr('cy', h*.5)
            .attr('r', 10)
            .attr('id', 'right_circle');
    visualization.append('circle')
            .attr('cx', w*.5)
            .attr('cy', h*.9)
            .attr('r', 10)
            .attr('id', 'bottom_circle');
    visualization.append('circle')
            .attr('cx', w*.1)
            .attr('cy', h*.5)
            .attr('r', 10)
            .attr('id', 'left_circle');
    // add four boxes that will come up on hover to show PILLARS which will show comments with
    // most PCA SUPPORT both positively and negatively

      $('#toparrow').hover(function(){
          $('.visualization').addClass('.toparrow_hover');
          $('visualization').addClass
        }, function() {

        });

      $('#centercircle').hover(function(){})

      //make this more robust using conditionals to make sure the class isn't misapplied:

      $('#centercircle').click(function(){
        $('#centercircle_content').removeClass('hidden');
      });

      $('#centercircle_content, #top_pillar, #right_pillar, #bottom_pillar, #left_pillar').click(function(){
        $(this).addClass('hidden');
      })

      $('#top_circle').click(function(){
        $('#top_pillar').toggleClass('hidden');
      });
      $('#right_circle').click(function(){
        $('#right_pillar').toggleClass('hidden');
      });
      $('#bottom_circle').click(function(){
        $('#bottom_pillar').toggleClass('hidden');
      });
      $('#left_circle').click(function(){
        $('#left_pillar').toggleClass('hidden');
      });

}()); // End setup overlays

// pca plotting setup
(function() {

    var nodes = [];

    var force = d3.layout.force()
        .nodes(nodes)
        .links([])
        .gravity(0)
        .size([w, h]);

    force.on("tick", function(e) {

      // Push nodes toward their designated location
      var k = .1 * e.alpha;
      nodes.forEach( function(o, i) {
        if (o.children && o.children.length) {
            return;
        }
        o.x = o.data.projection[0] * w / 2 + w/2;
        o.y = o.data.projection[1] * h / 2 + h/2;

      });

      // TODO Can we do this less frequently?
      var node = visualization.selectAll("circle.node")
          .attr("cx", function(d) { return d.x; })
          .attr("cy", function(d) { return d.y; });

    });

    function hashCode(s){
        var hash = 0, i, char;
        if (s.length == 0) return hash;
        for (i = 0; i < s.length; i++) {
            char = s.charCodeAt(i);
            hash = ((hash<<5)-hash)+char;
            hash = hash & hash; // Convert to 32bit integer
        }
        return hash;
    }

    var colorFromString = _.compose(d3.scale.category20(), function(s) {
        return hashCode(s) % 20;
    });

    //principlecomponents

    setInterval(function(){
      if  (dataFromPca.length === 0) {
        return;
      }
      nodes.push(dataFromPca.shift());
      force.start();

      visualization.selectAll("circle.node")
          .data(nodes)
        .enter().append("svg:circle")
          .attr("class", "node")
          .attr("cx", function(d) { return d.x; })
          .attr("cy", function(d) { return d.y; })
          .attr("r", 8)
          .style("fill", function(d) {
                if (d.children && d.children.length) {
                    // only render leaves - may change? render large transucent circles?
                    return "rgba(0,0,0,0)";
                }
                var color = colorFromString(d.data && d.data.meta && d.data.meta.country || "");
                if (!color) {
                    console.error(29384723897);
                    return "black";
                }
                return color;
          })
          .style("stroke-width", 1.5)
          .call(force.drag);
    }, 10);

    // Normalize to [-1,1]
    function normalize(projectionDimension) {
        return projectionDimension / 6;
    }
    tree.traverseDown(function(n) {
        if (n.data.projection) {
            n.data.projection = n.data.projection.map(normalize);
        }
    });

    var dataFromPca = tree.toArray();

}()); // end pca plot setup

}

$(document).ready(setupVis);
<commit_msg>making lint happy<commit_after>var tree = Arboreal.parse(survey200, 'children');

//the h and w values should be locked at a 1:2 ratio of h to w
var h = 450;
var w = 900;

function setupVis(){

//create svg, appended to a div with the id #visualization_div, w and h values to be computed by jquery later
//to connect viz to responsive layout if desired
var visualization = d3.select('#visualization_div').append('svg')
              .attr('width', w)
              .attr('height', h)
              .attr('class', 'visualization');

// setup overlays
(function() {

    //add four directional arrows, scalable on resize of parent container which must be a square to preserve dimensions of viz.
    visualization.append('line')
            .attr('x1', w * 0.5)
            .attr('y1', h * 0.25)
            .attr('x2', w * 0.5)
            .attr('y2', 15)
            .attr('id', 'toparrow')
            .attr('marker-end', "url(#Triangle)");
    visualization.append('line')
            .attr('x1', w * 0.75)
            .attr('y1', h * 0.5)
            .attr('x2', w - 15)
            .attr('y2', h * 0.5)
            .attr('id', 'rightarrow')
            .attr('marker-end', "url(#Triangle)");
    visualization.append('line')
            .attr('x1', w * 0.25)
            .attr('y1', h * 0.5)
            .attr('x2', 15)
            .attr('y2', h * 0.5)
            .attr('id', 'leftarrow')
            .attr('marker-end', "url(#Triangle)");
    visualization.append('line')
            .attr('x1', w * 0.5)
            .attr('y1', h * 0.75)
            .attr('x2', w * 0.5)
            .attr('y2', h - 15)
            .attr('id', 'bottomarrow')
            .attr('marker-end', "url(#Triangle)");
    // add the center circle
    visualization.append('circle')
            .attr('cx', w * 0.5)
            .attr('cy', h * 0.5)
            .attr('r', 7)
            .attr('id', 'centercircle');
    // add four hover circles on lines
    visualization.append('circle')
            .attr('cx', w * 0.5)
            .attr('cy', h * 0.1)
            .attr('r', 10)
            .attr('id', 'top_circle');
    visualization.append('circle')
            .attr('cx', w * 0.9)
            .attr('cy', h * 0.5)
            .attr('r', 10)
            .attr('id', 'right_circle');
    visualization.append('circle')
            .attr('cx', w * 0.5)
            .attr('cy', h * 0.9)
            .attr('r', 10)
            .attr('id', 'bottom_circle');
    visualization.append('circle')
            .attr('cx', w * 0.1)
            .attr('cy', h * 0.5)
            .attr('r', 10)
            .attr('id', 'left_circle');
    // add four boxes that will come up on hover to show PILLARS which will show comments with
    // most PCA SUPPORT both positively and negatively

      $('#toparrow').hover(function(){
          $('.visualization').addClass('.toparrow_hover');
        }, function() {

        });

      $('#centercircle').hover(function(){});

      //make this more robust using conditionals to make sure the class isn't misapplied:

      $('#centercircle').click(function(){
        $('#centercircle_content').removeClass('hidden');
      });

      $('#centercircle_content, #top_pillar, #right_pillar, #bottom_pillar, #left_pillar').click(function(){
        $(this).addClass('hidden');
      });

      $('#top_circle').click(function(){
        $('#top_pillar').toggleClass('hidden');
      });
      $('#right_circle').click(function(){
        $('#right_pillar').toggleClass('hidden');
      });
      $('#bottom_circle').click(function(){
        $('#bottom_pillar').toggleClass('hidden');
      });
      $('#left_circle').click(function(){
        $('#left_pillar').toggleClass('hidden');
      });

}()); // End setup overlays

// pca plotting setup
(function() {

    var nodes = [];

    var force = d3.layout.force()
        .nodes(nodes)
        .links([])
        .gravity(0)
        .size([w, h]);

    force.on("tick", function(e) {

      // Push nodes toward their designated location
      var k = 0.1 * e.alpha;
      nodes.forEach( function(o, i) {
        if (o.children && o.children.length) {
            return;
        }
        o.x = o.data.projection[0] * w / 2 + w/2;
        o.y = o.data.projection[1] * h / 2 + h/2;

      });

      // TODO Can we do this less frequently?
      var node = visualization.selectAll("circle.node")
          .attr("cx", function(d) { return d.x; })
          .attr("cy", function(d) { return d.y; });

    });

    function hashCode(s){
        var hash = 0,
            i,
            char;
        if (s.length === 0) {
            return hash;
        }
        for (i = 0; i < s.length; i++) {
            char = s.charCodeAt(i);
            hash = ((hash<<5)-hash)+char;
            hash = hash & hash; // Convert to 32bit integer
        }
        return hash;
    }

    var colorFromString = _.compose(d3.scale.category20(), function(s) {
        return hashCode(s) % 20;
    });

    //principlecomponents

    setInterval(function(){
      if  (dataFromPca.length === 0) {
        return;
      }
      nodes.push(dataFromPca.shift());
      force.start();

      visualization.selectAll("circle.node")
          .data(nodes)
        .enter().append("svg:circle")
          .attr("class", "node")
          .attr("cx", function(d) { return d.x; })
          .attr("cy", function(d) { return d.y; })
          .attr("r", 8)
          .style("fill", function(d) {
                if (d.children && d.children.length) {
                    // only render leaves - may change? render large transucent circles?
                    return "rgba(0,0,0,0)";
                }
                var color = colorFromString(d.data && d.data.meta && d.data.meta.country || "");
                if (!color) {
                    console.error(29384723897);
                    return "black";
                }
                return color;
          })
          .style("stroke-width", 1.5)
          .call(force.drag);
    }, 10);

    // Normalize to [-1,1]
    function normalize(projectionDimension) {
        return projectionDimension / 6;
    }
    tree.traverseDown(function(n) {
        if (n.data.projection) {
            n.data.projection = n.data.projection.map(normalize);
        }
    });

    var dataFromPca = tree.toArray();

}()); // end pca plot setup

}

$(document).ready(setupVis);
<|endoftext|>


<commit_before>/*

 This file is part of the Sonata package.

 (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>

 For the full copyright and license information, please view the LICENSE
 file that was distributed with this source code.

 */

jQuery(document).ready(function() {
    jQuery('html').removeClass('no-js');
    if (window.SONATA_CONFIG && window.SONATA_CONFIG.CONFIRM_EXIT) {
        jQuery('.sonata-ba-form form').each(function () { $(this).confirmExit(); });
    }

    Admin.setup_per_page_switcher(document);

    Admin.shared_setup(document);
});

jQuery(document).on('sonata-admin-append-form-element', function(e) {
    Admin.setup_select2(e.target);
    Admin.setup_icheck(e.target);
});

var Admin = {

    /**
     * This function must called when a ajax call is done, to ensure
     * retrieve html is properly setup
     *
     * @param subject
     */
    shared_setup: function(subject) {
        Admin.log("[Admin] apply shared_setup");
        Admin.setup_collection_buttons(subject);
        Admin.set_object_field_value(subject);
        Admin.setup_select2(subject);
        Admin.setup_icheck(subject);
        Admin.add_filters(subject);
        Admin.setup_xeditable(subject);
        Admin.add_pretty_errors(subject);
        Admin.setup_form_tabs_for_errors(subject);
        Admin.setup_inline_form_errors(subject);
//        Admin.setup_list_modal(subject);
    },
    setup_list_modal: function(modal) {
        // this will force relation modal to open list of entity in a wider modal
        // to improve readability
        jQuery('div.modal-dialog', modal).css({
            width:  '90%', //choose your width
            height: '85%',
            padding: 0
        });
        jQuery('div.modal-content', modal).css({
            'border-radius':'0',
            height:   '100%',
            padding: 0
        });
        jQuery('.modal-body', modal).css({
            width:    'auto',
            height:   '90%',
            padding: 5,
            overflow: 'scroll'
        });
    },
    setup_select2: function(subject) {
        if (window.SONATA_CONFIG && window.SONATA_CONFIG.USE_SELECT2 && window.Select2) {

            jQuery('select:not([data-sonata-select2="false"])', subject).each(function() {
                var select = $(this);

                var allowClearEnabled = false;

                if (select.find('option[value=""]').length) {
                    allowClearEnabled = true;
                }

                if (select.attr('data-sonata-select2-allow-clear')==='true') {
                    allowClearEnabled = true;
                } else if (select.attr('data-sonata-select2-allow-clear')==='false') {
                    allowClearEnabled = false;
                }

                select.select2({
                    width: 'resolve',
                    minimumResultsForSearch: 10,
                    allowClear: allowClearEnabled
                });

                var popover = select.data('popover');

                if (undefined !== popover) {
                    select
                        .select2('container')
                        .popover(popover.options)
                    ;
                }
            });
        }
    },
    setup_icheck: function(subject) {
        if (window.SONATA_CONFIG && window.SONATA_CONFIG.USE_ICHECK) {
            jQuery("input[type='checkbox']:not('label.btn>input'), input[type='radio']:not('label.btn>input')", subject).iCheck({
                checkboxClass: 'icheckbox_minimal',
                radioClass: 'iradio_minimal'
            });
        }
    },

    setup_xeditable: function(subject) {
        jQuery('.x-editable', subject).editable({
            emptyclass: 'editable-empty btn btn-sm',
            emptytext: '',
            container: 'body',
            success: function(response) {
                if('KO' === response.status) {
                    return response.message;
                }

                var html = jQuery(response.content);
                Admin.setup_xeditable(html);

                jQuery(this)
                    .closest('td')
                    .replaceWith(html)
                ;
            }
        });
    },

    /**
     * render log message
     * @param mixed
     */
    log: function() {
        var msg = '[Sonata.Admin] ' + Array.prototype.join.call(arguments,', ');
        if (window.console && window.console.log) {
            window.console.log(msg);
        } else if (window.opera && window.opera.postError) {
            window.opera.postError(msg);
        }
    },

    /**
     * display related errors messages
     *
     * @param subject
     */
    add_pretty_errors: function(subject) {
        jQuery('div.sonata-ba-field-error', subject).each(function(index, element) {
            var input = jQuery(':input', element);

            if (!input.length) {
                return;
            }

            var message = jQuery('div.sonata-ba-field-error-messages', element).html();
            jQuery('div.sonata-ba-field-error-messages', element).remove();

            if (!message || message.length == 0) {
                return;
            }

            var target = input,
                fieldShortDescription = input.closest('.field-container').find('.field-short-description'),
                select2 = input.closest('.select2-container')
                ;

            if (fieldShortDescription.length) {
                target = fieldShortDescription;
            } else if (select2.length) {
                target= select2;
            }

            target.popover({
                content: message,
                trigger: 'hover',
                html: true,
                placement: 'top',
                template: '

'
            });

        });
    },

    stopEvent: function(event) {
        // https://github.com/sonata-project/SonataAdminBundle/issues/151
        //if it is a standard browser use preventDefault otherwise it is IE then return false
        if(event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }

        //if it is a standard browser get target otherwise it is IE then adapt syntax and get target
        if (typeof event.target != 'undefined') {
            targetElement = event.target;
        } else {
            targetElement = event.srcElement;
        }

        return targetElement;
    },

    add_filters: function(subject) {
        jQuery('div.filter_container .sonata-filter-option', subject).hide();
        jQuery('h4.filter_legend', subject).click(function(event) {
            jQuery('div.filter_container .sonata-filter-option').toggle();
        });
    },

    /**
     * Change object field value
     * @param subject
     */
    set_object_field_value: function(subject) {

        this.log(jQuery('a.sonata-ba-edit-inline', subject));
        jQuery('a.sonata-ba-edit-inline', subject).click(function(event) {
            Admin.stopEvent(event);

            var subject = jQuery(this);
            jQuery.ajax({
                url: subject.attr('href'),
                type: 'POST',
                success: function(json) {
                    if(json.status === "OK") {
                        var elm = jQuery(subject).parent();
                        elm.children().remove();
                        // fix issue with html comment ...
                        elm.html(jQuery(json.content.replace(//g, "")).html());
                        elm.effect("highlight", {'color' : '#57A957'}, 2000);
                        Admin.set_object_field_value(elm);
                    } else {
                        jQuery(subject).parent().effect("highlight", {'color' : '#C43C35'}, 2000);
                    }
                }
            });
        });
    },

    setup_collection_buttons: function(subject) {

        jQuery(subject).on('click', '.sonata-collection-add', function(event) {
            Admin.stopEvent(event);

            var container = jQuery(this).closest('[data-prototype]');
            var proto = container.attr('data-prototype');
            var protoName = container.attr('data-prototype-name') || '__name__';
            // Set field id
            var idRegexp = new RegExp(container.attr('id')+'_'+protoName,'g');
            proto = proto.replace(idRegexp, container.attr('id')+'_'+(container.children().length - 1));

            // Set field name
            var parts = container.attr('id').split('_');
            var nameRegexp = new RegExp(parts[parts.length-1]+'\\]\\['+protoName,'g');
            proto = proto.replace(nameRegexp, parts[parts.length-1]+']['+(container.children().length - 1));
            jQuery(proto)
                .insertBefore(jQuery(this).parent())
                .trigger('sonata-admin-append-form-element')
            ;

            jQuery(this).trigger('sonata-collection-item-added');
        });

        jQuery(subject).on('click', '.sonata-collection-delete', function(event) {
            Admin.stopEvent(event);

            jQuery(this).trigger('sonata-collection-item-deleted');

            jQuery(this).closest('.sonata-collection-row').remove();
        });
    },

    setup_per_page_switcher: function(subject) {
        jQuery('select.per-page').change(function(event) {
            jQuery('input[type=submit]').hide();

            window.top.location.href=this.options[this.selectedIndex].value;
        });
    },

    setup_form_tabs_for_errors: function(subject) {
        // Switch to first tab with server side validation errors on page load
        jQuery('form', subject).each(function() {
            Admin.show_form_first_tab_with_errors(jQuery(this), '.sonata-ba-field-error');
        });

        // Switch to first tab with HTML5 errors on form submit
        jQuery(subject)
            .on('click', 'form [type="submit"]', function() {
                Admin.show_form_first_tab_with_errors(jQuery(this).closest('form'), ':invalid');
            })
            .on('keypress', 'form [type="text"]', function(e) {
                if (13 === e.which) {
                    Admin.show_form_first_tab_with_errors(jQuery(this), ':invalid');
                }
            })
        ;
    },

    show_form_first_tab_with_errors: function(form, errorSelector) {
        var tabs = form.find('.nav-tabs a'),
            firstTabWithErrors;

        tabs.each(function() {
            var id = jQuery(this).attr('href'),
                tab = jQuery(this),
                icon = tab.find('.has-errors');

            if (jQuery(id).find(errorSelector).length > 0) {
                // Only show first tab with errors
                if (!firstTabWithErrors) {
                    tab.tab('show');
                    firstTabWithErrors = tab;
                }

                icon.removeClass('hide');
            } else {
                icon.addClass('hide');
            }
        });
    },

    setup_inline_form_errors: function(subject) {
        var deleteCheckboxSelector = '.sonata-ba-field-inline-table [id$="_delete"][type="checkbox"]';

        jQuery(deleteCheckboxSelector, subject).each(function() {
            Admin.switch_inline_form_errors(jQuery(this));
        });

        $(subject).on('change', deleteCheckboxSelector, function() {
            Admin.switch_inline_form_errors(jQuery(this));
        });
    },

    /**
     * Disable inline form errors when the row is marked for deletion
     */
    switch_inline_form_errors: function(deleteCheckbox) {
        var row = deleteCheckbox.closest('.sonata-ba-field-inline-table'),
            errors = row.find('.sonata-ba-field-error-messages')
        ;

        if (deleteCheckbox.is(':checked')) {
            row
                .find('[required]')
                .removeAttr('required')
                .attr('data-required', 'required')
            ;

            errors.hide();
        } else {
            row
                .find('[data-required]')
                .attr('required', 'required')
            ;

            errors.show();
        }
    }
};
<commit_msg>$ to jQuery<commit_after>/*

 This file is part of the Sonata package.

 (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>

 For the full copyright and license information, please view the LICENSE
 file that was distributed with this source code.

 */

jQuery(document).ready(function() {
    jQuery('html').removeClass('no-js');
    if (window.SONATA_CONFIG && window.SONATA_CONFIG.CONFIRM_EXIT) {
        jQuery('.sonata-ba-form form').each(function () { $(this).confirmExit(); });
    }

    Admin.setup_per_page_switcher(document);

    Admin.shared_setup(document);
});

jQuery(document).on('sonata-admin-append-form-element', function(e) {
    Admin.setup_select2(e.target);
    Admin.setup_icheck(e.target);
});

var Admin = {

    /**
     * This function must called when a ajax call is done, to ensure
     * retrieve html is properly setup
     *
     * @param subject
     */
    shared_setup: function(subject) {
        Admin.log("[Admin] apply shared_setup");
        Admin.setup_collection_buttons(subject);
        Admin.set_object_field_value(subject);
        Admin.setup_select2(subject);
        Admin.setup_icheck(subject);
        Admin.add_filters(subject);
        Admin.setup_xeditable(subject);
        Admin.add_pretty_errors(subject);
        Admin.setup_form_tabs_for_errors(subject);
        Admin.setup_inline_form_errors(subject);
//        Admin.setup_list_modal(subject);
    },
    setup_list_modal: function(modal) {
        // this will force relation modal to open list of entity in a wider modal
        // to improve readability
        jQuery('div.modal-dialog', modal).css({
            width:  '90%', //choose your width
            height: '85%',
            padding: 0
        });
        jQuery('div.modal-content', modal).css({
            'border-radius':'0',
            height:   '100%',
            padding: 0
        });
        jQuery('.modal-body', modal).css({
            width:    'auto',
            height:   '90%',
            padding: 5,
            overflow: 'scroll'
        });
    },
    setup_select2: function(subject) {
        if (window.SONATA_CONFIG && window.SONATA_CONFIG.USE_SELECT2 && window.Select2) {

            jQuery('select:not([data-sonata-select2="false"])', subject).each(function() {
                var select = jQuery(this);

                var allowClearEnabled = false;

                if (select.find('option[value=""]').length) {
                    allowClearEnabled = true;
                }

                if (select.attr('data-sonata-select2-allow-clear')==='true') {
                    allowClearEnabled = true;
                } else if (select.attr('data-sonata-select2-allow-clear')==='false') {
                    allowClearEnabled = false;
                }

                select.select2({
                    width: 'resolve',
                    minimumResultsForSearch: 10,
                    allowClear: allowClearEnabled
                });

                var popover = select.data('popover');

                if (undefined !== popover) {
                    select
                        .select2('container')
                        .popover(popover.options)
                    ;
                }
            });
        }
    },
    setup_icheck: function(subject) {
        if (window.SONATA_CONFIG && window.SONATA_CONFIG.USE_ICHECK) {
            jQuery("input[type='checkbox']:not('label.btn>input'), input[type='radio']:not('label.btn>input')", subject).iCheck({
                checkboxClass: 'icheckbox_minimal',
                radioClass: 'iradio_minimal'
            });
        }
    },

    setup_xeditable: function(subject) {
        jQuery('.x-editable', subject).editable({
            emptyclass: 'editable-empty btn btn-sm',
            emptytext: '',
            container: 'body',
            success: function(response) {
                if('KO' === response.status) {
                    return response.message;
                }

                var html = jQuery(response.content);
                Admin.setup_xeditable(html);

                jQuery(this)
                    .closest('td')
                    .replaceWith(html)
                ;
            }
        });
    },

    /**
     * render log message
     * @param mixed
     */
    log: function() {
        var msg = '[Sonata.Admin] ' + Array.prototype.join.call(arguments,', ');
        if (window.console && window.console.log) {
            window.console.log(msg);
        } else if (window.opera && window.opera.postError) {
            window.opera.postError(msg);
        }
    },

    /**
     * display related errors messages
     *
     * @param subject
     */
    add_pretty_errors: function(subject) {
        jQuery('div.sonata-ba-field-error', subject).each(function(index, element) {
            var input = jQuery(':input', element);

            if (!input.length) {
                return;
            }

            var message = jQuery('div.sonata-ba-field-error-messages', element).html();
            jQuery('div.sonata-ba-field-error-messages', element).remove();

            if (!message || message.length == 0) {
                return;
            }

            var target = input,
                fieldShortDescription = input.closest('.field-container').find('.field-short-description'),
                select2 = input.closest('.select2-container')
                ;

            if (fieldShortDescription.length) {
                target = fieldShortDescription;
            } else if (select2.length) {
                target= select2;
            }

            target.popover({
                content: message,
                trigger: 'hover',
                html: true,
                placement: 'top',
                template: '

'
            });

        });
    },

    stopEvent: function(event) {
        // https://github.com/sonata-project/SonataAdminBundle/issues/151
        //if it is a standard browser use preventDefault otherwise it is IE then return false
        if(event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }

        //if it is a standard browser get target otherwise it is IE then adapt syntax and get target
        if (typeof event.target != 'undefined') {
            targetElement = event.target;
        } else {
            targetElement = event.srcElement;
        }

        return targetElement;
    },

    add_filters: function(subject) {
        jQuery('div.filter_container .sonata-filter-option', subject).hide();
        jQuery('h4.filter_legend', subject).click(function(event) {
            jQuery('div.filter_container .sonata-filter-option').toggle();
        });
    },

    /**
     * Change object field value
     * @param subject
     */
    set_object_field_value: function(subject) {

        this.log(jQuery('a.sonata-ba-edit-inline', subject));
        jQuery('a.sonata-ba-edit-inline', subject).click(function(event) {
            Admin.stopEvent(event);

            var subject = jQuery(this);
            jQuery.ajax({
                url: subject.attr('href'),
                type: 'POST',
                success: function(json) {
                    if(json.status === "OK") {
                        var elm = jQuery(subject).parent();
                        elm.children().remove();
                        // fix issue with html comment ...
                        elm.html(jQuery(json.content.replace(//g, "")).html());
                        elm.effect("highlight", {'color' : '#57A957'}, 2000);
                        Admin.set_object_field_value(elm);
                    } else {
                        jQuery(subject).parent().effect("highlight", {'color' : '#C43C35'}, 2000);
                    }
                }
            });
        });
    },

    setup_collection_buttons: function(subject) {

        jQuery(subject).on('click', '.sonata-collection-add', function(event) {
            Admin.stopEvent(event);

            var container = jQuery(this).closest('[data-prototype]');
            var proto = container.attr('data-prototype');
            var protoName = container.attr('data-prototype-name') || '__name__';
            // Set field id
            var idRegexp = new RegExp(container.attr('id')+'_'+protoName,'g');
            proto = proto.replace(idRegexp, container.attr('id')+'_'+(container.children().length - 1));

            // Set field name
            var parts = container.attr('id').split('_');
            var nameRegexp = new RegExp(parts[parts.length-1]+'\\]\\['+protoName,'g');
            proto = proto.replace(nameRegexp, parts[parts.length-1]+']['+(container.children().length - 1));
            jQuery(proto)
                .insertBefore(jQuery(this).parent())
                .trigger('sonata-admin-append-form-element')
            ;

            jQuery(this).trigger('sonata-collection-item-added');
        });

        jQuery(subject).on('click', '.sonata-collection-delete', function(event) {
            Admin.stopEvent(event);

            jQuery(this).trigger('sonata-collection-item-deleted');

            jQuery(this).closest('.sonata-collection-row').remove();
        });
    },

    setup_per_page_switcher: function(subject) {
        jQuery('select.per-page').change(function(event) {
            jQuery('input[type=submit]').hide();

            window.top.location.href=this.options[this.selectedIndex].value;
        });
    },

    setup_form_tabs_for_errors: function(subject) {
        // Switch to first tab with server side validation errors on page load
        jQuery('form', subject).each(function() {
            Admin.show_form_first_tab_with_errors(jQuery(this), '.sonata-ba-field-error');
        });

        // Switch to first tab with HTML5 errors on form submit
        jQuery(subject)
            .on('click', 'form [type="submit"]', function() {
                Admin.show_form_first_tab_with_errors(jQuery(this).closest('form'), ':invalid');
            })
            .on('keypress', 'form [type="text"]', function(e) {
                if (13 === e.which) {
                    Admin.show_form_first_tab_with_errors(jQuery(this), ':invalid');
                }
            })
        ;
    },

    show_form_first_tab_with_errors: function(form, errorSelector) {
        var tabs = form.find('.nav-tabs a'),
            firstTabWithErrors;

        tabs.each(function() {
            var id = jQuery(this).attr('href'),
                tab = jQuery(this),
                icon = tab.find('.has-errors');

            if (jQuery(id).find(errorSelector).length > 0) {
                // Only show first tab with errors
                if (!firstTabWithErrors) {
                    tab.tab('show');
                    firstTabWithErrors = tab;
                }

                icon.removeClass('hide');
            } else {
                icon.addClass('hide');
            }
        });
    },

    setup_inline_form_errors: function(subject) {
        var deleteCheckboxSelector = '.sonata-ba-field-inline-table [id$="_delete"][type="checkbox"]';

        jQuery(deleteCheckboxSelector, subject).each(function() {
            Admin.switch_inline_form_errors(jQuery(this));
        });

        $(subject).on('change', deleteCheckboxSelector, function() {
            Admin.switch_inline_form_errors(jQuery(this));
        });
    },

    /**
     * Disable inline form errors when the row is marked for deletion
     */
    switch_inline_form_errors: function(deleteCheckbox) {
        var row = deleteCheckbox.closest('.sonata-ba-field-inline-table'),
            errors = row.find('.sonata-ba-field-error-messages')
        ;

        if (deleteCheckbox.is(':checked')) {
            row
                .find('[required]')
                .removeAttr('required')
                .attr('data-required', 'required')
            ;

            errors.hide();
        } else {
            row
                .find('[data-required]')
                .attr('required', 'required')
            ;

            errors.show();
        }
    }
};
<|endoftext|>


<commit_before>'use strict';

// $viewPathProvider, to allow overriding system default views
angular.module('mean.system').provider('$viewPath', function() {
  function ViewPathProvider() {
    var overrides = {};

    this.path = function(path) {
      return function() {
        return overrides[path] || path;
      };
    };

    this.override = function(defaultPath, newPath) {
      if (overrides[defaultPath]) {
        throw new Error('View already has an override: ' + defaultPath);
      }
      overrides[defaultPath] = newPath;
      return this;
    };

    this.$get = function() {
      return this;
    };
  }

  return new ViewPathProvider();
});

// $meanStateProvider, provider to wire up $viewPathProvider to $stateProvider
angular.module('mean.system').provider('$meanState', ['$stateProvider', '$viewPathProvider', function($stateProvider, $viewPathProvider) {
  function MeanStateProvider() {
    this.state = function(stateName, data) {
      if (data.templateUrl) {
        data.templateUrl = $viewPathProvider.path(data.templateUrl);
      }
      $stateProvider.state(stateName, data);
      return this;
    };

    this.$get = function() {
      return this;
    };
  }

  return new MeanStateProvider();
}]);

//Setting up route
angular.module('mean.system').config(['$meanStateProvider', '$urlRouterProvider',
  function($meanStateProvider, $urlRouterProvider) {
    // For unmatched routes:
    $urlRouterProvider.otherwise('/');

    // states for my app
    $meanStateProvider
      .state('home', {
        url: '/',
        templateUrl: 'system/views/index.html'
      });
  }
]).config(['$locationProvider',
  function($locationProvider) {
  //  $locationProvider.html5Mode({
  //  enabled: true,
  //  requireBase: false
  //});

  ///$locationProvider.hashPrefix('!');
  $locationProvider.hashPrefix('!');

 }
]);
<commit_msg>Reverted to original file<commit_after>'use strict';

// $viewPathProvider, to allow overriding system default views
angular.module('mean.system').provider('$viewPath', function() {
  function ViewPathProvider() {
    var overrides = {};

    this.path = function(path) {
      return function() {
        return overrides[path] || path;
      };
    };

    this.override = function(defaultPath, newPath) {
      if (overrides[defaultPath]) {
        throw new Error('View already has an override: ' + defaultPath);
      }
      overrides[defaultPath] = newPath;
      return this;
    };

    this.$get = function() {
      return this;
    };
  }

  return new ViewPathProvider();
});

// $meanStateProvider, provider to wire up $viewPathProvider to $stateProvider
angular.module('mean.system').provider('$meanState', ['$stateProvider', '$viewPathProvider', function($stateProvider, $viewPathProvider) {
  function MeanStateProvider() {
    this.state = function(stateName, data) {
      if (data.templateUrl) {
        data.templateUrl = $viewPathProvider.path(data.templateUrl);
      }
      $stateProvider.state(stateName, data);
      return this;
    };

    this.$get = function() {
      return this;
    };
  }

  return new MeanStateProvider();
}]);

//Setting up route
angular.module('mean.system').config(['$meanStateProvider', '$urlRouterProvider',
  function($meanStateProvider, $urlRouterProvider) {
    // For unmatched routes:
    $urlRouterProvider.otherwise('/');

    // states for my app
    $meanStateProvider
      .state('home', {
        url: '/',
        templateUrl: 'system/views/index.html'
      });
  }
]).config(['$locationProvider',
  function($locationProvider) {
    $locationProvider.hashPrefix('!');
  }
]);
<|endoftext|>


<commit_before>// DefinitionList plugin for Xinha
// Distributed under the same terms as Xinha itself.
// This notice MUST stay intact for use (see license.txt).

function DefinitionList(editor) {
  this.editor = editor;
  var cfg = editor.config;
  var bl = DefinitionList.btnList;
  var self = this;
  // register the toolbar buttons provided by this plugin
  var toolbar = ["linebreak"];
  for (var i = 0; i < bl.length; ++i) {
    var btn = bl[i];
    if (!btn) {
      toolbar.push("separator");
    } else {
      var id = btn[0];
      cfg.registerButton(id, this._lc(btn[1]), editor.imgURL("ed_" + btn[0] + ".gif", "DefinitionList"), false,
             function(editor, id) {
               // dispatch button press event
               self.buttonPress(editor, id);
             });
      toolbar.push(id);
    }
  }
  // add a new line in the toolbar
  cfg.toolbar.push(toolbar);
}

DefinitionList._pluginInfo = {
  name          : "DefinitionList",
  version       : "1.0",
  developer     : "Udo Schmal",
  developer_url : "",
  c_owner       : "Udo Schmal",
  license       : "htmlArea"
};

// the list of buttons added by this plugin
DefinitionList.btnList = [
  ["dl", "definition list"],
  ["dt", "definition term"],
  ["dd", "definition description"]
  ];

DefinitionList.prototype._lc = function(string) {
  return Xinha._lc(string, 'DefinitionList');
};

DefinitionList.prototype.onGenerate = function() {
  this.editor.addEditorStylesheet(Xinha.getPluginDir('DefinitionList') + '/definition-list.css');
};

DefinitionList.prototype.buttonPress = function(editor,button_id) {
  if (button_id=='dl') { //definition list
    var pe = editor.getParentElement();
    while (pe.parentNode.tagName.toLowerCase() != 'body') {
      pe = pe.parentNode;
    }
    var dx = editor._doc.createElement(button_id);
    dx.innerHTML = ' ';
    if(pe.parentNode.lastChild==pe) {
      pe.parentNode.appendChild(dx);
    }else{
      pe.parentNode.insertBefore(dx,pe.nextSibling);
    }
  } else if ((button_id=='dt')||(button_id=='dd')) { //definition term or description
    var pe = editor.getParentElement();
    while (pe && (pe.nodeType == 1) && (pe.tagName.toLowerCase() != 'body')) {
      if(pe.tagName.toLowerCase() == 'dl') {
        var dx = editor._doc.createElement(button_id);
        dx.innerHTML = ' ';
        pe.appendChild(dx);
        break;
      }else if((pe.tagName.toLowerCase() == 'dt')||(pe.tagName.toLowerCase() == 'dd')){
        var dx = editor._doc.createElement(button_id)
        dx.innerHTML = ' ';
        if(pe.parentNode.lastChild==pe) {
        pe.parentNode.appendChild(dx);
        }else{
          pe.parentNode.insertBefore(dx,pe.nextSibling);
        }
        break;
      }
      pe = pe.parentNode;
    }
    if(pe.tagName.toLowerCase() == 'body')
  alert('You can insert a definition term or description only in a definition list!');
  }
};<commit_msg>closes #1559, <dl> button throws a JS error if the cursor context is the body element itself<commit_after>// DefinitionList plugin for Xinha
// Distributed under the same terms as Xinha itself.
// This notice MUST stay intact for use (see license.txt).

function DefinitionList(editor) {
  this.editor = editor;
  var cfg = editor.config;
  var bl = DefinitionList.btnList;
  var self = this;
  // register the toolbar buttons provided by this plugin
  var toolbar = ["linebreak"];
  for (var i = 0; i < bl.length; ++i) {
    var btn = bl[i];
    if (!btn) {
      toolbar.push("separator");
    } else {
      var id = btn[0];
      cfg.registerButton(id, this._lc(btn[1]), editor.imgURL("ed_" + btn[0] + ".gif", "DefinitionList"), false,
             function(editor, id) {
               // dispatch button press event
               self.buttonPress(editor, id);
             });
      toolbar.push(id);
    }
  }
  // add a new line in the toolbar
  cfg.toolbar.push(toolbar);
}

DefinitionList._pluginInfo = {
  name          : "DefinitionList",
  version       : "1.0",
  developer     : "Udo Schmal",
  developer_url : "",
  c_owner       : "Udo Schmal",
  license       : "htmlArea"
};

// the list of buttons added by this plugin
DefinitionList.btnList = [
  ["dl", "definition list"],
  ["dt", "definition term"],
  ["dd", "definition description"]
  ];

DefinitionList.prototype._lc = function(string) {
  return Xinha._lc(string, 'DefinitionList');
};

DefinitionList.prototype.onGenerate = function() {
  this.editor.addEditorStylesheet(Xinha.getPluginDir('DefinitionList') + '/definition-list.css');
};

DefinitionList.prototype.buttonPress = function(editor,button_id) {
  if (button_id=='dl') { //definition list
    var pe = editor.getParentElement();
    if( pe.tagName.toLowerCase() != 'body' ) {
      while (pe.parentNode.tagName.toLowerCase() != 'body') {
        pe = pe.parentNode;
      }
    }
    var dx = editor._doc.createElement(button_id);
    dx.innerHTML = ' ';
    if( pe.tagName.toLowerCase() == 'body' ) {
      pe.appendChild(dx);
    }else if(pe.parentNode.lastChild==pe) {
      pe.parentNode.appendChild(dx);
    }else{
      pe.parentNode.insertBefore(dx,pe.nextSibling);
    }
  } else if ((button_id=='dt')||(button_id=='dd')) { //definition term or description
    var pe = editor.getParentElement();
    while (pe && (pe.nodeType == 1) && (pe.tagName.toLowerCase() != 'body')) {
      if(pe.tagName.toLowerCase() == 'dl') {
        var dx = editor._doc.createElement(button_id);
        dx.innerHTML = ' ';
        pe.appendChild(dx);
        break;
      }else if((pe.tagName.toLowerCase() == 'dt')||(pe.tagName.toLowerCase() == 'dd')){
        var dx = editor._doc.createElement(button_id)
        dx.innerHTML = ' ';
        if(pe.parentNode.lastChild==pe) {
        pe.parentNode.appendChild(dx);
        }else{
          pe.parentNode.insertBefore(dx,pe.nextSibling);
        }
        break;
      }
      pe = pe.parentNode;
    }
    if(pe.tagName.toLowerCase() == 'body')
  alert('You can insert a definition term or description only in a definition list!');
  }
};<|endoftext|>