<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { handleRoute } from 'fluxible-router';
import PresentationSlide from './PresentationSlide';
import { connectToStores } from 'fluxible-addons-react';
import { Microservices } from '../../../configs/microservices';
import PresentationStore from '../../../stores/PresentationStore';

// if(process.env.BROWSER){
//    require('../../../assets/css/PresentationDefaults.css');
// }

class Presentation extends React.Component{
    constructor(props){
        super(props);
        this.playerCss = { height: '100%', position: 'absolute', top: '0' };
        this.clearStyle = { clear: 'both' };
        this.startingSlide = this.props.PresentationStore.selector.sid;
        this.revealDiv = null;
        this.secret = props.currentRoute.query.secret;
        this.id = props.currentRoute.query.id;
    }

    componentDidMount(){
        if(process.env.BROWSER){
            //$('[style*="absolute"]').children().attr('tabindex', 0);

            //remove existing tabindices
            $('[style*="absolute"]').each(function () {
                let el = $(this);
                if(el.attr('tabindex') !== 0)
                    el.attr('tabindex', 0);
            });
            //add tabindices to all children in absolute elements
            $('[style*="absolute"]').each(function () {
                $(this).children().attr('tabindex', 0);
                //if($(this).attr('tabindex') !== 0)
                //{
                //    $(this).attr('tabindex', 0);
                //}
            });
            //TODO: add hidden element at start of PPTX slide content + to focus on this.

             //loading reveal style

            // $('html.ios, html.ios body').css('height': '100% !important');
            // Get the theme information, and download the stylesheet

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

            //SWIK-1321 - Non-canvas/pptx2html content is not scaled in presentation mode and bottom content is hidden
            let pptxwidth = '100%'; //use 100% of screen width
            let pptxheight = '100%'; //use 100% of screen height
            //if($('.pptx2html').html() !== ''){
            if($('.pptx2html').html()){
                pptxwidth = $('.pptx2html').width();
                pptxheight = $('.pptx2html').height();
            } else {
                pptxwidth = '100%';
                pptxheight = '100%';
            }

            window.location.hash = '#slide-' + this.startingSlide;

            let multiplexFileToLoad = (this.secret) ? '/custom_modules/reveal.js/plugin/multiplex/master.js' : '/custom_modules/reveal.js/plugin/multiplex/client.js' ;
            multiplexFileToLoad = (this.id) ? multiplexFileToLoad : '' ;
            let multiplexConfig = (this.secret) ? {secret: this.secret, id: this.id} : {secret: null, id: this.id};
            multiplexConfig.url = Microservices.webrtc.uri;
            multiplexConfig = (this.id) ? multiplexConfig : {};
            let dependencySocketIO = (this.id) ? Microservices.webrtc.uri.replace('http:','').replace('https:','') + '/socket.io/socket.io.js' : '' ;
            Reveal.initialize({
                width: pptxwidth,
                height: pptxheight,
                // margin: 0.2,
                transition: 'none',
                backgroundTransition: 'none',
                history: true,
                viewDistance: 2,
                dependencies: [
                    { src: dependencySocketIO, async: true },
                    { src: multiplexFileToLoad, async: true },
                    { src: '/custom_modules/reveal.js/plugin/notes/notes.js', async: true },
                    { src: '/custom_modules/reveal.js/plugin/zoom-js/zoom.js', async: true },
                    // { src: '/custom_modules/reveal.js/plugin/reveal.js-toolbar/toolbar.js', async: true},
                    { src: '/reveal.js-menu/menu.js', async: true},
                    { src: '/custom_modules/reveal.js/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
                    // Plugin from https://github.com/marcysutton/reveal-a11y
                    //{ src: '/custom_modules/reveal.js/plugin/accessibility/helper.js', async: false,condition: function() {return !!document.body.classList;}}
                ],
                keyboard: {
                    72: null,
                    78: null
                },
                toolbar: {
                    captureMenu: false,  // set to false so it doesn't crash the plugin
                    deckUrl: ['/deck', this.props.PresentationStore.selector.id, this.props.PresentationStore.deckSlug].join('/')
                },
                menu: {
                    deckUrl: ['/deck', this.props.PresentationStore.selector.id, this.props.PresentationStore.deckSlug].join('/'),
                    speakerNotes: '/custom_modules/reveal.js/plugin/notes/notes.html',
                    overview: true,
                    side: 'left',
                    width: 'normal',
                    numbers: false,
                    titleSelector: 'h1, h2, h3, h4, h5, h6',
                    useTextContentForMissingTitles: true,
                    hideMissingTitles: false,
                    markers: true,

                    // Specify custom panels to be included in the menu, by
                    // providing an array of objects with 'title', 'icon'
                    // properties, and either a 'src' or 'content' property.
                    custom: false,

                    // Specifies the themes that will be available in the themes
                    // menu panel. Set to 'true' to show the themes menu panel
                    // with the default themes list. Alternatively, provide an
                    // array to specify the themes to make available in the
                    // themes menu panel, for example...
                    // [
                    //     { name: 'Black', theme: 'css/theme/black.css' },
                    //     { name: 'White', theme: 'css/theme/white.css' },
                    //     { name: 'League', theme: 'css/theme/league.css' }
                    // ]
                    themes: false,

                    themesPath: 'css/theme/',
                    transitions: false,
                    openButton: true,
                    openSlideNumber: false,
                    keyboard: true,
                    sticky: false,
                    autoOpen: true,
                    delayInit: false,
                    openOnInit: false,
                    loadIcons: true
                },
                multiplex: multiplexConfig
            });

            Reveal.addEventListener( 'ready', ( event ) => {
                //$('.accessibilityWrapper').attr('tabindex', '');
                //$('.present > .accessibilityWrapper > .pptx2html div:first-child').focus();
                //console.log($('.present > .accessibilityWrapper > .pptx2html div:first').html());
            	// event.currentSlide, event.indexh, event.indexv
                this.resize();
            } );

            Reveal.addEventListener( 'slidechanged', ( event ) => {
                //console.log('slidechanged: ' + $('.present > .accessibilityWrapper > .pptx2html div:first').html());
                //$('.present > .accessibilityWrapper > .pptx2html div:first-child').focus();
                //console.log('resize non-pptx2html slide content - presentwidth: ' + presentwidth + ' and height: ' + presentheight);
                this.resize();
            } );

            //$('.present > .pptx2html div:first').focus();

        //listen to resize event and resize.
        /*ReactDOM.findDOMNode(this.refs.container).addEventListener('resize', (evt) =>
            {
            //console.log('resize');
            this.resize();
        });*/
            window.addEventListener('resize', this.resize());
        }
        //$('.present >  .pptx2html div:first').focus();

        // update mathjax rendering
        // add to the mathjax rendering queue the command to type-set the slide content
        MathJax.Hub.Queue(['Typeset',MathJax.Hub,'slides']);

    }
    resize(){
        if(process.env.BROWSER){
            let pptxwidth;
            let pptxheight;
            if( $('.present > .pptx2html').html() ){
                pptxwidth = $('.present > .pptx2html').width();
                pptxheight = $('.present > .pptx2html').height();
            } else {

                pptxwidth = '100%';
                pptxheight = '100%';

                //resize non-pptx2html slide content based on current height of window
                //reimplemented based on old SlideWiki https://github.com/AKSW/SlideWiki/blob/307e9e87aee08543e46d270fe267aeaa5cdbfe3b/slidewiki/static/js/scale.js
                //let presentwidth = $('.present').width();
                let presentheight = $('.present').height();
                //console.log('resize non-pptx2html slide content - presentwidth: ' + presentwidth + ' and height: ' + presentheight);
                //let screenwidth = document.getElementsByClassName('reveal')[0].offsetWidth * 0.85;
                //let screenwidth = document.getElementsByClassName('reveal')[0].offsetWidth * 0.85;
                //let screenheight = (document.getElementsByClassName('reveal')[0].offsetHeight * 0.85);
                let screenheight = document.getElementsByClassName('reveal')[0].offsetHeight;
                //console.log('resize non-pptx2html slide content - screenwidth: ' + screenwidth + ' and height: ' + screenheight);
                let heightratio = screenheight / presentheight ;
                //let widthratio = screenwidth / presentwidth;
                let scaleratio = 1;
                //if (widthratio < heightratio){scaleratio = widthratio;} else {scaleratio = heightratio;}
                if (presentheight > screenheight){scaleratio = heightratio;}
                //console.log('resize non-pptx2html slide content - widthratio: ' + widthratio + ' and heightratioratio: ' + heightratio);
                //console.log('resize non-pptx2html slide content - scaleratio: ' + scaleratio);

                $('.present').css({'transform': '', 'transform-origin': ''});
                $('.present').css({'transform': 'scale('+scaleratio+','+scaleratio+')', 'transform-origin': 'center top'});

            }
            // event.previousSlide, event.currentSlide, event.indexh, event.indexv
            //let state = Reveal.getState();
            //console.log('state: ' + JSON.stringify(state));
            //console.log('slidechanged dimensions: ' + pptxheight + ' by ' + pptxwidth);
            Reveal.configure({
                width: pptxwidth,
                height: pptxheight,
                slideNumber: true
            });

        }
    }

    render(){

        // Load the theme stylesheet
        let styleName = 'default';
        if(this.props.PresentationStore.theme && typeof this.props.PresentationStore.theme !== 'undefined')
            styleName = this.props.PresentationStore.theme;
        if (styleName === '' || typeof styleName === 'undefined' || styleName === 'undefined')//if none of above yield a theme they will be legacy decks:
            styleName = 'white';
        let style = require('../../../custom_modules/reveal.js/css/theme/' + styleName + '.css');
        let slides = this.getSlides();
        return(
            //<ResizeAware ref='container' id='container'>

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

      			     	     {slides}

            //</ResizeAware>
        );
    }

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

        let html =
;
        if (slides) {
            html = slides.map((slide) => {
                let content = slide.content.replace(' src=', ' data-src=') + ((slide.speakernotes) ? '' + slide.speakernotes + '' : '');
                let bgColor = content.split('background-color: ');
                let bgImgTemp = content.split('background-image: ');
                let transition = slide.transition ? slide.transition : 'none';
                let resultingSlide =
;
                //need to check if bg is provided
                if (bgImgTemp.length > 1) {
                    let backgroundImageExtr = content.split('background-image: url("'); // url("
                    backgroundImageExtr = backgroundImageExtr.length > 1 ? backgroundImageExtr[1] :  undefined;
                    if (backgroundImageExtr) backgroundImageExtr = backgroundImageExtr.split('");').length > 1 ? backgroundImageExtr.split('");')[0] : undefined;
                    if (backgroundImageExtr) {
                        // Remove background of the inner slide
                        content = content.split('background-image: url("')[0] + content.split('");')[1];
                        if(bgColor.length > 1) content =  content.split('background-color: ')[0] + content.split('background-color: ')[1].split(';').slice(1).join('');
                        // Add resulting slide.
                        resultingSlide =
;
                    } else {
                        console.log('Problem extracting the background image: ', bgImgTemp[1]);
                    }
                } else if (bgColor.length > 1) {
                    let backgroundColour = bgColor[1].split(';').length > 1 ? bgColor[1].split(';')[0] : undefined;
                    if (backgroundColour) {
                        resultingSlide =
;
                    } else {
                        console.log('Problem extracting the background colour: ', bgColor[1]);
                    }
                }
                return resultingSlide;
            });
        }
        return html;
    }

}

