<commit_before>/*
 * @copyright Adam Benda, 2016
 *
 */

/* global Blob, File, SVGSVGElement, EventTarget */

/**
 * @classdesc SVG Rendering library
 * @class
 */
var SVGRender = function () {

};

/**
 * Loads one SVG image from various source.
 * Will wipe out previously loaded image
 * @param {SVGSVGElement |  Blob | File | String} svg - svg element or its source
 * @returns {undefined}
 *
 * @public
 **/
SVGRender.prototype.load = function (svg) {
    /**
     * Loading from a file is asynchronous = do not call render() untill file is loaded.
     * @type {Boolean}
     * @private
     */
    this.loaded = false;

    /**
     * Signalizes that computation was interrupted/paused
     * @type Boolean
     */
    this.interrupted = false;

    /**
     * Signalizes that computation finished sucessfully
     * @type Boolean
     */
    this.finished = false;

    if (Blob.prototype.isPrototypeOf(svg) || File.prototype.isPrototypeOf(svg)) {
//to be read with FileReader
        if (!svg.type || svg.type !== "image/svg+xml") {
            throw "Wrong file/blob type, should be image/svg+xml, is " + svg.type;
        }

        /**
         * File reader of input File / Blob
         * @type {FileReader}
         * @private
         */
        this.reader = new FileReader();
        this.reader.readAsDataURL(svg);
        this.reader.onload = function () {
            //File was loaded from input to dataURI

            //http://stackoverflow.com/questions/11335460/how-do-i-parse-a-data-url-in-node
            var svgCodeB64 = this.reader.result;
            var regex = /^data:.+\/(.+);base64,(.*)$/;
            var matches = svgCodeB64.match(regex);
            var data = matches[2];
            var svgCode = atob(data);
            this.load.bind(this)(svgCode);
            //Call load function again - but with svg source loaded from file
            return;
        }.bind(this);
        return;

    } else if (typeof svg === "string") {
        //svg xml code
        var svgCode = svg;
        //var svgCode = this.result.replace(/<?xml[^>]*/,"").replace(/<!DOCTYPE[^>]*/,"");

        //We are using document from global namespace
        //todo: cleanup afterwards
        this.svgDivElement = document.createElement('div');
        this.svgDivElement.innerHTML = svgCode;
        var svgElement = this.svgDivElement.children[0];
        document.body.appendChild(this.svgDivElement);
        //this.svgDivElement.style.visibility = 'hidden';
        this.svgDivElement.style.border = '2px solid black';
        this.load(svgElement);
        return;
    } else if (SVGSVGElement.prototype.isPrototypeOf(svg)) {

        /**
         * SVG element present in document.
         * @type {SVGSVGElement}
         * @private
         */
        this.svgElement = svg;
        this.loaded = true;
        return;
    } else {
        throw "Unknown svg type in svg-render!";
    }
};

/**
 * Start rendering
 * @param {Object} options - contains numbers FPS, time, imagesCount and function progressSignal
 * @param {function} callback
 * @returns {undefined}
 *
 * @public
 */
SVGRender.prototype.render = function (options, callback) {
    if (!options) {
        options = {};
    }

    /**
     * Will be called after rendering is finished
     * @type {function}
     */
    this.callback = callback;
    if (!this.callback) {
        this.callback = function () {};
    }

    if (!this.loaded) {
        //todo: more elegant solution
        setTimeout(this.render.bind(this, options, callback), 100);
        return;
    }

    /**
     * Function to be called repeatedly when frame is rendered.
     * has two parameters; count(total #frames) and doneCount(#frames rendered)
     * @type {function}
     * @private
     */
    this.progressSignal = (options.progressSignal || function () {});

    /**
     * begin time (seconds)
     * @type {number}
     * @private
     */
    this.beginMS = (options.begin * 1000 || 0); //default begin time

    /**
     * Frames per Second
     * @type {number}
     * @private
     */
    this.FPS = (options.FPS || 60); //default FPS

    /**
     * total time in miliseconds
     * @type {number}
     * @private
     */
    this.timeMS = (options.time * 1000 || 1000);

    /**
     * Number of frames to render
     * @type {number}
     * @private
     */
    this.imagesCount = Math.round(this.FPS * this.timeMS / 1000);

    if (options.imagesCount && options.imagesCount !== this.imagesCount) {
        //imagesCount was given
        if (options.time && options.FPS) {
            //FPS+time were also given and the tree given parameters are contradicting
            throw "Conflicting parameters FPS,time,imagesCount";
        } else if (options.time) {
            this.FPS = this.imagesCount * 1000 / this.timeMS;
        } else if (options.FPS) {
            this.timeMS = this.imagesCount * 1000 / this.FPS;
        }
    }

    /**
     * Time in miliseconds from the animation start time.
     * @type {int}
     * @private
     */
    this.SVGtime = 0; //in miliseconds

    /**
     * Number of already rendered images
     * @type {int}
     * @public
     */
    this.imagesDoneCount = 0;

    /**
     * Array of all rendered images in png format
     * @type {base64}
     * @public
     */
    this.images = [];

    /**
     * Array of all rendered images in png format
     * @type {number}
     * @private
     */
    this.nextFrame = setTimeout(this.renderNextFrame.bind(this), 0);

    /**
     * Canvas to draw on (optional - drawing is invisible if not provided)
     * @type {HTMLCanvasElement}
     * @private
     */
    this.canvas = (options.canvas || document.createElement('canvas')); //default begin time

};

/**
 * Goes through DOM tree of given HTMLElement and removes specific tags
 * @param {HTMLElement} htmlElement
 * @param {String[]} tags
 * @return {integer} - number of elements removed
 *
 * @private
 */
SVGRender.prototype.filterOut = function (htmlElement, tags) {
    var ret = 0;
    if (tags.indexOf(htmlElement.tagName) >= 0) {
        htmlElement.parentNode.removeChild(htmlElement);
        return 1;
    } else {
        //call filterOut recursively
        for (var i = 0; i < htmlElement.children.length; i++) {
            ret += this.filterOut(htmlElement.children[i], tags);
        }
    }
    return ret;
};

/**
 * Render next frame and schedule next run of render next frame
 * @returns {undefined}
 * @private
 */
SVGRender.prototype.renderNextFrame = function () {
    if (!this.svgElement) {
        throw "Cannot render - no svgElement loaded!";
    }

    if (this.interrupted) {
        //rendering was stopped
        //(this.nextFrame timeout should have been removed already!)
        throw "this.nextFrame timeout should have been removed already!";
        return;
    }

    this.SVGtime = this.beginMS + Math.round(1000 * this.imagesDoneCount) / (this.FPS);

    this.svgElement.pauseAnimations();
    this.svgElement.setCurrentTime(this.SVGtime / 1000);
    this.svgElement.forceRedraw();

    //Do deep copy of svgElement!
    var svgElementNew = this.svgElement.cloneNode(true);
    //Copy styles
    this.additionalData = this.exportStyle(this.svgElement);

    this.filterOut(svgElementNew, "animate");
    this.filterOut(svgElementNew, "animateTransform");
    this.filterOut(svgElementNew, "animateColor");
    //animateMotion does NOT propagate into XML or style
    this.filterOut(svgElementNew, "animateMotion");

    //maybe unnescessary
    /*
     console.log(this.SVGtime / 1000);
     svgElementNew.pauseAnimations();
     svgElementNew.setCurrentTime(this.SVGtime / 1000);
     svgElementNew.forceRedraw();
     */

    var svgString = new XMLSerializer().serializeToString(svgElementNew);
    this.svgImage = new Image();
    this.svgImage.onload = function () {

        this.importStyle(this.svgImage, this.additionalData);

        tmpCanvasx = this.canvas.getContext('2d');
        this.canvas.width = this.svgImage.width;
        this.canvas.height = this.svgImage.height;
        tmpCanvasx.clearRect(0, 0, this.svgImage.width, this.svgImage.height);
        tmpCanvasx.drawImage(this.svgImage, 0, 0);
        //image now in tmpCanvas

        //signalize progress
        if (this.progressSignal && typeof this.progressSignal === "function") {
            this.progressSignal(this.imagesDoneCount, this.imagesCount);
        }

        this.images[this.imagesDoneCount++] = this.canvas.toDataURL("image/png").replace(/^data:.+\/(.+);base64,/, "");
        if (this.imagesDoneCount < this.imagesCount) {
            this.nextFrame = setTimeout(this.renderNextFrame.bind(this), 0);
        } else {
            this.finished = true;
            this.callback();
        }
    }.bind(this);

    this.svgImage.src = "data:image/svg+xml;base64," + btoa("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n\
        <!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" + unescape(encodeURIComponent(svgString)));
};

/**
 * Pause rendering
 * @returns {undefined}
 */
SVGRender.prototype.pause = function () {
    this.interrupted = true;
    clearTimeout(this.nextFrame);
    this.nextFrame = null;
};

/**
 * Resumes rendering
 * @returns {undefined}
 */
SVGRender.prototype.resume = function () {
    if (this.finished || !this.interrupted) {
        //not needed
        return;
    }

    this.interrupted = false;
    if (!this.nextFrame) {
        //next frame is not scheduled
        this.nextFrame = setTimeout(this.renderNextFrame.bind(this), 0);
    }
};

SVGElement.prototype.getTransformAnim = function () {
    var matrix = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix();
    if (!this.transform || !this.transform.animVal) {
        return matrix;
    }
    for (var i = 0; i < this.transform.animVal.length; i++) {
        matrix = matrix.multiply(this.transform.animVal[i].matrix);
    }
    return matrix;
};

//copy style: http://stackoverflow.com/questions/2087778/javascript-copy-style
//also copy out transformMatrix
SVGRender.prototype.exportStyle = function (el) {
    var ret = {};
    ret.children = [];
    for (var i = 0; i < el.children.length; i++) {
        ret.children[i] = this.exportStyle(el.children[i]);
    }
    var transformAnim = el.getTransformAnim();
    if (transformAnim) {
        ret.transformAnim = transformAnim;
    }

    ret.value = [];
    var styles = window.getComputedStyle(el);

    for (var i = styles.length; i-- > 0; ) {
        var name = styles[i];
        if (!name.match(/^height$/) && !name.match(/^width$/) && !name.match(/^visibility/)) {
            ret.value.push({
                "name": name,
                "value": styles.getPropertyValue(name),
                "priority": styles.getPropertyPriority(name)
            });
        }
    }
    return ret;
};

