<commit_before>/*!
 * jQuery Mobile v@VERSION
 * http://jquerymobile.com/
 *
 * Copyright 2010, jQuery Project
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 */

(function( $, window, undefined ) {
	var	$html = $( "html" ),
			$head = $( "head" ),
			$window = $( window );

	$.extend($.mobile, {
		// find and enhance the pages in the dom and transition to the first page.
		initializePage: function(){
			//find present pages
			var $pages = $( "[data-role='page']" );

			//add dialogs, set data-url attrs
			$pages.add( "[data-role='dialog']" ).each(function(){
				$(this).attr( "data-url", $(this).attr( "id" ));
			});

			//define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)
			$.mobile.firstPage = $pages.first();

			//define page container
			$.mobile.pageContainer = $pages.first().parent().addClass( "ui-mobile-viewport" );

			//cue page loading message
			$.mobile.pageLoading();

			// if hashchange listening is disabled or there's no hash deeplink, change to the first page in the DOM
			if( !$.mobile.hashListeningEnabled || !$.mobile.path.stripHash( location.hash ) ){
				$.mobile.changePage( $.mobile.firstPage, false, true, false, true );
			}
			// otherwise, trigger a hashchange to load a deeplink
			else {
				$window.trigger( "hashchange", [ true ] );
			}
		}
	});

 	//trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
	$( window.document ).trigger( "mobileinit" );

	//support conditions
	//if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,
	//otherwise, proceed with the enhancements
	if ( !$.mobile.gradeA() ) {
		return;
	}

	//add mobile, initial load "rendering" classes to docEl
	$html.addClass( "ui-mobile ui-mobile-rendering" );

	//define & prepend meta viewport tag, if content is defined
	$.mobile.metaViewportContent ? $( "<meta>", { name: "viewport", content: $.mobile.metaViewportContent}).prependTo( $head ) : undefined;

	//dom-ready inits
	$( $.mobile.initializePage );

	//window load event
	//hide iOS browser chrome on load
	$window.load( $.mobile.silentScroll );
})( jQuery, this );
<commit_msg>prevent setting the data url on pages where it is already set<commit_after>/*!
 * jQuery Mobile v@VERSION
 * http://jquerymobile.com/
 *
 * Copyright 2010, jQuery Project
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 */

(function( $, window, undefined ) {
	var	$html = $( "html" ),
			$head = $( "head" ),
			$window = $( window );

	$.extend($.mobile, {
		// find and enhance the pages in the dom and transition to the first page.
		initializePage: function(){
			//find present pages
			var $pages = $( "[data-role='page']" );

			//add dialogs, set data-url attrs
			$pages.add( "[data-role='dialog']" ).each(function(){
				var $this = $(this);

				// unless the data url is already set set it to the id
				if( !$this.data('url') ){
					$this.attr( "data-url", $this.attr( "id" ) );
				}
			});

			//define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)
			$.mobile.firstPage = $pages.first();

			//define page container
			$.mobile.pageContainer = $pages.first().parent().addClass( "ui-mobile-viewport" );

			//cue page loading message
			$.mobile.pageLoading();

			// if hashchange listening is disabled or there's no hash deeplink, change to the first page in the DOM
			if( !$.mobile.hashListeningEnabled || !$.mobile.path.stripHash( location.hash ) ){
				$.mobile.changePage( $.mobile.firstPage, false, true, false, true );
			}
			// otherwise, trigger a hashchange to load a deeplink
			else {
				$window.trigger( "hashchange", [ true ] );
			}
		}
	});

 	//trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
	$( window.document ).trigger( "mobileinit" );

	//support conditions
	//if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,
	//otherwise, proceed with the enhancements
	if ( !$.mobile.gradeA() ) {
		return;
	}

	//add mobile, initial load "rendering" classes to docEl
	$html.addClass( "ui-mobile ui-mobile-rendering" );

	//define & prepend meta viewport tag, if content is defined
	$.mobile.metaViewportContent ? $( "<meta>", { name: "viewport", content: $.mobile.metaViewportContent}).prependTo( $head ) : undefined;

	//dom-ready inits
	$( $.mobile.initializePage );

	//window load event
	//hide iOS browser chrome on load
	$window.load( $.mobile.silentScroll );
})( jQuery, this );
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

import {toArray} from "../utils";
import {CameraState} from "./CameraState";

function copyIfSet(dest, src, prop) {
    if (src.hasOwnProperty(prop)) {
        dest[prop] = src[prop];
    }
}

export var LayerProperties = {

    link: false,
    referenceElementId: "",
    referenceElementAuto: true,
    transitionTimingFunction: "linear",
    transitionRelativeZoom: 0,
    transitionPathId: "",

    init(frame) {
        this.frame = frame;
        return this;
    },

    initFrom(other) {
        this.frame = other.frame;
        this.link = other.link;
        this.referenceElementId = other.referenceElementId;
        this.referenceElementAuto = other.referenceElementAuto;
        this.transitionTimingFunction = other.transitionTimingFunction;
        this.transitionRelativeZoom = other.transitionRelativeZoom;
        this.transitionPathId = other.transitionPathId;
        return this;
    },

    toStorable() {
        return {
            link: this.link,
            referenceElementId: this.referenceElementId,
            referenceElementAuto: this.referenceElementAuto,
            transitionTimingFunction: this.transitionTimingFunction,
            transitionRelativeZoom: this.transitionRelativeZoom,
            transitionPathId: this.transitionPathId
        };
    },

    toMinimalStorable() {
        return {
            transitionTimingFunction: this.transitionTimingFunction,
            transitionRelativeZoom: this.transitionRelativeZoom,
            transitionPathId: this.transitionPathId
        };
    },

    fromStorable(storable) {
        copyIfSet(this, storable, "link");
        copyIfSet(this, storable, "referenceElementId");
        copyIfSet(this, storable, "referenceElementAuto");
        copyIfSet(this, storable, "transitionTimingFunction");
        copyIfSet(this, storable, "transitionRelativeZoom");
        copyIfSet(this, storable, "transitionPathId");
        return this;
    },

    get index() {
        return this.frame.layerProperties.indexOf(this);
    },

    get referenceElement() {
        return this.frame.presentation.document.root.getElementById(this.referenceElementId);
    },

    get transitionPath() {
        return this.frame.presentation.document.root.getElementById(this.transitionPathId);
    },

    get referenceElementHide() {
        return this.frame.presentation.elementsToHide.indexOf(this.referenceElementId) >= 0;
    },

    set referenceElementHide(hide) {
        var hidden = this.referenceElementHide;
        if (hide && !hidden) {
            this.frame.presentation.elementsToHide.push(this.referenceElementId);
        }
        else if (!hide && hidden) {
            var index = this.frame.presentation.elementsToHide.indexOf(this.referenceElementId);
            this.frame.presentation.elementsToHide.splice(index, 1);
        }
        if (this.referenceElement) {
            this.referenceElement.style.visibility = hide ? "hidden" : "visible";
        }
    },

    get transitionPathHide() {
        return this.frame.presentation.elementsToHide.indexOf(this.transitionPathId) >= 0;
    },

    set transitionPathHide(hide) {
        var hidden = this.transitionPathHide;
        if (hide && !hidden) {
            this.frame.presentation.elementsToHide.push(this.transitionPathId);
        }
        else if (!hide && hidden) {
            var index = this.frame.presentation.elementsToHide.indexOf(this.transitionPathId);
            this.frame.presentation.elementsToHide.splice(index, 1);
        }
        if (this.transitionPath) {
            this.transitionPath.style.visibility = hide ? "hidden" : "visible";
        }
    }
};

