<commit_before>/*
 *
 * (c) Copyright Ascensio System Limited 2010-2016
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
 * EU, LV-1021.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
*/
var ApplicationController = new(function(){
    var me,
        api,
        config = {},
        docConfig = {},
        embedConfig = {},
        permissions = {},
        maxPages = 0,
        created = false,
        ttOffset = [0, -10];

    // Initialize analytics
    // -------------------------

//    Common.Analytics.initialize('UA-12442749-13', 'Embedded ONLYOFFICE Document');

    // Check browser
    // -------------------------

    if (typeof isBrowserSupported !== 'undefined' && !isBrowserSupported()){
        Common.Gateway.reportError(undefined, 'Your browser is not supported.');
        return;
    }

    // Utils
    // -------------------------

    function htmlEncode(value){
        return $('<div/>').text(value).html();
    }

    // Handlers
    // -------------------------

    function loadConfig(data) {
        config = $.extend(config, data.config);
        embedConfig = $.extend(embedConfig, data.config.embedded);

        common.controller.modals.init(embedConfig);
        if ( !embedConfig.shareUrl )
            $('#idt-share').hide();

        if ( !embedConfig.embedUrl )
            $('#idt-embed').hide();

        if (typeof embedConfig.fullscreenUrl === 'undefined')
            $('#idt-fullscr').hide();

        if (config.canBackToFolder === false || !(config.customization && config.customization.goback && config.customization.goback.url))
            $('#id-btn-close').hide();

        // Docked toolbar
        if (embedConfig.toolbarDocked === 'top') {
            $('#toolbar').addClass('top');
            $('#editor_sdk').addClass('top');
        } else {
            $('#toolbar').addClass('bottom');
            $('#editor_sdk').addClass('bottom');
        }

        // Hide last separator
        if (!$('#id-btn-close').is(":visible")) {
            $('#toolbar .right .separator').hide();
            $('#pages').css('margin-right', '12px');
        }
    }

    function loadDocument(data) {
        docConfig = data.doc;

        if (docConfig) {
            permissions = $.extend(permissions, docConfig.permissions);

            var docInfo = new Asc.asc_CDocInfo();
            docInfo.put_Id(docConfig.key);
            docInfo.put_Url(docConfig.url);
            docInfo.put_Title(docConfig.title);
            docInfo.put_Format(docConfig.fileType);
            docInfo.put_VKey(docConfig.vkey);

            if (api) {
                api.asc_registerCallback('asc_onGetEditorPermissions', onEditorPermissions);
                api.asc_setDocInfo(docInfo);
                api.asc_getEditorPermissions(config.licenseUrl, config.customerId);
                api.asc_enableKeyEvents(true);

                Common.Analytics.trackEvent('Load', 'Start');
            }

            if ( !embedConfig.saveUrl && permissions.print === false)
                $('#idt-copy').hide();
        }
    }

    function onCountPages(count) {
        maxPages = count;
        $('#pages').text('of ' + count);
    }

    function onCurrentPage(number) {
        $('#page-number').val(number + 1);
    }

    function onLongActionBegin(type, id) {
        var text = '';
        switch (id)
        {
            case Asc.c_oAscAsyncAction['Print']:
                text = 'Downloading document...';
                break;
            default:
                text = 'Please wait...';
                break;
        }

        if (type == Asc.c_oAscAsyncActionType['BlockInteraction']) {
            $('#id-loadmask .cmd-loader-title').html(text);
            showMask();
        }
    }

    function onLongActionEnd(){
        hideMask();
    }

    function onDocMouseMoveStart() {
        me.isHideBodyTip = true;
    }

    function onDocMouseMoveEnd() {
        if (me.isHideBodyTip) {
            if ( $tooltip ) {
                $tooltip.tooltip('hide');
                $tooltip = false;
            }
        }
    }

    var $ttEl, $tooltip;
    function onDocMouseMove(data) {
        if (data) {
            if (data.get_Type() == 1) { // hyperlink
                me.isHideBodyTip = false;

                if ( !$ttEl ) {
                    $ttEl = $('.hyperlink-tooltip');
                    $ttEl.tooltip({'container':'body', 'trigger':'manual'});
                    $ttEl.on('shown.bs.tooltip', function(e) {
                        $tooltip = $ttEl.data('bs.tooltip').tip();

                        $tooltip.css({
                            left: $ttEl.ttpos[0] - 10,
                            top: $ttEl.ttpos[1] - 5
                        });

                        $tooltip.find('.tooltip-arrow').css({left: 10});
                    });
                }

                if ( !$tooltip ) {
                    $ttEl.ttpos = [data.get_X(), data.get_Y()];
                    $ttEl.tooltip('show');
                } else {
                    $tooltip.css({
                        left:data.get_X() - 10,
                        top:data.get_Y() - 5
                    });
                }
            }
        }
    }

    function onDownloadUrl(url) {
        Common.Gateway.downloadAs(url);
    }

    function onPrint() {
        if (api && permissions.print!==false)
            api.asc_Print($.browser.chrome || $.browser.safari || $.browser.opera);
    }

    function onPrintUrl(url) {
        common.utils.dialogPrint(url);
    }

    function hidePreloader() {
        $('#loading-mask').fadeOut('slow');
    }

    function onDocumentContentReady() {
        hidePreloader();

        common.controller.modals.attach({
            share: '#idt-share',
            embed: '#idt-embed'
        });

        api.asc_registerCallback('asc_onStartAction',           onLongActionBegin);
        api.asc_registerCallback('asc_onEndAction',             onLongActionEnd);
        api.asc_registerCallback('asc_onMouseMoveStart',        onDocMouseMoveStart);
        api.asc_registerCallback('asc_onMouseMoveEnd',          onDocMouseMoveEnd);
        api.asc_registerCallback('asc_onMouseMove',             onDocMouseMove);
        api.asc_registerCallback('asc_onHyperlinkClick',        common.utils.openLink);
        api.asc_registerCallback('asc_onDownloadUrl',           onDownloadUrl);
        api.asc_registerCallback('asc_onPrint',                 onPrint);

        Common.Gateway.on('processmouse',       onProcessMouse);
        Common.Gateway.on('downloadas',         onDownloadAs);

        ApplicationView.tools.get('#idt-fullscreen')
            .on('click', function(){
                common.utils.openLink(embedConfig.fullscreenUrl);
            });

        ApplicationView.tools.get('#idt-download')
            .on('click', function(){
                    if ( !!embedConfig.saveUrl ){
                        common.utils.openLink(embedConfig.saveUrl);
                    } else
                    if (api && permissions.print!==false){
                        api.asc_Print($.browser.chrome || $.browser.safari || $.browser.opera);
                    }

                    Common.Analytics.trackEvent('Save');
            });

        $('#id-btn-close').on('click', function(){
            if (config.customization && config.customization.goback && config.customization.goback.url)
                window.parent.location.href = config.customization.goback.url;
        });

        $('#id-btn-zoom-in').on('click', api.zoomIn.bind(this));
        $('#id-btn-zoom-out').on('click', api.zoomOut.bind(this));

        var $pagenum = $('#page-number');
        $pagenum.on({
            'keyup': function(e){
                if ( e.keyCode == 13 ){
                    var newPage = parseInt($('#page-number').val());

                    if ( newPage > maxPages ) newPage = maxPages;
                    if (newPage < 2 || isNaN(newPage)) newPage = 1;

                    api.goToPage(newPage-1);
                    $pagenum.blur();
                }
            }
            , 'focusin' : function(e) {
                $pagenum.removeClass('masked');
            }
            , 'focusout': function(e){
                !$pagenum.hasClass('masked') && $pagenum.addClass('masked');
            }
        });

        $('#pages').on('click', function(e) {
            $pagenum.focus();
        });

        var documentMoveTimer;
        var ismoved = false;
        $(document).mousemove(function(event){
            $('#id-btn-zoom-in').fadeIn();
            $('#id-btn-zoom-out').fadeIn();

            ismoved = true;
            if ( !documentMoveTimer ) {
                documentMoveTimer = setInterval(function(){
                    if ( !ismoved ) {
                        $('#id-btn-zoom-in').fadeOut();
                        $('#id-btn-zoom-out').fadeOut();
                        clearInterval(documentMoveTimer);
                        documentMoveTimer = undefined;
                    }

                    ismoved = false;
                }, 2000);
            }
        });

        Common.Analytics.trackEvent('Load', 'Complete');
    }

    function onEditorPermissions(params) {
        if ( params.asc_getCanBranding() && (typeof config.customization == 'object') &&
             config.customization && config.customization.logo ) {

            var logo = $('#header-logo');
            if (config.customization.logo.imageEmbedded) {
                logo.html('<img src="'+config.customization.logo.imageEmbedded+'" style="max-width:124px; max-height:20px;"/>');
                logo.css({'background-image': 'none', width: 'auto', height: 'auto'});
            }

            if (config.customization.logo.url) {
                logo.attr('href', config.customization.logo.url);
            }
        }
        api.asc_setViewMode(true);
        api.asc_LoadDocument();
        api.Resize();
        api.zoomFitToWidth();
    }

    function showMask() {
        $('#id-loadmask').modal({
            backdrop: 'static',
            keyboard: false
        });
    }

    function hideMask() {
        $('#id-loadmask').modal('hide');
    }

    function onOpenDocument(progress) {
        var proc = (progress.asc_getCurrentFont() + progress.asc_getCurrentImage())/(progress.asc_getFontsCount() + progress.asc_getImagesCount());
        $('#loadmask-text').html('Loading document: ' + Math.min(Math.round(proc * 100), 100) + '%');
    }

    function onError(id, level, errData) {
        hidePreloader();

        var message;

        switch (id)
        {
            case Asc.c_oAscError.ID.Unknown:
                message = me.unknownErrorText;
                break;

            case Asc.c_oAscError.ID.ConvertationTimeout:
                message = me.convertationTimeoutText;
                break;

            case Asc.c_oAscError.ID.ConvertationError:
                message = me.convertationErrorText;
                break;

            case Asc.c_oAscError.ID.DownloadError:
                message = me.downloadErrorText;
                break;

            default:
                message = me.errorDefaultMessage.replace('%1', id);
                break;
        }

        if (level == Asc.c_oAscError.Level.Critical) {

            // report only critical errors
            Common.Gateway.reportError(id, message);

            $('#id-critical-error-title').text(me.criticalErrorTitle);
            $('#id-critical-error-message').text(message);
            $('#id-critical-error-close').off();
            $('#id-critical-error-close').on('click', function(){
                window.location.reload();
            });
        }
        else {
            $('#id-critical-error-title').text(me.notcriticalErrorTitle);
            $('#id-critical-error-message').text(message);
            $('#id-critical-error-close').off();
            $('#id-critical-error-close').on('click', function(){
                $('#id-critical-error-dialog').modal('hide');
            });
        }

        $('#id-critical-error-dialog').modal('show');

        Common.Analytics.trackEvent('Internal Error', id.toString());
    }

    function onExternalError(error) {
        if (error) {
            hidePreloader();
            $('#id-error-mask-title').text(error.title);
            $('#id-error-mask-text').text(error.msg);
            $('#id-error-mask').css('display', 'block');

            Common.Analytics.trackEvent('External Error', error.title);
        }
    }

    function onProcessMouse(data) {
        if (data.type == 'mouseup') {
            var e = document.getElementById('editor_sdk');
            if (e) {
                var r = e.getBoundingClientRect();
                api.OnMouseUp(
                    data.x - r.left,
                    data.y - r.top
                );
            }
        }
    }

    function onDownloadAs() {
        if (api) api.asc_DownloadAs(Asc.c_oAscFileType.DOCX, true);
    }

    // Helpers
    // -------------------------

    function onDocumentResize() {
        api && api.Resize();
    }

    function createController(){
        if (created)
            return me;

        me = this;
        created = true;

        $(window).resize(function(){
            onDocumentResize();
        });

        var ismodalshown = false;
        $(document.body).on('show.bs.modal', '.modal',
            function(e) {
                ismodalshown = true;
                api.asc_enableKeyEvents(false);
            }
        ).on('hidden.bs.modal', '.modal',
            function(e) {
                ismodalshown = false;
                api.asc_enableKeyEvents(true);
            }
        ).on('hidden.bs.dropdown', '.dropdown',
            function(e) {
                if ( !ismodalshown )
                    api.asc_enableKeyEvents(true);
            }
        ).on('blur', 'input, textarea',
            function(e) {
                if ( !ismodalshown ) {
                    if (!/area_id/.test(e.target.id) ) {
                        api.asc_enableKeyEvents(true);
                    }
                }
            }
        );

        $('#editor_sdk').on('click', function(e) {
            if ( e.target.localName == 'canvas' ) {
                e.currentTarget.focus();
            }
        });

        window["flat_desine"] = true;
        api = new Asc.asc_docs_api({
            'id-view'  : 'editor_sdk'
        });

        if (api){
            api.asc_registerCallback('asc_onError',                 onError);
            api.asc_registerCallback('asc_onDocumentContentReady',  onDocumentContentReady);
            api.asc_registerCallback('asc_onOpenDocumentProgress',  onOpenDocument);
            api.asc_registerCallback('asc_onPrintUrl',              onPrintUrl);

            api.asc_registerCallback('asc_onCountPages',            onCountPages);
//            api.asc_registerCallback('OnCurrentVisiblePage',    onCurrentPage);
            api.asc_registerCallback('asc_onCurrentPage',           onCurrentPage);

            // Initialize api gateway
            Common.Gateway.on('init',               loadConfig);
            Common.Gateway.on('opendocument',       loadDocument);
            Common.Gateway.on('showerror',          onExternalError);
            Common.Gateway.ready();
        }

        return me;
    }

    return {
        create                  : createController,
        errorDefaultMessage     : 'Error code: %1',
        unknownErrorText        : 'Unknown error.',
        convertationTimeoutText : 'Convertation timeout exceeded.',
        convertationErrorText   : 'Convertation failed.',
        downloadErrorText       : 'Download failed.',
        criticalErrorTitle      : 'Error',
        notcriticalErrorTitle   : 'Warning'
    }
})();<commit_msg>[DE embed] refactoring<commit_after>/*
 *
 * (c) Copyright Ascensio System Limited 2010-2016
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
 * EU, LV-1021.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
*/
var ApplicationController = new(function(){
    var me,
        api,
        config = {},
        docConfig = {},
        embedConfig = {},
        permissions = {},
        maxPages = 0,
        created = false,
        ttOffset = [0, -10];

    // Initialize analytics
    // -------------------------

//    Common.Analytics.initialize('UA-12442749-13', 'Embedded ONLYOFFICE Document');

    // Check browser
    // -------------------------

    if (typeof isBrowserSupported !== 'undefined' && !isBrowserSupported()){
        Common.Gateway.reportError(undefined, 'Your browser is not supported.');
        return;
    }

    // Utils
    // -------------------------

    function htmlEncode(value){
        return $('<div/>').text(value).html();
    }

    // Handlers
    // -------------------------

    function loadConfig(data) {
        config = $.extend(config, data.config);
        embedConfig = $.extend(embedConfig, data.config.embedded);

        common.controller.modals.init(embedConfig);

        // Docked toolbar
        if (embedConfig.toolbarDocked === 'top') {
            $('#toolbar').addClass('top');
            $('#editor_sdk').addClass('top');
        } else {
            $('#toolbar').addClass('bottom');
            $('#editor_sdk').addClass('bottom');
        }

        if (config.canBackToFolder === false || !(config.customization && config.customization.goback && config.customization.goback.url)) {
            $('#id-btn-close').hide();

            // Hide last separator
            $('#toolbar .right .separator').hide();
            $('#pages').css('margin-right', '12px');
        }
    }

    function loadDocument(data) {
        docConfig = data.doc;

        if (docConfig) {
            permissions = $.extend(permissions, docConfig.permissions);

            var docInfo = new Asc.asc_CDocInfo();
            docInfo.put_Id(docConfig.key);
            docInfo.put_Url(docConfig.url);
            docInfo.put_Title(docConfig.title);
            docInfo.put_Format(docConfig.fileType);
            docInfo.put_VKey(docConfig.vkey);

            if (api) {
                api.asc_registerCallback('asc_onGetEditorPermissions', onEditorPermissions);
                api.asc_setDocInfo(docInfo);
                api.asc_getEditorPermissions(config.licenseUrl, config.customerId);
                api.asc_enableKeyEvents(true);

                Common.Analytics.trackEvent('Load', 'Start');
            }

            if ( !embedConfig.saveUrl && permissions.print === false)
                $('#idt-copy').hide();
        }
    }

    function onCountPages(count) {
        maxPages = count;
        $('#pages').text('of ' + count);
    }

    function onCurrentPage(number) {
        $('#page-number').val(number + 1);
    }

    function onLongActionBegin(type, id) {
        var text = '';
        switch (id)
        {
            case Asc.c_oAscAsyncAction['Print']:
                text = 'Downloading document...';
                break;
            default:
                text = 'Please wait...';
                break;
        }

        if (type == Asc.c_oAscAsyncActionType['BlockInteraction']) {
            $('#id-loadmask .cmd-loader-title').html(text);
            showMask();
        }
    }

    function onLongActionEnd(){
        hideMask();
    }

    function onDocMouseMoveStart() {
        me.isHideBodyTip = true;
    }

    function onDocMouseMoveEnd() {
        if (me.isHideBodyTip) {
            if ( $tooltip ) {
                $tooltip.tooltip('hide');
                $tooltip = false;
            }
        }
    }

    var $ttEl, $tooltip;
    function onDocMouseMove(data) {
        if (data) {
            if (data.get_Type() == 1) { // hyperlink
                me.isHideBodyTip = false;

                if ( !$ttEl ) {
                    $ttEl = $('.hyperlink-tooltip');
                    $ttEl.tooltip({'container':'body', 'trigger':'manual'});
                    $ttEl.on('shown.bs.tooltip', function(e) {
                        $tooltip = $ttEl.data('bs.tooltip').tip();

                        $tooltip.css({
                            left: $ttEl.ttpos[0] + ttOffset[0],
                            top: $ttEl.ttpos[1] + ttOffset[1]
                        });

                        $tooltip.find('.tooltip-arrow').css({left: 10});
                    });
                }

                if ( !$tooltip ) {
                    $ttEl.ttpos = [data.get_X(), data.get_Y()];
                    $ttEl.tooltip('show');
                } else {
                    $tooltip.css({
                        left:data.get_X() + ttOffset[0],
                        top:data.get_Y() + ttOffset[1]
                    });
                }
            }
        }
    }

    function onDownloadUrl(url) {
        Common.Gateway.downloadAs(url);
    }

    function onPrint() {
        if ( permissions.print!==false )
            api.asc_Print($.browser.chrome || $.browser.safari || $.browser.opera);
    }

    function onPrintUrl(url) {
        common.utils.dialogPrint(url);
    }

    function hidePreloader() {
        $('#loading-mask').fadeOut('slow');
    }

    function onDocumentContentReady() {
        hidePreloader();

        if ( !embedConfig.shareUrl )
            $('#idt-share').hide();

        if ( !embedConfig.embedUrl )
            $('#idt-embed').hide();

        if ( !embedConfig.fullscreenUrl )
            $('#idt-fullscr').hide();

        common.controller.modals.attach({
            share: '#idt-share',
            embed: '#idt-embed'
        });

        api.asc_registerCallback('asc_onStartAction',           onLongActionBegin);
        api.asc_registerCallback('asc_onEndAction',             onLongActionEnd);
        api.asc_registerCallback('asc_onMouseMoveStart',        onDocMouseMoveStart);
        api.asc_registerCallback('asc_onMouseMoveEnd',          onDocMouseMoveEnd);
        api.asc_registerCallback('asc_onMouseMove',             onDocMouseMove);
        api.asc_registerCallback('asc_onHyperlinkClick',        common.utils.openLink);
        api.asc_registerCallback('asc_onDownloadUrl',           onDownloadUrl);
        api.asc_registerCallback('asc_onPrint',                 onPrint);
        api.asc_registerCallback('asc_onPrintUrl',              onPrintUrl);

        Common.Gateway.on('processmouse',       onProcessMouse);
        Common.Gateway.on('downloadas',         onDownloadAs);

        ApplicationView.tools.get('#idt-fullscreen')
            .on('click', function(){
                common.utils.openLink(embedConfig.fullscreenUrl);
            });

        ApplicationView.tools.get('#idt-download')
            .on('click', function(){
                    if ( !!embedConfig.saveUrl ){
                        common.utils.openLink(embedConfig.saveUrl);
                    } else
                    if (api && permissions.print!==false){
                        api.asc_Print($.browser.chrome || $.browser.safari || $.browser.opera);
                    }

                    Common.Analytics.trackEvent('Save');
            });

        $('#id-btn-close').on('click', function(){
            if (config.customization && config.customization.goback && config.customization.goback.url)
                window.parent.location.href = config.customization.goback.url;
        });

        $('#id-btn-zoom-in').on('click', api.zoomIn.bind(this));
        $('#id-btn-zoom-out').on('click', api.zoomOut.bind(this));

        var $pagenum = $('#page-number');
        $pagenum.on({
            'keyup': function(e){
                if ( e.keyCode == 13 ){
                    var newPage = parseInt($('#page-number').val());

                    if ( newPage > maxPages ) newPage = maxPages;
                    if (newPage < 2 || isNaN(newPage)) newPage = 1;

                    api.goToPage(newPage-1);
                    $pagenum.blur();
                }
            }
            , 'focusin' : function(e) {
                $pagenum.removeClass('masked');
            }
            , 'focusout': function(e){
                !$pagenum.hasClass('masked') && $pagenum.addClass('masked');
            }
        });

        $('#pages').on('click', function(e) {
            $pagenum.focus();
        });

        var documentMoveTimer;
        var ismoved = false;
        $(document).mousemove(function(event){
            $('#id-btn-zoom-in').fadeIn();
            $('#id-btn-zoom-out').fadeIn();

            ismoved = true;
            if ( !documentMoveTimer ) {
                documentMoveTimer = setInterval(function(){
                    if ( !ismoved ) {
                        $('#id-btn-zoom-in').fadeOut();
                        $('#id-btn-zoom-out').fadeOut();
                        clearInterval(documentMoveTimer);
                        documentMoveTimer = undefined;
                    }

                    ismoved = false;
                }, 2000);
            }
        });

        Common.Analytics.trackEvent('Load', 'Complete');
    }

    function onEditorPermissions(params) {
        if ( params.asc_getCanBranding() && (typeof config.customization == 'object') &&
             config.customization && config.customization.logo ) {

            var logo = $('#header-logo');
            if (config.customization.logo.imageEmbedded) {
                logo.html('<img src="'+config.customization.logo.imageEmbedded+'" style="max-width:124px; max-height:20px;"/>');
                logo.css({'background-image': 'none', width: 'auto', height: 'auto'});
            }

            if (config.customization.logo.url) {
                logo.attr('href', config.customization.logo.url);
            }
        }
        api.asc_setViewMode(true);
        api.asc_LoadDocument();
        api.Resize();
        api.zoomFitToWidth();
    }

    function showMask() {
        $('#id-loadmask').modal({
            backdrop: 'static',
            keyboard: false
        });
    }

    function hideMask() {
        $('#id-loadmask').modal('hide');
    }

    function onOpenDocument(progress) {
        var proc = (progress.asc_getCurrentFont() + progress.asc_getCurrentImage())/(progress.asc_getFontsCount() + progress.asc_getImagesCount());
        $('#loadmask-text').html('Loading document: ' + Math.min(Math.round(proc * 100), 100) + '%');
    }

    function onError(id, level, errData) {
        hidePreloader();

        var message;

        switch (id)
        {
            case Asc.c_oAscError.ID.Unknown:
                message = me.unknownErrorText;
                break;

            case Asc.c_oAscError.ID.ConvertationTimeout:
                message = me.convertationTimeoutText;
                break;

            case Asc.c_oAscError.ID.ConvertationError:
                message = me.convertationErrorText;
                break;

            case Asc.c_oAscError.ID.DownloadError:
                message = me.downloadErrorText;
                break;

            default:
                message = me.errorDefaultMessage.replace('%1', id);
                break;
        }

        if (level == Asc.c_oAscError.Level.Critical) {

            // report only critical errors
            Common.Gateway.reportError(id, message);

            $('#id-critical-error-title').text(me.criticalErrorTitle);
            $('#id-critical-error-message').text(message);
            $('#id-critical-error-close').off();
            $('#id-critical-error-close').on('click', function(){
                window.location.reload();
            });
        }
        else {
            $('#id-critical-error-title').text(me.notcriticalErrorTitle);
            $('#id-critical-error-message').text(message);
            $('#id-critical-error-close').off();
            $('#id-critical-error-close').on('click', function(){
                $('#id-critical-error-dialog').modal('hide');
            });
        }

        $('#id-critical-error-dialog').modal('show');

        Common.Analytics.trackEvent('Internal Error', id.toString());
    }

    function onExternalError(error) {
        if (error) {
            hidePreloader();
            $('#id-error-mask-title').text(error.title);
            $('#id-error-mask-text').text(error.msg);
            $('#id-error-mask').css('display', 'block');

            Common.Analytics.trackEvent('External Error', error.title);
        }
    }

    function onProcessMouse(data) {
        if (data.type == 'mouseup') {
            var e = document.getElementById('editor_sdk');
            if (e) {
                var r = e.getBoundingClientRect();
                api.OnMouseUp(
                    data.x - r.left,
                    data.y - r.top
                );
            }
        }
    }

    function onDownloadAs() {
        if (api) api.asc_DownloadAs(Asc.c_oAscFileType.DOCX, true);
    }

    // Helpers
    // -------------------------

    function onDocumentResize() {
        api && api.Resize();
    }

    function createController(){
        if (created)
            return me;

        me = this;
        created = true;

        $(window).resize(function(){
            onDocumentResize();
        });

        var ismodalshown = false;
        $(document.body).on('show.bs.modal', '.modal',
            function(e) {
                ismodalshown = true;
                api.asc_enableKeyEvents(false);
            }
        ).on('hidden.bs.modal', '.modal',
            function(e) {
                ismodalshown = false;
                api.asc_enableKeyEvents(true);
            }
        ).on('hidden.bs.dropdown', '.dropdown',
            function(e) {
                if ( !ismodalshown )
                    api.asc_enableKeyEvents(true);
            }
        ).on('blur', 'input, textarea',
            function(e) {
                if ( !ismodalshown ) {
                    if (!/area_id/.test(e.target.id) ) {
                        api.asc_enableKeyEvents(true);
                    }
                }
            }
        );

        $('#editor_sdk').on('click', function(e) {
            if ( e.target.localName == 'canvas' ) {
                e.currentTarget.focus();
            }
        });

        window["flat_desine"] = true;
        api = new Asc.asc_docs_api({
            'id-view'  : 'editor_sdk'
        });

        if (api){
            api.asc_registerCallback('asc_onError',                 onError);
            api.asc_registerCallback('asc_onDocumentContentReady',  onDocumentContentReady);
            api.asc_registerCallback('asc_onOpenDocumentProgress',  onOpenDocument);

            api.asc_registerCallback('asc_onCountPages',            onCountPages);
//            api.asc_registerCallback('OnCurrentVisiblePage',    onCurrentPage);
            api.asc_registerCallback('asc_onCurrentPage',           onCurrentPage);

            // Initialize api gateway
            Common.Gateway.on('init',               loadConfig);
            Common.Gateway.on('opendocument',       loadDocument);
            Common.Gateway.on('showerror',          onExternalError);
            Common.Gateway.ready();
        }

        return me;
    }

    return {
        create                  : createController,
        errorDefaultMessage     : 'Error code: %1',
        unknownErrorText        : 'Unknown error.',
        convertationTimeoutText : 'Convertation timeout exceeded.',
        convertationErrorText   : 'Convertation failed.',
        downloadErrorText       : 'Download failed.',
        criticalErrorTitle      : 'Error',
        notcriticalErrorTitle   : 'Warning'
    }
})();<|endoftext|>