Presentation = connectToStores(Presentation, [PresentationStore], (context, props) => {
    return {
        PresentationStore: context.getStore(PresentationStore).getState()
    };
});
Presentation = handleRoute(Presentation);//NOTE add currentRoute attribute to constructor props

export default Presentation;
<commit_msg>Fix loading sub deck theme<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { handleRoute } from 'fluxible-router';
import PresentationSlide from './PresentationSlide';
import { connectToStores } from 'fluxible-addons-react';
import { Microservices } from '../../../configs/microservices';
import PresentationStore from '../../../stores/PresentationStore';

// if(process.env.BROWSER){
//    require('../../../assets/css/PresentationDefaults.css');
// }

class Presentation extends React.Component{
    constructor(props){
        super(props);
        this.playerCss = { height: '100%', position: 'absolute', top: '0' };
        this.clearStyle = { clear: 'both' };
        this.startingSlide = this.props.PresentationStore.selector.sid;
        this.revealDiv = null;
        this.secret = props.currentRoute.query.secret;
        this.id = props.currentRoute.query.id;
        this.state = {
            theme: ''
        };
    }

    componentDidMount(){
        if(process.env.BROWSER){
            //$('[style*="absolute"]').children().attr('tabindex', 0);

            //remove existing tabindices
            $('[style*="absolute"]').each(function () {
                let el = $(this);
                if(el.attr('tabindex') !== 0)
                    el.attr('tabindex', 0);
            });
            //add tabindices to all children in absolute elements
            $('[style*="absolute"]').each(function () {
                $(this).children().attr('tabindex', 0);
                //if($(this).attr('tabindex') !== 0)
                //{
                //    $(this).attr('tabindex', 0);
                //}
            });
            //TODO: add hidden element at start of PPTX slide content + to focus on this.

             //loading reveal style

            // $('html.ios, html.ios body').css('height': '100% !important');
            // Get the theme information, and download the stylesheet

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

            //SWIK-1321 - Non-canvas/pptx2html content is not scaled in presentation mode and bottom content is hidden
            let pptxwidth = '100%'; //use 100% of screen width
            let pptxheight = '100%'; //use 100% of screen height
            //if($('.pptx2html').html() !== ''){
            if($('.pptx2html').html()){
                pptxwidth = $('.pptx2html').width();
                pptxheight = $('.pptx2html').height();
            } else {
                pptxwidth = '100%';
                pptxheight = '100%';
            }

            window.location.hash = '#slide-' + this.startingSlide;

            let multiplexFileToLoad = (this.secret) ? '/custom_modules/reveal.js/plugin/multiplex/master.js' : '/custom_modules/reveal.js/plugin/multiplex/client.js' ;
            multiplexFileToLoad = (this.id) ? multiplexFileToLoad : '' ;
            let multiplexConfig = (this.secret) ? {secret: this.secret, id: this.id} : {secret: null, id: this.id};
            multiplexConfig.url = Microservices.webrtc.uri;
            multiplexConfig = (this.id) ? multiplexConfig : {};
            let dependencySocketIO = (this.id) ? Microservices.webrtc.uri.replace('http:','').replace('https:','') + '/socket.io/socket.io.js' : '' ;
            Reveal.initialize({
                width: pptxwidth,
                height: pptxheight,
                // margin: 0.2,
                transition: 'none',
                backgroundTransition: 'none',
                history: true,
                viewDistance: 2,
                dependencies: [
                    { src: dependencySocketIO, async: true },
                    { src: multiplexFileToLoad, async: true },
                    { src: '/custom_modules/reveal.js/plugin/notes/notes.js', async: true },
                    { src: '/custom_modules/reveal.js/plugin/zoom-js/zoom.js', async: true },
                    // { src: '/custom_modules/reveal.js/plugin/reveal.js-toolbar/toolbar.js', async: true},
                    { src: '/reveal.js-menu/menu.js', async: true},
                    { src: '/custom_modules/reveal.js/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
                    // Plugin from https://github.com/marcysutton/reveal-a11y
                    //{ src: '/custom_modules/reveal.js/plugin/accessibility/helper.js', async: false,condition: function() {return !!document.body.classList;}}
                ],
                keyboard: {
                    72: null,
                    78: null
                },
                toolbar: {
                    captureMenu: false,  // set to false so it doesn't crash the plugin
                    deckUrl: ['/deck', this.props.PresentationStore.selector.id, this.props.PresentationStore.deckSlug].join('/')
                },
                menu: {
                    deckUrl: ['/deck', this.props.PresentationStore.selector.id, this.props.PresentationStore.deckSlug].join('/'),
                    speakerNotes: '/custom_modules/reveal.js/plugin/notes/notes.html',
                    overview: true,
                    side: 'left',
                    width: 'normal',
                    numbers: false,
                    titleSelector: 'h1, h2, h3, h4, h5, h6',
                    useTextContentForMissingTitles: true,
                    hideMissingTitles: false,
                    markers: true,

                    // Specify custom panels to be included in the menu, by
                    // providing an array of objects with 'title', 'icon'
                    // properties, and either a 'src' or 'content' property.
                    custom: false,

                    // Specifies the themes that will be available in the themes
                    // menu panel. Set to 'true' to show the themes menu panel
                    // with the default themes list. Alternatively, provide an
                    // array to specify the themes to make available in the
                    // themes menu panel, for example...
                    // [
                    //     { name: 'Black', theme: 'css/theme/black.css' },
                    //     { name: 'White', theme: 'css/theme/white.css' },
                    //     { name: 'League', theme: 'css/theme/league.css' }
                    // ]
                    themes: false,

                    themesPath: 'css/theme/',
                    transitions: false,
                    openButton: true,
                    openSlideNumber: false,
                    keyboard: true,
                    sticky: false,
                    autoOpen: true,
                    delayInit: false,
                    openOnInit: false,
                    loadIcons: true
                },
                multiplex: multiplexConfig
            });

            Reveal.addEventListener( 'ready', ( event ) => {
                //$('.accessibilityWrapper').attr('tabindex', '');
                //$('.present > .accessibilityWrapper > .pptx2html div:first-child').focus();
                //console.log($('.present > .accessibilityWrapper > .pptx2html div:first').html());
            	// event.currentSlide, event.indexh, event.indexv
                this.resize();
            } );

            Reveal.addEventListener( 'slidechanged', ( event ) => {
                //console.log('slidechanged: ' + $('.present > .accessibilityWrapper > .pptx2html div:first').html());
                //$('.present > .accessibilityWrapper > .pptx2html div:first-child').focus();
                //console.log('resize non-pptx2html slide content - presentwidth: ' + presentwidth + ' and height: ' + presentheight);
                this.resize();

                this.setState({
                    theme: event.currentSlide.getAttribute('data-theme')
                });

            } );

            //$('.present > .pptx2html div:first').focus();

        //listen to resize event and resize.
        /*ReactDOM.findDOMNode(this.refs.container).addEventListener('resize', (evt) =>
            {
            //console.log('resize');
            this.resize();
        });*/
            window.addEventListener('resize', this.resize());
        }
        //$('.present >  .pptx2html div:first').focus();

        // update mathjax rendering
        // add to the mathjax rendering queue the command to type-set the slide content
        MathJax.Hub.Queue(['Typeset',MathJax.Hub,'slides']);

    }
    resize(){
        if(process.env.BROWSER){
            let pptxwidth;
            let pptxheight;
            if( $('.present > .pptx2html').html() ){
                pptxwidth = $('.present > .pptx2html').width();
                pptxheight = $('.present > .pptx2html').height();
            } else {

                pptxwidth = '100%';
                pptxheight = '100%';

                //resize non-pptx2html slide content based on current height of window
                //reimplemented based on old SlideWiki https://github.com/AKSW/SlideWiki/blob/307e9e87aee08543e46d270fe267aeaa5cdbfe3b/slidewiki/static/js/scale.js
                //let presentwidth = $('.present').width();
                let presentheight = $('.present').height();
                //console.log('resize non-pptx2html slide content - presentwidth: ' + presentwidth + ' and height: ' + presentheight);
                //let screenwidth = document.getElementsByClassName('reveal')[0].offsetWidth * 0.85;
                //let screenwidth = document.getElementsByClassName('reveal')[0].offsetWidth * 0.85;
                //let screenheight = (document.getElementsByClassName('reveal')[0].offsetHeight * 0.85);
                let screenheight = document.getElementsByClassName('reveal')[0].offsetHeight;
                //console.log('resize non-pptx2html slide content - screenwidth: ' + screenwidth + ' and height: ' + screenheight);
                let heightratio = screenheight / presentheight ;
                //let widthratio = screenwidth / presentwidth;
                let scaleratio = 1;
                //if (widthratio < heightratio){scaleratio = widthratio;} else {scaleratio = heightratio;}
                if (presentheight > screenheight){scaleratio = heightratio;}
                //console.log('resize non-pptx2html slide content - widthratio: ' + widthratio + ' and heightratioratio: ' + heightratio);
                //console.log('resize non-pptx2html slide content - scaleratio: ' + scaleratio);

                $('.present').css({'transform': '', 'transform-origin': ''});
                $('.present').css({'transform': 'scale('+scaleratio+','+scaleratio+')', 'transform-origin': 'center top'});

            }
            // event.previousSlide, event.currentSlide, event.indexh, event.indexv
            //let state = Reveal.getState();
            //console.log('state: ' + JSON.stringify(state));
            //console.log('slidechanged dimensions: ' + pptxheight + ' by ' + pptxwidth);
            Reveal.configure({
                width: pptxwidth,
                height: pptxheight,
                slideNumber: true
            });

        }
    }

    render(){

        // Load the theme stylesheet
        let styleName = 'default';
        if(this.props.PresentationStore.theme && typeof this.props.PresentationStore.theme !== 'undefined')
            styleName = this.props.PresentationStore.theme;

        // set theme based on slide theme (since sub decks might have an other theme than the main deck)
        styleName = this.state.theme || styleName;

        if (styleName === '' || typeof styleName === 'undefined' || styleName === 'undefined')//if none of above yield a theme they will be legacy decks:
            styleName = 'white';
        let style = require('../../../custom_modules/reveal.js/css/theme/' + styleName + '.css');
        let slides = this.getSlides();
        return(
            //<ResizeAware ref='container' id='container'>

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

      			     	     {slides}

            //</ResizeAware>
        );
    }

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

        let html =
;
        if (slides) {
            html = slides.map((slide) => {
                let content = slide.content.replace(' src=', ' data-src=') + ((slide.speakernotes) ? '' + slide.speakernotes + '' : '');
                let bgColor = content.split('background-color: ');
                let bgImgTemp = content.split('background-image: ');
                let transition = slide.transition ? slide.transition : 'none';
                let theme = slide.theme;
                let resultingSlide =
;
                //need to check if bg is provided
                if (bgImgTemp.length > 1) {
                    let backgroundImageExtr = content.split('background-image: url("'); // url("
                    backgroundImageExtr = backgroundImageExtr.length > 1 ? backgroundImageExtr[1] :  undefined;
                    if (backgroundImageExtr) backgroundImageExtr = backgroundImageExtr.split('");').length > 1 ? backgroundImageExtr.split('");')[0] : undefined;
                    if (backgroundImageExtr) {
                        // Remove background of the inner slide
                        content = content.split('background-image: url("')[0] + content.split('");')[1];
                        if(bgColor.length > 1) content =  content.split('background-color: ')[0] + content.split('background-color: ')[1].split(';').slice(1).join('');
                        // Add resulting slide.
                        resultingSlide =
;
                    } else {
                        console.log('Problem extracting the background image: ', bgImgTemp[1]);
                    }
                } else if (bgColor.length > 1) {
                    let backgroundColour = bgColor[1].split(';').length > 1 ? bgColor[1].split(';')[0] : undefined;
                    if (backgroundColour) {
                        resultingSlide =
;
                    } else {
                        console.log('Problem extracting the background colour: ', bgColor[1]);
                    }
                }
                return resultingSlide;
            });
        }
        return html;
    }

}