export var Frame = {

    // Default values for new frames
    title: "New frame",
    timeoutMs: 0,
    timeoutEnable: false,
    transitionDurationMs: 1000,
    showInFrameList: true,
    showFrameNumber: true,

    init(presentation) {
        this.presentation = presentation;
        this.frameId = presentation.makeFrameId();
        this.layerProperties = presentation.layers.map(lp => Object.create(LayerProperties).init(this));
        this.cameraStates = presentation.layers.map(cs => Object.create(CameraState).init(presentation.document.root));
        return this;
    },

    initFrom(other, preserveId) {
        this.presentation = other.presentation;
        if (!preserveId) {
            this.frameId = other.presentation.makeFrameId();
        }
        this.title = other.title;
        this.timeoutMs = other.timeoutMs;
        this.timeoutEnable = other.timeoutEnable;
        this.transitionDurationMs = other.transitionDurationMs;
        this.showInFrameList = other.showInFrameList;
        this.showFrameNumber = other.showFrameNumber;
        this.layerProperties = other.layerProperties.map(lp => Object.create(LayerProperties).initFrom(lp));
        this.cameraStates = other.cameraStates.map(cs => Object.create(CameraState).initFrom(cs));
        return this;
    },

    toStorable() {
        var layerProperties = {};
        var cameraStates = {};
        var cameraOffsets = {};

        this.presentation.layers.forEach((layer, index) => {
            var lp = this.layerProperties[index];
            var cs = this.cameraStates[index];
            var re = lp.referenceElement;

            var key = layer.groupId;
            layerProperties[key] = lp.toStorable();
            cameraStates[key] = cs.toStorable();
            if (re) {
                cameraOffsets[key] = this.cameraStates[index].offsetFromElement(re);
            }
        });

        return {
            frameId: this.frameId,
            title: this.title,
            timeoutMs: this.timeoutMs,
            timeoutEnable: this.timeoutEnable,
            transitionDurationMs: this.transitionDurationMs,
            showInFrameList: this.showInFrameList,
            showFrameNumber: this.showFrameNumber,
            layerProperties,
            cameraStates,
            cameraOffsets
        };
    },

    toMinimalStorable() {
        var layerProperties = {};
        var cameraStates = {};

        this.presentation.layers.forEach((layer, index) => {
            var lp = this.layerProperties[index];
            var cs = this.cameraStates[index];

            var key = layer.groupId;
            layerProperties[key] = lp.toMinimalStorable();
            cameraStates[key] = cs.toMinimalStorable();
        });

        return {
            frameId: this.frameId,
            title: this.title,
            timeoutMs: this.timeoutMs,
            timeoutEnable: this.timeoutEnable,
            transitionDurationMs: this.transitionDurationMs,
            showInFrameList: this.showInFrameList,
            showFrameNumber: this.showFrameNumber,
            layerProperties,
            cameraStates
        };
    },

    fromStorable(storable) {
        copyIfSet(this, storable, "frameId");
        copyIfSet(this, storable, "title");
        copyIfSet(this, storable, "timeoutMs");
        copyIfSet(this, storable, "timeoutEnable");
        copyIfSet(this, storable, "transitionDurationMs");
        copyIfSet(this, storable, "showInFrameList");
        copyIfSet(this, storable, "showFrameNumber");

        // TODO if storable.layerProperties has keys not in layers, create fake layers marked as "deleted"
        this.presentation.layers.forEach((layer, index) => {
            var key = layer.groupId;
            if (key in storable.layerProperties) {
                var lp = this.layerProperties[index];
                lp.fromStorable(storable.layerProperties[key]);

                var cs = this.cameraStates[index].fromStorable(storable.cameraStates[key]);
                var re = lp.referenceElement;
                if (re) {
                    var ofs = storable.cameraOffsets[key] || {};
                    cs.setAtElement(re, ofs.deltaX, ofs.deltaY,
                                    ofs.widthFactor, ofs.heightFactor,
                                    ofs.deltaAngle);
                    // TODO compare current camera state with stored camera state.
                    // If different, mark the current layer as "dirty".
                }
            }
            // TODO else, link to "auto" layer
        });

        return this;
    },

    get index() {
        return this.presentation.frames.indexOf(this);
    },

    setAtStates(states) {
        states.forEach((state, index) => {
            this.cameraStates[index].initFrom(state);
        });
    }
};

export var Layer = {

    init(presentation, label, auto) {
        this.presentation = presentation;
        this.label = label;
        this.auto = auto;
        this.svgNodes = [];
        return this;
    },

    get groupId() {
        return this.auto ? "__sozi_auto__" : this.svgNodes[0].getAttribute("id");
    },

    get index() {
        return this.presentation.layers.indexOf(this);
    },

    get isVisible() {
        return this.svgNodes.some(node => window.getComputedStyle(node).visibility === "visible");
    },

    set isVisible(visible) {
        this.svgNodes.forEach(node => {
            node.style.visibility = visible ? "visible" : "hidden";
        });
    }
};

// Constant: the SVG namespace
var SVG_NS = "http://www.w3.org/2000/svg";

export var Presentation = {

    aspectWidth: 4,
    aspectHeight: 3,

    /*
     * Initialize a Sozi document object.
     *
     * Returns:
     *    - The current presentation object.
     */
    init(svgDocument) {
        this.document = svgDocument;
        this.frames = [];
        this.layers = [];
        this.elementsToHide = [];

        // Create an empty wrapper layer for elements that do not belong to a valid layer
        var autoLayer = Object.create(Layer).init(this, "auto", true);

        toArray(this.document.root.childNodes).forEach(svgNode => {
            if (svgNode.localName === "g") {
                var nodeId = svgNode.getAttribute("id");
                if (nodeId === null) {
                    autoLayer.svgNodes.push(svgNode);
                }
                else {
                    // Add the current node as a new layer.
                    var layer = Object.create(Layer).init(this,
                        this.document.handler.getLabel(svgNode) || ("#" + nodeId),
                        false);
                    layer.svgNodes.push(svgNode);
                    this.layers.push(layer);
                }
            }
        });

        this.layers.push(autoLayer);

        return this;
    },

    toStorable() {
        return {
            aspectWidth: this.aspectWidth,
            aspectHeight: this.aspectHeight,
            frames: this.frames.map(frame => frame.toStorable()),
            elementsToHide: this.elementsToHide.slice()
        };
    },

    toMinimalStorable() {
        return {
            frames: this.frames.map(frame => frame.toMinimalStorable()),
            elementsToHide: this.elementsToHide.slice()
        };
    },

    fromStorable(storable) {
        copyIfSet(this, storable, "aspectWidth");
        copyIfSet(this, storable, "aspectHeight");

        this.frames = storable.frames.map(f => Object.create(Frame).init(this).fromStorable(f));

        if (storable.elementsToHide) {
            this.elementsToHide = storable.elementsToHide.slice();
        }

        return this;
    },

    get title() {
        var svgTitles = this.document.root.getElementsByTagNameNS(SVG_NS, "title");
        return svgTitles.length ? svgTitles[0].firstChild.wholeText.trim() : "Untitled";
    },

    makeFrameId() {
        var prefix = "frame";
        var suffix = Math.floor(1000 * (1 + 9 * Math.random()));
        var frameId;
        do {
            frameId = prefix + suffix;
            suffix ++;
        } while (this.frames.some(frame => frame.frameId === frameId));
        return frameId;
    },

    getFrameWithId(frameId) {
        for (var i = 0; i < this.frames.length; i ++) {
            if (this.frames[i].frameId === frameId) {
                return this.frames[i];
            }
        }
        return null;
    },

    getLayerWithId(groupId) {
        for (var i = 0; i < this.layers.length; i ++) {
            if (this.layers[i].groupId === groupId) {
                return this.layers[i];
            }
        }
        return null;
    },

    updateLinkedLayers() {
        if (!this.frames.length) {
            return;
        }

        var firstCameraStates = this.frames[0].cameraStates;
        var defaultCameraState = firstCameraStates[firstCameraStates.length - 1];

        this.layers.forEach((layer, layerIndex) => {
            var cameraState = defaultCameraState;

            this.frames.forEach(frame => {
                if (frame.layerProperties[layerIndex].link) {
                    frame.cameraStates[layerIndex].initFrom(cameraState);
                }
                else {
                    cameraState = frame.cameraStates[layerIndex];
                }
            });
        });
    }
};
<commit_msg>Fixes #296: toggle visibility of layer elements and their children<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

import {toArray} from "../utils";
import {CameraState} from "./CameraState";

function copyIfSet(dest, src, prop) {
    if (src.hasOwnProperty(prop)) {
        dest[prop] = src[prop];
    }
}

export var LayerProperties = {

    link: false,
    referenceElementId: "",
    referenceElementAuto: true,
    transitionTimingFunction: "linear",
    transitionRelativeZoom: 0,
    transitionPathId: "",

    init(frame) {
        this.frame = frame;
        return this;
    },

    initFrom(other) {
        this.frame = other.frame;
        this.link = other.link;
        this.referenceElementId = other.referenceElementId;
        this.referenceElementAuto = other.referenceElementAuto;
        this.transitionTimingFunction = other.transitionTimingFunction;
        this.transitionRelativeZoom = other.transitionRelativeZoom;
        this.transitionPathId = other.transitionPathId;
        return this;
    },

    toStorable() {
        return {
            link: this.link,
            referenceElementId: this.referenceElementId,
            referenceElementAuto: this.referenceElementAuto,
            transitionTimingFunction: this.transitionTimingFunction,
            transitionRelativeZoom: this.transitionRelativeZoom,
            transitionPathId: this.transitionPathId
        };
    },

    toMinimalStorable() {
        return {
            transitionTimingFunction: this.transitionTimingFunction,
            transitionRelativeZoom: this.transitionRelativeZoom,
            transitionPathId: this.transitionPathId
        };
    },

    fromStorable(storable) {
        copyIfSet(this, storable, "link");
        copyIfSet(this, storable, "referenceElementId");
        copyIfSet(this, storable, "referenceElementAuto");
        copyIfSet(this, storable, "transitionTimingFunction");
        copyIfSet(this, storable, "transitionRelativeZoom");
        copyIfSet(this, storable, "transitionPathId");
        return this;
    },

    get index() {
        return this.frame.layerProperties.indexOf(this);
    },

    get referenceElement() {
        return this.frame.presentation.document.root.getElementById(this.referenceElementId);
    },

    get transitionPath() {
        return this.frame.presentation.document.root.getElementById(this.transitionPathId);
    },

    get referenceElementHide() {
        return this.frame.presentation.elementsToHide.indexOf(this.referenceElementId) >= 0;
    },

    set referenceElementHide(hide) {
        var hidden = this.referenceElementHide;
        if (hide && !hidden) {
            this.frame.presentation.elementsToHide.push(this.referenceElementId);
        }
        else if (!hide && hidden) {
            var index = this.frame.presentation.elementsToHide.indexOf(this.referenceElementId);
            this.frame.presentation.elementsToHide.splice(index, 1);
        }
        if (this.referenceElement) {
            this.referenceElement.style.visibility = hide ? "hidden" : "visible";
        }
    },

    get transitionPathHide() {
        return this.frame.presentation.elementsToHide.indexOf(this.transitionPathId) >= 0;
    },

    set transitionPathHide(hide) {
        var hidden = this.transitionPathHide;
        if (hide && !hidden) {
            this.frame.presentation.elementsToHide.push(this.transitionPathId);
        }
        else if (!hide && hidden) {
            var index = this.frame.presentation.elementsToHide.indexOf(this.transitionPathId);
            this.frame.presentation.elementsToHide.splice(index, 1);
        }
        if (this.transitionPath) {
            this.transitionPath.style.visibility = hide ? "hidden" : "visible";
        }
    }
};