<commit_before>'use strict';

angular.module('myApp.view2', ['ngRoute'])

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

.controller('View2Ctrl', ['$scope', '$interval', function($scope, $interval) {

    // Set to false if NOT debugging
    $scope.debug = true;

    $scope.e1Action = "text to show elevator 1 action"
    $scope.e2Action = "text to show elevator 2 action"

    var Elevator = function () {
	this.floor = 1.0;
	this.direction = 0;
	this.queue = [];
	this.waitTime = 0;
	this.waitingQue = [];
	this.inMotion = 0;
    };

    var el1 = new Elevator();
    var el2 = new Elevator();

	$scope.e1b1 = "btn btn-primary"
	$scope.e1b2 = "btn btn-primary"
	$scope.e1b3 = "btn btn-primary"
	$scope.e1b4 = "btn btn-primary"
	$scope.e2b1 = "btn btn-primary"
	$scope.e2b2 = "btn btn-primary"
	$scope.e2b3 = "btn btn-primary"
	$scope.e2b4 = "btn btn-primary"

		// TODO: Make elevators and calls into objects
		// inMotion : 0 = idle, 1 = up, -1 = down

		$scope.toggleButton = function (elevator, number, bool) {
			console.log("Toggle elevator " + elevator + " button " + number)
			switch (elevator) {
				case 1:
					switch (number) {
						case 1:
							if (bool) { $scope.e1b1 = "btn btn-primary" }
							else { $scope.e1b1 = "btn btn-danger" }
							break;
						case 2:
							if (bool) { $scope.e1b2 = "btn btn-primary" }
							else { $scope.e1b2 = "btn btn-danger" }
							break;
						case 3:
							if (bool) { $scope.e1b3 = "btn btn-primary" }
							else { $scope.e1b3 = "btn btn-danger" }
							break;
						case 4:
							if (bool) { $scope.e1b4 = "btn btn-primary" }
							else { $scope.e1b4 = "btn btn-danger" }
							break;
						default:
							alert("fucked up again")
							break;
					}
					break;
				case 2:
					switch (number) {
						case 1:
							if (bool) { $scope.e2b1 = "btn btn-primary" }
							else { $scope.e2b1 = "btn btn-danger" }
							break;
						case 2:
							if (bool) { $scope.e2b2 = "btn btn-primary" }
							else { $scope.e2b2 = "btn btn-danger" }
							break;
						case 3:
							if (bool) { $scope.e2b3 = "btn btn-primary" }
							else { $scope.e2b3 = "btn btn-danger" }
							break;
						case 4:
							if (bool) { $scope.e2b4 = "btn btn-primary" }
							else { $scope.e2b4 = "btn btn-danger" }
							break;
						default:
							alert("fucked up again")
							break;
					}
					break;
				default:
					alert("Fucked up")
					break;
			}
		}

		//NEED TO CREATE A CHECK FLOOR FUNCTION -> checks waiting que of elevator to see if deselect button
		var checkFloor = function(elevator){
			switch(elevator){
				case 1:
					el1.waitingQue.forEach(function(floor, index){
						if(floor === el1.floor){
							el1.waitingQue.splice(index, 1)
							$scope.toggleButton(1, floor, true);
						}
					})
				break;
				case 2:
					el2.waitingQue.forEach(function(floor, index){
						if(floor === el2.floor){
							el2.waitingQue.splice(index, 1)
							$scope.toggleButton(2, floor, true);
						}
					})
				break;
			}
		}

		// Just sets the inMotion field based on current floor and new one
		var motion = function(elevator, floor){
			switch(elevator){
				case 1:
					if(el1.floor < floor)
						el1.inMotion = 1;
					else el1.inMotion = -1;
				break;
				case 2:
					if(el2.floor < floor)
						el2.inMotion = 1;
					else el2.inMotion = -1;
				break;
			}
		}

		$scope.setDestination = function (elevator, button) {
			switch(elevator){
				case 1:
					switch(button){
						case 1:
							// Case 1: elevator 1 clicks on button one ->
							// First check if on floor already
							//	toggle button
							// then check if already in motion,
								// if yes, then just put on que
								// if no, then put on que and set inMotion

							if(el1.floor !== 1){
								$scope.toggleButton(1,1,false);
								if(el1.inMotion !== 0){
									el1.waitingQue.push(1)
								}else{
									motion(1,1);
									el1.waitingQue.push(1);
								}
							}

						break;
						case 2:
							if(el1.floor !== 2){
								$scope.toggleButton(1,2,false);
								if(el1.inMotion !== 0){
									el1.waitingQue.push(2)
								}else{
									motion(1,2);
									el1.waitingQue.push(2);
								}
							}
						break;
						case 3:
							if(el1.floor !== 3){
								$scope.toggleButton(1,3,false);
								if(el1.inMotion !== 0){
									el1.waitingQue.push(3)
								}else{
									motion(1,3);
									el1.waitingQue.push(3);
								}
							}
						break;
						case 4:
							if(el1.floor !== 4){
								$scope.toggleButton(1,4,false);
								if(el1.inMotion !== 0){
									el1.waitingQue.push(4)
								}else{
									motion(1,4);
									el1.waitingQue.push(4);
								}
							}
						break;

					}
				break;
				case 2:
					console.log("asd")
					switch(button){
						case 1:
							if(el2.floor !== 1){
								$scope.toggleButton(2,1,false);
								if(el2.inMotion !== 0){
									el2.waitingQue.push(1)
								}else{
									motion(2,1);
									el2.waitingQue.push(1);
								}
							}
						break;
						case 2:
							if(el2.floor !== 2){
								$scope.toggleButton(2,2,false);
								if(el2.inMotion !== 0){
									el2.waitingQue.push(2)
								}else{
									motion(2,2);
									el2.waitingQue.push(2);
								}
							}
						break;
						case 3:
							if(el2.floor !== 3){
								$scope.toggleButton(2,3,false);
								if(el2.inMotion !== 0){
									el2.waitingQue.push(3)
								}else{
									motion(2,3);
									el2.waitingQue.push(3);
								}
							}
						break;
						case 4:
							if(el2.floor !== 4){
								$scope.toggleButton(2,4,false);
								if(el2.inMotion !== 0){
									el2.waitingQue.push(4)
								}else{
									motion(2,4);
									el2.waitingQue.push(4);
								}
							}
						break;

					}
				break;
				default:
					alert("Wrong elevator")
				break;
			}
		}

    // Advances elevator closer to target if not waiting or idle
    var updateElevator = function (elevator) {
	if (elevator.waitTime > 0) {
	    elevator.waitTime -= 0.01;
	} else {
	    var lastIndex = elevator.queue.length-1;
	    if (Math.abs(elevator.floor - elevator.queue[lastIndex]) <= 0.0001) {
		elevator.floor = elevator.queue[lastIndex];
		elevator.queue.pop();
		elevator.waitTime = 1;
	    }

	    if (elevator.queue.length == 0) {
		elevator.direction = 0;
	    } else if (elevator.waitTime <= 0) {
		if (elevator.direction == 1) {
		    elevator.floor += 0.01;
		} else if (elevator.direction == -1) {
		    elevator.floor -= 0.01;
		}
	    }
	}

    };

    $interval(function() {
	updateElevator(el1);
    }, 100);

    $interval(function() {
	updateElevator(el2);
    }, 100);

    // Sets floor of elevator "closest" to call
    //    - "closest" determined by FS value
    this.answerCall = function(fl, dir) {

	        var getDirection = function(f, ef) {
		    if (ef > f) {
			return -1;
		    } else if (ef < f) {
			return 1;
		    } else {
			return 0;
		    }
		};

		var getFS = function(f, d, e) {
			var fs = 4 - Math.abs(e.floor - f);

			if ((e.direction == 1 && f < e.floor) ||
			    (e.direction == 0 && f > e.floor) ||
			    (e.direction != d) && (f == e.floor)) {
			    fs = 1;
			} else {
			    if (e.direction == d) {
				fs += 2;
			    } else {
				fs ++;
			    }
			}

		    return fs;
		};

		var fs1 = getFS(fl, dir, el1);
		var fs2 = getFS(fl, dir, el2);

		// For debugging
		//alert(fs1.toString() + " and " + fs2.toString());

		// Randomly choose if neither is "closer"
		if (fs1 == fs2) {
		    var rand = Math.random();
		    if (rand > .5) {
			fs1++;
		    } else {
			fs2++;
		    }
		}

	        // Adds call to elevator queue and adjusts direction
	        var registerElevator = function(elevator) {
	            var newDir = 0;
		    if (elevator.queue.length == 0) {
			newDir = getDirection(fl, elevator.floor);
		    } else {
			newDir = elevator.direction;
		    }
		    if (elevator.queue.indexOf(fl) == -1 && elevator.floor != fl) {
			elevator.queue.push(fl);
			elevator.queue.sort();
			if (newDir == 1) {
			    elevator.queue.reverse();
			}
		    }
		    elevator.direction = newDir;

		};

		// Choose elevator that is "closer"
		if (fs1 > fs2) {
		    registerElevator(el1);
		} else {
		    registerElevator(el2);
		}
    };

    this.getE1Queue = function() {
	return el1.queue;
    };

    this.getE2Queue = function() {
	return el2.queue;
    };

    this.isE1AtFloor = function (f) {
	checkFloor(1);
	return f == el1.floor;
    }

    this.isE2AtFloor = function (f) {
	checkFloor(2);
	return f == el2.floor;
    }

    this.getE1Direction = function () {
	checkFloor(1);
	return el1.direction;
    };

    this.getE2Direction = function () {
	checkFloor(2);
	return el2.direction;
    };

    this.getE1Floor = function () {
	checkFloor(1);
	return el1.floor;
    };

    this.getE2Floor = function () {
	checkFloor(2);
	return el2.floor;
    };

}]);