SVGRender.prototype.importStyle = function (el, data) {
    if (el.transform && Array.isArray(el.transform.animVal)) {
        el.transform.animVal.push(data.transformAnim);
    }

    for (var i = 0; i < el.children.length; i++) {
        //recursive
        this.importStyle(el.children[i], data.children[i]);
    }
    for (var n = 0; n < data.value.length; n++) {
        el.style.setProperty(data.value[n].name,
                data.value[n].value,
                data.value[n].priority
                );
    }
};<commit_msg>Deep copy function<commit_after>/*
 * @copyright Adam Benda, 2016
 *
 */

/* global Blob, File, SVGSVGElement, EventTarget */

/**
 * @classdesc SVG Rendering library
 * @class
 */
var SVGRender = function () {

};

/**
 * Loads one SVG image from various source.
 * Will wipe out previously loaded image
 * @param {SVGSVGElement |  Blob | File | String} svg - svg element or its source
 * @returns {undefined}
 *
 * @public
 **/
SVGRender.prototype.load = function (svg) {
    /**
     * Loading from a file is asynchronous = do not call render() untill file is loaded.
     * @type {Boolean}
     * @private
     */
    this.loaded = false;

    /**
     * Signalizes that computation was interrupted/paused
     * @type Boolean
     */
    this.interrupted = false;

    /**
     * Signalizes that computation finished sucessfully
     * @type Boolean
     */
    this.finished = false;

    if (Blob.prototype.isPrototypeOf(svg) || File.prototype.isPrototypeOf(svg)) {
//to be read with FileReader
        if (!svg.type || svg.type !== "image/svg+xml") {
            throw "Wrong file/blob type, should be image/svg+xml, is " + svg.type;
        }

        /**
         * File reader of input File / Blob
         * @type {FileReader}
         * @private
         */
        this.reader = new FileReader();
        this.reader.readAsDataURL(svg);
        this.reader.onload = function () {
            //File was loaded from input to dataURI

            //http://stackoverflow.com/questions/11335460/how-do-i-parse-a-data-url-in-node
            var svgCodeB64 = this.reader.result;
            var regex = /^data:.+\/(.+);base64,(.*)$/;
            var matches = svgCodeB64.match(regex);
            var data = matches[2];
            var svgCode = atob(data);
            this.load.bind(this)(svgCode);
            //Call load function again - but with svg source loaded from file
            return;
        }.bind(this);
        return;

    } else if (typeof svg === "string") {
        //svg xml code
        var svgCode = svg;
        //var svgCode = this.result.replace(/<?xml[^>]*/,"").replace(/<!DOCTYPE[^>]*/,"");

        //We are using document from global namespace
        //todo: cleanup afterwards
        this.svgDivElement = document.createElement('div');
        this.svgDivElement.innerHTML = svgCode;
        var svgElement = this.svgDivElement.children[0];
        document.body.appendChild(this.svgDivElement);
        //this.svgDivElement.style.visibility = 'hidden';
        this.svgDivElement.style.border = '2px solid black';
        this.load(svgElement);
        return;
    } else if (SVGSVGElement.prototype.isPrototypeOf(svg)) {

        /**
         * SVG element present in document.
         * @type {SVGSVGElement}
         * @private
         */
        this.svgElement = svg;
        this.loaded = true;
        return;
    } else {
        throw "Unknown svg type in svg-render!";
    }
};

/**
 * Start rendering
 * @param {Object} options - contains numbers FPS, time, imagesCount and function progressSignal
 * @param {function} callback
 * @returns {undefined}
 *
 * @public
 */
SVGRender.prototype.render = function (options, callback) {
    if (!options) {
        options = {};
    }

    /**
     * Will be called after rendering is finished
     * @type {function}
     */
    this.callback = callback;
    if (!this.callback) {
        this.callback = function () {};
    }

    if (!this.loaded) {
        //todo: more elegant solution
        setTimeout(this.render.bind(this, options, callback), 100);
        return;
    }

    /**
     * Function to be called repeatedly when frame is rendered.
     * has two parameters; count(total #frames) and doneCount(#frames rendered)
     * @type {function}
     * @private
     */
    this.progressSignal = (options.progressSignal || function () {});

    /**
     * begin time (seconds)
     * @type {number}
     * @private
     */
    this.beginMS = (options.begin * 1000 || 0); //default begin time

    /**
     * Frames per Second
     * @type {number}
     * @private
     */
    this.FPS = (options.FPS || 60); //default FPS

    /**
     * total time in miliseconds
     * @type {number}
     * @private
     */
    this.timeMS = (options.time * 1000 || 1000);

    /**
     * Number of frames to render
     * @type {number}
     * @private
     */
    this.imagesCount = Math.round(this.FPS * this.timeMS / 1000);

    if (options.imagesCount && options.imagesCount !== this.imagesCount) {
        //imagesCount was given
        if (options.time && options.FPS) {
            //FPS+time were also given and the tree given parameters are contradicting
            throw "Conflicting parameters FPS,time,imagesCount";
        } else if (options.time) {
            this.FPS = this.imagesCount * 1000 / this.timeMS;
        } else if (options.FPS) {
            this.timeMS = this.imagesCount * 1000 / this.FPS;
        }
    }

    /**
     * Time in miliseconds from the animation start time.
     * @type {int}
     * @private
     */
    this.SVGtime = 0; //in miliseconds

    /**
     * Number of already rendered images
     * @type {int}
     * @public
     */
    this.imagesDoneCount = 0;

    /**
     * Array of all rendered images in png format
     * @type {base64}
     * @public
     */
    this.images = [];

    /**
     * Array of all rendered images in png format
     * @type {number}
     * @private
     */
    this.nextFrame = setTimeout(this.renderNextFrame.bind(this), 0);

    /**
     * Canvas to draw on (optional - drawing is invisible if not provided)
     * @type {HTMLCanvasElement}
     * @private
     */
    this.canvas = (options.canvas || document.createElement('canvas')); //default begin time

};

/**
 * Goes through DOM tree of given HTMLElement and removes specific tags
 * @param {HTMLElement} htmlElement
 * @param {String[]} tags
 * @return {integer} - number of elements removed
 *
 * @private
 */
SVGRender.prototype.filterOut = function (htmlElement, tags) {
    var ret = 0;
    if (tags.indexOf(htmlElement.tagName) >= 0) {
        htmlElement.parentNode.removeChild(htmlElement);
        return 1;
    } else {
        //call filterOut recursively
        for (var i = 0; i < htmlElement.children.length; i++) {
            ret += this.filterOut(htmlElement.children[i], tags);
        }
    }
    return ret;
};

/**
 * Render next frame and schedule next run of render next frame
 * @returns {undefined}
 * @private
 */
SVGRender.prototype.renderNextFrame = function () {
    if (!this.svgElement) {
        throw "Cannot render - no svgElement loaded!";
    }

    if (this.interrupted) {
        //rendering was stopped
        //(this.nextFrame timeout should have been removed already!)
        throw "this.nextFrame timeout should have been removed already!";
        return;
    }

    this.SVGtime = this.beginMS + Math.round(1000 * this.imagesDoneCount) / (this.FPS);

    this.svgElement.pauseAnimations();
    this.svgElement.setCurrentTime(this.SVGtime / 1000);
    this.svgElement.forceRedraw();

    //Do deep copy of svgElement!
    var svgElementNew = this.svgElement.cloneNode(true);
    //Copy styles
    this.additionalData = this.exportStyle(this.svgElement);

    this.filterOut(svgElementNew, "animate");
    this.filterOut(svgElementNew, "animateTransform");
    this.filterOut(svgElementNew, "animateColor");
    //animateMotion does NOT propagate into XML or style
    this.filterOut(svgElementNew, "animateMotion");

    //maybe unnescessary
    /*
     console.log(this.SVGtime / 1000);
     svgElementNew.pauseAnimations();
     svgElementNew.setCurrentTime(this.SVGtime / 1000);
     svgElementNew.forceRedraw();
     */

    var svgString = new XMLSerializer().serializeToString(svgElementNew);
    this.svgImage = new Image();
    this.svgImage.onload = function () {

        this.importStyle(this.svgImage, this.additionalData);

        tmpCanvasx = this.canvas.getContext('2d');
        this.canvas.width = this.svgImage.width;
        this.canvas.height = this.svgImage.height;
        tmpCanvasx.clearRect(0, 0, this.svgImage.width, this.svgImage.height);
        tmpCanvasx.drawImage(this.svgImage, 0, 0);
        //image now in tmpCanvas

        //signalize progress
        if (this.progressSignal && typeof this.progressSignal === "function") {
            this.progressSignal(this.imagesDoneCount, this.imagesCount);
        }

        this.images[this.imagesDoneCount++] = this.canvas.toDataURL("image/png").replace(/^data:.+\/(.+);base64,/, "");
        if (this.imagesDoneCount < this.imagesCount) {
            this.nextFrame = setTimeout(this.renderNextFrame.bind(this), 0);
        } else {
            this.finished = true;
            this.callback();
        }
    }.bind(this);

    this.svgImage.src = "data:image/svg+xml;base64," + btoa("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n\
        <!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" + unescape(encodeURIComponent(svgString)));
};

/**
 * Pause rendering
 * @returns {undefined}
 */
SVGRender.prototype.pause = function () {
    this.interrupted = true;
    clearTimeout(this.nextFrame);
    this.nextFrame = null;
};

/**
 * Resumes rendering
 * @returns {undefined}
 */
SVGRender.prototype.resume = function () {
    if (this.finished || !this.interrupted) {
        //not needed
        return;
    }

    this.interrupted = false;
    if (!this.nextFrame) {
        //next frame is not scheduled
        this.nextFrame = setTimeout(this.renderNextFrame.bind(this), 0);
    }
};

SVGElement.prototype.getTransformAnim = function () {
    var matrix = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix();
    if (!this.transform || !this.transform.animVal) {
        return matrix;
    }
    for (var i = 0; i < this.transform.animVal.length; i++) {
        matrix = matrix.multiply(this.transform.animVal[i].matrix);
    }
    return matrix;
};

//copy style: http://stackoverflow.com/questions/2087778/javascript-copy-style
//also copy out transformMatrix
SVGRender.prototype.exportStyle = function (el) {
    var ret = {};
    ret.children = [];
    for (var i = 0; i < el.children.length; i++) {
        ret.children[i] = this.exportStyle(el.children[i]);
    }
    var transformAnim = el.getTransformAnim();
    if (transformAnim) {
        ret.transformAnim = transformAnim;
    }

    ret.value = [];
    var styles = window.getComputedStyle(el);

    for (var i = styles.length; i-- > 0; ) {
        var name = styles[i];
        if (!name.match(/^height$/) && !name.match(/^width$/) && !name.match(/^visibility/)) {
            ret.value.push({
                "name": name,
                "value": styles.getPropertyValue(name),
                "priority": styles.getPropertyPriority(name)
            });
        }
    }
    return ret;
};