Presentation = connectToStores(Presentation, [PresentationStore], (context, props) => {
    return {
        PresentationStore: context.getStore(PresentationStore).getState()
    };
});
Presentation = handleRoute(Presentation);//NOTE add currentRoute attribute to constructor props

export default Presentation;
<|endoftext|>


<commit_before>/* GiDebug -- a debug overlay interface for GlkOte
 * Designed by Andrew Plotkin <erkyrath@eblong.com>
 * <http://eblong.com/zarf/glk/glkote.html>
 *
 * This Javascript library is copyright 2017 by Andrew Plotkin.
 * It is distributed under the MIT license; see the "LICENSE" file.
 *
 * This library adds a simple debug console, overlaid onto the GlkOte
 * UI. Or it can be used with any HTML interface, really. GlkOte is set
 * up to activate the debug console if you set the "debug_commands" option
 * in the GlkOte game interface object.
 *
 * The library has these APIs:
 *
 * GiDebug.init(handler) -- activate the console
 *
 * Call this during initialization to set up the debug console. The
 * handler should be a function that accepts debug command strings.
 *
 * GiDebug.open() -- make the console visible
 *
 * The console is not initially visible, unless it generates output
 * on startup. Call this to make it visible.
 *
 * GiDebug.output(ls) -- display a list of text lines in the console
 *
 * Your command handler (and perhaps other parts of the game) calls this
 * to display output in the console. The argument is a *list* of lines of
 * text. (Don't call this with a bare string!)
 */

/* Put everything inside the GiDebug namespace. */

GiDebug = function() {

var debug_el_id = 'gidebug';

var is_open = false;
var use_touch_ui;
var drag_mode = null;
var drag_context = null;
var min_width = 200;
var cmd_handler = null;

function debug_init(handler)
{
    cmd_handler = handler;
}

function debug_open()
{
    if (is_open)
        return;

    use_touch_ui = (window.TouchEvent != undefined);

    /* Figure out what the root div is called. The dialog box will be
       positioned in this div. We use the same default as GlkOte:
       "gameport". We also try to interrogate GlkOte to see if that
       default has been changed. */
    var root_el_id = 'gameport';
    var iface = window.Game;
    if (window.GlkOte)
        iface = window.GlkOte.getinterface();
    if (iface && iface.gameport)
        root_el_id = iface.gameport;

    var rootel = $('#'+root_el_id);
    if (!rootel.length)
        throw new Error('GiDebug: unable to find root element #' + root_el_id + '.');

    dia = $('<div>', { id: debug_el_id });
    var el, subel;

    function set_drag_effect(el, tag) {
        if (!use_touch_ui)
            el.on('mousedown', { tag:tag }, evhan_dragstart);
        else
            el.on('touchstart', { tag:tag }, evhan_dragstart);
    };

    el = $('<div>', { class: 'GiDebugHeader GiDebugRoundNE GiDebugRoundNW' });
    el.text('Debugging');
    dia.append(el);
    el.css({ cursor:'move' });
    set_drag_effect(el, 'position');

    subel = $('<div>', { class: 'GiDebugRightButton GiDebugRoundNE' });
    subel.css({ cursor:'ne-resize' });
    el.append(subel);
    set_drag_effect(subel, 'size-ne');

    subel = $('<div>', { class: 'GiDebugLeftButton GiDebugRoundNW' });
    subel.css({ cursor:'nw-resize' });
    el.append(subel);
    set_drag_effect(subel, 'size-nw');

    el = $('<div>', { class: 'GiDebugFooter GiDebugRoundSE GiDebugRoundSW' });
    dia.append(el);
    el.css({ cursor:'s-resize' });
    set_drag_effect(el, 'height');

    subel = $('<div>', { class: 'GiDebugRightButton GiDebugRoundSE' });
    subel.css({ cursor:'se-resize' });
    el.append(subel);
    set_drag_effect(subel, 'size');

    subel = $('<div>', { class: 'GiDebugLeftButton GiDebugRoundSW' });
    subel.css({ cursor:'sw-resize' });
    el.append(subel);
    set_drag_effect(subel, 'size-sw');

    el = $('<div>', { id: debug_el_id+'_body', class: 'GiDebugBody' });
    dia.append(el);

    subel = $('<div>', { id: debug_el_id+'_text', class: 'GiDebugText' });
    el.append(subel);

    subel = $('<div>', { class: 'GiDebugPrompt' });
    subel.text('>');
    el.append(subel);

    subel = $('<input>', { id: debug_el_id+'_input', type: 'text', class: 'GiDebugInput' });
    subel.attr({ autocapitalize:'off', 'aria-live':'off' });
    subel.on('keypress', function(ev) {
        if (ev.keyCode == 13) {
            evhan_input(ev);
        }
    });
    el.append(subel);

    rootel.append(dia);
    is_open = true;
}

function debug_output(ls)
{
    if (!is_open)
        debug_open();

    add_lines(ls);
}

function add_lines(ls, style)
{
    var textel = $('#'+debug_el_id+'_text');
    if (!textel.length)
        return;

    var cla = 'GiDebugTextLine';
    if (style)
        cla = cla + ' ' + style;

    for (var ix=0; ix<ls.length; ix++) {
        var el = $('<div>', { class:cla });
        var val = ls[ix];
        val = val.replace(regex_long_whitespace, func_long_whitespace);
        el.text(val);
        textel.append(el);
    }

    textel.scrollTop(textel.get(0).scrollHeight);
}

var regex_long_whitespace = new RegExp('  +', 'g'); /* two or more spaces */

/* Given a run of N spaces (N >= 2), return N-1 non-breaking spaces plus
   a normal one. */
function func_long_whitespace(match) {
  var len = match.length;
  if (len == 1)
    return ' ';
  /* Evil trick I picked up from Prototype. Gives len-1 copies of NBSP. */
  var res = new Array(len).join('\xa0');
  return res + ' ';
}

function evhan_input(ev)
{
    var inputel = $('#'+debug_el_id+'_input');
    if (!inputel.length)
        return;

    var val = inputel.val().trim();
    inputel.val('');

    if (!val.length)
        return;

    add_lines(['> '+val], 'GiDebugTextLineBold');

    if (cmd_handler)
        cmd_handler(val);
    else
        add_lines(['There is no debug command handler.']);
}

function event_pos(ev)
{
    if (!use_touch_ui)
        return { left:ev.clientX, top:ev.clientY };
    else
        return { left:ev.originalEvent.pageX, top:ev.originalEvent.pageY };
}

function evhan_dragstart(ev)
{
    if (drag_mode)
        return;

    var dia = $('#'+debug_el_id);
    if (!dia.length)
        return;

    drag_mode = ev.data.tag;

    ev.preventDefault();
    ev.stopPropagation();

    switch (drag_mode) {
    case 'position':
        drag_context = dia.offset();
        break;
    case 'size':
    case 'width':
    case 'height':
        drag_context = { width:dia.width(), height:dia.height() };
        break;
    case 'size-ne':
    case 'size-sw':
    case 'size-nw':
        drag_context = dia.offset();
        drag_context.width = dia.width();
        drag_context.height = dia.height();
        drag_context.xmax = drag_context.left + drag_context.width;
        drag_context.ymax = drag_context.top + drag_context.height;
        break;
    default:
        drag_context = {};
        break;
    }

    drag_context.basepos = event_pos(ev);
    drag_context.porttop = $('#gidebug').parent().offset().top + 4;

    if (!use_touch_ui) {
        $('body').on('mousemove', evhan_dragdrag);
        $('body').on('mouseup', evhan_dragstop);
    }
    else {
        $('body').on('touchmove', evhan_dragdrag);
        $('body').on('touchend', evhan_dragstop);
        $('body').on('touchcancel', evhan_dragstop);
    }
}

function evhan_dragdrag(ev, ui)
{
    if (!drag_mode)
        return;

    var dia = $('#'+debug_el_id);
    if (!dia.length)
        return;

    var pos = event_pos(ev);
    var deltax = pos.left - drag_context.basepos.left;
    var deltay = pos.top - drag_context.basepos.top;

    switch (drag_mode) {
    case 'position':
        pos.left = drag_context.left + deltax;
        pos.top = Math.max(drag_context.porttop, drag_context.top + deltay);
        dia.offset(pos);
        break;
    case 'size':
        dia.width(Math.max(min_width, drag_context.width + deltax));
        dia.height(Math.max(min_width, drag_context.height + deltay));
        break;
    case 'width':
        dia.width(Math.max(min_width, drag_context.width + deltax));
        break;
    case 'height':
        dia.height(Math.max(min_width, drag_context.height + deltay));
        break;
    case 'size-ne':
        var ypos = Math.max(drag_context.porttop, drag_context.top + deltay);
        pos.left = drag_context.left;
        pos.top = Math.min(drag_context.ymax-min_width, ypos);
        dia.offset(pos);
        dia.width(Math.max(min_width, drag_context.width + deltax));
        dia.height(drag_context.ymax - pos.top);
        break;
    case 'size-sw':
        var xpos = drag_context.left + deltax;
        pos.top = drag_context.top;
        pos.left = Math.min(drag_context.xmax-min_width, xpos);
        dia.offset(pos);
        dia.height(Math.max(min_width, drag_context.height + deltay));
        dia.width(drag_context.xmax - pos.left);
        break;
    case 'size-nw':
        var xpos = drag_context.left + deltax;
        var ypos = Math.max(drag_context.porttop, drag_context.top + deltay);
        pos.left = Math.min(drag_context.xmax-min_width, xpos);
        pos.top = Math.min(drag_context.ymax-min_width, ypos);
        dia.offset(pos);
        dia.width(drag_context.xmax - pos.left);
        dia.height(drag_context.ymax - pos.top);
        break;
    }
}

function evhan_dragstop(ev, ui)
{
    if (!use_touch_ui) {
        $('body').off('mousemove');
        $('body').off('mouseup');
    }
    else {
        $('body').off('touchmove');
        $('body').off('touchend');
        $('body').off('touchcancel');
    }

    drag_mode = null;
    drag_context = null;
}

/* End of GiDebug namespace function. Return the object which will
   become the GiDebug global. */
return {
    init: debug_init,
    open: debug_open,
    output: debug_output
};

}();