<commit_msg>hopefully stopped elevators going to positive/negative infinity<commit_after>'use strict';

angular.module('myApp.view2', ['ngRoute'])

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

.controller('View2Ctrl', ['$scope', '$interval', function($scope, $interval) {

    // Set to false if NOT debugging
    $scope.debug = true;

    $scope.e1Action = "text to show elevator 1 action"
    $scope.e2Action = "text to show elevator 2 action"

    var Elevator = function () {
	this.floor = 1.0;
	this.direction = 0;               // 1 = UP, 0 = IDLE, -1 = DOWN
	this.queue = [];                  // Holds button calls from FLOOR BUTTONS
	this.waitTime = 0;                // Should only be non-zero if stopped at floor for pick-up
	this.waitingQue = [];             // Holds button calls from ELEVATORS
	this.inMotion = 0;                // Probably redundant given direction
    };

    var el1 = new Elevator();
    var el2 = new Elevator();

	$scope.e1b1 = "btn btn-primary"
	$scope.e1b2 = "btn btn-primary"
	$scope.e1b3 = "btn btn-primary"
	$scope.e1b4 = "btn btn-primary"
	$scope.e2b1 = "btn btn-primary"
	$scope.e2b2 = "btn btn-primary"
	$scope.e2b3 = "btn btn-primary"
	$scope.e2b4 = "btn btn-primary"

		$scope.toggleButton = function (elevator, number, bool) {
			console.log("Toggle elevator " + elevator + " button " + number)
			switch (elevator) {
				case 1:
					switch (number) {
						case 1:
							if (bool) { $scope.e1b1 = "btn btn-primary" }
							else { $scope.e1b1 = "btn btn-danger" }
							break;
						case 2:
							if (bool) { $scope.e1b2 = "btn btn-primary" }
							else { $scope.e1b2 = "btn btn-danger" }
							break;
						case 3:
							if (bool) { $scope.e1b3 = "btn btn-primary" }
							else { $scope.e1b3 = "btn btn-danger" }
							break;
						case 4:
							if (bool) { $scope.e1b4 = "btn btn-primary" }
							else { $scope.e1b4 = "btn btn-danger" }
							break;
						default:
							alert("fucked up again")
							break;
					}
					break;
				case 2:
					switch (number) {
						case 1:
							if (bool) { $scope.e2b1 = "btn btn-primary" }
							else { $scope.e2b1 = "btn btn-danger" }
							break;
						case 2:
							if (bool) { $scope.e2b2 = "btn btn-primary" }
							else { $scope.e2b2 = "btn btn-danger" }
							break;
						case 3:
							if (bool) { $scope.e2b3 = "btn btn-primary" }
							else { $scope.e2b3 = "btn btn-danger" }
							break;
						case 4:
							if (bool) { $scope.e2b4 = "btn btn-primary" }
							else { $scope.e2b4 = "btn btn-danger" }
							break;
						default:
							alert("fucked up again")
							break;
					}
					break;
				default:
					alert("Fucked up")
					break;
			}
		}

		//NEED TO CREATE A CHECK FLOOR FUNCTION -> checks waiting que of elevator to see if deselect button
		var checkFloor = function(elevator){
			switch(elevator){
				case 1:
					el1.waitingQue.forEach(function(floor, index){
						if(floor === el1.floor){
							el1.waitingQue.splice(index, 1)
							$scope.toggleButton(1, floor, true);
						}
					})
				break;
				case 2:
					el2.waitingQue.forEach(function(floor, index){
						if(floor === el2.floor){
							el2.waitingQue.splice(index, 1)
							$scope.toggleButton(2, floor, true);
						}
					})
				break;
			}
		}

		// Just sets the inMotion field based on current floor and new one
		var motion = function(elevator, floor){
			switch(elevator){
				case 1:
					if(el1.floor < floor)
						el1.inMotion = 1;
					else el1.inMotion = -1;
				break;
				case 2:
					if(el2.floor < floor)
						el2.inMotion = 1;
					else el2.inMotion = -1;
				break;
			}
		}

		$scope.setDestination = function (elevator, button) {
			switch(elevator){
				case 1:
					switch(button){
						case 1:
							// Case 1: elevator 1 clicks on button one ->
							// First check if on floor already
							//	toggle button
							// then check if already in motion,
								// if yes, then just put on que
								// if no, then put on que and set inMotion

							if(el1.floor !== 1){
								$scope.toggleButton(1,1,false);
								if(el1.inMotion !== 0){
									el1.waitingQue.push(1)
								}else{
									motion(1,1);
									el1.waitingQue.push(1);
								}
							}

						break;
						case 2:
							if(el1.floor !== 2){
								$scope.toggleButton(1,2,false);
								if(el1.inMotion !== 0){
									el1.waitingQue.push(2)
								}else{
									motion(1,2);
									el1.waitingQue.push(2);
								}
							}
						break;
						case 3:
							if(el1.floor !== 3){
								$scope.toggleButton(1,3,false);
								if(el1.inMotion !== 0){
									el1.waitingQue.push(3)
								}else{
									motion(1,3);
									el1.waitingQue.push(3);
								}
							}
						break;
						case 4:
							if(el1.floor !== 4){
								$scope.toggleButton(1,4,false);
								if(el1.inMotion !== 0){
									el1.waitingQue.push(4)
								}else{
									motion(1,4);
									el1.waitingQue.push(4);
								}
							}
						break;

					}
				break;
				case 2:
					console.log("asd")
					switch(button){
						case 1:
							if(el2.floor !== 1){
								$scope.toggleButton(2,1,false);
								if(el2.inMotion !== 0){
									el2.waitingQue.push(1)
								}else{
									motion(2,1);
									el2.waitingQue.push(1);
								}
							}
						break;
						case 2:
							if(el2.floor !== 2){
								$scope.toggleButton(2,2,false);
								if(el2.inMotion !== 0){
									el2.waitingQue.push(2)
								}else{
									motion(2,2);
									el2.waitingQue.push(2);
								}
							}
						break;
						case 3:
							if(el2.floor !== 3){
								$scope.toggleButton(2,3,false);
								if(el2.inMotion !== 0){
									el2.waitingQue.push(3)
								}else{
									motion(2,3);
									el2.waitingQue.push(3);
								}
							}
						break;
						case 4:
							if(el2.floor !== 4){
								$scope.toggleButton(2,4,false);
								if(el2.inMotion !== 0){
									el2.waitingQue.push(4)
								}else{
									motion(2,4);
									el2.waitingQue.push(4);
								}
							}
						break;

					}
				break;
				default:
					alert("Wrong elevator")
				break;
			}
		}

    // Advances elevator closer to target if not waiting or idle
    var updateElevator = function (elevator) {
	if (elevator.waitTime > 0) {
	    elevator.waitTime -= 0.01;
	} else {
	    var lastIndex = elevator.queue.length-1;

	    elevator.queue.forEach(function (floor, index) {
		if (Math.abs(elevator.floor - floor) <= 0.0001) {
		    elevator.floor = floor;
		    elevator.queue.splice(index,1);
		    elevator.waitTime = 1;
		}
	    });

	    if (elevator.queue.length == 0) {
		elevator.direction = 0;
	    } else if (elevator.waitTime <= 0) {
		if ((elevator.floor == 4 && elevator.direction == 1) ||
		    (elevator.floor == 1 && elevator.direction == -1)) {
		    elevator.direction *= -1;
		}
		if (elevator.direction == 1) {
		    elevator.floor += 0.01;
		} else if (elevator.direction == -1) {
		    elevator.floor -= 0.01;
		}
	    }
	}

    };

    $interval(function() {
	updateElevator(el1);
    }, 100);

    $interval(function() {
	updateElevator(el2);
    }, 100);

    // Sets floor of elevator "closest" to call
    //    - "closest" determined by FS value
    this.answerCall = function(fl, dir) {

	        var getDirection = function(f, ef) {
		    if (ef > f) {
			return -1;
		    } else if (ef < f) {
			return 1;
		    } else {
			return 0;
		    }
		};

		var getFS = function(f, d, e) {
			var fs = 4 - Math.abs(e.floor - f);

			if ((e.direction == 1 && f < e.floor) ||
			    (e.direction == -1 && f > e.floor) ||
			    (e.direction != d) && (f == e.floor)) {
			    fs = 1;
			} else {
			    if (e.direction == d || e.direction == 0) {
				fs += 2;
			    } else {
				fs ++;
			    }
			}

		    return fs;
		};

		var fs1 = getFS(fl, dir, el1);
		var fs2 = getFS(fl, dir, el2);

		// For debugging
		//alert(fs1.toString() + " and " + fs2.toString());

		// Randomly choose if neither is "closer"
		if (fs1 == fs2) {
		    var rand = Math.random();
		    if (rand > .5) {
			fs1++;
		    } else {
			fs2++;
		    }
		}

	        // Adds call to elevator queue and adjusts direction
	        var registerElevator = function(elevator) {
	            var newDir = 0;
		    if (elevator.queue.length == 0) {
			newDir = getDirection(fl, elevator.floor);
		    } else {
			newDir = elevator.direction;
		    }
		    if (elevator.queue.indexOf(fl) == -1 && elevator.floor != fl) {
			elevator.queue.push(fl);
			elevator.queue.sort();
		    }
		    elevator.direction = newDir;

		};

		// Choose elevator that is "closer"
		if (fs1 > fs2) {
		    registerElevator(el1);
		} else {
		    registerElevator(el2);
		}
    };

    this.getE1Queue = function() {
	return el1.queue;
    };

    this.getE2Queue = function() {
	return el2.queue;
    };

    this.isE1AtFloor = function (f) {
	checkFloor(1);
	return f == el1.floor;
    }

    this.isE2AtFloor = function (f) {
	checkFloor(2);
	return f == el2.floor;
    }

    this.getE1Direction = function () {
	checkFloor(1);
	return el1.direction;
    };

    this.getE2Direction = function () {
	checkFloor(2);
	return el2.direction;
    };

    this.getE1Floor = function () {
	checkFloor(1);
	return el1.floor;
    };

    this.getE2Floor = function () {
	checkFloor(2);
	return el2.floor;
    };

}]);