SVGRender.prototype.importStyle = function (el, data) {
    if (el.transform && Array.isArray(el.transform.animVal)) {
        el.transform.animVal.push(data.transformAnim);
    }

    for (var i = 0; i < el.children.length; i++) {
        //recursive
        this.importStyle(el.children[i], data.children[i]);
    }
    for (var n = 0; n < data.value.length; n++) {
        el.style.setProperty(data.value[n].name,
                data.value[n].value,
                data.value[n].priority
                );
    }
};

/**
 * Deep-copy element (recursive)
 * @param {Array|String|Number|Boolean|Object} src
 * @returns {Array|String|Number|Boolean|Object}
 */
SVGRender.prototype.deepCopy = function (src) {
    var dst;
    if (Array.isArray(src)) {
        dst = [];
        for (var i = 0; i < src.length; i++) {
            dst[i] = this.deepCopy(src[i]);
        }
    } else if (typeof (src) === "string" || typeof (src) === "number" || typeof (src) === "boolean") {
        return src;
    } else if (typeof (src) === "function") {
        return null;
    } else if (typeof (src) === "object") {
        dst = {};
        for (var at in src) {
            dst[at] = this.deepCopy(src[at]);
        }
    } else {
        throw "deepCopy unknown ";
    }

    return dst;
};<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import {NavLink} from 'fluxible-router';
import {connectToStores} from 'fluxible-addons-react';
import PresentationSlide from './PresentationSlide';
import DeckTreeStore from '../../../stores/DeckTreeStore';
import PresentationStore from '../../../stores/PresentationStore';
import loadPresentation from '../../../actions/loadPresentation';
//if(process.env.BROWSER){
//    require('../../../assets/css/PresentationDefaults.css');
//}

let playerCss = {
    height: '100%',
    position: 'absolute',
    top: '0',
};

let clearStyle = {
    clear: 'both'
};

class Presentation extends React.Component{
    constructor(props){
        super(props);
        this.playerCss = playerCss;
        this.slides = [];
        this.startingSlide = this.props.PresentationStore.selector.sid;
        this.deck = this.props.PresentationStore.selector.id;
        this.revealDiv = null;

    }

    componentDidMount(){
        if(process.env.BROWSER){
             //loading reveal style
            //Hide the header and footer
            $('.ui.footer.sticky.segment').css({'display': 'none'});
            $('.ui.inverted.blue.menu, .ui.inverted.menu .blue.active.item').css({'display': 'none'});
            $('.ui.footer.sticky.segment').attr({'aria-hidden': 'hidden', 'hidden': 'hidden'});
            $('.ui.inverted.blue.menu, .ui.inverted.menu .blue.active.item').attr({'aria-hidden': 'hidden', 'hidden': 'hidden'});
            $('.ui.horizontal.segments.footer').css({'display': 'none'});
            $('.ui.horizontal.segments.footer').attr({'aria-hidden': 'hidden', 'hidden': 'hidden'});

            let styleName = this.props.PresentationStore.theme;

            this.revealDiv.style.display = 'inline';

            let pptxwidth = $('.pptx2html').width();
            let pptxheight = $('.pptx2html').height();

            Reveal.initialize({
                width: pptxwidth,
    			height: pptxheight,
                transition: 'none',
                backgroundTransition: 'none',
                history: true,
                dependencies: [
                    { src: '/custom_modules/reveal.js/plugin/notes/notes.js', async: true }
                ]
            });

        }
    }

    componentDidUpdate(){

    }
    render(){
        this.slides = this.getSlides();
        return(

 this.revealDiv = refToDiv} data-transition="none" data-background-transition="none">

        			     	{this.slides}

        );
    }

    getSlides(){
        let slides = this.props.PresentationStore.content;

        let returnList = [];
        if(slides){
            for (let i = 0; i < slides.length; i++) {
                let slide = slides[i];
                let notes = '';
                if(slide.speakernotes){
                    notes =  '' + slide.speakernotes + '';
                }
                let content = slide.content + notes;
                returnList.push(<PresentationSlide content={content} key={slide.id} id={'slide-' + slide.id} />);
            }
            return returnList;

        }
        else{
            return (
);
        }
    }

}

Presentation.contextTypes = {
    executeAction: React.PropTypes.func.isRequired
};

Presentation = connectToStores(Presentation, [PresentationStore], (context, props) => {
    return {
        PresentationStore: context.getStore(PresentationStore).getState()
    };
});

export default Presentation;
<commit_msg>Add zoom-js plugin to initizalize<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import {NavLink} from 'fluxible-router';
import {connectToStores} from 'fluxible-addons-react';
import PresentationSlide from './PresentationSlide';
import DeckTreeStore from '../../../stores/DeckTreeStore';
import PresentationStore from '../../../stores/PresentationStore';
import loadPresentation from '../../../actions/loadPresentation';
//if(process.env.BROWSER){
//    require('../../../assets/css/PresentationDefaults.css');
//}

let playerCss = {
    height: '100%',
    position: 'absolute',
    top: '0',
};

let clearStyle = {
    clear: 'both'
};

class Presentation extends React.Component{
    constructor(props){
        super(props);
        this.playerCss = playerCss;
        this.slides = [];
        this.startingSlide = this.props.PresentationStore.selector.sid;
        this.deck = this.props.PresentationStore.selector.id;
        this.revealDiv = null;

    }

    componentDidMount(){
        if(process.env.BROWSER){
             //loading reveal style
            //Hide the header and footer
            $('.ui.footer.sticky.segment').css({'display': 'none'});
            $('.ui.inverted.blue.menu, .ui.inverted.menu .blue.active.item').css({'display': 'none'});
            $('.ui.footer.sticky.segment').attr({'aria-hidden': 'hidden', 'hidden': 'hidden'});
            $('.ui.inverted.blue.menu, .ui.inverted.menu .blue.active.item').attr({'aria-hidden': 'hidden', 'hidden': 'hidden'});
            $('.ui.horizontal.segments.footer').css({'display': 'none'});
            $('.ui.horizontal.segments.footer').attr({'aria-hidden': 'hidden', 'hidden': 'hidden'});

            let styleName = this.props.PresentationStore.theme;

            this.revealDiv.style.display = 'inline';

            let pptxwidth = $('.pptx2html').width();
            let pptxheight = $('.pptx2html').height();

            Reveal.initialize({
                width: pptxwidth,
    			height: pptxheight,
                transition: 'none',
                backgroundTransition: 'none',
                history: true,
                dependencies: [
                    { src: '/custom_modules/reveal.js/plugin/notes/notes.js', async: true },
                    { src: '/custom_modules/reveal.js/plugin/zoom-js/zoom.js', async: true },
                ]
            });

        }
    }

    componentDidUpdate(){

    }
    render(){
        this.slides = this.getSlides();
        return(

 this.revealDiv = refToDiv} data-transition="none" data-background-transition="none">

        			     	{this.slides}

        );
    }

    getSlides(){
        let slides = this.props.PresentationStore.content;

        let returnList = [];
        if(slides){
            for (let i = 0; i < slides.length; i++) {
                let slide = slides[i];
                let notes = '';
                if(slide.speakernotes){
                    notes =  '' + slide.speakernotes + '';
                }
                let content = slide.content + notes;
                returnList.push(<PresentationSlide content={content} key={slide.id} id={'slide-' + slide.id} />);
            }
            return returnList;

        }
        else{
            return (
);
        }
    }

}

Presentation.contextTypes = {
    executeAction: React.PropTypes.func.isRequired
};

Presentation = connectToStores(Presentation, [PresentationStore], (context, props) => {
    return {
        PresentationStore: context.getStore(PresentationStore).getState()
    };
});

export default Presentation;
<|endoftext|>