export var Frame = {

    // Default values for new frames
    title: "New frame",
    timeoutMs: 0,
    timeoutEnable: false,
    transitionDurationMs: 1000,
    showInFrameList: true,
    showFrameNumber: true,

    init(presentation) {
        this.presentation = presentation;
        this.frameId = presentation.makeFrameId();
        this.layerProperties = presentation.layers.map(lp => Object.create(LayerProperties).init(this));
        this.cameraStates = presentation.layers.map(cs => Object.create(CameraState).init(presentation.document.root));
        return this;
    },

    initFrom(other, preserveId) {
        this.presentation = other.presentation;
        if (!preserveId) {
            this.frameId = other.presentation.makeFrameId();
        }
        this.title = other.title;
        this.timeoutMs = other.timeoutMs;
        this.timeoutEnable = other.timeoutEnable;
        this.transitionDurationMs = other.transitionDurationMs;
        this.showInFrameList = other.showInFrameList;
        this.showFrameNumber = other.showFrameNumber;
        this.layerProperties = other.layerProperties.map(lp => Object.create(LayerProperties).initFrom(lp));
        this.cameraStates = other.cameraStates.map(cs => Object.create(CameraState).initFrom(cs));
        return this;
    },

    toStorable() {
        var layerProperties = {};
        var cameraStates = {};
        var cameraOffsets = {};

        this.presentation.layers.forEach((layer, index) => {
            var lp = this.layerProperties[index];
            var cs = this.cameraStates[index];
            var re = lp.referenceElement;

            var key = layer.groupId;
            layerProperties[key] = lp.toStorable();
            cameraStates[key] = cs.toStorable();
            if (re) {
                cameraOffsets[key] = this.cameraStates[index].offsetFromElement(re);
            }
        });

        return {
            frameId: this.frameId,
            title: this.title,
            timeoutMs: this.timeoutMs,
            timeoutEnable: this.timeoutEnable,
            transitionDurationMs: this.transitionDurationMs,
            showInFrameList: this.showInFrameList,
            showFrameNumber: this.showFrameNumber,
            layerProperties,
            cameraStates,
            cameraOffsets
        };
    },

    toMinimalStorable() {
        var layerProperties = {};
        var cameraStates = {};

        this.presentation.layers.forEach((layer, index) => {
            var lp = this.layerProperties[index];
            var cs = this.cameraStates[index];

            var key = layer.groupId;
            layerProperties[key] = lp.toMinimalStorable();
            cameraStates[key] = cs.toMinimalStorable();
        });

        return {
            frameId: this.frameId,
            title: this.title,
            timeoutMs: this.timeoutMs,
            timeoutEnable: this.timeoutEnable,
            transitionDurationMs: this.transitionDurationMs,
            showInFrameList: this.showInFrameList,
            showFrameNumber: this.showFrameNumber,
            layerProperties,
            cameraStates
        };
    },

    fromStorable(storable) {
        copyIfSet(this, storable, "frameId");
        copyIfSet(this, storable, "title");
        copyIfSet(this, storable, "timeoutMs");
        copyIfSet(this, storable, "timeoutEnable");
        copyIfSet(this, storable, "transitionDurationMs");
        copyIfSet(this, storable, "showInFrameList");
        copyIfSet(this, storable, "showFrameNumber");

        // TODO if storable.layerProperties has keys not in layers, create fake layers marked as "deleted"
        this.presentation.layers.forEach((layer, index) => {
            var key = layer.groupId;
            if (key in storable.layerProperties) {
                var lp = this.layerProperties[index];
                lp.fromStorable(storable.layerProperties[key]);

                var cs = this.cameraStates[index].fromStorable(storable.cameraStates[key]);
                var re = lp.referenceElement;
                if (re) {
                    var ofs = storable.cameraOffsets[key] || {};
                    cs.setAtElement(re, ofs.deltaX, ofs.deltaY,
                                    ofs.widthFactor, ofs.heightFactor,
                                    ofs.deltaAngle);
                    // TODO compare current camera state with stored camera state.
                    // If different, mark the current layer as "dirty".
                }
            }
            // TODO else, link to "auto" layer
        });

        return this;
    },

    get index() {
        return this.presentation.frames.indexOf(this);
    },

    setAtStates(states) {
        states.forEach((state, index) => {
            this.cameraStates[index].initFrom(state);
        });
    }
};

export var Layer = {

    init(presentation, label, auto) {
        this.presentation = presentation;
        this.label = label;
        this.auto = auto;
        this.svgNodes = [];
        return this;
    },

    get groupId() {
        return this.auto ? "__sozi_auto__" : this.svgNodes[0].getAttribute("id");
    },

    get index() {
        return this.presentation.layers.indexOf(this);
    },

    get isVisible() {
        return this.svgNodes.some(node => window.getComputedStyle(node).display !== "none");
    },

    set isVisible(visible) {
        this.svgNodes.forEach(node => {
            node.style.display = visible ? "inline" : "none";
        });
    }
};

// Constant: the SVG namespace
var SVG_NS = "http://www.w3.org/2000/svg";

export var Presentation = {

    aspectWidth: 4,
    aspectHeight: 3,

    /*
     * Initialize a Sozi document object.
     *
     * Returns:
     *    - The current presentation object.
     */
    init(svgDocument) {
        this.document = svgDocument;
        this.frames = [];
        this.layers = [];
        this.elementsToHide = [];

        // Create an empty wrapper layer for elements that do not belong to a valid layer
        var autoLayer = Object.create(Layer).init(this, "auto", true);

        toArray(this.document.root.childNodes).forEach(svgNode => {
            if (svgNode.localName === "g") {
                var nodeId = svgNode.getAttribute("id");
                if (nodeId === null) {
                    autoLayer.svgNodes.push(svgNode);
                }
                else {
                    // Add the current node as a new layer.
                    var layer = Object.create(Layer).init(this,
                        this.document.handler.getLabel(svgNode) || ("#" + nodeId),
                        false);
                    layer.svgNodes.push(svgNode);
                    this.layers.push(layer);
                }
            }
        });

        this.layers.push(autoLayer);

        return this;
    },

    toStorable() {
        return {
            aspectWidth: this.aspectWidth,
            aspectHeight: this.aspectHeight,
            frames: this.frames.map(frame => frame.toStorable()),
            elementsToHide: this.elementsToHide.slice()
        };
    },

    toMinimalStorable() {
        return {
            frames: this.frames.map(frame => frame.toMinimalStorable()),
            elementsToHide: this.elementsToHide.slice()
        };
    },

    fromStorable(storable) {
        copyIfSet(this, storable, "aspectWidth");
        copyIfSet(this, storable, "aspectHeight");

        this.frames = storable.frames.map(f => Object.create(Frame).init(this).fromStorable(f));

        if (storable.elementsToHide) {
            this.elementsToHide = storable.elementsToHide.slice();
        }

        return this;
    },

    get title() {
        var svgTitles = this.document.root.getElementsByTagNameNS(SVG_NS, "title");
        return svgTitles.length ? svgTitles[0].firstChild.wholeText.trim() : "Untitled";
    },

    makeFrameId() {
        var prefix = "frame";
        var suffix = Math.floor(1000 * (1 + 9 * Math.random()));
        var frameId;
        do {
            frameId = prefix + suffix;
            suffix ++;
        } while (this.frames.some(frame => frame.frameId === frameId));
        return frameId;
    },

    getFrameWithId(frameId) {
        for (var i = 0; i < this.frames.length; i ++) {
            if (this.frames[i].frameId === frameId) {
                return this.frames[i];
            }
        }
        return null;
    },

    getLayerWithId(groupId) {
        for (var i = 0; i < this.layers.length; i ++) {
            if (this.layers[i].groupId === groupId) {
                return this.layers[i];
            }
        }
        return null;
    },

    updateLinkedLayers() {
        if (!this.frames.length) {
            return;
        }

        var firstCameraStates = this.frames[0].cameraStates;
        var defaultCameraState = firstCameraStates[firstCameraStates.length - 1];

        this.layers.forEach((layer, layerIndex) => {
            var cameraState = defaultCameraState;

            this.frames.forEach(frame => {
                if (frame.layerProperties[layerIndex].link) {
                    frame.cameraStates[layerIndex].initFrom(cameraState);
                }
                else {
                    cameraState = frame.cameraStates[layerIndex];
                }
            });
        });
    }
};
<|endoftext|>