<|endoftext|>


<commit_before>"use strict";

// Requires
var vscode = require("vscode");
var markdownlint = require("markdownlint");
var fs = require("fs");
var path = require("path");
var packageJson = require("./package.json");
var defaultConfig = require("./default-config.json");

// Constants
var extensionName = packageJson.name;
var markdownlintVersion = packageJson
	.dependencies
	.markdownlint
	.replace(/[^\d.]/, "");
var configFileName = ".markdownlint.json";
var markdownLanguageId = "markdown";
var markdownlintRulesMdPrefix = "https://github.com/DavidAnson/markdownlint/blob/v";
var markdownlintRulesMdPostfix = "/doc/Rules.md";
var codeActionPrefix = "Click for more information about ";
var badConfig = "Unable to read configuration file ";
var throttleDuration = 500;

// Variables
var diagnosticCollection = null;
var customConfig = null;
var throttle = {
	"document": null,
	"timeout": null
};

// Lints a Markdown document
function lint (document) {
	// Skip if not Markdown
	if (document.languageId !== markdownLanguageId) {
		return;
	}

	// Configure
	var options = {
		"strings": {
			"document": document.getText()
		},
		"config": customConfig || defaultConfig,
		"resultVersion": 1
	};
	var diagnostics = [];

	// Lint and create Diagnostics
	markdownlint
		.sync(options)
		.document
		.forEach(function forResult (result) {
			var ruleName = result.ruleName;
			var ruleDescription = result.ruleDescription;
			var message = ruleName + "/" + result.ruleAlias + ": " + ruleDescription;
			if (result.errorDetail) {
				message += " [" + result.errorDetail + "]";
			}
			var range = document.lineAt(result.lineNumber - 1).range;
			if (result.errorRange) {
				var start = result.errorRange[0] - 1;
				var end = start + result.errorRange[1];
				range = range.with(range.start.with(undefined, start), range.end.with(undefined, end));
			}
			var diagnostic = new vscode.Diagnostic(range, message, vscode.DiagnosticSeverity.Warning);
			diagnostic.code = markdownlintRulesMdPrefix + markdownlintVersion + markdownlintRulesMdPostfix +
				"#" + ruleName.toLowerCase() + "---" + ruleDescription.toLowerCase().replace(/ /g, "-");
			diagnostics.push(diagnostic);
		});

	// Publish
	diagnosticCollection.set(document.uri, diagnostics);
}