<commit_before>module.exports = (app, mydata, socketIO) => {

  var _ = require('lodash')
    , fs = require('fs')
    , cv = require('opencv/lib/opencv')
    , async = require('async')
    ;

	var slides = mydata.slides = {
	  '100': [
      {
      slideId: 12340,
      slideNo: 0,
      title: 'Wasabi 1',
      url: 'ws1.jpg',
      urlThumb: 'ws1-thumb.jpg'
      },
      {
      slideId: 12341,
      slideNo: 1,
      title: 'Wasabi 2',
      url: 'ws2.jpg',
      urlThumb: 'ws2-thumb.jpg'
      },
      {
      slideId: 12342,
      slideNo: 2,
      title: 'Wasabi 3',
      url: 'ws3.jpg',
      urlThumb: 'ws3-thumb.jpg'
      },
      {
      slideId: 12343,
      slideNo: 3,
      title: 'Wasabi 4',
      url: 'ws4.jpg',
      urlThumb: 'ws4-thumb.jpg'
      },
      {
      slideId: 12344,
      slideNo: 4,
      title: 'Wasabi 5',
      url: 'ws5.jpg',
      urlThumb: 'ws5-thumb.jpg'
      }
    ]
	};

	app.get('/slides/:slideDeckId', function(req, res) {
	    res.contentType('json');
	    var s = slides[req.params.slideDeckId];
	    res.json({slideDeckData: s, slideDeckLength: s.length});
	});

	socketIO
  .on('connection', function(socket) {
    socket.mydata = socket.mydata || {};

    socket.on('subSlide', function(msg) {
      socketIO.emit('subSlide', msg);

      socket.mydata.user = msg.user;
      socket.mydata.slideRoom = 'slideDeckId/'+msg.slideDeckId;
      socket.mydata.slideDeckId = msg.slideDeckId;

      socket.join(socket.mydata.slideRoom);
      if (socket.mydata.slideRoom && socket.mydata.user.role !== 'lecturer') {
        // socket.emit('slideUpdate/'+socket.mydata.slideDeckId,{slideNo: msg.slideNo, username: socket.mydata.user.username});
      }
      mydata.db.insertOne({cmd: 'subSlide/'+socket.mydata.slideDeckId, msg: msg, timestamp: (new Date()), user: socket.mydata.user})
    });

    socket.on('unsubSlide', function(msg) {
      socketIO.emit('unsubSlide', msg);
      socket.leave(socket.mydata.slideRoom);
      socket.mydata.slideRoom = null;
      socket.mydata.slideDeckId = null;

      mydata.db.insertOne({cmd: 'subSlide/'+socket.mydata.slideDeckId, msg: msg, timestamp: (new Date()), user: socket.mydata.user})
    });

    socket.on('pushLocalSlide', function(msg) {
      if (socket.mydata.slideRoom && socket.mydata.user.role === 'lecturer') {
        socket.mydata.slideNo = msg.slideNo;

        socketIO.to(socket.mydata.slideRoom)
        .emit('slideUpdate/'+socket.mydata.slideDeckId,{slideNoLecturer: msg.slideNoLocal, username: socket.mydata.user.username});
        });
      }
        mydata.db.insertOne({cmd: 'slideUpdate/'+socket.mydata.slideDeckId, msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
          // console.log(arguments);
    });

/*
    socket.on('hi', function(msg) {
        socketIO.to(socket.mydata.slideRoom)
        .emit('hi', msg);
         mydata.db.insertOne({cmd: 'slideUpdate/'+socket.mydata.slideDeckId, msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
          console.log(arguments);
        });
    })
*/

    socket.on('AskQuestion', function(msg) {
      console.log('AskQuestion', msg);
        socketIO.to(socket.mydata.slideRoom)
        .emit('AskQuestion', msg);
         mydata.db.insertOne({cmd: 'AskQuestion', msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
        });
    })

    socket.on('AlertTeacher', function(msg) {
        socketIO.to(socket.mydata.slideRoom)
        .emit('AlertTeacher', msg);
         mydata.db.insertOne({cmd: 'AlertTeacher', msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
         //           if (err)
         // console.log(arguments);
        });
    })

    socket.on('ReplyQuestion', function(msg) {
        socketIO.to(socket.mydata.slideRoom)
        .emit('ReplyQuestion', msg);
         mydata.db.insertOne({cmd: 'ReplyQuestion', msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
          //         if (err)
          // console.log(arguments);
        });
    })

//================================================================================>> This is Changed
  socket.on('pushQuizQuestion', function(msg) {
//    if (socket.mydata.slideRoom && socket.mydata.user.role === 'student') {
        socketIO.to(socket.mydata.slideRoom)
        .emit('pushQuizQuestion', msg);
         mydata.db.insertOne({cmd: 'ReplyQuestion', msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
        });
//    }
    })
  socket.on('pushQuizAnswer', function(msg) {
//    if (socket.mydata.slideRoom && socket.mydata.user.role === 'student') {
        socketIO.to(socket.mydata.slideRoom)
        .emit('pushQuizAnswer', msg);
         mydata.db.insertOne({cmd: 'ReplyQuestion', msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
        //           if (err)
        //   console.log(arguments);
        });
//    }
    })
//================================================================================>

     socket.on('class/img', function(msg) {
        try {
        async.waterfall([
          function writeFile(callback) {
            if (msg.jpg.length) {
              // console.log(msg);
              // var tmpFilename = '/tmp/'+msg.user.username+msg.jpg.length+'.jpg';
              var tmpFilename;
              try {
                tmpFilename = '/tmp/'+( socket.mydata.user.username ? socket.mydata.user.username : 'user-') +msg.jpg.length+'.jpg';
              } catch (e) {
                tmpFilename = '/tmp/image-' +msg.jpg.length+'.jpg';

              }
              var jpgData = new Buffer(msg.jpg.replace(/.+base64,/,''), 'base64');
              fs.writeFile(tmpFilename, jpgData, function(err) {
                if (err)
                  tmpFilename = null;
                callback(err, tmpFilename);
              });
            }
            else
              callback('err', null);
          },
          function readImage(tmpFilename, callback) {
            cv.readImage(tmpFilename, function(err, im) {
              if (err)
                callback(err,tmpFilename);
              if (im.width() < 1 || im.height < 1)
                callback(im, tmpFilename);
              callback(null, tmpFilename, im);
            });
          },
          function detectObject(tmpFilename, im, callback) {
            im.detectObject(cv.FACE_CASCADE, {}, function(err, faces) {
              // console.log('faces',faces);
              if (faces && faces.length) {
                msg.faces = faces;
                mydata.db.insertOne({cmd: 'face-count', msg: msg, timestamp: (new Date()), user: socket.mydata.user});
              }
              callback(err, tmpFilename);
            });
          }
        ], function(err, result) {
          if (result) {
            // fs.unlink(result, function(err) {
            //   if (err)
            //     console.log('unlink err', err, result);
            // })
          }
          msg.jpg = msg.jpg.length;
          // console.log('receive vid capture', msg);
          socket.emit('rtc-vidcap-reply',msg);
          delete msg.jpg;
        });
      }
      catch(e) { console.log('rtc-vidcap err',e); }

    });

  });

}<commit_msg>usermedia<commit_after>module.exports = (app, mydata, socketIO) => {

  var _ = require('lodash')
    , fs = require('fs')
    , cv = require('opencv/lib/opencv')
    , async = require('async')
    ;

	var slides = mydata.slides = {
	  '100': [
      {
      slideId: 12340,
      slideNo: 0,
      title: 'Wasabi 1',
      url: 'ws1.jpg',
      urlThumb: 'ws1-thumb.jpg'
      },
      {
      slideId: 12341,
      slideNo: 1,
      title: 'Wasabi 2',
      url: 'ws2.jpg',
      urlThumb: 'ws2-thumb.jpg'
      },
      {
      slideId: 12342,
      slideNo: 2,
      title: 'Wasabi 3',
      url: 'ws3.jpg',
      urlThumb: 'ws3-thumb.jpg'
      },
      {
      slideId: 12343,
      slideNo: 3,
      title: 'Wasabi 4',
      url: 'ws4.jpg',
      urlThumb: 'ws4-thumb.jpg'
      },
      {
      slideId: 12344,
      slideNo: 4,
      title: 'Wasabi 5',
      url: 'ws5.jpg',
      urlThumb: 'ws5-thumb.jpg'
      }
    ]
	};

	app.get('/slides/:slideDeckId', function(req, res) {
	    res.contentType('json');
	    var s = slides[req.params.slideDeckId];
	    res.json({slideDeckData: s, slideDeckLength: s.length});
	});

	socketIO
  .on('connection', function(socket) {
    socket.mydata = socket.mydata || {};

    socket.on('subSlide', function(msg) {
      socketIO.emit('subSlide', msg);

      socket.mydata.user = msg.user;
      socket.mydata.slideRoom = 'slideDeckId/'+msg.slideDeckId;
      socket.mydata.slideDeckId = msg.slideDeckId;

      socket.join(socket.mydata.slideRoom);
      if (socket.mydata.slideRoom && socket.mydata.user.role !== 'lecturer') {
        // socket.emit('slideUpdate/'+socket.mydata.slideDeckId,{slideNo: msg.slideNo, username: socket.mydata.user.username});
      }
      mydata.db.insertOne({cmd: 'subSlide/'+socket.mydata.slideDeckId, msg: msg, timestamp: (new Date()), user: socket.mydata.user})
    });

    socket.on('unsubSlide', function(msg) {
      socketIO.emit('unsubSlide', msg);
      socket.leave(socket.mydata.slideRoom);
      socket.mydata.slideRoom = null;
      socket.mydata.slideDeckId = null;

      mydata.db.insertOne({cmd: 'subSlide/'+socket.mydata.slideDeckId, msg: msg, timestamp: (new Date()), user: socket.mydata.user})
    });

    socket.on('pushLocalSlide', function(msg) {
      if (socket.mydata.slideRoom && socket.mydata.user.role === 'lecturer') {
        socket.mydata.slideNo = msg.slideNo;

        socketIO.to(socket.mydata.slideRoom)
        .emit('slideUpdate/'+socket.mydata.slideDeckId,{slideNoLecturer: msg.slideNoLocal, username: socket.mydata.user.username});
        });
      }
        mydata.db.insertOne({cmd: 'slideUpdate/'+socket.mydata.slideDeckId, msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
          // console.log(arguments);
    });

/*
    socket.on('hi', function(msg) {
        socketIO.to(socket.mydata.slideRoom)
        .emit('hi', msg);
         mydata.db.insertOne({cmd: 'slideUpdate/'+socket.mydata.slideDeckId, msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
          console.log(arguments);
        });
    })
*/

    socket.on('AskQuestion', function(msg) {
      console.log('AskQuestion', msg);
        socketIO.to(socket.mydata.slideRoom)
        .emit('AskQuestion', msg);
         mydata.db.insertOne({cmd: 'AskQuestion', msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
        });
    })

    socket.on('AlertTeacher', function(msg) {
        socketIO.to(socket.mydata.slideRoom)
        .emit('AlertTeacher', msg);
         mydata.db.insertOne({cmd: 'AlertTeacher', msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
         //           if (err)
         // console.log(arguments);
        });
    })

    socket.on('ReplyQuestion', function(msg) {
        socketIO.to(socket.mydata.slideRoom)
        .emit('ReplyQuestion', msg);
         mydata.db.insertOne({cmd: 'ReplyQuestion', msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
          //         if (err)
          // console.log(arguments);
        });
    })

//================================================================================>> This is Changed
  socket.on('pushQuizQuestion', function(msg) {
//    if (socket.mydata.slideRoom && socket.mydata.user.role === 'student') {
        socketIO.to(socket.mydata.slideRoom)
        .emit('pushQuizQuestion', msg);
         mydata.db.insertOne({cmd: 'ReplyQuestion', msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
        });
//    }
    })
  socket.on('pushQuizAnswer', function(msg) {
//    if (socket.mydata.slideRoom && socket.mydata.user.role === 'student') {
        socketIO.to(socket.mydata.slideRoom)
        .emit('pushQuizAnswer', msg);
         mydata.db.insertOne({cmd: 'ReplyQuestion', msg: msg, timestamp: (new Date()), user: socket.mydata.user}, function() {
        //           if (err)
        //   console.log(arguments);
        });
//    }
    })
//================================================================================>

     socket.on('class/img', function(msg) {
        try {
        async.waterfall([
          function writeFile(callback) {
            if (msg.jpg.length) {
              // console.log(msg);
              // var tmpFilename = '/tmp/'+msg.user.username+msg.jpg.length+'.jpg';
              var tmpFilename;
              try {
                tmpFilename = '/tmp/'+( socket.mydata.user.username ? socket.mydata.user.username : 'user-') +msg.jpg.length+'.jpg';
              } catch (e) {
                tmpFilename = '/tmp/image-' +msg.jpg.length+'.jpg';

              }
              var jpgData = new Buffer(msg.jpg.replace(/.+base64,/,''), 'base64');
              fs.writeFile(tmpFilename, jpgData, function(err) {
                if (err)
                  tmpFilename = null;
                callback(err, tmpFilename);
              });
            }
            else
              callback('err', null);
          },
          function readImage(tmpFilename, callback) {
            cv.readImage(tmpFilename, function(err, im) {
              if (err)
                callback(err,tmpFilename);
              if (im.width() < 1 || im.height < 1)
                callback(im, tmpFilename);
              callback(null, tmpFilename, im);
            });
          },
          function detectObject(tmpFilename, im, callback) {
            im.detectObject(cv.FACE_CASCADE, {}, function(err, faces) {
              // console.log('faces',faces);
              if (faces && faces.length) {
                msg.faces = faces;
                msg.jpg = msg.jpg.length;
                mydata.db.insertOne({cmd: 'face-count', msg: msg, timestamp: (new Date()), user: socket.mydata.user});
              }
              callback(err, tmpFilename);
            });
          }
        ], function(err, result) {
          if (result) {
            // fs.unlink(result, function(err) {
            //   if (err)
            //     console.log('unlink err', err, result);
            // })
          }
          msg.jpg = msg.jpg.length;
          // console.log('receive vid capture', msg);
          socket.emit('rtc-vidcap-reply',msg);
          delete msg.jpg;
        });
      }
      catch(e) { console.log('rtc-vidcap err',e); }

    });

  });

}<|endoftext|>