<commit_before>//= require ./collection_view
//= require ./list_item_view
//= require ./list_view_drag_helper

/**
  Displays a list of items. Allows reordering if allowReordering is true.

  The reordering support is probably the most complicated part of this. It turns out that when reordering items,
  we cannot allow any of the observers on the content or childViews to fire, as that causes childViews to be
  updated, which causes flickering. Thus we update the DOM directly, and sneakily update the content and childViews
  arrays while suppressing the observers.
*/
Flame.ListView = Flame.CollectionView.extend(Flame.Statechart, {
    classNames: ['flame-list-view'],
    classNameBindings: ['isFocused'],
    acceptsKeyResponder: true,
    allowSelection: true,
    allowReordering: true,
    selection: undefined,
    initialState: 'idle',
    reorderDelegate: null,
    init: function() {
        this._super();
        this._selectionDidChange();
    },

    itemViewClass: Flame.ListItemView.extend({
        templateContext: function(key, value) {
            return value !== undefined ? value : Ember.get(this, 'content');
        }.property('content'),
        templateBinding: "parentView.template",
        handlebars: "{{title}}"
    }),

    selectIndex: function(index) {
        if (!this.get('allowSelection')) return false;
        var content = this.get('content');
        if (content) {
            var childView = this.get('childViews').objectAt(index);
            if (childView && childView.get('isVisible') && childView.get('allowSelection') !== false) {
                var selection = content.objectAt(index);
                this.set('selection', selection);
                return true;
            }
        }
        return false;
    },

    // direction -1 for up, 1 for down
    // returns true if selection did change
    changeSelection: function(direction) {
        var content = this.get('content');
        var selection = this.get('selection');
        var index = content.indexOf(selection);
        var newIndex = index + direction, len = content.get('length');
        while (newIndex >= 0 && newIndex < len) {  // With this loop we jump over items that cannot be selected
            if (this.selectIndex(newIndex)) return true;
            newIndex += direction;
        }
        return false;
    },

    _selectionWillChange: function() {
        this._setIsSelectedStatus(this.get('selection'), false);
    }.observesBefore('selection'),

    _selectionDidChange: function() {
        this._setIsSelectedStatus(this.get('selection'), true);
    }.observes('selection'),

    _setIsSelectedStatus: function(contentItem, status) {
        if (contentItem) {
            var index = (this.get('content') || []).indexOf(contentItem);
            if (index >= 0) {
                var child = this.get('childViews').objectAt(index);
                if (child) child.set('isSelected', status);
            }
        }
    },

    // If items are removed or reordered, we must update the contentIndex of each childView to reflect their current position in the list
    _updateContentIndexes: function() {
        var childViews = this.get('childViews');
        var len = childViews.get('length');
        for (var i = 0; i < len; i++) {
            var childView = childViews.objectAt(i);
            if (childView) childView.set('contentIndex', i);
        }
        // In case the child views are using absolute positioning, also their positions need to be updated,
        // otherwise they don't appear to move anywhere.
        this.consultLayoutManager();
    },

    didReorderContent: function(content) {
        var delegate = this.get('reorderDelegate');
        if (delegate) {
            Ember.run.next(function() {
                delegate.didReorderContent(content);
            });
        }
    },

    isValidDrop: function(itemDragged, newParent, dropTarget) {
        var delegate = this.get('reorderDelegate');
        if (delegate && delegate.isValidDrop) {
            return delegate.isValidDrop(itemDragged, newParent, dropTarget);
        } else {
            return true;
        }
    },

    // Overridden in TreeView
    rootTreeView: function() {
        return this;
    }.property().volatile(),

    arrayWillChange: function(content, start, removedCount) {
        if (!this.getPath('rootTreeView.isDragging')) {
            return this._super.apply(this, arguments);
        }
    },

    arrayDidChange: function(content, start, removed, added) {
        if (!this.getPath('rootTreeView.isDragging')) {
            var result = this._super.apply(this, arguments);
            this._updateContentIndexes();
            return result;
        }
    },

    childViewsWillChange: function() {
        if (!this.getPath('rootTreeView.isDragging')) {
            return this._super.apply(this, arguments);
        }
    },

    childViewsDidChange: function() {
        if (!this.getPath('rootTreeView.isDragging')) {
            return this._super.apply(this, arguments);
        }
    },

    // Override if needed, return false to disallow reordering that particular item
    allowReorderingItem: function(itemIndex) {
        return true;
    },

    idle: Flame.State.extend({
        moveUp: function() { return this.get('owner').changeSelection(-1); },
        moveDown: function() { return this.get('owner').changeSelection(1); },

        mouseDownOnItem: function(itemIndex, evt) {
            var owner = this.get('owner');
            owner.selectIndex(itemIndex);

            // Store some information in case user starts dragging (i.e. moves mouse with the button pressed down),
            // but only if reordering is generally allowed for this list view and for the particular item
            if (owner.get('allowReordering') && itemIndex !== undefined) {
                if (owner.allowReorderingItem(itemIndex)) {
                    //console.log('Drag started on %s, dragging %s items', itemIndex, itemCount);
                    var childView = owner.get('childViews').objectAt(itemIndex);
                    owner.set('dragHelper', Flame.ListViewDragHelper.create({
                        listView: owner,
                        lastPageX: evt.pageX,
                        yOffset: evt.pageY - childView.$().offset().top,
                        itemPath: [itemIndex]
                    }));
                }
            }

            this.gotoState('mouseButtonPressed');

            // Have to always return true here because the user might start dragging, and if so, we need the mouseMove events.
            return true;
        },

        enterState: function() {
            this.get('owner').set('dragHelper', undefined);  // In case dragging was allowed but not started, clear the drag data
        }
    }),

    // This is here so that we can override the behaviour in tree views
    startReordering: function(dragHelper, event) {
        dragHelper.set('listView', this);
        this.set('dragHelper', dragHelper);
        this.gotoState('reordering');
        return this.mouseMove(event);  // Handle also this event in the new state
    },

    mouseButtonPressed: Flame.State.extend({
        mouseUpOnItem: Flame.State.gotoHandler('idle'),
        mouseUp: Flame.State.gotoHandler('idle'),

        mouseMove: function(event) {
            var owner = this.get('owner');
            if (owner.get('dragHelper')) {  // Only enter reordering state if it was allowed, indicated by the presence of dragHelper
                var dragHelper = owner.get('dragHelper');
                this.gotoState('idle');
                owner.startReordering(dragHelper, event);
            }
            return true;
        },

        touchEnd: Flame.State.gotoHandler('idle'),

        touchMove: function(event) {
            this.mouseMove(this.normalizeTouchEvents(event));
            return true;
        }
    }),

    reordering: Flame.State.extend({
        mouseMove: function(evt, view, scheduled) {
            return this.get('owner').get('dragHelper').updateDisplay(evt);
        },

        mouseUp: Flame.State.gotoHandler('idle'),

        touchMove: function(event) {
            this.mouseMove(this.normalizeTouchEvents(event));
            return true;
        },

        touchEnd: Flame.State.gotoHandler('idle'),

        // Start reorder drag operation
        enterState: function() {
            var owner = this.get('owner');
            owner.get('dragHelper').initReorder();
            owner.set('isDragging', true);
        },

        // When exiting the reorder state, we need to hide the dragged clone and restore the look of the dragged child view
        exitState: function() {
            var owner = this.get('owner');
            owner.get('dragHelper').finishReorder();
            owner.set('dragHelper', undefined);
            owner.set('isDragging', false);
        }
    })
});
<commit_msg>Start reordering only after movement of 4 or more pixels.<commit_after>//= require ./collection_view
//= require ./list_item_view
//= require ./list_view_drag_helper