// Implements CodeActionsProvider.provideCodeActions to open info links for rules
function provideCodeActions (document, range, codeActionContext) {
	var diagnostics = codeActionContext.diagnostics || [];
	return diagnostics.map(function forDiagnostic (diagnostic) {
		return {
			"title": codeActionPrefix + diagnostic.message.substr(0, 5),
			"command": "vscode.open",
			"arguments": [ vscode.Uri.parse(diagnostic.code) ]
		};
	});
}

// Loads custom rule configuration
function loadCustomConfig () {
	var settings = vscode.workspace.getConfiguration(packageJson.displayName);
	customConfig = settings.get("config");

	var rootPath = vscode.workspace.rootPath;
	if (rootPath) {
		var configFilePath = path.join(rootPath, configFileName);
		if (fs.existsSync(configFilePath)) {
			try {
				customConfig = JSON.parse(fs.readFileSync(configFilePath, "utf8"));
			} catch (ex) {
				vscode.window.showWarningMessage(badConfig + "'" + configFilePath + "' (" + (ex.message || ex.toString()) + ")");
			}
		}
	}

	// Re-lint all open files
	(vscode.workspace.textDocuments || []).forEach(lint);
}

// Suppresses a pending lint for the specified document
function suppressLint (document) {
	if (throttle.timeout && (document === throttle.document)) {
		clearTimeout(throttle.timeout);
		throttle.document = null;
		throttle.timeout = null;
	}
}

// Requests a lint of the specified document
function requestLint (document) {
	suppressLint(document);
	throttle.document = document;
	throttle.timeout = setTimeout(function waitThrottleDuration () {
		// Do not use throttle.document in this function; it may have changed
		lint(document);
		suppressLint(document);
	}, throttleDuration);
}

// Handles the didChangeTextDocument event
function didChangeTextDocument (change) {
	requestLint(change.document);
}

// Handles the didCloseTextDocument event
function didCloseTextDocument (document) {
	suppressLint(document);
	diagnosticCollection.delete(document.uri);
}

function activate (context) {
	// Hook up to workspace events
	context.subscriptions.push(
		vscode.workspace.onDidOpenTextDocument(lint),
		vscode.workspace.onDidChangeTextDocument(didChangeTextDocument),
		vscode.workspace.onDidCloseTextDocument(didCloseTextDocument),
		vscode.workspace.onDidChangeConfiguration(loadCustomConfig));

	// Register CodeActionsProvider
	context.subscriptions.push(
		vscode.languages.registerCodeActionsProvider(markdownLanguageId, {
			"provideCodeActions": provideCodeActions
		}));

	// Create DiagnosticCollection
	diagnosticCollection = vscode.languages.createDiagnosticCollection(extensionName);
	context.subscriptions.push(diagnosticCollection);

	// Hook up to file system changes for custom config file
	var rootPath = vscode.workspace.rootPath;
	if (rootPath) {
		var fileSystemWatcher = vscode.workspace.createFileSystemWatcher(path.join(rootPath, configFileName));
		context.subscriptions.push(
			fileSystemWatcher,
			fileSystemWatcher.onDidCreate(loadCustomConfig),
			fileSystemWatcher.onDidChange(loadCustomConfig),
			fileSystemWatcher.onDidDelete(loadCustomConfig));
	}

	// Load custom rule config
	loadCustomConfig();
}