<commit_before>import React from "react";
import PropTypes from "prop-types";
import { Link } from "gatsby";
import Article from "./Article";

const ArticlesList = ({ articles, withLink = true }) => {
  return (

      {articles.map(article => (

      ))}
      {withLink && (

          <Link
            to="/blog"
            className="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center justify-between"
          >
             Voir tous mes articles
            <svg
              className="fill-current h-6 ml-2"
              xmlns="http://www.w3.org/2000/svg"
              viewBox="0 0 32 32"
            >
              <path d="M16,4.96C9.913,4.96,4.96,9.912,4.96,16S9.913,27.04,16,27.04S27.04,22.088,27.04,16S22.087,4.96,16,4.96z M16,25.12  c-5.028,0-9.12-4.092-9.12-9.12S10.972,6.88,16,6.88s9.12,4.092,9.12,9.12S21.028,25.12,16,25.12z" />
              <polygon points="13.098,11.368 17.966,16 13.098,20.632 14.421,22.022 20.753,16 14.421,9.977 " />
            </svg>
          </Link>

      )}

  );
};

ArticlesList.propTypes = {
  articles: PropTypes.array.isRequired,
  withLink: PropTypes.bool,
};

export default ArticlesList;
<commit_msg>Update css<commit_after>import React from "react";
import PropTypes from "prop-types";
import { Link } from "gatsby";
import Article from "./Article";

const ArticlesList = ({ articles, withLink = true }) => {
  return (

      {articles.map(article => (

      ))}
      {withLink && (

          <Link
            to="/blog"
            className="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded inline-flex items-center justify-between"
          >
             Voir tous mes articles
            <svg
              className="fill-current h-6 ml-2"
              xmlns="http://www.w3.org/2000/svg"
              viewBox="0 0 32 32"
            >
              <path d="M16,4.96C9.913,4.96,4.96,9.912,4.96,16S9.913,27.04,16,27.04S27.04,22.088,27.04,16S22.087,4.96,16,4.96z M16,25.12  c-5.028,0-9.12-4.092-9.12-9.12S10.972,6.88,16,6.88s9.12,4.092,9.12,9.12S21.028,25.12,16,25.12z" />
              <polygon points="13.098,11.368 17.966,16 13.098,20.632 14.421,22.022 20.753,16 14.421,9.977 " />
            </svg>
          </Link>

      )}

  );
};

ArticlesList.propTypes = {
  articles: PropTypes.array.isRequired,
  withLink: PropTypes.bool,
};

export default ArticlesList;
<|endoftext|>


<commit_before>$(document).ready(function(){
	$(".advance-btn").click(function(){
      $("#advance-search-container").slideToggle();
    });
	$(window).scroll(function () {
            if ($(this).scrollTop() > 50) {
                $('#back-to-top').fadeIn();
            } else {
                $('#back-to-top').fadeOut();
            }
        });
        // scroll body to 0px on click
        $('#back-to-top').click(function () {
            $('body,html').animate({
                scrollTop: 0
            }, slow);
            return false;
        });

});
<commit_msg>Little changes<commit_after>$(document).ready(function(){
	$(".advance-btn").click(function(){
      $("#advance-search-container").slideToggle();
    });
	$(window).scroll(function () {
            if ($(this).scrollTop() > 50) {
                $('#back-to-top').fadeIn();
            } else {
                $('#back-to-top').fadeOut();
            }
        });
        // scroll body to 0px on click
        $('#back-to-top').click(function () {
            $('body,html').animate({
                scrollTop: 0
            }, 1000);
            return false;
        });

});
<|endoftext|>


<commit_before>/*
 * Handles snippet operations on the Pages main page
 */