/* End of GiDebug library. */
<commit_msg>Add an API to perform debugger commands.<commit_after>/* GiDebug -- a debug overlay interface for GlkOte
 * Designed by Andrew Plotkin <erkyrath@eblong.com>
 * <http://eblong.com/zarf/glk/glkote.html>
 *
 * This Javascript library is copyright 2017 by Andrew Plotkin.
 * It is distributed under the MIT license; see the "LICENSE" file.
 *
 * This library adds a simple debug console, overlaid onto the GlkOte
 * UI. Or it can be used with any HTML interface, really. GlkOte is set
 * up to activate the debug console if you set the "debug_commands" option
 * in the GlkOte game interface object.
 *
 * The library has these APIs:
 *
 * GiDebug.init(handler) -- activate the console
 *
 * Call this during initialization to set up the debug console. The
 * handler should be a function that accepts debug command strings.
 *
 * GiDebug.open() -- make the console visible
 *
 * The console is not initially visible, unless it generates output
 * on startup. Call this to make it visible.
 *
 * GiDebug.input(ls) -- perform a debugger command
 *
 * Perform a command as if it had been typed in the console.
 *
 * GiDebug.output(ls) -- display a list of text lines in the console
 *
 * Your command handler (and perhaps other parts of the game) calls this
 * to display output in the console. The argument is a *list* of lines of
 * text. (Don't call this with a bare string!)
 */

/* Put everything inside the GiDebug namespace. */

GiDebug = function() {

var debug_el_id = 'gidebug';

var is_open = false;
var use_touch_ui;
var drag_mode = null;
var drag_context = null;
var min_width = 200;
var cmd_handler = null;

function debug_init(handler)
{
    cmd_handler = handler;
}

function debug_open()
{
    if (is_open)
        return;

    use_touch_ui = (window.TouchEvent != undefined);

    /* Figure out what the root div is called. The dialog box will be
       positioned in this div. We use the same default as GlkOte:
       "gameport". We also try to interrogate GlkOte to see if that
       default has been changed. */
    var root_el_id = 'gameport';
    var iface = window.Game;
    if (window.GlkOte)
        iface = window.GlkOte.getinterface();
    if (iface && iface.gameport)
        root_el_id = iface.gameport;

    var rootel = $('#'+root_el_id);
    if (!rootel.length)
        throw new Error('GiDebug: unable to find root element #' + root_el_id + '.');

    dia = $('<div>', { id: debug_el_id });
    var el, subel;

    function set_drag_effect(el, tag) {
        if (!use_touch_ui)
            el.on('mousedown', { tag:tag }, evhan_dragstart);
        else
            el.on('touchstart', { tag:tag }, evhan_dragstart);
    };

    el = $('<div>', { class: 'GiDebugHeader GiDebugRoundNE GiDebugRoundNW' });
    el.text('Debugging');
    dia.append(el);
    el.css({ cursor:'move' });
    set_drag_effect(el, 'position');

    subel = $('<div>', { class: 'GiDebugRightButton GiDebugRoundNE' });
    subel.css({ cursor:'ne-resize' });
    el.append(subel);
    set_drag_effect(subel, 'size-ne');

    subel = $('<div>', { class: 'GiDebugLeftButton GiDebugRoundNW' });
    subel.css({ cursor:'nw-resize' });
    el.append(subel);
    set_drag_effect(subel, 'size-nw');

    el = $('<div>', { class: 'GiDebugFooter GiDebugRoundSE GiDebugRoundSW' });
    dia.append(el);
    el.css({ cursor:'s-resize' });
    set_drag_effect(el, 'height');

    subel = $('<div>', { class: 'GiDebugRightButton GiDebugRoundSE' });
    subel.css({ cursor:'se-resize' });
    el.append(subel);
    set_drag_effect(subel, 'size');

    subel = $('<div>', { class: 'GiDebugLeftButton GiDebugRoundSW' });
    subel.css({ cursor:'sw-resize' });
    el.append(subel);
    set_drag_effect(subel, 'size-sw');

    el = $('<div>', { id: debug_el_id+'_body', class: 'GiDebugBody' });
    dia.append(el);

    subel = $('<div>', { id: debug_el_id+'_text', class: 'GiDebugText' });
    el.append(subel);

    subel = $('<div>', { class: 'GiDebugPrompt' });
    subel.text('>');
    el.append(subel);

    subel = $('<input>', { id: debug_el_id+'_input', type: 'text', class: 'GiDebugInput' });
    subel.attr({ autocapitalize:'off', 'aria-live':'off' });
    subel.on('keypress', function(ev) {
        if (ev.keyCode == 13) {
            evhan_input(ev);
        }
    });
    el.append(subel);

    rootel.append(dia);
    is_open = true;
}

function debug_output(ls)
{
    if (!is_open)
        debug_open();

    add_lines(ls);
}

function debug_input(val)
{
    add_lines(['> '+val], 'GiDebugTextLineBold');

    if (cmd_handler)
        cmd_handler(val);
    else
        add_lines(['There is no debug command handler.']);
}

function add_lines(ls, style)
{
    var textel = $('#'+debug_el_id+'_text');
    if (!textel.length)
        return;

    var cla = 'GiDebugTextLine';
    if (style)
        cla = cla + ' ' + style;

    for (var ix=0; ix<ls.length; ix++) {
        var el = $('<div>', { class:cla });
        var val = ls[ix];
        val = val.replace(regex_long_whitespace, func_long_whitespace);
        el.text(val);
        textel.append(el);
    }

    textel.scrollTop(textel.get(0).scrollHeight);
}

var regex_long_whitespace = new RegExp('  +', 'g'); /* two or more spaces */

/* Given a run of N spaces (N >= 2), return N-1 non-breaking spaces plus
   a normal one. */
function func_long_whitespace(match) {
  var len = match.length;
  if (len == 1)
    return ' ';
  /* Evil trick I picked up from Prototype. Gives len-1 copies of NBSP. */
  var res = new Array(len).join('\xa0');
  return res + ' ';
}

function evhan_input(ev)
{
    var inputel = $('#'+debug_el_id+'_input');
    if (!inputel.length)
        return;

    var val = inputel.val().trim();
    inputel.val('');

    if (!val.length)
        return;

    debug_input(val);
}

function event_pos(ev)
{
    if (!use_touch_ui)
        return { left:ev.clientX, top:ev.clientY };
    else
        return { left:ev.originalEvent.pageX, top:ev.originalEvent.pageY };
}

function evhan_dragstart(ev)
{
    if (drag_mode)
        return;

    var dia = $('#'+debug_el_id);
    if (!dia.length)
        return;

    drag_mode = ev.data.tag;

    ev.preventDefault();
    ev.stopPropagation();

    switch (drag_mode) {
    case 'position':
        drag_context = dia.offset();
        break;
    case 'size':
    case 'width':
    case 'height':
        drag_context = { width:dia.width(), height:dia.height() };
        break;
    case 'size-ne':
    case 'size-sw':
    case 'size-nw':
        drag_context = dia.offset();
        drag_context.width = dia.width();
        drag_context.height = dia.height();
        drag_context.xmax = drag_context.left + drag_context.width;
        drag_context.ymax = drag_context.top + drag_context.height;
        break;
    default:
        drag_context = {};
        break;
    }

    drag_context.basepos = event_pos(ev);
    drag_context.porttop = $('#gidebug').parent().offset().top + 4;

    if (!use_touch_ui) {
        $('body').on('mousemove', evhan_dragdrag);
        $('body').on('mouseup', evhan_dragstop);
    }
    else {
        $('body').on('touchmove', evhan_dragdrag);
        $('body').on('touchend', evhan_dragstop);
        $('body').on('touchcancel', evhan_dragstop);
    }
}

function evhan_dragdrag(ev, ui)
{
    if (!drag_mode)
        return;

    var dia = $('#'+debug_el_id);
    if (!dia.length)
        return;

    var pos = event_pos(ev);
    var deltax = pos.left - drag_context.basepos.left;
    var deltay = pos.top - drag_context.basepos.top;

    switch (drag_mode) {
    case 'position':
        pos.left = drag_context.left + deltax;
        pos.top = Math.max(drag_context.porttop, drag_context.top + deltay);
        dia.offset(pos);
        break;
    case 'size':
        dia.width(Math.max(min_width, drag_context.width + deltax));
        dia.height(Math.max(min_width, drag_context.height + deltay));
        break;
    case 'width':
        dia.width(Math.max(min_width, drag_context.width + deltax));
        break;
    case 'height':
        dia.height(Math.max(min_width, drag_context.height + deltay));
        break;
    case 'size-ne':
        var ypos = Math.max(drag_context.porttop, drag_context.top + deltay);
        pos.left = drag_context.left;
        pos.top = Math.min(drag_context.ymax-min_width, ypos);
        dia.offset(pos);
        dia.width(Math.max(min_width, drag_context.width + deltax));
        dia.height(drag_context.ymax - pos.top);
        break;
    case 'size-sw':
        var xpos = drag_context.left + deltax;
        pos.top = drag_context.top;
        pos.left = Math.min(drag_context.xmax-min_width, xpos);
        dia.offset(pos);
        dia.height(Math.max(min_width, drag_context.height + deltay));
        dia.width(drag_context.xmax - pos.left);
        break;
    case 'size-nw':
        var xpos = drag_context.left + deltax;
        var ypos = Math.max(drag_context.porttop, drag_context.top + deltay);
        pos.left = Math.min(drag_context.xmax-min_width, xpos);
        pos.top = Math.min(drag_context.ymax-min_width, ypos);
        dia.offset(pos);
        dia.width(drag_context.xmax - pos.left);
        dia.height(drag_context.ymax - pos.top);
        break;
    }
}

function evhan_dragstop(ev, ui)
{
    if (!use_touch_ui) {
        $('body').off('mousemove');
        $('body').off('mouseup');
    }
    else {
        $('body').off('touchmove');
        $('body').off('touchend');
        $('body').off('touchcancel');
    }

    drag_mode = null;
    drag_context = null;
}

/* End of GiDebug namespace function. Return the object which will
   become the GiDebug global. */
return {
    init: debug_init,
    open: debug_open,
    input: debug_input,
    output: debug_output
};

}();