exports.activate = activate;
<commit_msg>Add info message when .markdownlint.json overrides configuration (fixes #8).<commit_after>"use strict";

// Requires
var vscode = require("vscode");
var markdownlint = require("markdownlint");
var fs = require("fs");
var path = require("path");
var packageJson = require("./package.json");
var defaultConfig = require("./default-config.json");

// Constants
var extensionName = packageJson.name;
var markdownlintVersion = packageJson
	.dependencies
	.markdownlint
	.replace(/[^\d.]/, "");
var configFileName = ".markdownlint.json";
var markdownLanguageId = "markdown";
var markdownlintRulesMdPrefix = "https://github.com/DavidAnson/markdownlint/blob/v";
var markdownlintRulesMdPostfix = "/doc/Rules.md";
var codeActionPrefix = "Click for more information about ";
var configOverride = "The '" + configFileName +
	"' file in this folder overrides any user/workspace configuration settings for the " +
	extensionName + " extension.";
var badConfig = "Unable to read configuration file ";
var throttleDuration = 500;

// Variables
var diagnosticCollection = null;
var customConfig = null;
var throttle = {
	"document": null,
	"timeout": null
};

// Lints a Markdown document
function lint (document) {
	// Skip if not Markdown
	if (document.languageId !== markdownLanguageId) {
		return;
	}

	// Configure
	var options = {
		"strings": {
			"document": document.getText()
		},
		"config": customConfig || defaultConfig,
		"resultVersion": 1
	};
	var diagnostics = [];

	// Lint and create Diagnostics
	markdownlint
		.sync(options)
		.document
		.forEach(function forResult (result) {
			var ruleName = result.ruleName;
			var ruleDescription = result.ruleDescription;
			var message = ruleName + "/" + result.ruleAlias + ": " + ruleDescription;
			if (result.errorDetail) {
				message += " [" + result.errorDetail + "]";
			}
			var range = document.lineAt(result.lineNumber - 1).range;
			if (result.errorRange) {
				var start = result.errorRange[0] - 1;
				var end = start + result.errorRange[1];
				range = range.with(range.start.with(undefined, start), range.end.with(undefined, end));
			}
			var diagnostic = new vscode.Diagnostic(range, message, vscode.DiagnosticSeverity.Warning);
			diagnostic.code = markdownlintRulesMdPrefix + markdownlintVersion + markdownlintRulesMdPostfix +
				"#" + ruleName.toLowerCase() + "---" + ruleDescription.toLowerCase().replace(/ /g, "-");
			diagnostics.push(diagnostic);
		});

	// Publish
	diagnosticCollection.set(document.uri, diagnostics);
}

// Implements CodeActionsProvider.provideCodeActions to open info links for rules
function provideCodeActions (document, range, codeActionContext) {
	var diagnostics = codeActionContext.diagnostics || [];
	return diagnostics.map(function forDiagnostic (diagnostic) {
		return {
			"title": codeActionPrefix + diagnostic.message.substr(0, 5),
			"command": "vscode.open",
			"arguments": [ vscode.Uri.parse(diagnostic.code) ]
		};
	});
}

// Loads custom rule configuration
function loadCustomConfig () {
	var settings = vscode.workspace.getConfiguration(packageJson.displayName);
	customConfig = settings.get("config");

	var rootPath = vscode.workspace.rootPath;
	if (rootPath) {
		var configFilePath = path.join(rootPath, configFileName);
		if (fs.existsSync(configFilePath)) {
			try {
				customConfig = JSON.parse(fs.readFileSync(configFilePath, "utf8"));
				vscode.window.showInformationMessage(configOverride);
			} catch (ex) {
				vscode.window.showWarningMessage(badConfig + "'" + configFilePath + "' (" + (ex.message || ex.toString()) + ")");
			}
		}
	}

	// Re-lint all open files
	(vscode.workspace.textDocuments || []).forEach(lint);
}

// Suppresses a pending lint for the specified document
function suppressLint (document) {
	if (throttle.timeout && (document === throttle.document)) {
		clearTimeout(throttle.timeout);
		throttle.document = null;
		throttle.timeout = null;
	}
}

// Requests a lint of the specified document
function requestLint (document) {
	suppressLint(document);
	throttle.document = document;
	throttle.timeout = setTimeout(function waitThrottleDuration () {
		// Do not use throttle.document in this function; it may have changed
		lint(document);
		suppressLint(document);
	}, throttleDuration);
}

// Handles the didChangeTextDocument event
function didChangeTextDocument (change) {
	requestLint(change.document);
}

// Handles the didCloseTextDocument event
function didCloseTextDocument (document) {
	suppressLint(document);
	diagnosticCollection.delete(document.uri);
}

function activate (context) {
	// Hook up to workspace events
	context.subscriptions.push(
		vscode.workspace.onDidOpenTextDocument(lint),
		vscode.workspace.onDidChangeTextDocument(didChangeTextDocument),
		vscode.workspace.onDidCloseTextDocument(didCloseTextDocument),
		vscode.workspace.onDidChangeConfiguration(loadCustomConfig));

	// Register CodeActionsProvider
	context.subscriptions.push(
		vscode.languages.registerCodeActionsProvider(markdownLanguageId, {
			"provideCodeActions": provideCodeActions
		}));

	// Create DiagnosticCollection
	diagnosticCollection = vscode.languages.createDiagnosticCollection(extensionName);
	context.subscriptions.push(diagnosticCollection);

	// Hook up to file system changes for custom config file
	var rootPath = vscode.workspace.rootPath;
	if (rootPath) {
		var fileSystemWatcher = vscode.workspace.createFileSystemWatcher(path.join(rootPath, configFileName));
		context.subscriptions.push(
			fileSystemWatcher,
			fileSystemWatcher.onDidCreate(loadCustomConfig),
			fileSystemWatcher.onDidChange(loadCustomConfig),
			fileSystemWatcher.onDidDelete(loadCustomConfig));
	}

	// Load custom rule config
	loadCustomConfig();
}

exports.activate = activate;
<|endoftext|>


<commit_before>/**
 * TXT export
 */

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

var async = require("async");
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
var padManager = require("../db/PadManager");
var ERR = require("async-stacktrace");
var Security = require('ep_etherpad-lite/static/js/security');
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
var getPadPlainText = require('./ExportHelper').getPadPlainText;
var _analyzeLine = require('./ExportHelper')._analyzeLine;
var _encodeWhitespace = require('./ExportHelper')._encodeWhitespace;

// This is slightly different than the HTML method as it passes the output to getTXTFromAText
function getPadTXT(pad, revNum, callback)
{
  var atext = pad.atext;
  var html;
  async.waterfall([
  // fetch revision atext

  function (callback)
  {
    if (revNum != undefined)
    {
      pad.getInternalRevisionAText(revNum, function (err, revisionAtext)
      {
        if(ERR(err, callback)) return;
        atext = revisionAtext;
        callback();
      });
    }
    else
    {
      callback(null);
    }
  },

  // convert atext to html

  function (callback)
  {
    html = getTXTFromAtext(pad, atext); // only this line is different to the HTML function
    callback(null);
  }],
  // run final callback

  function (err)
  {
    if(ERR(err, callback)) return;
    callback(null, html);
  });
}

exports.getPadTXT = getPadTXT;

// This is different than the functionality provided in ExportHtml as it provides formatting
// functionality that is designed specifically for TXT exports
function getTXTFromAtext(pad, atext, authorColors)
{
  var apool = pad.apool();
  var textLines = atext.text.slice(0, -1).split('\n');
  var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);

  var tags = ['h1', 'h2', 'strong', 'em', 'u', 's'];
  var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough'];
  var anumMap = {};
  var css = "";

  props.forEach(function (propName, i)
  {
    var propTrueNum = apool.putAttrib([propName, true], true);
    if (propTrueNum >= 0)
    {
      anumMap[propTrueNum] = i;
    }
  });

  function getLineTXT(text, attribs)
  {
    var propVals = [false, false, false];
    var ENTER = 1;
    var STAY = 2;
    var LEAVE = 0;

    // Use order of tags (b/i/u) as order of nesting, for simplicity
    // and decent nesting.  For example,
    // Just bold Bold and italics Just italics
    // becomes
    // Just bold Bold and italics Just italics
    var taker = Changeset.stringIterator(text);
    var assem = Changeset.stringAssembler();
    var openTags = [];

    var idx = 0;

    function processNextChars(numChars)
    {
      if (numChars <= 0)
      {
        return;
      }

      var iter = Changeset.opIterator(Changeset.subattribution(attribs, idx, idx + numChars));
      idx += numChars;

      while (iter.hasNext())
      {
        var o = iter.next();
        var propChanged = false;
        Changeset.eachAttribNumber(o.attribs, function (a)
        {
          if (a in anumMap)
          {
            var i = anumMap[a]; // i = 0 => bold, etc.
            if (!propVals[i])
            {
              propVals[i] = ENTER;
              propChanged = true;
            }
            else
            {
              propVals[i] = STAY;
            }
          }
        });
        for (var i = 0; i < propVals.length; i++)
        {
          if (propVals[i] === true)
          {
            propVals[i] = LEAVE;
            propChanged = true;
          }
          else if (propVals[i] === STAY)
          {
            propVals[i] = true; // set it back
          }
        }
        // now each member of propVal is in {false,LEAVE,ENTER,true}
        // according to what happens at start of span
        if (propChanged)
        {
          // leaving bold (e.g.) also leaves italics, etc.
          var left = false;
          for (var i = 0; i < propVals.length; i++)
          {
            var v = propVals[i];
            if (!left)
            {
              if (v === LEAVE)
              {
                left = true;
              }
            }
            else
            {
              if (v === true)
              {
                propVals[i] = STAY; // tag will be closed and re-opened
              }
            }
          }

          var tags2close = [];

          for (var i = propVals.length - 1; i >= 0; i--)
          {
            if (propVals[i] === LEAVE)
            {
              //emitCloseTag(i);
              tags2close.push(i);
              propVals[i] = false;
            }
            else if (propVals[i] === STAY)
            {
              //emitCloseTag(i);
              tags2close.push(i);
            }
          }

          for (var i = 0; i < propVals.length; i++)
          {
            if (propVals[i] === ENTER || propVals[i] === STAY)
            {
              propVals[i] = true;
            }
          }
          // propVals is now all {true,false} again
        } // end if (propChanged)

        var chars = o.chars;
        if (o.lines)
        {
          chars--; // exclude newline at end of line, if present
        }

        var s = taker.take(chars);

        // removes the characters with the code 12. Don't know where they come
        // from but they break the abiword parser and are completly useless
        // s = s.replace(String.fromCharCode(12), "");

        // remove * from s, it's just not needed on a blank line..  This stops
        // plugins from being able to display * at the beginning of a line
        // s = s.replace("*", ""); // Then remove it

        assem.append(_encodeWhitespace(s));
      } // end iteration over spans in line

      var tags2close = [];
      for (var i = propVals.length - 1; i >= 0; i--)
      {
        if (propVals[i])
        {
          tags2close.push(i);
          propVals[i] = false;
        }
      }

    } // end processNextChars
    processNextChars(text.length - idx);
    return(assem.toString());
  } // end getLineHTML
  var pieces = [css];

  // Need to deal with constraints imposed on HTML lists; can
  // only gain one level of nesting at once, can't change type
  // mid-list, etc.
  // People might use weird indenting, e.g. skip a level,
  // so we want to do something reasonable there.  We also
  // want to deal gracefully with blank lines.
  // => keeps track of the parents level of indentation
  var lists = []; // e.g. [[1,'bullet'], [3,'bullet'], ...]
  for (var i = 0; i < textLines.length; i++)
  {
    var line = _analyzeLine(textLines[i], attribLines[i], apool);
    var lineContent = getLineTXT(line.text, line.aline);
    if(line.listTypeName == "bullet"){
      lineContent = "* " + lineContent; // add a bullet
    }
    if(line.listLevel > 0){
      for (var j = line.listLevel - 1; j >= 0; j--){
        pieces.push('\t');
      }
      if(line.listTypeName == "number"){
        pieces.push(line.listLevel + ". ");
        // This is bad because it doesn't truly reflect what the user
        // sees because browsers do magic on nested

s
      }
      pieces.push(lineContent, '\n');
    }else{
      pieces.push(lineContent, '\n');
    }
  }

  return pieces.join('');
}
exports.getTXTFromAtext = getTXTFromAtext;