/**
  Displays a list of items. Allows reordering if allowReordering is true.

  The reordering support is probably the most complicated part of this. It turns out that when reordering items,
  we cannot allow any of the observers on the content or childViews to fire, as that causes childViews to be
  updated, which causes flickering. Thus we update the DOM directly, and sneakily update the content and childViews
  arrays while suppressing the observers.
*/
Flame.ListView = Flame.CollectionView.extend(Flame.Statechart, {
    classNames: ['flame-list-view'],
    classNameBindings: ['isFocused'],
    acceptsKeyResponder: true,
    allowSelection: true,
    allowReordering: true,
    selection: undefined,
    initialState: 'idle',
    reorderDelegate: null,
    _minimumDeltaToStartDrag: 4,
    init: function() {
        this._super();
        this._selectionDidChange();
    },

    itemViewClass: Flame.ListItemView.extend({
        templateContext: function(key, value) {
            return value !== undefined ? value : Ember.get(this, 'content');
        }.property('content'),
        templateBinding: "parentView.template",
        handlebars: "{{title}}"
    }),

    selectIndex: function(index) {
        if (!this.get('allowSelection')) return false;
        var content = this.get('content');
        if (content) {
            var childView = this.get('childViews').objectAt(index);
            if (childView && childView.get('isVisible') && childView.get('allowSelection') !== false) {
                var selection = content.objectAt(index);
                this.set('selection', selection);
                return true;
            }
        }
        return false;
    },

    // direction -1 for up, 1 for down
    // returns true if selection did change
    changeSelection: function(direction) {
        var content = this.get('content');
        var selection = this.get('selection');
        var index = content.indexOf(selection);
        var newIndex = index + direction, len = content.get('length');
        while (newIndex >= 0 && newIndex < len) {  // With this loop we jump over items that cannot be selected
            if (this.selectIndex(newIndex)) return true;
            newIndex += direction;
        }
        return false;
    },

    _selectionWillChange: function() {
        this._setIsSelectedStatus(this.get('selection'), false);
    }.observesBefore('selection'),

    _selectionDidChange: function() {
        this._setIsSelectedStatus(this.get('selection'), true);
    }.observes('selection'),

    _setIsSelectedStatus: function(contentItem, status) {
        if (contentItem) {
            var index = (this.get('content') || []).indexOf(contentItem);
            if (index >= 0) {
                var child = this.get('childViews').objectAt(index);
                if (child) child.set('isSelected', status);
            }
        }
    },

    // If items are removed or reordered, we must update the contentIndex of each childView to reflect their current position in the list
    _updateContentIndexes: function() {
        var childViews = this.get('childViews');
        var len = childViews.get('length');
        for (var i = 0; i < len; i++) {
            var childView = childViews.objectAt(i);
            if (childView) childView.set('contentIndex', i);
        }
        // In case the child views are using absolute positioning, also their positions need to be updated,
        // otherwise they don't appear to move anywhere.
        this.consultLayoutManager();
    },

    didReorderContent: function(content) {
        var delegate = this.get('reorderDelegate');
        if (delegate) {
            Ember.run.next(function() {
                delegate.didReorderContent(content);
            });
        }
    },

    isValidDrop: function(itemDragged, newParent, dropTarget) {
        var delegate = this.get('reorderDelegate');
        if (delegate && delegate.isValidDrop) {
            return delegate.isValidDrop(itemDragged, newParent, dropTarget);
        } else {
            return true;
        }
    },

    // Overridden in TreeView
    rootTreeView: function() {
        return this;
    }.property().volatile(),

    arrayWillChange: function(content, start, removedCount) {
        if (!this.getPath('rootTreeView.isDragging')) {
            return this._super.apply(this, arguments);
        }
    },

    arrayDidChange: function(content, start, removed, added) {
        if (!this.getPath('rootTreeView.isDragging')) {
            var result = this._super.apply(this, arguments);
            this._updateContentIndexes();
            return result;
        }
    },

    childViewsWillChange: function() {
        if (!this.getPath('rootTreeView.isDragging')) {
            this._super.apply(this, arguments);
        }
    },

    childViewsDidChange: function() {
        if (!this.getPath('rootTreeView.isDragging')) {
            this._super.apply(this, arguments);
        }
    },

    // Override if needed, return false to disallow reordering that particular item
    allowReorderingItem: function(itemIndex) {
        return true;
    },

    idle: Flame.State.extend({
        moveUp: function() { return this.get('owner').changeSelection(-1); },
        moveDown: function() { return this.get('owner').changeSelection(1); },

        mouseDownOnItem: function(itemIndex, evt) {
            var owner = this.get('owner');
            owner.selectIndex(itemIndex);

            // Store some information in case user starts dragging (i.e. moves mouse with the button pressed down),
            // but only if reordering is generally allowed for this list view and for the particular item
            if (owner.get('allowReordering') && itemIndex !== undefined) {
                if (owner.allowReorderingItem(itemIndex)) {
                    //console.log('Drag started on %s, dragging %s items', itemIndex, itemCount);
                    var childView = owner.get('childViews').objectAt(itemIndex);
                    owner.set('dragHelper', Flame.ListViewDragHelper.create({
                        listView: owner,
                        lastPageX: evt.pageX,
                        lastPageY: evt.pageY,
                        yOffset: evt.pageY - childView.$().offset().top,
                        itemPath: [itemIndex]
                    }));
                }
            }

            this.gotoState('mouseButtonPressed');

            // Have to always return true here because the user might start dragging, and if so, we need the mouseMove events.
            return true;
        },

        enterState: function() {
            this.get('owner').set('dragHelper', undefined);  // In case dragging was allowed but not started, clear the drag data
        }
    }),

    _shouldStartDragging: function(event) {
        var dragHelper = this.get('dragHelper');
        if (dragHelper) {
            // Only enter reordering state if it was allowed, indicated by the presence of dragHelper and then only if
            // we've moved the mouse enough from the start.
            var deltaX = Math.abs(dragHelper.get("lastPageX") - event.pageX);
            var deltaY = Math.abs(dragHelper.get("lastPageY") - event.pageY);
            return deltaX > this._minimumDeltaToStartDrag || deltaY > this._minimumDeltaToStartDrag;
        }
        return false;
    },

    // This is here so that we can override the behaviour in tree views
    startReordering: function(dragHelper, event) {
        dragHelper.set('listView', this);
        this.set('dragHelper', dragHelper);
        this.gotoState('reordering');
        return this.mouseMove(event);  // Handle also this event in the new state
    },

    mouseButtonPressed: Flame.State.extend({
        mouseUpOnItem: Flame.State.gotoHandler('idle'),
        mouseUp: Flame.State.gotoHandler('idle'),

        mouseMove: function(event) {
            var owner = this.get('owner');
            var dragHelper = owner.get('dragHelper');
            if (owner._shouldStartDragging(event)) {
                this.gotoState('idle');
                owner.startReordering(dragHelper, event);
            }
            return true;
        },

        touchEnd: Flame.State.gotoHandler('idle'),

        touchMove: function(event) {
            this.mouseMove(this.normalizeTouchEvents(event));
            return true;
        }
    }),

    reordering: Flame.State.extend({
        mouseMove: function(evt, view, scheduled) {
            return this.get('owner').get('dragHelper').updateDisplay(evt);
        },

        mouseUp: Flame.State.gotoHandler('idle'),

        touchMove: function(event) {
            this.mouseMove(this.normalizeTouchEvents(event));
            return true;
        },

        touchEnd: Flame.State.gotoHandler('idle'),

        // Start reorder drag operation
        enterState: function() {
            var owner = this.get('owner');
            owner.get('dragHelper').initReorder();
            owner.set('isDragging', true);
        },

        // When exiting the reorder state, we need to hide the dragged clone and restore the look of the dragged child view
        exitState: function() {
            var owner = this.get('owner');
            owner.get('dragHelper').finishReorder();
            owner.set('dragHelper', undefined);
            owner.set('isDragging', false);
        }
    })
});
<|endoftext|>