/* End of GiDebug library. */
<|endoftext|>


<commit_before>'use strict';

const router = require('express').Router();
module.exports = router;

router.use(function(req, res) {
  res.status(404).end();
});
<commit_msg>forgot to add to the index.js in the server file to include the new routes<commit_after>'use strict';

const router = require('express').Router();
module.exports = router;

router.use('/relations', require('./relations'));
router.use('/subreddits', require('./subreddits'));

router.use(function(req, res) {
  res.status(404).end();
});
<|endoftext|>


<commit_before>'use strict';

var globalModule_Try__func_var = function globalModule_Try(moduleString) {
	try {
		return require(moduleString);
	} catch (exception) {
		console.log("FAILED TO LOAD: \"" + moduleString + "\"");
		console.log(exception);
		return null;
	}
};

var serialize_object_to_disk__func_var = function serialize_object_to_disk(object, entire_file_name) {
	var fileSystem_Module = globalModule_Try__func_var('fs');
	var inHouseFileHandle = fileSystem_Module.openSync(entire_file_name, 'w');
	fileSystem_Module.writeFileSync(inHouseFileHandle, JSON.stringify(object));
	fileSystem_Module.closeSync(inHouseFileHandle);
};

function dump_debug_string(string) {
	var fileSystem_Module = globalModule_Try__func_var('fs');
	var inHouseFileHandle = fileSystem_Module.openSync("./local_debug_dump.txt", 'a');
	fileSystem_Module.writeSync(inHouseFileHandle, string);
	fileSystem_Module.closeSync(inHouseFileHandle);
}

function message_locator_service(mainMessage) {
	var path_Module = globalModule_Try__func_var('path');
	var stackTrace_Module = globalModule_Try__func_var('stack-trace');
	var currentFrame = stackTrace_Module.get()[1];
	console.log(mainMessage + " >>> \"" + path_Module.basename(currentFrame.getFileName()) + ":" +
	    currentFrame.getLineNumber() + "\"\n");
}

function spot_the_head(htmlLineArray) {
	var headAreaMark_Array = [ -1, -1 ];
	var headMark_RegExp = new RegExp("<\\s*\\/?\\s*head\\s*>", "i");
	for (var i = 0; i < htmlLineArray.length; i++) {
		if (headMark_RegExp.exec(htmlLineArray[i]) !== null) {
			if (headAreaMark_Array[0] === -1) {
				headAreaMark_Array[0] = i;
			} else {
				headAreaMark_Array[1] = i;
				break;
			}
		}
	}
	if (headAreaMark_Array[0] === -1 || headAreaMark_Array[1] === -1) {
		message_locator_service("HEAD AREA BOUNDRIES BUGGY OR NOT FOUND AT ALL...!");
		return false;
	} else {
		return headAreaMark_Array;
	}
}

function carriage_return_needed() {
	var os_Module = globalModule_Try__func_var('os');
	var windowsSpotter_RegExp = new RegExp("windows", "i");
	if (windowsSpotter_RegExp.exec(os_Module.type()) !== null) {
		return true;
	} else {
		return false;
	}
}

function end_of_line_clean_save(fileName, array, carriageReturn) {
	var carriageReturnString = "";
	if (carriageReturn) {
		carriageReturnString = "\r";
	}
	var fileSystem_Module = globalModule_Try__func_var('fs');
	var currentFileHandle = fileSystem_Module.openSync(fileName, 'w');

	var lineSpotter_RegExp = new RegExp("^([\\x20\\x09]*)(.*)\\x0d*$", "i");
	var initialLineResultArray = lineSpotter_RegExp.exec(array[0]);
	if (initialLineResultArray !== null) {
		if (initialLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, initialLineResultArray[1] + initialLineResultArray[2] +
			    carriageReturnString + "\n");
		}
	} else {
		message_locator_service("MISSED THE INITIAL LINE...!");
		return false;
	}
	for (var j = 1; j < (array.length - 1); j++) {
		var lineResultArray = lineSpotter_RegExp.exec(array[j]);
		if (lineResultArray !== null) {
			if (j === (array.length - 2)) {
				var nextToLast_ResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
				if (!nextToLast_ResultArray[2]) {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2]);
				} else {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
					    "\n");
				}
			} else {
				fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
				    "\n");
			}
		} else {
			message_locator_service("MISSED A LINE...!");
			return false;
		}
	}
	var finalLineResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
	if (finalLineResultArray !== null) {
		if (finalLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, finalLineResultArray[1] + finalLineResultArray[2]);
		}
	} else {
		message_locator_service("MISSED THE FINAL LINE...!");
		return false;
	}
	fileSystem_Module.closeSync(currentFileHandle);
	return true;
}