exports.getPadTXTDocument = function (padId, revNum, noDocType, callback)
{
  padManager.getPad(padId, function (err, pad)
  {
    if(ERR(err, callback)) return;

    getPadTXT(pad, revNum, function (err, html)
    {
      if(ERR(err, callback)) return;
      callback(null, html);
    });
  });
}

function _encodeWhitespace(s) {
  return s.replace(/[^\x21-\x7E\s\t\n\r]/g, function(c)
  {
    return "&#" +c.charCodeAt(0) + ";"
  });
}
<commit_msg>nice chars n no cruft<commit_after>/**
 * TXT export
 */

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

var async = require("async");
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
var padManager = require("../db/PadManager");
var ERR = require("async-stacktrace");
var Security = require('ep_etherpad-lite/static/js/security');
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
var getPadPlainText = require('./ExportHelper').getPadPlainText;
var _analyzeLine = require('./ExportHelper')._analyzeLine;

// This is slightly different than the HTML method as it passes the output to getTXTFromAText
function getPadTXT(pad, revNum, callback)
{
  var atext = pad.atext;
  var html;
  async.waterfall([
  // fetch revision atext

  function (callback)
  {
    if (revNum != undefined)
    {
      pad.getInternalRevisionAText(revNum, function (err, revisionAtext)
      {
        if(ERR(err, callback)) return;
        atext = revisionAtext;
        callback();
      });
    }
    else
    {
      callback(null);
    }
  },

  // convert atext to html

  function (callback)
  {
    html = getTXTFromAtext(pad, atext); // only this line is different to the HTML function
    callback(null);
  }],
  // run final callback

  function (err)
  {
    if(ERR(err, callback)) return;
    callback(null, html);
  });
}

exports.getPadTXT = getPadTXT;

// This is different than the functionality provided in ExportHtml as it provides formatting
// functionality that is designed specifically for TXT exports
function getTXTFromAtext(pad, atext, authorColors)
{
  var apool = pad.apool();
  var textLines = atext.text.slice(0, -1).split('\n');
  var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);

  var tags = ['h1', 'h2', 'strong', 'em', 'u', 's'];
  var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough'];
  var anumMap = {};
  var css = "";

  props.forEach(function (propName, i)
  {
    var propTrueNum = apool.putAttrib([propName, true], true);
    if (propTrueNum >= 0)
    {
      anumMap[propTrueNum] = i;
    }
  });

  function getLineTXT(text, attribs)
  {
    var propVals = [false, false, false];
    var ENTER = 1;
    var STAY = 2;
    var LEAVE = 0;

    // Use order of tags (b/i/u) as order of nesting, for simplicity
    // and decent nesting.  For example,
    // Just bold Bold and italics Just italics
    // becomes
    // Just bold Bold and italics Just italics
    var taker = Changeset.stringIterator(text);
    var assem = Changeset.stringAssembler();
    var openTags = [];

    var idx = 0;

    function processNextChars(numChars)
    {
      if (numChars <= 0)
      {
        return;
      }

      var iter = Changeset.opIterator(Changeset.subattribution(attribs, idx, idx + numChars));
      idx += numChars;

      while (iter.hasNext())
      {
        var o = iter.next();
        var propChanged = false;
        Changeset.eachAttribNumber(o.attribs, function (a)
        {
          if (a in anumMap)
          {
            var i = anumMap[a]; // i = 0 => bold, etc.
            if (!propVals[i])
            {
              propVals[i] = ENTER;
              propChanged = true;
            }
            else
            {
              propVals[i] = STAY;
            }
          }
        });
        for (var i = 0; i < propVals.length; i++)
        {
          if (propVals[i] === true)
          {
            propVals[i] = LEAVE;
            propChanged = true;
          }
          else if (propVals[i] === STAY)
          {
            propVals[i] = true; // set it back
          }
        }
        // now each member of propVal is in {false,LEAVE,ENTER,true}
        // according to what happens at start of span
        if (propChanged)
        {
          // leaving bold (e.g.) also leaves italics, etc.
          var left = false;
          for (var i = 0; i < propVals.length; i++)
          {
            var v = propVals[i];
            if (!left)
            {
              if (v === LEAVE)
              {
                left = true;
              }
            }
            else
            {
              if (v === true)
              {
                propVals[i] = STAY; // tag will be closed and re-opened
              }
            }
          }

          var tags2close = [];

          for (var i = propVals.length - 1; i >= 0; i--)
          {
            if (propVals[i] === LEAVE)
            {
              //emitCloseTag(i);
              tags2close.push(i);
              propVals[i] = false;
            }
            else if (propVals[i] === STAY)
            {
              //emitCloseTag(i);
              tags2close.push(i);
            }
          }

          for (var i = 0; i < propVals.length; i++)
          {
            if (propVals[i] === ENTER || propVals[i] === STAY)
            {
              propVals[i] = true;
            }
          }
          // propVals is now all {true,false} again
        } // end if (propChanged)

        var chars = o.chars;
        if (o.lines)
        {
          chars--; // exclude newline at end of line, if present
        }

        var s = taker.take(chars);

        // removes the characters with the code 12. Don't know where they come
        // from but they break the abiword parser and are completly useless
        // s = s.replace(String.fromCharCode(12), "");

        // remove * from s, it's just not needed on a blank line..  This stops
        // plugins from being able to display * at the beginning of a line
        // s = s.replace("*", ""); // Then remove it

        assem.append(s);
      } // end iteration over spans in line

      var tags2close = [];
      for (var i = propVals.length - 1; i >= 0; i--)
      {
        if (propVals[i])
        {
          tags2close.push(i);
          propVals[i] = false;
        }
      }

    } // end processNextChars
    processNextChars(text.length - idx);
    return(assem.toString());
  } // end getLineHTML
  var pieces = [css];

  // Need to deal with constraints imposed on HTML lists; can
  // only gain one level of nesting at once, can't change type
  // mid-list, etc.
  // People might use weird indenting, e.g. skip a level,
  // so we want to do something reasonable there.  We also
  // want to deal gracefully with blank lines.
  // => keeps track of the parents level of indentation
  var lists = []; // e.g. [[1,'bullet'], [3,'bullet'], ...]
  for (var i = 0; i < textLines.length; i++)
  {
    var line = _analyzeLine(textLines[i], attribLines[i], apool);
    var lineContent = getLineTXT(line.text, line.aline);
    if(line.listTypeName == "bullet"){
      lineContent = "* " + lineContent; // add a bullet
    }
    if(line.listLevel > 0){
      for (var j = line.listLevel - 1; j >= 0; j--){
        pieces.push('\t');
      }
      if(line.listTypeName == "number"){
        pieces.push(line.listLevel + ". ");
        // This is bad because it doesn't truly reflect what the user
        // sees because browsers do magic on nested

s
      }
      pieces.push(lineContent, '\n');
    }else{
      pieces.push(lineContent, '\n');
    }
  }

  return pieces.join('');
}
exports.getTXTFromAtext = getTXTFromAtext;

exports.getPadTXTDocument = function (padId, revNum, noDocType, callback)
{
  padManager.getPad(padId, function (err, pad)
  {
    if(ERR(err, callback)) return;

    getPadTXT(pad, revNum, function (err, html)
    {
      if(ERR(err, callback)) return;
      callback(null, html);
    });
  });
}

<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { googleAnalyticsId } from '../../config';

class Html extends Component {

	static propTypes = {
		title: PropTypes.string,
		description: PropTypes.string,
		css: PropTypes.string,
		body: PropTypes.string.isRequired,
		entry: PropTypes.string.isRequired,
	};

	static defaultProps = {
		title: '',
		description: '',
	};

	trackingCode() {
		return ({ __html:
		`(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=` +
			`function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;` +
			`e=o.createElement(i);r=o.getElementsByTagName(i)[0];` +
			`e.src='https://www.google-analytics.com/analytics.js';` +
			`r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));` +
			`ga('create','${googleAnalyticsId}','auto');ga('send','pageview');`,
		});
	}

	typekit() {
		return ({ __html:
			`(function() {` +
			`var config = {` +
			`	kitId: 'zgp0frb'` +
			`};` +
			`var d = false;` +
			`var tk = document.createElement('script');` +
			`tk.src = '//use.typekit.net/' + config.kitId + '.js';` +
			`tk.type = 'text/javascript';` +
			`tk.async = 'true';` +
			`tk.onload = tk.onreadystatechange = function() {` +
				`	var rs = this.readyState;` +
				`	if (d || rs && rs !== 'complete' && rs !== 'loaded') {` +
				`		return;` +
				`	}` +
				`	d = true;` +
				`	try {` +
					`		Typekit.load(config);` +
					`	} catch (e) {}` +
					`};` +
					`var s = document.getElementsByTagName('script')[0];` +
					`s.parentNode.insertBefore(tk, s);` +
					`})();`,
		});
	}