<commit_before>(function () {
    "use strict";

    var canvas = new draw2d.Canvas("canvas");

    function initRectangles() {

        var rectRight = new draw2d.shape.basic.Rectangle({
            x: 410,
            y: 10,
            width: 80,
            height: 80,
            bgColor: '#D3D3D3'
        });

        rectRight.add(new draw2d.shape.basic.Label({
            text: "Rect", stroke: 0
        }), new draw2d.layout.locator.CenterLocator());
        rectRight.createPort("input", new draw2d.layout.locator.LeftLocator(rectRight));
        rectRight.setDashArray("- ");
        canvas.add(rectRight);
        rectRight.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());

        var rectLeft = new draw2d.shape.basic.Rectangle({
            x: 10,
            y: 10,
            width: 80,
            height: 80,
            bgColor: '#D3D3D3'
            // bgColor: 'lightgrey'
        });
        rectLeft.add(new draw2d.shape.basic.Label({text: "Rect", stroke: 0}), new draw2d.layout.locator.CenterLocator());
        rectLeft.createPort("output", new draw2d.layout.locator.RightLocator(rectLeft));
        canvas.add(rectLeft);
        rectLeft.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());

        var label = new draw2d.shape.basic.Label({text: "Label", stroke: 0});

        var connection = new draw2d.Connection({
            source: rectLeft.getOutputPort(0),
            target: rectRight.getInputPort(0),
            router: new draw2d.layout.connection.InteractiveManhattanConnectionRouter(),
            color:"#000"
        });
        connection.add(label, new draw2d.layout.locator.ManhattanMidpointLocator());
        canvas.add(connection);
    }

    function initCircle() {

        var circleLeft = new draw2d.shape.basic.Circle({radius: 40});
        //circleLeft.setColor("#000000");
        circleLeft.setBackgroundColor("#FFFFFF");
        circleLeft.add(new draw2d.shape.basic.Label({
            text: "Circle",
            stroke: 0
        }), new draw2d.layout.locator.CenterLocator());
        circleLeft.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());

        var circleRight = new draw2d.shape.basic.Circle({radius: 40});
        //circleRight.setColor("#000000");
        circleRight.setBackgroundColor("#FFFFFF");
        circleRight.add(new draw2d.shape.basic.Label({
            text: "Circle",
            stroke: 0,
            fill: '#FFFFFF'
        }).setColor("#FFFFFF"), new draw2d.layout.locator.CenterLocator());
        circleRight.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());
        circleRight.createPort("input", new draw2d.layout.locator.LeftLocator(circleRight));
        canvas.add(circleRight, 410, 410 );
        circleLeft.createPort("output", new draw2d.layout.locator.RightLocator(circleLeft));
        canvas.add(circleLeft, 10, 410);

        var connection = new draw2d.Connection({
            stroke: '1',
            source: circleLeft.getOutputPort(0),
            target: circleRight.getInputPort(0),
            router: new draw2d.layout.connection.InteractiveManhattanConnectionRouter(),
            color:"#000"
        });
        connection.setDashArray("--");
        canvas.add(connection);
    }

    function exportAsImage() {
        var downloadWindow = window.open();
        var writer = new draw2d.io.png.Writer();
        downloadWindow.document.write('');
        var element = downloadWindow.document.getElementById("download");

        writer.marshal(canvas, function (image) {
            element.setAttribute("src", image);
        });
    }

    function createNewRect() {

        var rect = new draw2d.shape.node.Between({
            x: 210,
            y: 210,
            width: 80,
            height: 80,
            bgColor: "#D3D3D3"
        });

        rect.add(new draw2d.shape.basic.Label({text: "Rect", stroke: 0}), new draw2d.layout.locator.CenterLocator());
        rect.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());
        canvas.add(rect);
        canvas.installEditPolicy(new draw2d.policy.canvas.CoronaDecorationPolicy());
    }

    function createNewCircle() {
        var leftCircle = new draw2d.shape.basic.Circle({radius: 40});
        leftCircle.setBackgroundColor("#FFFFFF");
        leftCircle.add(new draw2d.shape.basic.Label({
            text: "Circle",
            stroke: 0
        }), new draw2d.layout.locator.CenterLocator());
        leftCircle.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());
        canvas.add(leftCircle, 200, 200);
    }

    function main() {
        initRectangles();
        initCircle();
        $("#addRectBtn").click(createNewRect);
        $("#addCircleBtn").click(createNewCircle);
        $('#exportBtn').click(exportAsImage);
    }

    main();
}());
<commit_msg>Fixed which is not exported by the css for draw2d<commit_after>(function () {
    "use strict";

    var canvas = new draw2d.Canvas("canvas");

    function initRectangles() {

        var rectRight = new draw2d.shape.basic.Rectangle({
            x: 410,
            y: 10,
            width: 80,
            height: 80,
            bgColor: '#D3D3D3'
        });

        rectRight.add(new draw2d.shape.basic.Label({
            text: "Rect", stroke: 0, fontSize: 20
        }), new draw2d.layout.locator.CenterLocator());
        rectRight.createPort("input", new draw2d.layout.locator.LeftLocator(rectRight));
        rectRight.setDashArray("- ");
        canvas.add(rectRight);
        rectRight.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());

        var rectLeft = new draw2d.shape.basic.Rectangle({
            x: 10,
            y: 10,
            width: 80,
            height: 80,
            bgColor: '#D3D3D3'
            // bgColor: 'lightgrey'
        });
        rectLeft.add(new draw2d.shape.basic.Label({
            text: "Rect",
            stroke: 0,
            fontSize: 20
        }), new draw2d.layout.locator.CenterLocator());
        rectLeft.createPort("output", new draw2d.layout.locator.RightLocator(rectLeft));
        canvas.add(rectLeft);
        rectLeft.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());

        var label = new draw2d.shape.basic.Label({text: "Label", stroke: 0, fontSize: 20});

        var connection = new draw2d.Connection({
            source: rectLeft.getOutputPort(0),
            target: rectRight.getInputPort(0),
            router: new draw2d.layout.connection.InteractiveManhattanConnectionRouter(),
            color: "#000"
        });
        connection.add(label, new draw2d.layout.locator.ManhattanMidpointLocator());
        canvas.add(connection);
    }

    function initCircle() {

        var circleLeft = new draw2d.shape.basic.Circle({radius: 40});
        //circleLeft.setColor("#000000");
        circleLeft.setBackgroundColor("#FFFFFF");
        circleLeft.add(new draw2d.shape.basic.Label({
            text: "Circle",
            stroke: 0,
            fontSize: 20
        }), new draw2d.layout.locator.CenterLocator());
        circleLeft.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());

        var circleRight = new draw2d.shape.basic.Circle({radius: 40});
        //circleRight.setColor("#000000");
        circleRight.setBackgroundColor("#FFFFFF");
        circleRight.add(new draw2d.shape.basic.Label({
            text: "Circle",
            stroke: 0,
            fill: '#FFFFFF',
            fontSize: 20
        }).setColor("#FFFFFF"), new draw2d.layout.locator.CenterLocator());
        circleRight.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());
        circleRight.createPort("input", new draw2d.layout.locator.LeftLocator(circleRight));
        canvas.add(circleRight, 410, 410);
        circleLeft.createPort("output", new draw2d.layout.locator.RightLocator(circleLeft));
        canvas.add(circleLeft, 10, 410);

        var connection = new draw2d.Connection({
            stroke: '1',
            source: circleLeft.getOutputPort(0),
            target: circleRight.getInputPort(0),
            router: new draw2d.layout.connection.InteractiveManhattanConnectionRouter(),
            color: "#000"
        });
        connection.setDashArray("--");
        canvas.add(connection);
    }

    function exportAsImage() {
        var downloadWindow = window.open();
        var writer = new draw2d.io.png.Writer();
        downloadWindow.document.write('');
        var element = downloadWindow.document.getElementById("download");

        writer.marshal(canvas, function (image) {
            element.setAttribute("src", image);
        });
    }

    function createNewRect() {

        var rect = new draw2d.shape.node.Between({
            x: 210,
            y: 210,
            width: 80,
            height: 80,
            bgColor: "#D3D3D3"
        });

        rect.add(new draw2d.shape.basic.Label({text: "Rect", stroke: 0}), new draw2d.layout.locator.CenterLocator());
        rect.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());
        canvas.add(rect);
        canvas.installEditPolicy(new draw2d.policy.canvas.CoronaDecorationPolicy());
    }

    function createNewCircle() {
        var leftCircle = new draw2d.shape.basic.Circle({radius: 40});
        leftCircle.setBackgroundColor("#FFFFFF");
        leftCircle.add(new draw2d.shape.basic.Label({
            text: "Circle",
            stroke: 0
        }), new draw2d.layout.locator.CenterLocator());
        leftCircle.installEditPolicy(new draw2d.policy.figure.GlowSelectionFeedbackPolicy());
        canvas.add(leftCircle, 200, 200);
    }

    function main() {
        initRectangles();
        initCircle();
        $("#addRectBtn").click(createNewRect);
        $("#addCircleBtn").click(createNewCircle);
        $('#exportBtn').click(exportAsImage);
    }

    main();
}());
<|endoftext|>


<commit_before><commit_msg>don't add buffers in an async way for now<commit_after><|endoftext|>


<commit_before>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2010-2012 Zynga Inc.
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