function array_from_file_delete(entire_fileName) {
	var fileSystem_Module = globalModule_Try__func_var('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		fileSystem_Module.unlinkSync(entire_fileName);
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

function array_from_file(entire_fileName) {
	var fileSystem_Module = globalModule_Try__func_var('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

// Switching html head area to minified targets...
function toMin(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var hasMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(?:\\.min)+(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	var carelessAboutMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		if (hasMin_RegExp.exec(contentArray[i]) === null) {
			var regExp_ResultArray = carelessAboutMin_RegExp.exec(contentArray[i]);
			if (regExp_ResultArray !== null) {
				contentArray[i] = regExp_ResultArray[1] + ".min" + regExp_ResultArray[2] + carriageReturn;
				if (!changed) {
					changed = true;
				}
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

// Switching html head area to regular targets...
function toRegular(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var minSuspect_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)\\.min(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		var regExp_ResultArray = minSuspect_RegExp.exec(contentArray[i]);
		if (regExp_ResultArray !== null) {
			contentArray[i] = regExp_ResultArray[1] + regExp_ResultArray[2] + carriageReturn;
			if (!changed) {
				changed = true;
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

function delete_writingArray_ToFile(fileName, array) {
	var fileSystem_Module = globalModule_Try__func_var('fs');
	if (fileSystem_Module.existsSync(fileName)) {
		fileSystem_Module.unlinkSync(fileName);
	}
	var inHouseFileHandle = fileSystem_Module.openSync(fileName, 'w');
	for (var i = 0; i < (array.length - 1); i++) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[i] + "\n");
	}
	if (array[array.length - 1]) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[array.length - 1]);
	}
	fileSystem_Module.closeSync(inHouseFileHandle);
}

module.exports = {
  globalModule_Try : globalModule_Try__func_var,
  serialize_object_to_disk : serialize_object_to_disk__func_var,
  casual__options_property_servant : function(options_object, options_reference_object, requested_property) {
	  for ( var property_from_options_object in options_object) {
		  if (requested_property === property_from_options_object) {
			  if (options_reference_object.hasOwnProperty(property_from_options_object)) {
				  if (options_reference_object[property_from_options_object].includes(options_object[property_from_options_object])) {
					  return options_object[property_from_options_object];
				  } else {
					  console
					      .log("GIVEN PROPERTIES VALUE IS NOT A VALUE OF THE EQUAL REFERENCE OBJETCS PROPERTY AND THEREFORE INVALID...! PLEASE CHECK THE DOCUMENTATION AND YOUR \"Gruntfile.js\" OPTIONS.");
					  return false;
				  }
			  } else {
				  console
				      .log("GIVEN PROPERTY IS NOT A PROPERTY OF THE REFERENCE OPTIONS...! PLEASE CHECK THE DOCUMENTATION AND YOUR \"Gruntfile.js\" OPTIONS.");
				  return false;
			  }
		  }
	  }
	  console.log("COULD NOT SPOT A VALID OPTION INSIDE THE GIVEN OPTIONS OBJECT...!");
	  return false;
  },

  add_on_options__servant : function(global_object) {
	  var noisy = true;
	  var global_options_object = global_object.data.options;
	  var global_add_on_options_object = {
		  chattiness : [ 'true', 'false' ]
	  };
	  if (global_options_object !== undefined) {
		  if (noisy) {
			  console.log(">>> Options section found... Doing further checking... <<<");
		  }
		  for ( var item in global_add_on_options_object) {
			  if (global_options_object.hasOwnProperty(item)) {
				  var contains_valid_value = false;
				  for (var i = 0; i < global_add_on_options_object[item].length; i++) {
					  if (global_add_on_options_object[item].includes(global_options_object[item])) {
						  contains_valid_value = true;
						  break;
					  }
				  }
				  if (!contains_valid_value) {
					  console.log("\"" + global_options_object[item] + "\" IS NOT A VALID OPTION WITH \"" + item + "\" ...!");
					  return false;
				  }
			  } else {
				  if (noisy) {
					  console.log("MISSING OBJECTS OPTIONS PROPERTY: \"" + item + "\" ...!");
				  }
				  return false;
			  }
		  }
		  return true;
	  } else {
		  console.log(">>> NO VALID OPTIONS SECTION FOUND...! <<<");
		  return false;
	  }
  },

  private_action_checker : function(global_object, reference_object, noisy) {
	  var global_options_object = global_object.data.options;
	  if (global_options_object !== undefined) {
		  if (noisy) {
			  console.log(">>> Options section found... Doing further checking... <<<");
		  }
		  for ( var item in reference_object) {
			  if (global_options_object.hasOwnProperty(item)) {
				  var contains_valid_value = false;
				  for (var i = 0; i < reference_object[item].length; i++) {
					  if (reference_object[item].includes(global_options_object[item])) {
						  contains_valid_value = true;
						  break;
					  }
				  }
				  if (!contains_valid_value) {
					  console.log("\"" + global_options_object[item] + "\" IS NOT A VALID OPTION WITH \"" + item + "\" ...!");
					  return false;
				  }
			  } else {
				  if (noisy) {
					  console.log("MISSING OBJECTS OPTIONS PROPERTY: \"" + item + "\" ...!");
				  }
				  return false;
			  }
		  }
		  return true;
	  } else {
		  console.log(">>> NO VALID OPTIONS SECTION FOUND...! <<<");
		  return false;
	  }
  },

  process_wildcard_input : function(source, directory) {
	  var wildcard_extractor_RegExp = new RegExp("^\\*(.+)$");
	  var result_array = wildcard_extractor_RegExp.exec(source);
	  var final_files_array = [];
	  if (result_array) {
		  var tail_string = result_array[1];
		  var prepared_tail = tail_string.replace(/\./ig, "\\.");
		  var wildcard_RegExp = new RegExp("^(.+" + prepared_tail + ")$", "i");
		  var fileSystem_Module = globalModule_Try__func_var('fs');
		  var raw_file_array = fileSystem_Module.readdirSync(directory);
		  var targets_file_array = [];
		  for (var i = 0; i < raw_file_array.length; i++) {
			  var single_file_result_array = wildcard_RegExp.exec(raw_file_array[i]);
			  if (single_file_result_array) {
				  final_files_array.push(directory + single_file_result_array[1]);
			  }
		  }
		  return final_files_array;
	  } else {
		  message_locator_service("NO VALID WILDCARD FOUND...!");
		  return false;
	  }
  },

  toggle_all_head_links : function(direction, file) {
	  var pointToMin = false;
	  if (direction === 'min') {
		  pointToMin = true;
	  }
	  var targetFile_LineArray = array_from_file(file);
	  if (targetFile_LineArray) {
		  var windowsNeeded_carriageReturn = "";
		  if (carriage_return_needed) {
			  windowsNeeded_carriageReturn = "\r";
		  }
		  var headStart = spot_the_head(targetFile_LineArray)[0];
		  var headEnd = spot_the_head(targetFile_LineArray)[1];

		  // Actual array manipulation...
		  if (pointToMin) {
			  targetFile_LineArray = toMin(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  } else {
			  targetFile_LineArray = toRegular(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  }
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  },

  end_of_line_refresh : function(file) {
	  var targetFile_LineArray = array_from_file_delete(file);
	  if (targetFile_LineArray) {
		  return end_of_line_clean_save(file, targetFile_LineArray, carriage_return_needed());
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  }
};
<commit_msg>Introduction of the chat on meter... - MH - PT<commit_after>'use strict';

var globalModule_Try__func_var = function globalModule_Try(moduleString) {
	try {
		return require(moduleString);
	} catch (exception) {
		console.log("FAILED TO LOAD: \"" + moduleString + "\"");
		console.log(exception);
		return null;
	}
};

var chat_o_meter__func_var = function chat_o_meter(options_object) {
	console.log("MESSAGE FRIM YOUR \"CHAT O METER\"...!");
};

var serialize_object_to_disk__func_var = function serialize_object_to_disk(object, entire_file_name) {
	var fileSystem_Module = globalModule_Try__func_var('fs');
	var inHouseFileHandle = fileSystem_Module.openSync(entire_file_name, 'w');
	fileSystem_Module.writeFileSync(inHouseFileHandle, JSON.stringify(object));
	fileSystem_Module.closeSync(inHouseFileHandle);
};

function dump_debug_string(string) {
	var fileSystem_Module = globalModule_Try__func_var('fs');
	var inHouseFileHandle = fileSystem_Module.openSync("./local_debug_dump.txt", 'a');
	fileSystem_Module.writeSync(inHouseFileHandle, string);
	fileSystem_Module.closeSync(inHouseFileHandle);
}

function message_locator_service(mainMessage) {
	var path_Module = globalModule_Try__func_var('path');
	var stackTrace_Module = globalModule_Try__func_var('stack-trace');
	var currentFrame = stackTrace_Module.get()[1];
	console.log(mainMessage + " >>> \"" + path_Module.basename(currentFrame.getFileName()) + ":" +
	    currentFrame.getLineNumber() + "\"\n");
}

function spot_the_head(htmlLineArray) {
	var headAreaMark_Array = [ -1, -1 ];
	var headMark_RegExp = new RegExp("<\\s*\\/?\\s*head\\s*>", "i");
	for (var i = 0; i < htmlLineArray.length; i++) {
		if (headMark_RegExp.exec(htmlLineArray[i]) !== null) {
			if (headAreaMark_Array[0] === -1) {
				headAreaMark_Array[0] = i;
			} else {
				headAreaMark_Array[1] = i;
				break;
			}
		}
	}
	if (headAreaMark_Array[0] === -1 || headAreaMark_Array[1] === -1) {
		message_locator_service("HEAD AREA BOUNDRIES BUGGY OR NOT FOUND AT ALL...!");
		return false;
	} else {
		return headAreaMark_Array;
	}
}

function carriage_return_needed() {
	var os_Module = globalModule_Try__func_var('os');
	var windowsSpotter_RegExp = new RegExp("windows", "i");
	if (windowsSpotter_RegExp.exec(os_Module.type()) !== null) {
		return true;
	} else {
		return false;
	}
}

function end_of_line_clean_save(fileName, array, carriageReturn) {
	var carriageReturnString = "";
	if (carriageReturn) {
		carriageReturnString = "\r";
	}
	var fileSystem_Module = globalModule_Try__func_var('fs');
	var currentFileHandle = fileSystem_Module.openSync(fileName, 'w');

	var lineSpotter_RegExp = new RegExp("^([\\x20\\x09]*)(.*)\\x0d*$", "i");
	var initialLineResultArray = lineSpotter_RegExp.exec(array[0]);
	if (initialLineResultArray !== null) {
		if (initialLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, initialLineResultArray[1] + initialLineResultArray[2] +
			    carriageReturnString + "\n");
		}
	} else {
		message_locator_service("MISSED THE INITIAL LINE...!");
		return false;
	}
	for (var j = 1; j < (array.length - 1); j++) {
		var lineResultArray = lineSpotter_RegExp.exec(array[j]);
		if (lineResultArray !== null) {
			if (j === (array.length - 2)) {
				var nextToLast_ResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
				if (!nextToLast_ResultArray[2]) {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2]);
				} else {
					fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
					    "\n");
				}
			} else {
				fileSystem_Module.writeSync(currentFileHandle, lineResultArray[1] + lineResultArray[2] + carriageReturnString +
				    "\n");
			}
		} else {
			message_locator_service("MISSED A LINE...!");
			return false;
		}
	}
	var finalLineResultArray = lineSpotter_RegExp.exec(array[array.length - 1]);
	if (finalLineResultArray !== null) {
		if (finalLineResultArray[2]) {
			fileSystem_Module.writeSync(currentFileHandle, finalLineResultArray[1] + finalLineResultArray[2]);
		}
	} else {
		message_locator_service("MISSED THE FINAL LINE...!");
		return false;
	}
	fileSystem_Module.closeSync(currentFileHandle);
	return true;
}

function array_from_file_delete(entire_fileName) {
	var fileSystem_Module = globalModule_Try__func_var('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		fileSystem_Module.unlinkSync(entire_fileName);
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

function array_from_file(entire_fileName) {
	var fileSystem_Module = globalModule_Try__func_var('fs');
	if (fileSystem_Module.existsSync(entire_fileName)) {
		var targetFile_LineArray = fileSystem_Module.readFileSync(entire_fileName, 'utf8', 'r').toString().split('\n');
		return targetFile_LineArray;
	} else {
		message_locator_service("TARGET FILE DOES NOT EXIST...!");
		return false;
	}
}

// Switching html head area to minified targets...
function toMin(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var hasMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(?:\\.min)+(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	var carelessAboutMin_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		if (hasMin_RegExp.exec(contentArray[i]) === null) {
			var regExp_ResultArray = carelessAboutMin_RegExp.exec(contentArray[i]);
			if (regExp_ResultArray !== null) {
				contentArray[i] = regExp_ResultArray[1] + ".min" + regExp_ResultArray[2] + carriageReturn;
				if (!changed) {
					changed = true;
				}
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

// Switching html head area to regular targets...
function toRegular(headStart, headEnd, carriageReturn, contentArray) {
	var changed = false;
	var minSuspect_RegExp = new RegExp(
	    "^(.*(?:href|src)\\s*\\=\\s*(?:\"|\')?.+)\\.min(\\.(?:js|css)[\\x20\\t]*(?:\"|\')?[^\\x0d\\x0a]*)", "i");
	for (var i = (headStart + 1); i < headEnd; i++) {
		var regExp_ResultArray = minSuspect_RegExp.exec(contentArray[i]);
		if (regExp_ResultArray !== null) {
			contentArray[i] = regExp_ResultArray[1] + regExp_ResultArray[2] + carriageReturn;
			if (!changed) {
				changed = true;
			}
		}
	}
	if (changed) {
		return contentArray;
	} else {
		return false;
	}
}

function delete_writingArray_ToFile(fileName, array) {
	var fileSystem_Module = globalModule_Try__func_var('fs');
	if (fileSystem_Module.existsSync(fileName)) {
		fileSystem_Module.unlinkSync(fileName);
	}
	var inHouseFileHandle = fileSystem_Module.openSync(fileName, 'w');
	for (var i = 0; i < (array.length - 1); i++) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[i] + "\n");
	}
	if (array[array.length - 1]) {
		fileSystem_Module.writeSync(inHouseFileHandle, array[array.length - 1]);
	}
	fileSystem_Module.closeSync(inHouseFileHandle);
}

module.exports = {
  globalModule_Try : globalModule_Try__func_var,
  chat_o_meter : chat_o_meter__func_var,
  serialize_object_to_disk : serialize_object_to_disk__func_var,
  casual__options_property_servant : function(options_object, options_reference_object, requested_property) {
	  for ( var property_from_options_object in options_object) {
		  if (requested_property === property_from_options_object) {
			  if (options_reference_object.hasOwnProperty(property_from_options_object)) {
				  if (options_reference_object[property_from_options_object].includes(options_object[property_from_options_object])) {
					  return options_object[property_from_options_object];
				  } else {
					  console
					      .log("GIVEN PROPERTIES VALUE IS NOT A VALUE OF THE EQUAL REFERENCE OBJETCS PROPERTY AND THEREFORE INVALID...! PLEASE CHECK THE DOCUMENTATION AND YOUR \"Gruntfile.js\" OPTIONS.");
					  return false;
				  }
			  } else {
				  console
				      .log("GIVEN PROPERTY IS NOT A PROPERTY OF THE REFERENCE OPTIONS...! PLEASE CHECK THE DOCUMENTATION AND YOUR \"Gruntfile.js\" OPTIONS.");
				  return false;
			  }
		  }
	  }
	  console.log("COULD NOT SPOT A VALID OPTION INSIDE THE GIVEN OPTIONS OBJECT...!");
	  return false;
  },

  add_on_options__servant : function(global_object) {
	  var noisy = true;
	  var global_options_object = global_object.data.options;
	  var global_add_on_options_object = {
		  chattiness : [ 'true', 'false' ]
	  };
	  if (global_options_object !== undefined) {
		  if (noisy) {
			  console.log(">>> Options section found... Doing further checking... <<<");
		  }
		  for ( var item in global_add_on_options_object) {
			  if (global_options_object.hasOwnProperty(item)) {
				  var contains_valid_value = false;
				  for (var i = 0; i < global_add_on_options_object[item].length; i++) {
					  if (global_add_on_options_object[item].includes(global_options_object[item])) {
						  contains_valid_value = true;
						  break;
					  }
				  }
				  if (!contains_valid_value) {
					  console.log("\"" + global_options_object[item] + "\" IS NOT A VALID OPTION WITH \"" + item + "\" ...!");
					  return false;
				  }
			  } else {
				  if (noisy) {
					  console.log("MISSING OBJECTS OPTIONS PROPERTY: \"" + item + "\" ...!");
				  }
				  return false;
			  }
		  }
		  return true;
	  } else {
		  console.log(">>> NO VALID OPTIONS SECTION FOUND...! <<<");
		  return false;
	  }
  },

  private_action_checker : function(global_object, reference_object, noisy) {
	  var global_options_object = global_object.data.options;
	  if (global_options_object !== undefined) {
		  if (noisy) {
			  console.log(">>> Options section found... Doing further checking... <<<");
		  }
		  for ( var item in reference_object) {
			  if (global_options_object.hasOwnProperty(item)) {
				  var contains_valid_value = false;
				  for (var i = 0; i < reference_object[item].length; i++) {
					  if (reference_object[item].includes(global_options_object[item])) {
						  contains_valid_value = true;
						  break;
					  }
				  }
				  if (!contains_valid_value) {
					  console.log("\"" + global_options_object[item] + "\" IS NOT A VALID OPTION WITH \"" + item + "\" ...!");
					  return false;
				  }
			  } else {
				  if (noisy) {
					  console.log("MISSING OBJECTS OPTIONS PROPERTY: \"" + item + "\" ...!");
				  }
				  return false;
			  }
		  }
		  return true;
	  } else {
		  console.log(">>> NO VALID OPTIONS SECTION FOUND...! <<<");
		  return false;
	  }
  },

  process_wildcard_input : function(source, directory) {
	  var wildcard_extractor_RegExp = new RegExp("^\\*(.+)$");
	  var result_array = wildcard_extractor_RegExp.exec(source);
	  var final_files_array = [];
	  if (result_array) {
		  var tail_string = result_array[1];
		  var prepared_tail = tail_string.replace(/\./ig, "\\.");
		  var wildcard_RegExp = new RegExp("^(.+" + prepared_tail + ")$", "i");
		  var fileSystem_Module = globalModule_Try__func_var('fs');
		  var raw_file_array = fileSystem_Module.readdirSync(directory);
		  var targets_file_array = [];
		  for (var i = 0; i < raw_file_array.length; i++) {
			  var single_file_result_array = wildcard_RegExp.exec(raw_file_array[i]);
			  if (single_file_result_array) {
				  final_files_array.push(directory + single_file_result_array[1]);
			  }
		  }
		  return final_files_array;
	  } else {
		  message_locator_service("NO VALID WILDCARD FOUND...!");
		  return false;
	  }
  },

  toggle_all_head_links : function(direction, file) {
	  var pointToMin = false;
	  if (direction === 'min') {
		  pointToMin = true;
	  }
	  var targetFile_LineArray = array_from_file(file);
	  if (targetFile_LineArray) {
		  var windowsNeeded_carriageReturn = "";
		  if (carriage_return_needed) {
			  windowsNeeded_carriageReturn = "\r";
		  }
		  var headStart = spot_the_head(targetFile_LineArray)[0];
		  var headEnd = spot_the_head(targetFile_LineArray)[1];

		  // Actual array manipulation...
		  if (pointToMin) {
			  targetFile_LineArray = toMin(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  } else {
			  targetFile_LineArray = toRegular(headStart, headEnd, windowsNeeded_carriageReturn, targetFile_LineArray);
			  if (targetFile_LineArray) {
				  delete_writingArray_ToFile(file, targetFile_LineArray);
				  return true;
			  } else {
				  return true;
			  }
		  }
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  },

  end_of_line_refresh : function(file) {
	  var targetFile_LineArray = array_from_file_delete(file);
	  if (targetFile_LineArray) {
		  return end_of_line_clean_save(file, targetFile_LineArray, carriage_return_needed());
	  } else {
		  message_locator_service("FAILED TO GET VALID DATA ARRAY...!");
		  return false;
	  }
  }
};
<|endoftext|>


<commit_before>/*!
    Copyright (C) 2015 Google Inc., authors, and contributors <see AUTHORS file>
    Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
    Created By: swizec@reciprocitylabs.com
    Maintained By: swizec@reciprocitylabs.com
*/

can.Component.extend({
  tag: 'assessment-generator-button',
  template: '{{{> /static/mustache/base_objects/generate_assessments_button.mustache}}}',
  scope: {
    audit: null
  },
  events: {
    'a click': function (el, ev) {
      var instance = this.scope.attr('audit') || GGRC.page_instance();
      this._results = null;
      GGRC.Controllers.MapperModal.launch(el, {
        object: 'Audit',
        type: 'Control',
        'join-object-id': this.scope.audit.id,
        'join-mapping': 'program_controls',
        getList: true,
        useTemplates: true,
        relevantTo: [{
          type: instance.program.type,
          id: instance.program.id
        }],
        template: {
          title: '/static/mustache/assessments/generator_title.mustache',
          submitButton: 'Generate Assessments',
          count: 'assessment(s) will be generated'
        },
        callback: this.generateAssessments.bind(this)
      });
    },
    generateAssessments: function (list, options) {
      var que = new RefreshQueue();

      que.enqueue(list).trigger().then(function (items) {
        var results = _.map(items, function (item) {
          return this.generateModel(item);
        }.bind(this));
        this._results = results;

        $.when.apply($, results)
          .then(this.generateCustomAttributes(this, options.assessmentTemplate))
          .then(function () {
            options.context.closeModal();
          })
          .done(this.notify.bind(this))
          .fail(this.notify.bind(this));
      }.bind(this));
    },
    generateCustomAttributes: function (context, template) {
      return function (results) {
        var people = _.map(results, function (assessment) {
          var templates = this.getTemplatePeople(template, assessment.object);
          return _.map(templates, function (person, role) {
            return CMS.Models.Relationship.createAssignee({
              role: role,
              source: person,
              destination: assessment,
              context: assessment.context
            }).save();
          });
        }.bind(this));

        return $.when.apply($, people);
      }.bind(context);
    },
    generateModel: function (object, template) {
      var title = object.title + ' assessment for ' + this.scope.audit.title;
      var data = {
        audit: this.scope.audit,
        object: object.stub(),
        context: this.scope.audit.context,
        title: title,
        owners: [CMS.Models.Person.findInCacheById(GGRC.current_user.id)]
      };
      if (object.test_plan) {
        data.test_plan = object.test_plan;
      }
      return new CMS.Models.Assessment(data).save();
    },
    getTemplatePeople: function (id, object) {
      var model = CMS.Models.AssessmentTemplate.findInCacheById(id);
      var people;
      var types = {
        'Object Owners': function () {
          return this.object_owners;
        },
        'Audit Lead': this.scope.audit.contact,
        'Object Contact': function () {
          return this.contact;
        },
        'Primary Assessor': function () {
          return this.principal_assessor;
        },
        'Secondary Assessor': function () {
          return this.secondary_assessor;
        }
      };

      function getTypes(prop) {
        var type;
        if (_.isArray(prop)) {
          return prop;
        }
        type = types[prop];
        if (_.isFunction(type)) {
          return type.call(object);
        }
        return type;
      }

      if (!model) {
        return;
      }
      people = model.default_people;

      return {
        Assessor: getTypes(people.assessors),
        Verifier: getTypes(people.verifiers)
      };
    },
    notify: function () {
      var success;
      var errors;
      var msg;

      if (!this._results) {
        return;
      }
      success = _.filter(this._results, function (assessment) {
        return !_.isNull(assessment) &&
          !(assessment.state && assessment.state() === 'rejected');
      }).length;
      errors = _.filter(this._results, function (assessment) {
        return assessment.state && assessment.state() === 'rejected';
      }).length;

      if (errors < 1) {
        if (success === 0) {
          msg = {
            success: 'Every Control already has an Assessment!'
          };
        } else {
          msg = {
            success: success + ' Assessments successfully created.'
          };
        }
      } else {
        msg = {
          error: 'An error occured when creating Assessments.'
        };
      }

      $(document.body).trigger('ajax:flash', msg);
    }
  }
});
<commit_msg>Move assessment template generator to GGR.Component<commit_after>/*!
    Copyright (C) 2015 Google Inc., authors, and contributors <see AUTHORS file>
    Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>
    Created By: swizec@reciprocitylabs.com
    Maintained By: swizec@reciprocitylabs.com
*/

(function (can, $) {
  'use strict';

  GGRC.Components('assessmentGeneratorButton', {
    tag: 'assessment-generator-button',
    template: '{{{> /static/mustache/base_objects/generate_assessments_button.mustache}}}',
    scope: {
      audit: null
    },
    events: {
      'a click': function (el, ev) {
        var instance = this.scope.attr('audit') || GGRC.page_instance();
        this._results = null;
        GGRC.Controllers.MapperModal.launch(el, {
          object: 'Audit',
          type: 'Control',
          'join-object-id': this.scope.audit.id,
          'join-mapping': 'program_controls',
          getList: true,
          useTemplates: true,
          relevantTo: [{
            type: instance.program.type,
            id: instance.program.id
          }],
          template: {
            title: '/static/mustache/assessments/generator_title.mustache',
            submitButton: 'Generate Assessments',
            count: 'assessment(s) will be generated'
          },
          callback: this.generateAssessments.bind(this)
        });
      },
      generateAssessments: function (list, options) {
        var que = new RefreshQueue();

        this._results = null;
        que.enqueue(list).trigger().then(function (items) {
          var results = _.map(items, function (item) {
            return this.generateModel(item, options.assessmentTemplate);
          }.bind(this));
          this._results = results;

          $.when.apply($, results)
            .always(options.context.closeModal.bind(options.context))
            .done(this.notify.bind(this))
            .fail(this.notify.bind(this));
        }.bind(this));
      },
      generateModel: function (object, template) {
        var assessmentTemplate = CMS.Models.AssessmentTemplate.findInCacheById(
          template);
        var title = object.title + ' assessment for ' + this.scope.audit.title;
        var data = {
          audit: this.scope.audit,
          object: object.stub(),
          context: this.scope.audit.context,
          template: assessmentTemplate && assessmentTemplate.stub(),
          title: title,
          owners: [CMS.Models.Person.findInCacheById(GGRC.current_user.id)]
        };

        }
        return new CMS.Models.Assessment(data).save();
      },
      notify: function () {
        var success;
        var errors;
        var msg;

        if (!this._results) {
          return;
        }
        success = _.filter(this._results, function (assessment) {
          return !_.isNull(assessment) &&
            !(assessment.state && assessment.state() === 'rejected');
        }).length;
        errors = _.filter(this._results, function (assessment) {
          return assessment.state && assessment.state() === 'rejected';
        }).length;

        if (errors < 1) {
          if (success === 0) {
            msg = {
              success: 'Every Control already has an Assessment!'
            };
          } else {
            msg = {
              success: success + ' Assessments successfully created.'
            };
          }
        } else {
          msg = {
            error: 'An error occured when creating Assessments.'
          };
        }

        $(document.body).trigger('ajax:flash', msg);
      }
    }
  });
})(window.can, window.can.$);
<|endoftext|>


<commit_before>elation.require(["utils.dust"], function() {
  elation.extend("template", new function() {
    this.types = {};
    this.templates = {};
    this.defaulttype = false;

    this.addtype = function(type, wrapper) {
      this.types[type] = wrapper;
      if (!this.defaulttype && !this.types[type].failed) {
        this.setdefaulttype(type);
      }
    }
    this.setdefaulttype = function(type) {
      this.defaulttype = type;
    }

    this.add = function(name, tpl, type) {
      if (!type) type = this.defaulttype;
      this.types[type].add(name, tpl);
      this.templates[name] = {type: type, name: name, tpl: tpl};
      return this.templates[name];
    }
    this.remove = function(name) {
      if (this.templates[name] && this.types[this.templates[name].type]) {
        this.types[this.templates[name].type].remove();
        delete this.templates[name];
        return true;
      }
      return false;
    }
    this.get = function(name, args) {
      if (this.templates[name]) {
        var tpl = this.templates[name];
        if (this.types[tpl.type]) {
          return this.types[tpl.type].eval(name, args);
        } else {
          console.log('elation.template.get() - error: unknown template type for ' + name + ': ' + tpl.type);
        }
      } else {
        console.log('elation.template.get() - error: template not found: ' + name);
      }
      return '';
    }
    this.exists = function(name) {
      return (typeof this.templates[name] != 'undefined');
    }
  });
  elation.template.addtype("dust", new function() {
    this.failed = false;
    this.templates = {};
    this.init = function() {
      if (!dust) {
        console.log("elation.template.addtype('dust') - error: no dust library loaded");
        this.failed = true;
      }
    }
    this.add = function(name, tpl) {
      if (!this.failed) {
        //console.log('add template', name, tpl);
        this.templates[name] = dust.compile(tpl, name);
        dust.loadSource(this.templates[name]);
      }
    }
    this.remove = function(name) {
      if (this.templates[name]) {
        delete this.templates[name];
        return true;
      }
      return false;
    }
    this.eval = function(name, args) {
      // de-asynchronize template rendering.  templates can still trigger asynchronous output though...
      var result = '';
      if (!this.failed) {
        dust.render(name, args, function(err, res) {
          result = res;
        });
      }
      return result;
    }
  });
});
<commit_msg>Added event dependency<commit_after>elation.require(["utils.events", "utils.dust"], function() {
  elation.extend("template", new function() {
    this.types = {};
    this.templates = {};
    this.defaulttype = false;

    this.addtype = function(type, wrapper) {
      this.types[type] = wrapper;
      if (!this.defaulttype && !this.types[type].failed) {
        this.setdefaulttype(type);
      }
    }
    this.setdefaulttype = function(type) {
      this.defaulttype = type;
    }

    this.add = function(name, tpl, type) {
      if (!type) type = this.defaulttype;
      this.types[type].add(name, tpl);
      this.templates[name] = {type: type, name: name, tpl: tpl};
      return this.templates[name];
    }
    this.remove = function(name) {
      if (this.templates[name] && this.types[this.templates[name].type]) {
        this.types[this.templates[name].type].remove();
        delete this.templates[name];
        return true;
      }
      return false;
    }
    this.get = function(name, args) {
      if (this.templates[name]) {
        var tpl = this.templates[name];
        if (this.types[tpl.type]) {
          return this.types[tpl.type].eval(name, args);
        } else {
          console.log('elation.template.get() - error: unknown template type for ' + name + ': ' + tpl.type);
        }
      } else {
        console.log('elation.template.get() - error: template not found: ' + name);
      }
      return '';
    }
    this.exists = function(name) {
      return (typeof this.templates[name] != 'undefined');
    }
  });
  elation.template.addtype("dust", new function() {
    this.failed = false;
    this.templates = {};
    this.init = function() {
      if (!dust) {
        console.log("elation.template.addtype('dust') - error: no dust library loaded");
        this.failed = true;
      }
    }
    this.add = function(name, tpl) {
      if (!this.failed) {
        //console.log('add template', name, tpl);
        this.templates[name] = dust.compile(tpl, name);
        dust.loadSource(this.templates[name]);
      }
    }
    this.remove = function(name) {
      if (this.templates[name]) {
        delete this.templates[name];
        return true;
      }
      return false;
    }
    this.eval = function(name, args) {
      // de-asynchronize template rendering.  templates can still trigger asynchronous output though...
      var result = '';
      if (!this.failed) {
        dust.render(name, args, function(err, res) {
          result = res;
        });
      }
      return result;
    }
  });
});
<|endoftext|>


<commit_before>/**
 * @file
 */

(function ($, Drupal, drupalSettings) {
  'use strict';

  Drupal.behaviors.datetimepicker = {
    attach: function (context, settings) {

      // Setting the current language for the calendar.
      var language = drupalSettings.path.currentLanguage;
      var startDayWeek = 'Monday';
      var dateFormat = 'Y-m-d H:i';
      var allowTimepicker = true;
      var step = 15;
      var hoursFormat = 'H:i';
      var format = 'd.m.Y';

      $(context).find('input.datetimepicker').once('datePicker').each(function () {
        var input = $(this);
        $("#" + input.attr('id')).datetimepicker({
          lang: language,
          format: dateFormat,
          formatTime: hoursFormat,
          lazyInit: true,
          timepicker: allowTimepicker,
          todayButton: true,
          dayOfWeekStart: startDayWeek,
          step: step,
          formatDate: format,
        });
      });
    },
  };

})(jQuery, Drupal, drupalSettings);
<commit_msg>AFA-222 Force monday as first day<commit_after>/**
 * @file
 */

(function ($, Drupal, drupalSettings) {
  'use strict';

  Drupal.behaviors.datetimepicker = {
    attach: function (context, settings) {

      // Setting the current language for the calendar.
      var language = drupalSettings.path.currentLanguage;
      var startDayWeek = 1;
      var dateFormat = 'Y-m-d H:i';
      var allowTimepicker = true;
      var step = 15;
      var hoursFormat = 'H:i';
      var format = 'd.m.Y';

      $(context).find('input.datetimepicker').once('datePicker').each(function () {
        var input = $(this);
        $("#" + input.attr('id')).datetimepicker({
          lang: language,
          format: dateFormat,
          formatTime: hoursFormat,
          lazyInit: true,
          timepicker: allowTimepicker,
          todayButton: true,
          dayOfWeekStart: startDayWeek,
          step: step,
          formatDate: format,
        });
      });
    },
  };

})(jQuery, Drupal, drupalSettings);
<|endoftext|>