	render() {
		return (

					<meta charSet="utf-8" />
					<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
					<title>ARIES Automotive | {this.props.title}</title>
					<meta name="description" content={this.props.description} />
					<meta name="google-site-verification" content="2YAIw2si-iBLQTUFUuNXfq8u5uoXzTysfiBTsFntY00" />
					<meta name="keywords" ng-bind="pageKywds" content="" />
					<meta name="viewport" content="width=device-width, initial-scale=.9" />

					{/* For iPad with high-resolution Retina display running iOS ≥ 7: */}
					<link rel="apple-touch-icon-precomposed" sizes="152x152" href="/path/to/favicon-152.png?v=2" />

					{/* For iPad with high-resolution Retina display running iOS ≤ 6 */}
					<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/assets/img/ico/apple-touch-icon-144x144-precompressed.png?v=2" />
					<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/assets/img/ico/apple-icon-144x144.png?v=2" />

					{/* For iPhone with high-resolution Retina display running iOS ≥ 7 */}
					<link rel="apple-touch-icon-precomposed" sizes="120x120" href="/path/to/favicon-120.png?v=2" />

					{/* For iPhone with high-resolution Retina display running iOS ≤ 6 */}
					<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/assets/img/ico/apple-touch-icon-114x114-precompressed.png?v=2" />
					<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/assets/img/ico/apple-icon-114x114.png?v=2" />

					{/* For first- and second-generation iPad */}
					<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/assets/img/ico/apple-touch-icon-72x72-precompressed.png?v=2" />
					<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/assets/img/ico/apple-icon-72x72.png?v=2" />

					{/* For non-Retina iPhone, iPod Touch, and Android 2.1+ devices */}
					<link rel="apple-touch-icon-precomposed" href="/assets/img/ico/apple-touch-icon-57x57-precompressed.png?v=2" />
					<link rel="apple-touch-icon-precomposed" href="/assets/img/ico/apple-icon-57x57.png?v=2" />
					<link rel="icon" href="https://storage.googleapis.com/aries-website/favicons/favicon-32x32.png" sizes="32x32" />
					<meta name="msapplication-TileColor" content="#FFFFFF" />
					<meta name="msapplication-TileImage" content="/assets/img/ico/apple-touch-icon-144x144-precompressed.png?v=2" />

					<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />


<commit_before>'use babel'

import { client } from '../connection'
import tcp from '../connection/process/tcp'
import { CompositeDisposable } from 'atom'
import { paths } from '../misc'
import modules from './modules'
import * as pty from 'node-pty-prebuilt'
import { debounce, once } from 'underscore-plus'

var { changemodule, resetprompt, validatepath, fullpath } = client.import({msg: ['changemodule', 'resetprompt'], rpc: ['validatepath', 'fullpath']})

let uriRegex
if (process.platform == 'win32') {
  uriRegex = /((([a-zA-Z]:|\.\.?|\~)|([^\0<>\?\|\/\s!$`&*()\[\]+'":;])+)?((\\|\/)([^\0<>\?\|\/\s!$`&*()\[\]+'":;])+)+)(\:\d+)?/
} else {
  uriRegex = /(((\.\.?|\~)|([^\0\s!$`&*()\[\]+'":;\\])+)?(\/([^\0\s!$`&*()\[\]+'":;\\])+)+)(\:\d+)?/
}

export var terminal

export function activate (ink) {
  if (atom.config.get('julia-client.juliaOptions.consoleStyle') != 'REPL-based') return

  let subs = new CompositeDisposable()

  terminal = ink.InkTerminal.fromId('julia-terminal', {scrollback: atom.config.get('julia-client.maximumConsoleSize')})

  terminal.getTitle = () => {return 'REPL'}
  terminal.class = 'julia-terminal'

  terminal.write('\x1b[1m\x1b[32mPress Enter to start Julia.\x1b[0m\n\r')
  terminal.startRequested = () => client.boot()

  modules.onDidChange(debounce(() => changemodule({mod: modules.current(), cols: terminal.terminal.cols}), 200))

  let linkHandler

  client.onBoot((proc) => {
    terminal.attach(proc.ty)

    if (proc.flush) {
      proc.flush((d) => terminal.write(d), (d) => terminal.write(d))
    }

    linkHandler = (event, uri) => {
      let m = uri.match(/(.+)(?:\:(\d+))$/)
      fullpath(m[1]).then((path) => ink.Opener.open(path, parseInt(m[2]) - 1, {pending: true}))
    }

    let validator = (uri, cb) => {
      validatepath(uri).then((isvalid) => {
        cb(isvalid)
      })
    }
    if (process.platform != 'darwin') {
      terminal.attachCustomKeyEventHandler((e) => {
        // don't pass Ctrl-(Shift)-C/V/J/K to terminal so Atom can handle
        // interrupts/copying/pasting/julia-mode commands
        if (e.ctrlKey && (e.keyCode == 67 || e.keyCode == 86 || e.keyCode == 74 || e.keyCode == 75)) {
          return false
        }
        return e
      })
    } else {
      terminal.attachCustomKeyEventHandler((e) => {
        // don't pass ctrl-c to terminal
        if (e.ctrlKey && e.keyCode == 67) {
          return false
        }
        return e
      })
    }
    // doesn't handle multiline URIs properly due to upstream bug (xterm.js#24)
    terminal.terminal.registerLinkMatcher(uriRegex, linkHandler, {validationCallback: validator})

    client.onDetached(() => {
      client.ipc.loading.reset()
      terminal.detach()
      terminal.write('\x1b[1m\r\x1b[31mJulia has exited.\x1b[0m Press Enter to start a new session.\n\r')
      terminal.terminal.deregisterLinkMatcher(linkHandler)
    })
  })

  client.handle({
    updateWorkspace: () => require('./workspace').update(),
    clearconsole: () => terminal.clear()
  })

  subs.add(atom.commands.add('atom-workspace', 'julia-client:open-console', () => {
    terminal.open().then(() => terminal.show())
  }))

  subs.add(atom.commands.add('atom-workspace', 'julia-client:clear-console', () => {
    terminal.clear()
  }))

  subs.add(atom.commands.add('.julia-terminal', 'julia-client:copy-or-interrupt', () => {
    if (!terminal.copySelection()) {
      atom.commands.dispatch(terminal.view, 'julia-client:interrupt-julia')
    }
  }))

  subs.add(atom.commands.add('atom-workspace', 'julia-client:new-terminal', () => {
    let term = ink.InkTerminal.fromId(`terminal-julia-${Math.floor(Math.random()*10000000)}`, {scrollback: atom.config.get('julia-client.maximumConsoleSize')})
    shellPty().then((pty) => term.attach(pty, true))
    term.open().then(() => term.show())
  }))

  // handle deserialized terminals
  atom.workspace.getPaneItems().forEach((item) => {
    if (item.id && item.name === 'InkTerminal' && item.id.match(/terminal\-julia\-\d+/)) {
      if (!item.ty) {
        shellPty().then((pty) => item.attach(pty, true))
      }
    }
  })
}

function shellPty () {
  return new Promise((resolve) => paths.projectDir().then((cwd) => {
    resolve(pty.fork(atom.config.get("julia-client.shell"), [], {
      cols: 100,
      rows: 30,
      cwd: cwd
    }))
  }))
}

export function deactivate () {
  if (subs) subs.dispose()
}
<commit_msg>don't print multiple "Julia has exited" messages<commit_after>'use babel'

import { client } from '../connection'
import tcp from '../connection/process/tcp'
import { CompositeDisposable } from 'atom'
import { paths } from '../misc'
import modules from './modules'
import * as pty from 'node-pty-prebuilt'
import { debounce, once } from 'underscore-plus'

var { changemodule, resetprompt, validatepath, fullpath } = client.import({msg: ['changemodule', 'resetprompt'], rpc: ['validatepath', 'fullpath']})

let uriRegex
if (process.platform == 'win32') {
  uriRegex = /((([a-zA-Z]:|\.\.?|\~)|([^\0<>\?\|\/\s!$`&*()\[\]+'":;])+)?((\\|\/)([^\0<>\?\|\/\s!$`&*()\[\]+'":;])+)+)(\:\d+)?/
} else {
  uriRegex = /(((\.\.?|\~)|([^\0\s!$`&*()\[\]+'":;\\])+)?(\/([^\0\s!$`&*()\[\]+'":;\\])+)+)(\:\d+)?/
}

export var terminal

export function activate (ink) {
  if (atom.config.get('julia-client.juliaOptions.consoleStyle') != 'REPL-based') return

  let subs = new CompositeDisposable()

  terminal = ink.InkTerminal.fromId('julia-terminal', {scrollback: atom.config.get('julia-client.maximumConsoleSize')})

  terminal.getTitle = () => {return 'REPL'}
  terminal.class = 'julia-terminal'

  terminal.write('\x1b[1m\x1b[32mPress Enter to start Julia.\x1b[0m\n\r')
  terminal.startRequested = () => client.boot()

  modules.onDidChange(debounce(() => changemodule({mod: modules.current(), cols: terminal.terminal.cols}), 200))

  let linkHandler

  client.onBoot((proc) => {
    terminal.attach(proc.ty)

    if (proc.flush) {
      proc.flush((d) => terminal.write(d), (d) => terminal.write(d))
    }

    linkHandler = (event, uri) => {
      let m = uri.match(/(.+)(?:\:(\d+))$/)
      fullpath(m[1]).then((path) => ink.Opener.open(path, parseInt(m[2]) - 1, {pending: true}))
    }

    let validator = (uri, cb) => {
      validatepath(uri).then((isvalid) => {
        cb(isvalid)
      })
    }
    if (process.platform != 'darwin') {
      terminal.attachCustomKeyEventHandler((e) => {
        // don't pass Ctrl-(Shift)-C/V/J/K to terminal so Atom can handle
        // interrupts/copying/pasting/julia-mode commands
        if (e.ctrlKey && (e.keyCode == 67 || e.keyCode == 86 || e.keyCode == 74 || e.keyCode == 75)) {
          return false
        }
        return e
      })
    } else {
      terminal.attachCustomKeyEventHandler((e) => {
        // don't pass ctrl-c to terminal
        if (e.ctrlKey && e.keyCode == 67) {
          return false
        }
        return e
      })
    }
    // doesn't handle multiline URIs properly due to upstream bug (xterm.js#24)
    terminal.terminal.registerLinkMatcher(uriRegex, linkHandler, {validationCallback: validator})

  })

  client.onDetached(() => {
    client.ipc.loading.reset()
    terminal.detach()
    terminal.write('\x1b[1m\r\x1b[31mJulia has exited.\x1b[0m Press Enter to start a new session.\n\r')
    terminal.terminal.deregisterLinkMatcher(linkHandler)
  })

  client.handle({
    updateWorkspace: () => require('./workspace').update(),
    clearconsole: () => terminal.clear()
  })

  subs.add(atom.commands.add('atom-workspace', 'julia-client:open-console', () => {
    terminal.open().then(() => terminal.show())
  }))

  subs.add(atom.commands.add('atom-workspace', 'julia-client:clear-console', () => {
    terminal.clear()
  }))

  subs.add(atom.commands.add('.julia-terminal', 'julia-client:copy-or-interrupt', () => {
    if (!terminal.copySelection()) {
      atom.commands.dispatch(terminal.view, 'julia-client:interrupt-julia')
    }
  }))

  subs.add(atom.commands.add('atom-workspace', 'julia-client:new-terminal', () => {
    let term = ink.InkTerminal.fromId(`terminal-julia-${Math.floor(Math.random()*10000000)}`, {scrollback: atom.config.get('julia-client.maximumConsoleSize')})
    shellPty().then((pty) => term.attach(pty, true))
    term.open().then(() => term.show())
  }))

  // handle deserialized terminals
  atom.workspace.getPaneItems().forEach((item) => {
    if (item.id && item.name === 'InkTerminal' && item.id.match(/terminal\-julia\-\d+/)) {
      if (!item.ty) {
        shellPty().then((pty) => item.attach(pty, true))
      }
    }
  })
}

function shellPty () {
  return new Promise((resolve) => paths.projectDir().then((cwd) => {
    resolve(pty.fork(atom.config.get("julia-client.shell"), [], {
      cols: 100,
      rows: 30,
      cwd: cwd
    }))
  }))
}

export function deactivate () {
  if (subs) subs.dispose()
}
<|endoftext|>