(function(undef)
{
	/** {Map} Maps simple property names to global property IDs */
	var propertyNameToId = {};

	/** {=String} Field where the data is stored */
	var store = "$$data";

	/**
	 * Property handling for simple key/value like properties which might have an optional init value.
	 *
	 * Supports the following configuration keys:
	 *
	 * - `type`: Check the incoming value for the given type or function.
	 * - `apply`: Link to function to call after a new value has been stored. The signature of the method is
	 * `function(newValue, oldValue)`
	 * - `fire`: Event to fire after a new value has been stored (and apply has been called). The listeners
	 * are called with 3 parameters: value, old value and property name.
	 * - `init`: Init value for the property. If no value is set or the property gets reset, the getter
	 * will return the `init` value.
	 * - `nullable`: Whether the property is able to store null values. This also allows the system to
	 * return `null` when no other value is available. Otherwise an error is thrown whenever no value is
	 * available.
	 *
	 * #break(core.property.Debug)
	 * #break(core.property.Event)
	 */
	core.Module("core.property.Simple",
	{
		/**
		 * {Map} Creates a new set of member methods for the given property @config {Map}.
		 *
		 * Please note that you need to define one of "init" or "nullable". Otherwise you
		 * might get errors during runtime function calls.
		 */
		create : function(config)
		{
			/*
			---------------------------------------------------------------------------
				 INTRO
			---------------------------------------------------------------------------
			*/

			// Shorthands: Better compression/obfuscation/performance
			var propertyName = config.name;
			var propertyNullable = config.nullable;
			var propertyInit = config.init;
			var propertyType = config.type;
			var propertyFire = config.fire;
			var propertyApply = config.apply;
			var propertyCast = config.cast;

			// Validation
			if (jasy.Env.isSet("debug"))
			{
				/** #require(ext.sugar.Object) */
				var invalidKeys = Object.validateKeys(config, "name,nullable,init,type,fire,apply,wrap".split(","));
				if (invalidKeys.length > 0) {
					throw new Error("Property declaration of " + propertyName + " contains invalid configuration keys: " + invalidKeys.join(", ") + "!");
				}

				core.Assert.isType(propertyName, "String");

				if (propertyNullable !== undef) {
					core.Assert.isType(propertyNullable, "Boolean");
				}

				if (propertyType) {
					core.property.Debug.isValidType(propertyType);
				}

				if (propertyFire) {
					core.Assert.isType(propertyFire, "String");
				}

				if (propertyApply) {
					core.Assert.isType(propertyApply, "Function");
				}

				if (propertyCast != null)
				{
					core.Assert.isType(propertyCast, "Boolean");

					// When enabled the `type` should refer to a `core.Class`
					if (propertyCast && !core.Class.isClass(propertyType)) {
						throw new Error("Property declaration of " + propertyName + " contains invalid configuration: Casting support requires a core.Class for the type of the property!");
					}
				}
			}

			// Generate property ID
			// Identically named property might store data on the same field
			// as in this case this is typicall on different classes.
			var propertyId = propertyNameToId[propertyName];
			if (!propertyId) {
				propertyId = propertyNameToId[propertyName] = (core.property.Core.ID++);
			}

			// Prepare return value
			var members = {};

			/*
			---------------------------------------------------------------------------
				 METHODS :: GET
			---------------------------------------------------------------------------
			*/

			members.get = function()
			{
				var data, value;
				var context = this;

				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkGetter(context, config, arguments);
				}

				data = context[store];
				if (data) {
					value = data[propertyId];
				}

				if (value === undef)
				{
					if (propertyInit !== undef) {
						return propertyInit;
					}

					if (jasy.Env.isSet("debug"))
					{
						if (!propertyNullable) {
							context.error("Missing value for: " + propertyName + " (during get())");
						}
					}

					value = null;
				}

				return value;
			};

			/*
			---------------------------------------------------------------------------
				 METHODS :: INIT
			---------------------------------------------------------------------------
			*/

			if (propertyInit !== undef)
			{
				members.init = function()
				{
					var context = this;
					var data = context[store];

					// Check whether there is already local data (which is higher prio than init data)
					if (!data || data[propertyId] === undef)
					{
						// Call apply
						if (propertyApply) {
							propertyApply.call(context, propertyInit, undef);
						}

						// Fire event
						if (propertyFire)
						{
							var eventObject = core.property.Event.obtain(propertyFire, propertyInit, undef, propertyName);
							context.dispatchEvent(eventObject);
							eventObject.release();
						}
					}
				};
			}

			/*
			---------------------------------------------------------------------------
				 METHODS :: SET
			---------------------------------------------------------------------------
			*/

			members.set = function(value)
			{
				var context=this, data, old;

				// Wrap plain types to match property type
				// Modifying `value` should also modify the arguments object which
				// is required for value tests happening via checkSetter
				if (config.wrap && core.Main.isTypeOf(value, "Plain")) {
					value = new config.type(value);
				}

				// Check types
				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkSetter(context, config, arguments);
				}

				data = context[store];
				if (!data) {
					data = context[store] = {};
				} else {
					old = data[propertyId];
				}

				if (value !== old)
				{
					if (old === undef && propertyInit !== undef) {
						old = propertyInit;
					}

					data[propertyId] = value;

					if (propertyApply) {
						propertyApply.call(context, value, old);
					}

					if (propertyFire)
					{
						var eventObject = core.property.Event.obtain(propertyFire, value, old, propertyName);
						context.dispatchEvent(eventObject);
						eventObject.release();
					}
				}

				return value;
			};

			/*
			---------------------------------------------------------------------------
				 METHODS :: RESET
			---------------------------------------------------------------------------
			*/

			members.reset = function()
			{
				var context, data, old, value;
				context = this;

				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkResetter(context, config, arguments);
				}

				data = context[store];
				if (!data) {
					return;
				}

				old = data[propertyId];
				value = undef;

				if (old !== value)
				{
					data[propertyId] = value;

					if (propertyInit !== undef) {
						value = propertyInit;
					}
					else if (jasy.Env.isSet("debug"))
					{
						// Still no value. We warn about that the property is not nullable.
						if (!propertyNullable) {
							context.error("Missing value for: " + propertyName + " (during reset())");
						}
					}

					if (propertyApply) {
						propertyApply.call(context, value, old);
					}

					if (propertyFire)
					{
						var eventObject = core.property.Event.obtain(propertyFire, value, old, propertyName);
						context.dispatchEvent(eventObject);
						eventObject.release();
					}
				}
			};

			/*
			---------------------------------------------------------------------------
				 DONE
			---------------------------------------------------------------------------
			*/

			return members;
		}
	});
})()
<commit_msg>Dependency fix<commit_after>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2010-2012 Zynga Inc.
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

(function(undef)
{
	/** {Map} Maps simple property names to global property IDs */
	var propertyNameToId = {};

	/** {=String} Field where the data is stored */
	var store = "$$data";

	/**
	 * Property handling for simple key/value like properties which might have an optional init value.
	 *
	 * Supports the following configuration keys:
	 *
	 * - `type`: Check the incoming value for the given type or function.
	 * - `apply`: Link to function to call after a new value has been stored. The signature of the method is
	 * `function(newValue, oldValue)`
	 * - `fire`: Event to fire after a new value has been stored (and apply has been called). The listeners
	 * are called with 3 parameters: value, old value and property name.
	 * - `init`: Init value for the property. If no value is set or the property gets reset, the getter
	 * will return the `init` value.
	 * - `nullable`: Whether the property is able to store null values. This also allows the system to
	 * return `null` when no other value is available. Otherwise an error is thrown whenever no value is
	 * available.
	 *
	 * #break(core.property.Debug)
	 * #break(core.property.Event)
	 */
	core.Module("core.property.Simple",
	{
		/**
		 * {Map} Creates a new set of member methods for the given property @config {Map}.
		 *
		 * Please note that you need to define one of "init" or "nullable". Otherwise you
		 * might get errors during runtime function calls.
		 */
		create : function(config)
		{
			/*
			---------------------------------------------------------------------------
				 INTRO
			---------------------------------------------------------------------------
			*/

			// Shorthands: Better compression/obfuscation/performance
			var propertyName = config.name;
			var propertyNullable = config.nullable;
			var propertyInit = config.init;
			var propertyType = config.type;
			var propertyFire = config.fire;
			var propertyApply = config.apply;
			var propertyCast = config.cast;

			// Validation
			if (jasy.Env.isSet("debug"))
			{
				/** #require(ext.sugar.Object) */
				var invalidKeys = Object.validateKeys(config, "name,nullable,init,type,fire,apply,wrap".split(","));
				if (invalidKeys.length > 0) {
					throw new Error("Property declaration of " + propertyName + " contains invalid configuration keys: " + invalidKeys.join(", ") + "!");
				}

				core.Assert.isType(propertyName, "String");

				if (propertyNullable !== undef) {
					core.Assert.isType(propertyNullable, "Boolean");
				}

				if (propertyType) {
					core.property.Debug.isValidType(propertyType);
				}

				if (propertyFire) {
					core.Assert.isType(propertyFire, "String");
				}

				if (propertyApply) {
					core.Assert.isType(propertyApply, "Function");
				}

				if (propertyCast != null)
				{
					core.Assert.isType(propertyCast, "Boolean");

					/**
					 * When enabled the `type` should refer to a `core.Class`
					 *
					 * #break(core.Class)
					 */
					if (propertyCast && !core.Class.isClass(propertyType)) {
						throw new Error("Property declaration of " + propertyName + " contains invalid configuration: Casting support requires a core.Class for the type of the property!");
					}
				}
			}

			// Generate property ID
			// Identically named property might store data on the same field
			// as in this case this is typicall on different classes.
			var propertyId = propertyNameToId[propertyName];
			if (!propertyId) {
				propertyId = propertyNameToId[propertyName] = (core.property.Core.ID++);
			}

			// Prepare return value
			var members = {};

			/*
			---------------------------------------------------------------------------
				 METHODS :: GET
			---------------------------------------------------------------------------
			*/

			members.get = function()
			{
				var data, value;
				var context = this;

				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkGetter(context, config, arguments);
				}

				data = context[store];
				if (data) {
					value = data[propertyId];
				}

				if (value === undef)
				{
					if (propertyInit !== undef) {
						return propertyInit;
					}

					if (jasy.Env.isSet("debug"))
					{
						if (!propertyNullable) {
							context.error("Missing value for: " + propertyName + " (during get())");
						}
					}

					value = null;
				}

				return value;
			};

			/*
			---------------------------------------------------------------------------
				 METHODS :: INIT
			---------------------------------------------------------------------------
			*/

			if (propertyInit !== undef)
			{
				members.init = function()
				{
					var context = this;
					var data = context[store];

					// Check whether there is already local data (which is higher prio than init data)
					if (!data || data[propertyId] === undef)
					{
						// Call apply
						if (propertyApply) {
							propertyApply.call(context, propertyInit, undef);
						}

						// Fire event
						if (propertyFire)
						{
							var eventObject = core.property.Event.obtain(propertyFire, propertyInit, undef, propertyName);
							context.dispatchEvent(eventObject);
							eventObject.release();
						}
					}
				};
			}

			/*
			---------------------------------------------------------------------------
				 METHODS :: SET
			---------------------------------------------------------------------------
			*/

			members.set = function(value)
			{
				var context=this, data, old;

				// Wrap plain types to match property type
				// Modifying `value` should also modify the arguments object which
				// is required for value tests happening via checkSetter
				if (config.wrap && core.Main.isTypeOf(value, "Plain")) {
					value = new config.type(value);
				}

				// Check types
				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkSetter(context, config, arguments);
				}

				data = context[store];
				if (!data) {
					data = context[store] = {};
				} else {
					old = data[propertyId];
				}

				if (value !== old)
				{
					if (old === undef && propertyInit !== undef) {
						old = propertyInit;
					}

					data[propertyId] = value;

					if (propertyApply) {
						propertyApply.call(context, value, old);
					}

					if (propertyFire)
					{
						var eventObject = core.property.Event.obtain(propertyFire, value, old, propertyName);
						context.dispatchEvent(eventObject);
						eventObject.release();
					}
				}

				return value;
			};

			/*
			---------------------------------------------------------------------------
				 METHODS :: RESET
			---------------------------------------------------------------------------
			*/

			members.reset = function()
			{
				var context, data, old, value;
				context = this;

				if (jasy.Env.isSet("debug")) {
					core.property.Debug.checkResetter(context, config, arguments);
				}

				data = context[store];
				if (!data) {
					return;
				}

				old = data[propertyId];
				value = undef;

				if (old !== value)
				{
					data[propertyId] = value;

					if (propertyInit !== undef) {
						value = propertyInit;
					}
					else if (jasy.Env.isSet("debug"))
					{
						// Still no value. We warn about that the property is not nullable.
						if (!propertyNullable) {
							context.error("Missing value for: " + propertyName + " (during reset())");
						}
					}

					if (propertyApply) {
						propertyApply.call(context, value, old);
					}

					if (propertyFire)
					{
						var eventObject = core.property.Event.obtain(propertyFire, value, old, propertyName);
						context.dispatchEvent(eventObject);
						eventObject.release();
					}
				}
			};

			/*
			---------------------------------------------------------------------------
				 DONE
			---------------------------------------------------------------------------
			*/

			return members;
		}
	});
})()
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import { startCase } from 'lodash'
import Icon from './Icon'