+function ($) { "use strict";
    if ($.oc.pages === undefined)
        $.oc.pages = {}

    var SnippetManager = function ($masterTabs) {
        this.$masterTabs = $masterTabs

        var self = this

        $(document).on('hidden.oc.inspector', '.field-richeditor [data-snippet]', function() {
            self.syncEditorCode(this)
        })

        $(document).on('init.oc.richeditor', '.field-richeditor textarea', function(ev, richeditor) {
            self.initSnippets(richeditor.getElement())
        })

        $(document).on('setContent.oc.richeditor', '.field-richeditor textarea', function(ev, richeditor) {
            self.initSnippets(richeditor.getElement())
        })

        $(document).on('syncContent.oc.richeditor', '.field-richeditor textarea', function(ev, richeditor, container) {
            self.syncPageMarkup(ev, container)
        })

        $(document).on('figureKeydown.oc.richeditor', '.field-richeditor textarea', function(ev, originalEv, richeditor) {
            self.editorKeyDown(ev, originalEv, richeditor)
        })

        $(document).on('click', '[data-snippet]', function() {
            $.oc.inspector.manager.createInspector(this)
            return false
        })
    }

    SnippetManager.prototype.onSidebarSnippetClick = function($sidebarItem) {
        var $pageForm = $('div.tab-content > .tab-pane.active form[data-object-type=page]', this.$masterTabs)

        if (!$pageForm.length) {
            $.oc.alert('Snippets can only be added to Pages. Please open or create a Page first.')
            return
        }

        var $activeEditorTab = $('.control-tabs.secondary-tabs .tab-pane.active', $pageForm),
            $textarea = $activeEditorTab.find('[data-control="richeditor"] textarea'),
            $richeditorNode = $textarea.closest('[data-control="richeditor"]'),
            $snippetNode = $('

'),
            componentClass = $sidebarItem.attr('data-component-class'),
            snippetCode = $sidebarItem.data('snippet')

        if (!$textarea.length) {
            $.oc.alert('Snippets can only be added to page Content or HTML placeholders.')
            return
        }

        if (componentClass) {
            $snippetNode.attr({
                'data-component': componentClass,
                'data-inspector-class': componentClass
            })

            // If a component-based snippet was added, make sure that
            // its code is unique, as it will be used as a component
            // alias.

            snippetCode = this.generateUniqueComponentSnippetCode(componentClass, snippetCode, $pageForm)
        }

        $snippetNode.attr({
            'data-snippet': snippetCode,
            'data-name': $sidebarItem.data('snippet-name'),
            'tabindex': '0',
            'draggable': 'true',
            'data-ui-block': 'true'
        })

        $snippetNode.addClass('fr-draggable')

        $richeditorNode.richEditor('insertUiBlock', $snippetNode)
    }

    SnippetManager.prototype.generateUniqueComponentSnippetCode = function(componentClass, originalCode, $pageForm) {
        var updatedCode = originalCode,
            counter = 1,
            snippetFound = false

        do {
            snippetFound = false
            $('[data-control="richeditor"] textarea', $pageForm).each(function(){
                var $textarea = $(this),
                    $codeDom = $('
' + $textarea.val() + '
')

                if ($codeDom.find('[data-snippet="'+updatedCode+'"][data-component]').length > 0) {
                    snippetFound = true
                    updatedCode = originalCode + counter
                    counter++

                    return false
                }
            })

        } while (snippetFound)

        return updatedCode
    }

    SnippetManager.prototype.syncEditorCode = function(inspectable) {
        // Race condition
        setTimeout(function() {
            var $richeditor = $(inspectable).closest('[data-control=richeditor]')
            $richeditor.richEditor('syncContent')
            inspectable.focus()
        }, 0)
    }

    SnippetManager.prototype.initSnippets = function($editor) {
        var snippetCodes = []

        $('.fr-view [data-snippet]', $editor).each(function(){
            var $snippet = $(this),
                snippetCode = $snippet.attr('data-snippet'),
                componentClass = $snippet.attr('data-component')

            if (componentClass)
                snippetCode += '|' + componentClass

            snippetCodes.push(snippetCode)

            $snippet
                .addClass('loading')
                .addClass('fr-draggable')
                .attr({
                    'data-inspector-css-class': 'hero',
                    'data-name': 'Loading...',
                    'data-ui-block': 'true',
                    'draggable': 'true',
                    'tabindex': '0'
                })
                .html(' ')

            if (componentClass) {
                $snippet.attr('data-inspector-class', componentClass)
            }

            this.contentEditable = false
        })

        if (snippetCodes.length > 0) {
            var request = $editor.request('onGetSnippetNames', {
                data: {
                    codes: snippetCodes
                }
            }).done(function(data) {
                if (data.names !== undefined) {
                    $.each(data.names, function(code){
                        $('[data-snippet="'+code+'"]', $editor)
                            .attr('data-name', this)
                            .removeClass('loading')
                    })
                }
            })
        }
    }

    SnippetManager.prototype.syncPageMarkup = function(ev, container) {
        var $domTree = $('
'+container.html+'
')

        $('[data-snippet]', $domTree).each(function(){
            var $snippet = $(this)

            $snippet.removeAttr('contenteditable data-name tabindex data-inspector-css-class data-inspector-class data-property-inspectorclassname data-property-inspectorproperty data-ui-block draggable')
            $snippet.removeClass('fr-draggable fr-dragging')

            if (!$snippet.attr('class')) {
                $snippet.removeAttr('class')
            }
        })

        container.html = $domTree.html()
    }

    SnippetManager.prototype.editorKeyDown = function(ev, originalEv, richeditor) {
        if (richeditor.getTextarea() === undefined)
            return

        if (originalEv.target && $(originalEv.target).attr('data-snippet') !== undefined) {
            this.snippetKeyDown(originalEv, originalEv.target)
        }
    }

    SnippetManager.prototype.snippetKeyDown = function(ev, snippet) {
        if (ev.which == 32) {
            switch (ev.which) {
                case 32:
                    // Space key
                    $.oc.inspector.manager.createInspector(snippet)
                break
            }
        }
    }

    $.oc.pages.snippetManager = SnippetManager
}(window.jQuery);
<commit_msg>Minor revert<commit_after>/*
 * Handles snippet operations on the Pages main page
 */
+function ($) { "use strict";
    if ($.oc.pages === undefined)
        $.oc.pages = {}

    var SnippetManager = function ($masterTabs) {
        this.$masterTabs = $masterTabs

        var self = this

        $(document).on('hidden.oc.inspector', '.field-richeditor [data-snippet]', function() {
            self.syncEditorCode(this)
        })

        $(document).on('init.oc.richeditor', '.field-richeditor textarea', function(ev, richeditor) {
            self.initSnippets(richeditor.getElement())
        })

        $(document).on('setContent.oc.richeditor', '.field-richeditor textarea', function(ev, richeditor) {
            self.initSnippets(richeditor.getElement())
        })

        $(document).on('syncContent.oc.richeditor', '.field-richeditor textarea', function(ev, richeditor, container) {
            self.syncPageMarkup(ev, container)
        })

        $(document).on('figureKeydown.oc.richeditor', '.field-richeditor textarea', function(ev, originalEv, richeditor) {
            self.editorKeyDown(ev, originalEv, richeditor)
        })

        $(document).on('click', '[data-snippet]', function() {
            $.oc.inspector.manager.createInspector(this)
            return false
        })
    }

    SnippetManager.prototype.onSidebarSnippetClick = function($sidebarItem) {
        var $pageForm = $('div.tab-content > .tab-pane.active form[data-object-type=page]', this.$masterTabs)

        if (!$pageForm.length) {
            $.oc.alert('Snippets can only be added to Pages. Please open or create a Page first.')
            return
        }

        var $activeEditorTab = $('.control-tabs.secondary-tabs .tab-pane.active', $pageForm),
            $textarea = $activeEditorTab.find('[data-control="richeditor"] textarea'),
            $richeditorNode = $textarea.closest('[data-control="richeditor"]'),
            $snippetNode = $('

'),
            componentClass = $sidebarItem.attr('data-component-class'),
            snippetCode = $sidebarItem.data('snippet')

        if (!$textarea.length) {
            $.oc.alert('Snippets can only be added to page Content or HTML placeholders.')
            return
        }

        if (componentClass) {
            $snippetNode.attr({
                'data-component': componentClass,
                'data-inspector-class': componentClass
            })

            // If a component-based snippet was added, make sure that
            // its code is unique, as it will be used as a component
            // alias.

            snippetCode = this.generateUniqueComponentSnippetCode(componentClass, snippetCode, $pageForm)
        }

        $snippetNode.attr({
            'data-snippet': snippetCode,
            'data-name': $sidebarItem.data('snippet-name'),
            'tabindex': '0',
            'draggable': 'true',
            'data-ui-block': 'true'
        })

        $snippetNode.addClass('fr-draggable')

        $richeditorNode.richEditor('insertUiBlock', $snippetNode)
    }

    SnippetManager.prototype.generateUniqueComponentSnippetCode = function(componentClass, originalCode, $pageForm) {
        var updatedCode = originalCode,
            counter = 1,
            snippetFound = false

        do {
            snippetFound = false

            $('[data-control="richeditor"] textarea', $pageForm).each(function(){
                var $textarea = $(this),
                    $codeDom = $('
' + $textarea.val() + '
')

                if ($codeDom.find('[data-snippet="'+updatedCode+'"][data-component]').length > 0) {
                    snippetFound = true
                    updatedCode = originalCode + counter
                    counter++

                    return false
                }
            })

        } while (snippetFound)

        return updatedCode
    }

    SnippetManager.prototype.syncEditorCode = function(inspectable) {
        // Race condition
        setTimeout(function() {
            var $richeditor = $(inspectable).closest('[data-control=richeditor]')
            $richeditor.richEditor('syncContent')
            inspectable.focus()
        }, 0)
    }

    SnippetManager.prototype.initSnippets = function($editor) {
        var snippetCodes = []

        $('.fr-view [data-snippet]', $editor).each(function(){
            var $snippet = $(this),
                snippetCode = $snippet.attr('data-snippet'),
                componentClass = $snippet.attr('data-component')

            if (componentClass)
                snippetCode += '|' + componentClass

            snippetCodes.push(snippetCode)

            $snippet
                .addClass('loading')
                .addClass('fr-draggable')
                .attr({
                    'data-inspector-css-class': 'hero',
                    'data-name': 'Loading...',
                    'data-ui-block': 'true',
                    'draggable': 'true',
                    'tabindex': '0'
                })
                .html(' ')

            if (componentClass) {
                $snippet.attr('data-inspector-class', componentClass)
            }

            this.contentEditable = false
        })

        if (snippetCodes.length > 0) {
            var request = $editor.request('onGetSnippetNames', {
                data: {
                    codes: snippetCodes
                }
            }).done(function(data) {
                if (data.names !== undefined) {
                    $.each(data.names, function(code){
                        $('[data-snippet="'+code+'"]', $editor)
                            .attr('data-name', this)
                            .removeClass('loading')
                    })
                }
            })
        }
    }

    SnippetManager.prototype.syncPageMarkup = function(ev, container) {
        var $domTree = $('
'+container.html+'
')

        $('[data-snippet]', $domTree).each(function(){
            var $snippet = $(this)

            $snippet.removeAttr('contenteditable data-name tabindex data-inspector-css-class data-inspector-class data-property-inspectorclassname data-property-inspectorproperty data-ui-block draggable')
            $snippet.removeClass('fr-draggable fr-dragging')

            if (!$snippet.attr('class')) {
                $snippet.removeAttr('class')
            }
        })

        container.html = $domTree.html()
    }

    SnippetManager.prototype.editorKeyDown = function(ev, originalEv, richeditor) {
        if (richeditor.getTextarea() === undefined)
            return

        if (originalEv.target && $(originalEv.target).attr('data-snippet') !== undefined) {
            this.snippetKeyDown(originalEv, originalEv.target)
        }
    }

    SnippetManager.prototype.snippetKeyDown = function(ev, snippet) {
        if (ev.which == 32) {
            switch (ev.which) {
                case 32:
                    // Space key
                    $.oc.inspector.manager.createInspector(snippet)
                break
            }
        }
    }

    $.oc.pages.snippetManager = SnippetManager
}(window.jQuery);
<|endoftext|>


<commit_before>function $(s){

	return document.getElementById(s);
}

var valuta = "kr";

var VARS=
{
	'transactions':
	{
		field: 'transactions',
		query: 'trn',
		type: 'int',
		default: 100
	},
	'average_value':
	{
		field: 'value',
		query: 'avg',
		type: 'int',
		default: 570
	},
	'acquirer_selection':
	{
		field: 'selectacquirer',
		query: 'acq',
		type: 'select',
		default: 'teller'
	},
	'acquirer_fee':
	{
		field: 'acquirerFixedRate',
		query: 'fee',
		type: 'int',
		default: function()
				{
					var curAcq=$('selectacquirer').options[ $('selectacquirer').selectedIndex ].id.substring(7);
					return ACQUIRER[curAcq].fixedTransactionFee;
				}
	},
	'acquirer_percent':
	{
		field: 'acquirerPercentageRate',
		query: 'pfee',
		type: 'int',
		default: function()
				{
					var curAcq=$('selectacquirer').options[ $('selectacquirer').selectedIndex ].id.substring(7);
					return ACQUIRER[curAcq].percentageTransactionFee;
				}
	},
	'3dsecure':
	{
		field: '3d',
		query: '3ds',
		type: 'checkbox',
		default: 1
	},
	'include_setup_fee':
	{
		field: 'incSetupFee',
		query: 'isf', //Med OprettelsesGebyr
		type: 'checkbox',
		default: 1
	},
	'dankort':
	{
		field: 'dankort',
		query: 'dk',
		type: 'checkbox',
		default: 1
	},
	'visa_mastercard':
	{
		field: 'visamc',
		query: 'vmc',
		type: 'checkbox',
		default: 1
	}

}
function setFieldValue(key,value){
	switch(VARS[key].type)
	{
	case 'int':
		$(VARS[key].field).value=value;
		break;
	case 'checkbox':
		$(VARS[key].field).checked =( value === 1);
		break;
	case 'select':
		$('option_'+value).selected = true;
	}
}
function getFieldValue(key){
	var value;
	switch(VARS[key].type)
	{
	case 'int':
		value=$(VARS[key].field).value.replace(',','.').replace('k','').replace('r','').replace(' ','');
		break;
	case 'checkbox':
		value=$(VARS[key].field).checked;
		break;
	case 'select':
		value=$(VARS[key].field).options[ $(VARS[key].field).selectedIndex ].id.substr(7);
		break;
	}
	return value;
}

function getValue(n)
{
	if(typeof n == 'function')
	{
		return n();
	}
	else return n;
}

function parseUrlVars()
{
	if ( location.search !== "" )
	{
		var varTable = [];
		var x = location.search.substr(1).toLowerCase().split("&");

		for (var i=0; i<x.length; i++)
		{
			var y = x[i].split("=");
			varTable[y[0]] = y[1];
		}
	}
	for(key in VARS)
	{
		if(varTable && varTable[VARS[key].query])
		{

			setFieldValue( key , varTable[VARS[key].query] );
		}
		else
		{
			setFieldValue( key , getValue(VARS[key].default) );
		}

	}
}

function saveUrlVars()
{

	var str='';

	for(key in VARS)
	{

		if(getFieldValue(key) != getValue(VARS[key].default))
		{
			str += VARS[key].query+'='+getFieldValue(key);
			if (str!=='') { str+='&'; }
		}
	}
	var qmark = '';
	if (str[str.length - 1]==='&') { str=str.substring(0, str.length - 1); }
	if (str!=='') { qmark='?'; }
	if(window.location.pathname+qmark+str !== window.location.pathname+window.location.search )
	{
		history.pushState({ foo: window.location.search },'b', window.location.pathname+qmark+str);
	}
}
window.addEventListener('popstate', function(event) {
    if (event.state) {
		parseUrlVars();
		build('popstate');
    }
}, false);

function build(condition)
{
	//Generer muligheden for at vælge indløser, samt vælg indløser:

	if(condition === 'init')
	{
		var acquirersString="";
		for(var key in ACQUIRER)
		{
			if( key !== 'nets' )
			{
				acquirersString += '<option id="option_'+ key + '">' + ACQUIRER[key].name + '</option>';
			}
		}
		$('selectacquirer').innerHTML = acquirersString;
		parseUrlVars();
		history.replaceState({ foo: window.location.search },'b',window.location.pathname+window.location.search);

	}
	var selectedAcquirer = $('selectacquirer').options[ $('selectacquirer').selectedIndex ].id.substring(7);
	if( selectedAcquirer !== this.previousAcquirer && condition !== 'init')
	{
		$('acquirerFixedRate').value=(ACQUIRER[selectedAcquirer].fixedTransactionFee+'kr').replace(".", ",");
		$('acquirerPercentageRate').value=(ACQUIRER[selectedAcquirer].percentageTransactionFee+'%').replace(".", ",");
	}
	this.previousAcquirer=selectedAcquirer;
	if(selectedAcquirer==='teller'){
		$('acquirerFixedRate').parentNode.style.display='none';
		$('acquirerPercentageRate').parentNode.style.display='none';
	}
	else{
		$('acquirerFixedRate').parentNode.style.display='inline';
		$('acquirerPercentageRate').parentNode.style.display='inline';
	}

	// Variable brugt hele vejen igennem genereringen af tabellen:

	var transactions = $("transactions").value.replace(",", ".");
	var value = $("value").value.replace(",", ".");
	var table = $("data");
	var rowValue = [];
	table.innerHTML = "";

	for (var key in PSP)
	{

		if ((PSP[key].isAcquirer || PSP[key].availableAcquirers.indexOf(selectedAcquirer) >-1 || PSP[key].availableAcquirers == 0)
		&& ( !( $('dankort').checked && $('visamc').checked )
			|| ( PSP[key].cards.indexOf('visa') > -1 && PSP[key].cards.indexOf('mastercard') > -1 ) ) )
		{
			var netsSupport = 0, otherAcquirerSupport = 0;
			var HTML_cards = "";
			var isAcquirer = PSP[key].isAcquirer;

			for(var i in PSP[key].cards)
			{
				var n= PSP[key].cards[i];
				var dankortCheck = ( $('dankort').checked && n === 'dankort');
				var visamcCheck= ( $('visamc').checked && ACQUIRER[selectedAcquirer].cards.indexOf(n) > -1  );

				netsSupport|= dankortCheck;
				otherAcquirerSupport|=visamcCheck;

				if ( (visamcCheck|| dankortCheck) && (n!=='maestro'|| $('3d').checked ) )
				{

					HTML_cards += "";

				}
			}

			// Fortsæt kun hvis PSP'en supporter nogen af de valgte kort:
			if ( HTML_cards !== "")
			{
				var indloser_icons='';
				var info_icon ='
';
				var info_icon_end='
';

				//Assumed 80% Dankort og 20% visa/mastercard jf. statistik
				var dkshare, vmshare;

				if ( netsSupport && (!isAcquirer) )
				{
					indloser_icons='';
					if ( otherAcquirerSupport )
					{
						indloser_icons += '
';
						dkshare = 0.82; vmshare=0.18;
					}
					else
					{
						dkshare=1; vmshare=0;
					}
				}
				else
				{
					if (!isAcquirer)
					{
						indloser_icons+= '
';
						dkshare=0  ;vmshare=1;
					}

				}

				// Rækken bliver nu konstrueret:

				var samlet = PSP[key].costfn(transactions,value);
				var samlet_info = info_icon + PSP[key].name + ': ' + toMoney(samlet);
				var samletgebyr_info = info_icon + PSP[key].name + ': ' + toMoney(samlet / transactions);
				var oprettelse_info = info_icon + PSP[key].name + ': ' + toMoney(PSP[key].setupFee);
				var faste_info = info_icon + PSP[key].name + ': '+ toMoney(PSP[key].monthlyFee + $('3d').checked * PSP[key].monthly3dsecureFee);
				var addcost;
				if (!isAcquirer && netsSupport)
				{
					addcost = ACQUIRER.nets.costfn( transactions * dkshare,value );
					samlet_info += '
' + ACQUIRER.nets.name + ' ('+(dkshare * 100) + '% tr.): '+ toMoney(addcost);
					samletgebyr_info += '
'+ACQUIRER.nets.name+' ('+(dkshare * 100)+'% tr.): '+ toMoney(addcost/transactions);
					oprettelse_info += '
'+ACQUIRER.nets.name+': '+ toMoney(ACQUIRER.nets.setupFee);
					faste_info += '
'+ACQUIRER.nets.name + ': ' + toMoney(ACQUIRER.nets.monthlyFee);
					samlet += addcost;
				}
				if (!isAcquirer && otherAcquirerSupport)
				{
					addcost = ACQUIRER[selectedAcquirer].costfn( transactions * vmshare, value);
					samlet_info += '
' + ACQUIRER[selectedAcquirer].name + ' (' + (vmshare * 100) + '% tr.): ' + toMoney(addcost);
					samletgebyr_info += '
' + ACQUIRER[selectedAcquirer].name+' (' + (vmshare * 100) + '% tr.): ' + toMoney(addcost/transactions);
					oprettelse_info += '
' + ACQUIRER[selectedAcquirer].name + ': ' + toMoney(ACQUIRER[selectedAcquirer].setupFee);
					faste_info += '
' + ACQUIRER[selectedAcquirer].name + ': ' + toMoney(ACQUIRER[selectedAcquirer].monthlyFee);
					samlet += addcost;
				}

				//Insert at the right place to sort the PSPs by cost

				var rowcounter=0;
				while(rowcounter<rowValue.length && samlet>rowValue[rowcounter])
				{
					rowcounter++;
				}

				var row = table.insertRow(rowcounter);
				rowValue.splice(rowcounter,0,samlet);

				// Insert HTML
				var logo_cell = row.insertCell(0);
				var indloser_cell = row.insertCell(1);
				var kort_cell = row.insertCell(2);
				var oprettelse_cell = row.insertCell(3);
				var faste_cell = row.insertCell(4);
				var samlet_cell = row.insertCell(5);
				var samletgebyr_cell = row.insertCell(6);

				logo_cell.innerHTML = '

'+PSP[key].name+'
';

				kort_cell.innerHTML = HTML_cards;
				kort_cell.className = 'kort';
				oprettelse_cell.innerHTML = toMoney( PSP[key].setupFee + ACQUIRER[selectedAcquirer].setupFee * otherAcquirerSupport * (!isAcquirer)+ ACQUIRER.nets.setupFee * netsSupport * (!isAcquirer) );

				faste_cell.innerHTML = toMoney( PSP[key].monthlyFee + $('3d').checked * PSP[key].monthly3dsecureFee + ACQUIRER[selectedAcquirer].monthlyFee * otherAcquirerSupport * (!isAcquirer)+ ACQUIRER.nets.monthlyFee * netsSupport * (!isAcquirer) );
				indloser_cell.innerHTML = indloser_icons;
				indloser_cell.className = 'acquirer';

				oprettelse_cell.innerHTML += oprettelse_info+info_icon_end;
				faste_cell.innerHTML += faste_info+info_icon_end;
				samlet_info += info_icon_end;
				samletgebyr_info += info_icon_end;
				samlet_cell.innerHTML = toMoney(samlet) + samlet_info;
				samletgebyr_cell.innerHTML = toMoney(samlet/transactions) + samletgebyr_info;
			}

		}

	}
	if(condition!=='init' && condition !== 'popstate' && condition!=='keyup')
		saveUrlVars();

}

function toMoney(x)
{
	var number = Math.round(x * 100) / 100;

    var parts = number.toString().split(".");
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
    parts.join(",");
    return parts+ " " + valuta;
}
<commit_msg>Ændret location.search til location.hash<commit_after>function $(s){

	return document.getElementById(s);
}

var valuta = "kr";

var VARS=
{
	'transactions':
	{
		field: 'transactions',
		query: 't',
		type: 'int',
		default: 100
	},
	'average_value':
	{
		field: 'value',
		query: 'p',
		type: 'int',
		default: 570
	},
	'acquirer_selection':
	{
		field: 'selectacquirer',
		query: 'acq',
		type: 'select',
		default: 'teller'
	},
	'acquirer_fee':
	{
		field: 'acquirerFixedRate',
		query: 'fee',
		type: 'int',
		default: function()
				{
					var curAcq=$('selectacquirer').options[ $('selectacquirer').selectedIndex ].id.substring(7);
					return ACQUIRER[curAcq].fixedTransactionFee;
				}
	},
	'acquirer_percent':
	{
		field: 'acquirerPercentageRate',
		query: 'pfee',
		type: 'int',
		default: function()
				{
					var curAcq=$('selectacquirer').options[ $('selectacquirer').selectedIndex ].id.substring(7);
					return ACQUIRER[curAcq].percentageTransactionFee;
				}
	},
	'3dsecure':
	{
		field: '3d',
		query: '3ds',
		type: 'checkbox',
		default: 1
	},
	'include_setup_fee':
	{
		field: 'incSetupFee',
		query: 'isf', //Med OprettelsesGebyr
		type: 'checkbox',
		default: 1
	},
	'dankort':
	{
		field: 'dankort',
		query: 'dk',
		type: 'checkbox',
		default: 1
	},
	'visa_mastercard':
	{
		field: 'visamc',
		query: 'vmc',
		type: 'checkbox',
		default: 1
	}

}
function setFieldValue(key,value){
	switch(VARS[key].type)
	{
	case 'int':
		$(VARS[key].field).value=value;
		break;
	case 'checkbox':
		$(VARS[key].field).checked =( value === 1);
		break;
	case 'select':
		$('option_'+value).selected = true;
	}
}
function getFieldValue(key){
	var value;
	switch(VARS[key].type)
	{
	case 'int':
		value=$(VARS[key].field).value.replace(',','.').replace('k','').replace('r','').replace(' ','');
		break;
	case 'checkbox':
		value=$(VARS[key].field).checked;
		break;
	case 'select':
		value=$(VARS[key].field).options[ $(VARS[key].field).selectedIndex ].id.substr(7);
		break;
	}
	return value;
}

function getValue(n)
{
	if(typeof n == 'function')
	{
		return n();
	}
	else return n;
}

function parseUrlVars()
{

	var hash = window.location.hash;

	if ( hash !== "" )
	{
		var varTable = [];
		var x = hash.substr(1).toLowerCase().split("&");

		for (var i=0; i<x.length; i++)
		{
			var y = x[i].split("=");
			varTable[y[0]] = y[1];
		}
	}
	for(key in VARS)
	{
		if(varTable && varTable[VARS[key].query])
		{

			setFieldValue( key , varTable[VARS[key].query] );
		}
		else
		{
			setFieldValue( key , getValue(VARS[key].default) );
		}

	}
}

function saveUrlVars()
{

	var str='';

	for(key in VARS)
	{

		if(getFieldValue(key) != getValue(VARS[key].default))
		{
			str += VARS[key].query+'='+getFieldValue(key);
			if (str!=='') { str+='&'; }
		}
	}
	var qmark = '';
	if (str[str.length - 1]==='&') { str=str.substring(0, str.length - 1); }
	if (str!=='') { qmark='#'; }
	if(window.location.pathname+qmark+str !== window.location.pathname+window.location.hash )
	{
		history.pushState({ foo: window.location.hash },'b', window.location.pathname+qmark+str);
	}
}
window.addEventListener('popstate', function(event) {
    if (event.state) {
		parseUrlVars();
		build('popstate');
    }
}, false);

function build(condition)
{
	//Generer muligheden for at vælge indløser, samt vælg indløser:

	if(condition === 'init')
	{
		var acquirersString="";
		for(var key in ACQUIRER)
		{
			if( key !== 'nets' )
			{
				acquirersString += '<option id="option_'+ key + '">' + ACQUIRER[key].name + '</option>';
			}
		}
		$('selectacquirer').innerHTML = acquirersString;
		parseUrlVars();
		history.replaceState({ foo: window.location.hash },'b',window.location.pathname+window.location.hash);

	}
	var selectedAcquirer = $('selectacquirer').options[ $('selectacquirer').selectedIndex ].id.substring(7);
	if( selectedAcquirer !== this.previousAcquirer && condition !== 'init')
	{
		$('acquirerFixedRate').value=(ACQUIRER[selectedAcquirer].fixedTransactionFee+'kr').replace(".", ",");
		$('acquirerPercentageRate').value=(ACQUIRER[selectedAcquirer].percentageTransactionFee+'%').replace(".", ",");
	}
	this.previousAcquirer=selectedAcquirer;
	if(selectedAcquirer==='teller'){
		$('acquirerFixedRate').parentNode.style.display='none';
		$('acquirerPercentageRate').parentNode.style.display='none';
	}
	else{
		$('acquirerFixedRate').parentNode.style.display='inline';
		$('acquirerPercentageRate').parentNode.style.display='inline';
	}

	// Variable brugt hele vejen igennem genereringen af tabellen:

	var transactions = $("transactions").value.replace(",", ".");
	var value = $("value").value.replace(",", ".");
	var table = $("data");
	var rowValue = [];
	table.innerHTML = "";

	for (var key in PSP)
	{

		if ((PSP[key].isAcquirer || PSP[key].availableAcquirers.indexOf(selectedAcquirer) >-1 || PSP[key].availableAcquirers == 0)
		&& ( !( $('dankort').checked && $('visamc').checked )
			|| ( PSP[key].cards.indexOf('visa') > -1 && PSP[key].cards.indexOf('mastercard') > -1 ) ) )
		{
			var netsSupport = 0, otherAcquirerSupport = 0;
			var HTML_cards = "";
			var isAcquirer = PSP[key].isAcquirer;

			for(var i in PSP[key].cards)
			{
				var n= PSP[key].cards[i];
				var dankortCheck = ( $('dankort').checked && n === 'dankort');
				var visamcCheck= ( $('visamc').checked && ACQUIRER[selectedAcquirer].cards.indexOf(n) > -1  );

				netsSupport|= dankortCheck;
				otherAcquirerSupport|=visamcCheck;

				if ( (visamcCheck|| dankortCheck) && (n!=='maestro'|| $('3d').checked ) )
				{

					HTML_cards += "";

				}
			}

			// Fortsæt kun hvis PSP'en supporter nogen af de valgte kort:
			if ( HTML_cards !== "")
			{
				var indloser_icons='';
				var info_icon ='
';
				var info_icon_end='
';

				//Assumed 80% Dankort og 20% visa/mastercard jf. statistik
				var dkshare, vmshare;

				if ( netsSupport && (!isAcquirer) )
				{
					indloser_icons='';
					if ( otherAcquirerSupport )
					{
						indloser_icons += '
';
						dkshare = 0.82; vmshare=0.18;
					}
					else
					{
						dkshare=1; vmshare=0;
					}
				}
				else
				{
					if (!isAcquirer)
					{
						indloser_icons+= '
';
						dkshare=0  ;vmshare=1;
					}

				}

				// Rækken bliver nu konstrueret:

				var samlet = PSP[key].costfn(transactions,value);
				var samlet_info = info_icon + PSP[key].name + ': ' + toMoney(samlet);
				var samletgebyr_info = info_icon + PSP[key].name + ': ' + toMoney(samlet / transactions);
				var oprettelse_info = info_icon + PSP[key].name + ': ' + toMoney(PSP[key].setupFee);
				var faste_info = info_icon + PSP[key].name + ': '+ toMoney(PSP[key].monthlyFee + $('3d').checked * PSP[key].monthly3dsecureFee);
				var addcost;
				if (!isAcquirer && netsSupport)
				{
					addcost = ACQUIRER.nets.costfn( transactions * dkshare,value );
					samlet_info += '
' + ACQUIRER.nets.name + ' ('+(dkshare * 100) + '% tr.): '+ toMoney(addcost);
					samletgebyr_info += '
'+ACQUIRER.nets.name+' ('+(dkshare * 100)+'% tr.): '+ toMoney(addcost/transactions);
					oprettelse_info += '
'+ACQUIRER.nets.name+': '+ toMoney(ACQUIRER.nets.setupFee);
					faste_info += '
'+ACQUIRER.nets.name + ': ' + toMoney(ACQUIRER.nets.monthlyFee);
					samlet += addcost;
				}
				if (!isAcquirer && otherAcquirerSupport)
				{
					addcost = ACQUIRER[selectedAcquirer].costfn( transactions * vmshare, value);
					samlet_info += '
' + ACQUIRER[selectedAcquirer].name + ' (' + (vmshare * 100) + '% tr.): ' + toMoney(addcost);
					samletgebyr_info += '
' + ACQUIRER[selectedAcquirer].name+' (' + (vmshare * 100) + '% tr.): ' + toMoney(addcost/transactions);
					oprettelse_info += '
' + ACQUIRER[selectedAcquirer].name + ': ' + toMoney(ACQUIRER[selectedAcquirer].setupFee);
					faste_info += '
' + ACQUIRER[selectedAcquirer].name + ': ' + toMoney(ACQUIRER[selectedAcquirer].monthlyFee);
					samlet += addcost;
				}

				//Insert at the right place to sort the PSPs by cost

				var rowcounter=0;
				while(rowcounter<rowValue.length && samlet>rowValue[rowcounter])
				{
					rowcounter++;
				}

				var row = table.insertRow(rowcounter);
				rowValue.splice(rowcounter,0,samlet);

				// Insert HTML
				var logo_cell = row.insertCell(0);
				var indloser_cell = row.insertCell(1);
				var kort_cell = row.insertCell(2);
				var oprettelse_cell = row.insertCell(3);
				var faste_cell = row.insertCell(4);
				var samlet_cell = row.insertCell(5);
				var samletgebyr_cell = row.insertCell(6);

				logo_cell.innerHTML = '

'+PSP[key].name+'
';

				kort_cell.innerHTML = HTML_cards;
				kort_cell.className = 'kort';
				oprettelse_cell.innerHTML = toMoney( PSP[key].setupFee + ACQUIRER[selectedAcquirer].setupFee * otherAcquirerSupport * (!isAcquirer)+ ACQUIRER.nets.setupFee * netsSupport * (!isAcquirer) );

				faste_cell.innerHTML = toMoney( PSP[key].monthlyFee + $('3d').checked * PSP[key].monthly3dsecureFee + ACQUIRER[selectedAcquirer].monthlyFee * otherAcquirerSupport * (!isAcquirer)+ ACQUIRER.nets.monthlyFee * netsSupport * (!isAcquirer) );
				indloser_cell.innerHTML = indloser_icons;
				indloser_cell.className = 'acquirer';

				oprettelse_cell.innerHTML += oprettelse_info+info_icon_end;
				faste_cell.innerHTML += faste_info+info_icon_end;
				samlet_info += info_icon_end;
				samletgebyr_info += info_icon_end;
				samlet_cell.innerHTML = toMoney(samlet) + samlet_info;
				samletgebyr_cell.innerHTML = toMoney(samlet/transactions) + samletgebyr_info;
			}

		}

	}
	if(condition!=='init' && condition !== 'popstate' && condition!=='keyup')
		saveUrlVars();

}

function toMoney(x)
{
	var number = Math.round(x * 100) / 100;

    var parts = number.toString().split(".");
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
    parts.join(",");
    return parts+ " " + valuta;
}
<|endoftext|>


<commit_before>'use babel';

import MoleculeDevEnvironment from '../lib/molecule-dev-environment';

// Use the command `window:run-package-specs` (cmd-alt-ctrl-p) to run specs.
//
// To run a specific `it` or `describe` block add an `f` to the front (e.g. `fit`
// or `fdescribe`). Remove the `f` to unfocus the block.

describe('MoleculeDevEnvironment', () => {
  let workspaceElement, activationPromise;

  beforeEach(() => {
    workspaceElement = atom.views.getView(atom.workspace);
    activationPromise = atom.packages.activatePackage('molecule-dev-environment');
  });

  describe('when the molecule-dev-environment:toggle event is triggered', () => {
    it('hides and shows the modal panel', () => {
      // Before the activation event the view is not on the DOM, and no panel
      // has been created
      expect(workspaceElement.querySelector('.molecule-dev-environment')).not.toExist();

      // This is an activation event, triggering it will cause the package to be
      // activated.
      atom.commands.dispatch(workspaceElement, 'molecule-dev-environment:toggle');

      waitsForPromise(() => {
        return activationPromise;
      });

      runs(() => {
        expect(workspaceElement.querySelector('.molecule-dev-environment')).toExist();

        let moleculeDevEnvironmentElement = workspaceElement.querySelector('.molecule-dev-environment');
        expect(moleculeDevEnvironmentElement).toExist();

        let moleculeDevEnvironmentPanel = atom.workspace.panelForItem(moleculeDevEnvironmentElement);
        expect(moleculeDevEnvironmentPanel.isVisible()).toBe(true);
        atom.commands.dispatch(workspaceElement, 'molecule-dev-environment:toggle');
        expect(moleculeDevEnvironmentPanel.isVisible()).toBe(false);
      });
    });

    it('hides and shows the view', () => {
      // This test shows you an integration test testing at the view level.

      // Attaching the workspaceElement to the DOM is required to allow the
      // `toBeVisible()` matchers to work. Anything testing visibility or focus
      // requires that the workspaceElement is on the DOM. Tests that attach the
      // workspaceElement to the DOM are generally slower than those off DOM.
      jasmine.attachToDOM(workspaceElement);

      expect(workspaceElement.querySelector('.molecule-dev-environment')).not.toExist();

      // This is an activation event, triggering it causes the package to be
      // activated.
      atom.commands.dispatch(workspaceElement, 'molecule-dev-environment:toggle');

      waitsForPromise(() => {
        return activationPromise;
      });

      runs(() => {
        // Now we can test for view visibility
        let moleculeDevEnvironmentElement = workspaceElement.querySelector('.molecule-dev-environment');
        expect(moleculeDevEnvironmentElement).toBeVisible();
        atom.commands.dispatch(workspaceElement, 'molecule-dev-environment:toggle');
        expect(moleculeDevEnvironmentElement).not.toBeVisible();
      });
    });
  });
});
<commit_msg>Delete unused spec folder<commit_after><|endoftext|>