const range = (start, stop) => Array.from(new Array((stop - start) + 1), (_, i) => i + start)

const ArticleChildren = ({ articles = [], numberOfColumns = 4 }) => {
  if (!articles || !Array.isArray(articles) || !articles.length) {
    return

  }

  const sorted = articles.sort()
  const columnSize = Math.ceil(sorted.length / numberOfColumns)
  const classes = `column is-${Math.floor(12 / numberOfColumns)}`

  const columns = range(0, numberOfColumns).map((index) => {
    const first = index * columnSize
    const last = (index * columnSize) + columnSize
    const list = sorted.slice(first, last)

    return (

{list.map(slug =>

<a href={`/page/${slug}`}>{startCase(slug)}

      )}

    )
  })

  return (

<Icon name="tag" /> Child Articles:

{columns}

  )
}
ArticleChildren.defaultProps = {
  articles:        [],
  numberOfColumns: 4,
}
ArticleChildren.propTypes = {
  articles:        PropTypes.arrayOf(PropTypes.string),
  numberOfColumns: PropTypes.number,
}

export default ArticleChildren
<commit_msg>Add support for titles, refactored column calculation<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import { startCase } from 'lodash'
import Icon from './Icon'

const STYLE = {
  CONTAINER: {
    display:       'flex',
    flexDirection: 'column',
    flexWrap:      'wrap',
    padding:       '.25rem',
  },
  CHILD: {
    height:     '1.5rem',
    fontSize:   '1rem',
    lineHeight: '1rem',
    padding:    '.25rem 0',
  },
}

const ArticleChildren = ({ articles = [], numberOfColumns = 4 }) => {
  if (!articles || !Array.isArray(articles) || !articles.length) {
    return

  }

  const links = articles
    .map((item) => {
      if (!item) return null
      if (typeof item === 'string') return { slug: item, title: startCase(item) }
      if (!item.slug) return null
      if (!item.title) return { slug: item.slug, title: startCase(item.slug) }
      return item
    })
    .filter(Boolean)
    .sort((a, b) => a.title.localeCompare(b.title))
    .map(({ slug, title }) =>

<a href={`/page/${slug}`}>{title}

    )

  const rows = Math.ceil(links.length / numberOfColumns)
  const containerStyle = {
    ...STYLE.CONTAINER,
    height: `${(rows * 1.5) + 1}rem`,
  }

  return (

<Icon name="tag" /> Child Articles:

{links}

  )
}
ArticleChildren.defaultProps = {
  articles:        [],
  numberOfColumns: 4,
}
ArticleChildren.propTypes = {
  articles: PropTypes.arrayOf(PropTypes.oneOfType([
    PropTypes.shape({
      slug:  PropTypes.string,
      title: PropTypes.string,
    }),
    PropTypes.string,
  ])),
  numberOfColumns: PropTypes.number,
}

export default ArticleChildren
<|endoftext|>


<commit_before>// Copyright 2018-2019, University of Colorado Boulder

/**
 * Reports a (delayed) page load (or error) to the parent frame for Aqua continuous testing.
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */

'use strict';

( function() {

  let hasErrored = false;

  window.addEventListener( 'error', data => {
    if ( !hasErrored ) {
      hasErrored = true;

      let message = '';
      let stack = '';
      if ( data && data.message ) {
        message = data.message;
      }
      if ( data && data.error && data.error.stack ) {
        stack = data.error.stack;
      }
      ( window.parent !== window ) && window.parent.postMessage( JSON.stringify( {
        type: 'pageload-error',
        url: window.location.href,
        message: message,
        stack: stack
      } ), '*' );
      console.log( 'error' );
    }
  } );

  window.addEventListener( 'load', event => {
    // Wait 4 seconds before reporting load, to see if it errors first
    setTimeout( () => {
      if ( !hasErrored ) {
        ( window.parent !== window ) && window.parent.postMessage( JSON.stringify( {
          type: 'pageload-load',
          url: window.location.href
        } ), '*' );

        console.log( 'load' );
      }
    }, 4000 );
  }, false );
} )();
<commit_msg>update copyright dates from daily grunt work<commit_after>// Copyright 2018-2021, University of Colorado Boulder

/**
 * Reports a (delayed) page load (or error) to the parent frame for Aqua continuous testing.
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */

'use strict';

( function() {

  let hasErrored = false;

  window.addEventListener( 'error', data => {
    if ( !hasErrored ) {
      hasErrored = true;

      let message = '';
      let stack = '';
      if ( data && data.message ) {
        message = data.message;
      }
      if ( data && data.error && data.error.stack ) {
        stack = data.error.stack;
      }
      ( window.parent !== window ) && window.parent.postMessage( JSON.stringify( {
        type: 'pageload-error',
        url: window.location.href,
        message: message,
        stack: stack
      } ), '*' );
      console.log( 'error' );
    }
  } );

  window.addEventListener( 'load', event => {
    // Wait 4 seconds before reporting load, to see if it errors first
    setTimeout( () => {
      if ( !hasErrored ) {
        ( window.parent !== window ) && window.parent.postMessage( JSON.stringify( {
          type: 'pageload-load',
          url: window.location.href
        } ), '*' );

        console.log( 'load' );
      }
    }, 4000 );
  }, false );
} )();
<|endoftext|>


<commit_before>// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.

var config = {

    // Loggly configs
    LogglyWriteKey: "",
    LogglyConsoleErrors: true,

    // Segment configs
    SegmentWriteKey: "",

    // Feature switches
    AllowPublicLink: true,
    AllowInviteNames: true,
    AllowSignupDomainsWizard: false,

    // Privacy switches
    ShowEmail: true,

    // Links
    TermsLink: "/static/help/configure_links.html",
    PrivacyLink: "/static/help/configure_links.html",
    AboutLink: "/static/help/configure_links.html",
    HelpLink: "/static/help/configure_links.html",
    ReportProblemLink: "/static/help/configure_links.html",
    HomeLink: "",

    ThemeColors: ["#2389d7", "#008a17", "#dc4fad", "#ac193d", "#0072c6", "#d24726", "#ff8f32", "#82ba00", "#03b3b2", "#008299", "#4617b4", "#8c0095", "#004b8b", "#004b8b", "#570000", "#380000", "#585858", "#000000"]
};

// Flavor strings
var strings = {
    Team: "team",
    TeamPlural: "teams",
    Company: "company",
    CompanyPlural: "companies",
};
<commit_msg>Removed unnecessary comma<commit_after>// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.

var config = {

    // Loggly configs
    LogglyWriteKey: "",
    LogglyConsoleErrors: true,

    // Segment configs
    SegmentWriteKey: "",

    // Feature switches
    AllowPublicLink: true,
    AllowInviteNames: true,
    AllowSignupDomainsWizard: false,

    // Privacy switches
    ShowEmail: true,

    // Links
    TermsLink: "/static/help/configure_links.html",
    PrivacyLink: "/static/help/configure_links.html",
    AboutLink: "/static/help/configure_links.html",
    HelpLink: "/static/help/configure_links.html",
    ReportProblemLink: "/static/help/configure_links.html",
    HomeLink: "",

    ThemeColors: ["#2389d7", "#008a17", "#dc4fad", "#ac193d", "#0072c6", "#d24726", "#ff8f32", "#82ba00", "#03b3b2", "#008299", "#4617b4", "#8c0095", "#004b8b", "#004b8b", "#570000", "#380000", "#585858", "#000000"]
};

// Flavor strings
var strings = {
    Team: "team",
    TeamPlural: "teams",
    Company: "company",
    CompanyPlural: "companies"
};
<|endoftext|>