text:
/*global define,require*/
/*jslint white: true*/
// leave at least 2 line with only a star on it below, or doc generation fails
/**
 *
 *
 * Placeholder for custom user javascript
 * mainly to be overridden in profile/static/custom/custom.js
 * This will always be an empty file in Jupyter
 *
 * User could add any javascript in the `profile/static/custom/custom.js` file.
 * It will be executed by the Jupyter notebook at load time.
 *
 * Same thing with `profile/static/custom/custom.css` to inject custom css into the notebook.
 *
 *
 * The object available at load time depend on the version of Jupyter in use.
 * there is no guaranties of API stability.
 *
 * The example below explain the principle, and might not be valid.
 *
 * Instances are created after the loading of this file and might need to be accessed using events:
 *     define (
 [
 'kbwidget',
 'bootstrap',
 '*        base/js/namespace',
 '*        base/js/events
 *'
 ], function(
 KBWidget,
 bootstrap,
 Jupyter,
 events
 ) {
 *         events.on("app_initialized.NotebookApp", function () {
 *             Jupyter.keyboard_manager....
 *         });
 *     });
 *
 * __Example 1:__
 *
 * Create a custom button in toolbar that execute `%qtconsole` in kernel
 * and hence open a qtconsole attached to the same kernel as the current notebook
 *
 *    define([
 *        'base/js/namespace',
 *        'base/js/events'
 *    ], function(Jupyter, events) {
 *        events.on('app_initialized.NotebookApp', function(){
 *            Jupyter.toolbar.add_buttons_group([
 *                {
 *                    'label'   : 'run qtconsole',
 *                    'icon'    : 'icon-terminal', // select your icon from http://fortawesome.github.io/Font-Awesome/icons
 *                    'callback': function () {
 *                        Jupyter.notebook.kernel.execute('%qtconsole')
 *                    }
 *                }
 *                // add more button here if needed.
 *                ]);
 *        });
 *    });
 *
 * __Example 2:__
 *
 * At the completion of the dashboard loading, load an unofficial javascript extension
 * that is installed in profile/static/custom/
 *
 *    define([
 *        'base/js/events'
 *    ], function(events) {
 *        events.on('app_initialized.DashboardApp', function(){
 *            require(['custom/unofficial_extension.js'])
 *        });
 *    });
 *
 * __Example 3:__
 *
 *  Use `jQuery.getScript(url [, success(script, textStatus, jqXHR)] );`
 *  to load custom script into the notebook.
 *
 *    // to load the metadata ui extension example.
 *    $.getScript('/static/notebook/js/celltoolbarpresets/example.js');
 *    // or
 *    // to load the metadata ui extension to control slideshow mode / reveal js for nbconvert
 *    $.getScript('/static/notebook/js/celltoolbarpresets/slideshow.js');
 *
 *
 * @module Jupyter
 * @namespace Jupyter
 * @class customjs
 * @static
 */
define([
    'jquery',
    'base/js/namespace',
    'kbaseNarrative',
    'base/js/security',
    'base/js/utils',
    'base/js/page',
    'notebook/js/codecell',
    'notebook/js/notebook',
    'notebook/js/textcell',
    'notebook/js/savewidget',
    'notebook/js/celltoolbar',
    'base/js/dialog',
    'base/js/keyboard',
    'notebook/js/keyboardmanager',
    'notebook/js/cell',
    'common/utils',
    'common/jupyter',
    'kb_common/html',
    'narrativeConfig',

    'components/requirejs/require',
    'narrative_paths'
], function (
    $,
    Jupyter,
    Narrative,
    security,
    nbUtils,
    page,
    codeCell,
    notebook,
    textCell,
    saveWidget,
    cellToolbar,
    dialog,
    keyboard,
    keyboardManager,
    cell,
    utils,
    NarrativeRuntime,
    html,
    narrativeConfig
) {
    'use strict';

    var t = html.tag,
        span = t('span');

    // GLOBAL EVENTS AND OVERRIDES

    // inject necessary environment vars into the kernel as soon as it's ready.
    $([Jupyter.events]).on('kernel_ready.Kernel', function () {
        Jupyter.notebook.kernel.execute(
            'import os;' +
            'os.environ["KB_AUTH_TOKEN"]="' + Jupyter.narrative.authToken + '";' +
            'os.environ["KB_WORKSPACE_ID"]="' + Jupyter.notebook.metadata.ws_name + '"'
        );
    });

    // Kickstart the Narrative loading routine once the notebook is loaded.
    $([Jupyter.events]).on('app_initialized.NotebookApp', function () {
        require(['kbaseNarrative'], function (Narrative) {

            Jupyter.narrative = new Narrative();
            Jupyter.narrative.init();

            /*
             * Override the move-cursor-down-or-next-cell and
             * move-cursor-up-or-previous-cell actions.
             *
             * When editing a textcell (markdown or code), if a user uses
             * the arrow keys to move to another cell, it normally lands
             * there in edit mode.
             *
             * This is bad for KBase-ified markdown cells, since it shows
             * the div and script tags that are used to render them, and
             * screws up the state management. These overrides just
             * check if the next cell is a KBase cell, and doesn't enable
             * edit mode if so.
             */
            Jupyter.keyboard_manager.actions.register({
                    handler: function (env, event) {
                        var index = env.notebook.get_selected_index();
                        var cell = env.notebook.get_cell(index);
                        if (cell.at_bottom() && index !== (env.notebook.ncells() - 1)) {
                            if (event) {
                                event.preventDefault();
                            }
                            env.notebook.command_mode();
                            env.notebook.select_next(true);
                            if (!env.notebook.get_selected_cell().metadata['kb-cell']) {
                                env.notebook.edit_mode();
                                var cm = env.notebook.get_selected_cell().code_mirror;
                                cm.setCursor(0, 0);
                            }
                        }
                        return false;
                    }
                },
                'move-cursor-down',
                'jupyter-notebook');

            Jupyter.keyboard_manager.actions.register({
                    handler: function (env, event) {
                        var index = env.notebook.get_selected_index(),
                            cell = env.notebook.get_cell(index),
                            cm = env.notebook.get_selected_cell().code_mirror,
                            cur = cm.getCursor();
                        if (cell && cell.at_top() && index !== 0 && cur.ch === 0) {
                            if (event) {
                                event.preventDefault();
                            }
                            env.notebook.command_mode();
                            env.notebook.select_prev(true);
                            if (!env.notebook.get_selected_cell().metadata['kb-cell']) {
                                env.notebook.edit_mode();
                                cm = env.notebook.get_selected_cell().code_mirror;
                                cm.setCursor(cm.lastLine(), 0);
                            }
                        }
                        return false;
                    }
                },
                'move-cursor-up',
                'jupyter-notebook');
        });
    });

    /*
     * We override this method because jupyter uses .height() rather than
     * css('height'). In the former just the internal height is returned,
     * although later versions of jquery (should be the one we are using,
     * but it didn't appear to be so) should have fixed this behavior when
     * box-sizing: border-box is used. I tried that, but it didn't seem to
     * work. Using css('height'), however, works.
     * This bug was manifested in a permanent scrollbar for the main content
     * area, since its size was set too tall.
     */
    page.Page.prototype._resize_site = function () {
        // Update the site's size.
        $('div#site').height($(window).height() - $('#header').css('height'));
    };

    // Patch the security mechanisms to allow any JavaScript to run for now.
    // TODO: update this so only the few KBase commands run.
    security.sanitize_html = function (html, allow_css) {
        return html;
    };
    security.sanitize_css = function (css, tagPolicy) {
        return css;
    };
    security.sanitize_stylesheets = function (html, tagPolicy) {
        return html;
    };

    // TODO: refactor
    function cellType(cell) {
        // Cells are (currently) rendered twice. The first time the kb metadata
        // is not available, but we can rely on future renders.
        if (cell.renderCount > 1) {
            return;
        }

        var type = cell.metadata &&
            cell.metadata['kb-cell'] &&
            cell.metadata['kb-cell']['type'];

        // Markdown cells don't of course have a kb cell type.
        if (type === undefined) {
            return;
        }

        switch (type) {
        case 'function_input':
            return 'method';
        case 'kb_app':
            return 'app';
        case 'function_output':
            return 'output';
        default:
            return 'unknown';
        }

    }

    // CELLTOOLBAR

    // disable hiding of the toolbar
    cellToolbar.CellToolbar.prototype.hide = function () {
        return;
    };

    // CELL

    (function () {
        var p = cell.Cell.prototype;

        // This is how we extend methods.
        (function () {
            var originalMethod = p.select;
            p.select = function () {
                var wasSelected = originalMethod.apply(this);
                if (wasSelected) {
                    $(this.element).trigger('selected.cell');
                }
                return wasSelected;
            };
        }());

        // Extend
        (function () {
            var originalMethod = cell.Cell.prototype.unselect;
            cell.Cell.prototype.unselect = function (leave_selected) {
                var wasSelected = originalMethod.apply(this, [leave_selected]);
                $(this.element).trigger('unselected.cell');
                return wasSelected;
            };
        }());

        p.renderMinMax = function () {
            var $cellNode = $(this.element),
                metaToggleMode = utils.getCellMeta(this, 'kbase.cellState.toggleMinMax'),
                toggleMode = $cellNode.data('toggleMinMax');

            if (metaToggleMode) {
                if (!toggleMode) {
                    // The first time an existing cell is rendered after loading a
                    // notebook, the node data for toggleMinMax
                    // will be empty, so we need to initialize it. This is an auto-initialize.
                    toggleMode = metaToggleMode;
                    $cellNode.data('toggleMinMax', toggleMode);
                }
            } else if (!toggleMode) {
                // If there is neither a data attribute on the node nor a metadata
                // property, then this is a new cell, and it will be maximized.
                toggleMode = 'maximized';
                $cellNode.data('toggleMinMax', toggleMode);
            }

            switch (toggleMode) {
            case 'maximized':
                if (!this.maximize) {
                    console.log('HELP', this);
                    return;
                }
                this.maximize();
                break;
            case 'minimized':
                this.minimize();
                break;
            }
        };

        p.toggleMinMax = function () {
            var $cellNode = $(this.element),
                toggleMode = $cellNode.data('toggleMinMax') || 'maximized';

            switch (toggleMode) {
            case 'maximized':
                toggleMode = 'minimized';
                break;
            case 'minimized':
                toggleMode = 'maximized';
                break;
            }

            // NB namespacing is important with jquery messages because they
            // propagate through nodes like DOM messages (i.e. the toolbar, being
            // contained within the cell, propagates the event upwards, after
            // which it continues to the cell (and perhaps beyond). So using
            // the same event name will lead to an infinite loop.
            // this.celltoolbar.element.trigger('toggleMinMax.toolbar');

            $cellNode.data('toggleMinMax', toggleMode);

            this.renderMinMax();

            utils.setCellMeta(this, 'kbase.cellState.toggleMinMax', toggleMode, true);
        };

        (function () {
            var originalMethod = p.bind_events;
            p.bind_events = function () {
                var $el = $(this.element);
                originalMethod.apply(this);

                //                $el.on('toggle.cell', function () {
                //                    // Alas, it has no discriminating attributes!
                //                    thisCell.toggle();
                //                });
                //                $el.on('rendered.cell', function () {
                //                    thisCell.renderToggleState();
                //                    $(thisCell.element).trigger('set-title.cell', thisCell.getCellState('title'));
                //                });

                // Universal invocation of cell min max
                $el.on('toggleMinMax.cell', function () {
                    this.toggleMinMax();
                }.bind(this));

                // This is triggered by the installation of the 'KBase' cell toolbar. Before this event we
                // cannot safely rely upon the cell toolbar, which provides the min-max ui.
                // I believe the original reason for this event (it may be possible to also use notebook_loaded.Notebook,
                // but I'm not sure), is that the extensions were originally developed in raw Jupyter,
                // and only some cells had the KBase toolbar and behavior.
                // Actually, we do need to use the preset_activated event
                // because WE generate this event by activating the KBase
                // cell toolbar (in kbaseNarrative) after receiving
                // the notebeook_loaded event and also after setting up
                // the basic narrController with some info needed by the
                // cell toolbar (readonly, e.g.)
                this.events.on('preset_activated.CellToolbar', function (e, data) {
                    if (data.name === 'KBase') {
                        this.renderMinMax();
                    }
                }.bind(this));
            };
        }());
    }());

    // RAW CELL

    (function () {
        var p = textCell.RawCell.prototype;

        p.minimize = function () {
            var $cellNode = $(this.element);
            $cellNode.find('.inner_cell > div:nth-child(2)').addClass('hidden');
            $cellNode.find('.inner_cell > div:nth-child(3)').addClass('hidden');
            utils.setCellMeta(this, 'kbase.cellState.showTitle', true);
        };

        p.maximize = function () {
            var $cellNode = $(this.element);
            $cellNode.find('.inner_cell > div:nth-child(2)').removeClass('hidden');
            $cellNode.find('.inner_cell > div:nth-child(3)').removeClass('hidden');
            utils.setCellMeta(this, 'kbase.cellState.showTitle', false);
        };

        // We need this method because the layout of each type of cell and
        // interactions with min/max can be complex.
        p.renderPrompt = function () {
            var prompt = this.element[0].querySelector('.input_prompt');
            if (!prompt) {
                return;
            }
            prompt.innerHTML = '';
        };

        /** @method bind_events **/
        p.bind_events = function () {
            textCell.TextCell.prototype.bind_events.apply(this);

            var cell = this,
                $cellNode = $(this.element);

            // why here in rawcell
            // this.element.dblclick(function() {
            //     var cont = cell.unrender();
            //     if (cont) {
            //         cell.focus_editor();
            //     }
            // });

            // /*
            //  * This is the trick to get the markdown to render, and the edit area
            //  * to disappear, when the user clicks out of the edit area.
            //  */
            // this.code_mirror.on('blur', function() {
            //     cell.render();
            // });

            /*
             * The cell toolbar buttons area knows how to set the title and
             * icon for itself. But we store the title and icon here in case
             * the celltoolbar is not fully built yet. In that case, it will
             * look at the containing cell to see if it has been set yet, and if
             * so will use that (of course listening for these events too.)
             */
            $cellNode.on('set-title.cell', function (e, title) {
                if (title === undefined) {
                    return;
                }
                // cell.setCellState('title', title);
                utils.setCellMeta(cell, 'kbase.cellState.title', title);
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                $menu.trigger('set-title.toolbar', [title || '']);
                if (cellType(cell) !== undefined) {
                    $(cell.element).trigger('show-title.cell');
                }
            });

            $cellNode.on('hide-title.cell', function (e) {
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                $menu.trigger('hide-title.toolbar');
            });

            $cellNode.on('show-title.cell', function (e) {
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                $menu.trigger('show-title.toolbar');
            });

            $cellNode.on('set-icon.cell', function (e, icon) {
                // cell.setCellState('icon', icon);
                utils.setCellMeta(cell, 'kbase.cellState.icon', icon);
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                $menu.trigger('set-icon.toolbar', [icon]);
            });

            /*
             * This is how the cell propagates the select/unselect events to
             * the child "widget" -- the celltoolbar in this case.
             * But, of course, it is a hack.
             * - we should be able to add it as a behavior on the cell prototype
             * - we should be able to propagate it to the celltoolbar itself, we
             *   are talking to the button area, because that is what we are able
             *   to control inside the celltoolbar
             */
            // this.events
            $cellNode.on('unselected.cell', function () {
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                // cell.setCellState('selected', false);
                utils.setCellMeta(cell, 'kbase.cellState.selected', false);
                $menu.trigger('unselected.toolbar');
            });

            // this.events
            $cellNode.on('selected.cell', function () {
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                utils.setCellMeta(cell, 'kbase.cellState.selected', true);
                // cell.setCellState('selected', true);
                $menu.trigger('selected.toolbar');
            });

            // Note - this event needs to be subscribed to in each cell interested.
            // This is really the kick-off for the narrative, since the
            // presets on the celltoobar are loaded via event calls,
            // so are not part of the synchronous process
            // which builds the UI.
            this.events.on('preset_activated.CellToolbar', function (e, data) {
                if (data.name === 'KBase') {
                    // ensure the icon is set?
                    utils.setCellMeta(this, 'kbase.attributes.icon', 'font');
                    // Set up the toolbar based on the state.
                    // TODO: refactor in general -- reconcile cellState and attributes

                    //$cellNode.trigger('set-title.cell', [cell.getCellState('title', '')]);
                    //$cellNode.trigger('set-icon.cell', [cell.getCellState('icon', '')]);

                    // DISABLED: toggling
                    // TODO: re-enable!
                    // cell.renderToggleState();
                }
            }.bind(this));
        };
    }());

    // MARKDOWN CELL

    (function () {
        var p = textCell.MarkdownCell.prototype;

        p.minimize = function () {
            var $cellNode = $(this.element);
            $cellNode.find('.inner_cell > div:nth-child(2)').addClass('hidden');
            $cellNode.find('.inner_cell > div:nth-child(3)').addClass('hidden');
            utils.setCellMeta(this, 'kbase.cellState.showTitle', true);
            utils.setCellMeta(this, 'kbase.cellState.message', '', true);
        };

        p.maximize = function () {
            var $cellNode = $(this.element);
            $cellNode.find('.inner_cell > div:nth-child(2)').removeClass('hidden');
            $cellNode.find('.inner_cell > div:nth-child(3)').removeClass('hidden');
            utils.setCellMeta(this, 'kbase.cellState.showTitle', false);

            // this is a little distracting to see in all markdown cells at all times.
            // it might make more sense in some kind of help settings? or as a tooltip?
            // but there's also already a placeholder in shiny new markdown cells, making this
            // redundant. This text has been moved there.
            // if (NarrativeRuntime.canEdit()) {
            //     utils.setCellMeta(this, 'kbase.cellState.message', 'Double click content to edit; click out of the edit area to preview', true);
            // }
        };

        // We need this method because the layout of each type of cell and
        // interactions with min/max can be complex.
        p.renderPrompt = function () {
            var prompt = this.element[0].querySelector('.input_prompt');
            if (!prompt) {
                return;
            }
            prompt.innerHTML = '';
        };

        p.getIcon = function () {
            var iconColor = 'silver';

            return span({ style: '' }, [
                span({ class: 'fa-stack fa-2x', style: { textAlign: 'center', color: iconColor } }, [
                    span({ class: 'fa fa-square fa-stack-2x', style: { color: iconColor } }),
                    span({ class: 'fa fa-inverse fa-stack-1x fa-' + 'paragraph' })
                ])
            ]);
        };

        /** @method bind_events **/
        // NOTE: We need to completely replace the markdown cell bind_events because we
        // need to disable the double-click to edit if in view mode. We would need to unregister
        // the original dbclick event handler, and we can't do that without
        var originalBindEvents = p.bind_events;
        p.bind_events = function () {
            originalBindEvents.apply(this);

            var cell = this,
                $cellNode = $(this.element);

            this.element.off('dblclick');

            this.element.on('dblclick', '.text_cell_render', function () {
                if (!NarrativeRuntime.canEdit()) {
                    return;
                }
                var cont = cell.unrender();
                if (cont) {

                    cell.focus_editor();
                }
            });

            // /*
            //  * This is the trick to get the markdown to render, and the edit area
            //  * to disappear, when the user clicks out of the edit area.
            //  */
            this.code_mirror.on('blur', function () {

                cell.render();
            });

            /*
             * The cell toolbar buttons area knows how to set the title and
             * icon for itself. But we store the title and icon here in case
             * the celltoolbar is not fully built yet. In that case, it will
             * look at the containing cell to see if it has been set yet, and if
             * so will use that (of course listening for these events too.)
             */
            $cellNode.on('set-title.cell', function (e, title) {
                if (title === undefined) {
                    return;
                }
                // cell.setCellState('title', title);
                utils.setCellMeta(cell, 'kbase.cellState.title', title);
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                $menu.trigger('set-title.toolbar', [title || '']);
                if (cellType(cell) !== undefined) {
                    $(cell.element).trigger('show-title.cell');
                }
            });

            $cellNode.on('hide-title.cell', function (e) {
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                $menu.trigger('hide-title.toolbar');
            });

            $cellNode.on('show-title.cell', function (e) {
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                $menu.trigger('show-title.toolbar');
            });

            $cellNode.on('set-icon.cell', function (e, icon) {
                // cell.setCellState('icon', icon);
                utils.setCellMeta(cell, 'kbase.cellState.icon', icon);
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                $menu.trigger('set-icon.toolbar', [icon]);
            });

            $cellNode.on('job-state.cell', function (e, data) {
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                $menu.trigger('job-state.toolbar', data);
            });

            /*
             * This is how the cell propagates the select/unselect events to
             * the child "widget" -- the celltoolbar in this case.
             * But, of course, it is a hack.
             * - we should be able to add it as a behavior on the cell prototype
             * - we should be able to propagate it to the celltoolbar itself, we
             *   are talking to the button area, because that is what we are able
             *   to control inside the celltoolbar
             */
            // this.events
            $cellNode.on('unselected.cell', function () {
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                // cell.setCellState('selected', false);
                utils.setCellMeta(cell, 'kbase.cellState.selected', false);
                $menu.trigger('unselected.toolbar');
            });

            // this.events
            $cellNode.on('selected.cell', function () {
                var $menu = $(cell.celltoolbar.element).find('.button_container');
                utils.setCellMeta(cell, 'kbase.cellState.selected', true);
                // cell.setCellState('selected', true);
                $menu.trigger('selected.toolbar');
            });

            this.events.on('rendered.MarkdownCell', function (e, data) {
                // cell.setCellState('icon', 'paragraph');
                utils.setCellMeta(cell, 'kbase.attributes.icon', 'paragraph');

                // DISABLED toggleing
                // TODO: re-enable!
                // cell.renderToggleState();

                // get the h1 if it exists.
                var title,
                    renderedContent = cell.element.find('.rendered_html'),
                    h1 = renderedContent.find('h1');
                if (h1.length > 0) {
                    title = h1[0].innerText;
                } else {
                    title = renderedContent[0].textContent;
                }

                if (title) {
                    // trim down to max 50 characters
                    if (title.length > 50) {
                        title = title.substr(0, 50) + '...';
                    }
                    // trim down to the 'paragraph' char - signifies the end of a header element
                    var paraIdx = title.indexOf('¶');
                    if (paraIdx !== -1) {
                        title = title.substr(0, paraIdx);
                    }
                    // trim down to the end of the first newline - a linebreak should be a title
                    var newLineIdx = title.indexOf('\n');
                    if (newLineIdx !== -1) {
                        title = title.substr(0, newLineIdx);
                    }
                } else {
                    title = '<i>empty markdown cell - add a title with # </i>';
                }

                utils.setCellMeta(cell, 'kbase.attributes.title', title, true);
            }.bind(this));

            // Note - this event needs to be subscribed to in each cell interested.
            // This is really the kick-off for the narrative, since the
            // presets on the celltoobar are loaded via event calls,
            // so are not part of the synchronous process
            // which builds the UI.
            this.events.on('preset_activated.CellToolbar', function (e, data) {
                if (data.name === 'KBase') {
                    // ensure the icon is set?
                    utils.setCellMeta(this, 'kbase.attributes.icon', 'paragraph');
                }
            }.bind(this));
        };
    }());

    // Patch the MarkdownCell renderer to run the Javascript we need.
    textCell.MarkdownCell.options_default = {
        cm_config: {
            mode: 'ipythongfm'
        },
        placeholder: '_Markdown_/LaTeX cell - double click here to edit, click out of the edit area to preview.'
            // "Type _Markdown_ and LaTeX: $\\alpha^2$" +
            //     "<!-- " +
            //     "The above text is Markdown and LaTeX markup.\n" +
            //     "It is provided as a quick sample of what you can do in a Markdown cell.\n" +
            //     "Markdown cells are marked with the paragraph icon.\n" +
            //     "This is a comment, so it does not appear when rendered.\n" +
            //     "Also note that the first item in the cell or the first first-level" +
            //     "header will appear as the cell title." +
            //     "-->"
    };

    // KEYBOARD MANAGER

    /*
     * Ensure that the keyboard manager does not reactivate during interaction
     * with the Narrative.
     *
     * Although we disable the keyboard manager at the outset, Jupyter will
     * hook into the blur event for inputs  within an inserted dom node.
     * This causes havoc when kbase widgets manipulate the dom by inserting
     * form controls.
     *
     * So ... we just disable this behavior by overriding the register_events
     * method.
     *
     */

    (function () {
        keyboardManager.KeyboardManager.prototype.register_events = function (e) {
            // NOOP
            return;
        };
    }());

    // CODE CELL

    /*
     *
     * Extend the CodeCell bind_events method to add handling of toolbar
     * events.
     *
     *  A note on "extension" of a function object's function prototype:
     *  We first save the existing function, and then replace it with a new
     *  one which in its first statement executes the original one.
     *  This represents the existing behavior.
     *  Code following this represents the additional or extended behavior.
     *
     */
    (function () {
        var p = codeCell.CodeCell.prototype;

        p.minimize = function () {
            var inputArea = this.input.find('.input_area').get(0),
                outputArea = this.element.find('.output_wrapper');

            inputArea.classList.remove('-show');
            outputArea.addClass('hidden');
        };

        p.maximize = function () {
            var inputArea = this.input.find('.input_area').get(0),
                outputArea = this.element.find('.output_wrapper');

            // if (!inputArea.classList.contains('-show')) {
            //     inputArea.classList.add('-show');
            // }
            // if (this.code_mirror) {
            //     this.code_mirror.refresh();
            // }
            outputArea.removeClass('hidden');
        };

        // We need this method because the layout of each type of cell and
        // interactions with min/max can be complex.
        p.renderIcon = function () {
            var prompt = this.element.querySelector('.input_prompt');

            if (!prompt) {
                return;
            }

            prompt.innerHTML = 'prompt here';
        };

        p.getIcon = function () {
            var iconColor = 'silver';
            var icon;
            icon = span({ class: 'fa fa-inverse fa-stack-1x fa-spinner fa-pulse fa-fw' });

            return span({ style: '' }, [
                span({ class: 'fa-stack fa-2x', style: { textAlign: 'center', color: iconColor } }, [
                    span({ class: 'fa fa-square fa-stack-2x', style: { color: iconColor } }),
                    icon
                ])
            ]);
        };

        var originalBindEvents = codeCell.CodeCell.prototype.bind_events;
        p.bind_events = function () {
            originalBindEvents.apply(this);
            var $cellNode = $(this.element),
                thisCell = this;

            // TODO: toggle state on the cell object so we can be sure about this.

            $cellNode.on('unselected.cell', function () {
                var $menu = $(thisCell.celltoolbar.element).find('.button_container');
                utils.setCellMeta(cell, 'kbase.cellState.selected', false);
                $menu.trigger('unselected.toolbar');
            });

            // this.events
            $cellNode.on('selected.cell', function () {
                var $menu = $(thisCell.celltoolbar.element).find('.button_container');
                utils.setCellMeta(cell, 'kbase.cellState.selected', true);
                $menu.trigger('selected.toolbar');
            });

            $cellNode.on('toggleCodeArea.cell', function () {
                thisCell.toggleCodeInputArea();
            });

            $cellNode.on('hideCodeArea.cell', function () {
                thisCell.hideCodeInputArea();
            });

            if (this.code_mirror) {
                this.code_mirror.on('change', function (cm, change) {
                    var lineCount = cm.lineCount(),
                        commentRe = /^\.*?\#\s*(.*)$/;
                    for (var i = 0; i < lineCount; i += 1) {
                        var line = cm.getLine(i),
                            m = commentRe.exec(line);
                        if (m) {
                            utils.setCellMeta(thisCell, 'kbase.attributes.title', m[1], true);
                            break;
                        }
                    }
                });
            }
        };

        p.hideCodeInputArea = function () {
            var codeInputArea = this.input.find('.input_area')[0];
            if (codeInputArea) {
                codeInputArea.classList.remove('-show');
            }
        };

        p.isCodeShowing = function () {
            var codeInputArea = this.input.find('.input_area')[0];
            if (codeInputArea) {
                return codeInputArea.classList.contains('-show');
            }
            return false;
        };

        p.toggleCodeInputArea = function () {
            var codeInputArea = this.input.find('.input_area')[0];
            if (codeInputArea) {
                codeInputArea.classList.toggle('-show');
                this.metadata = this.metadata;
            }
        };

        // Filter execute through read-only mode
        // In generally we don't "run" code cells in ui view (aka read-only) mode,
        // because the back-end code may make modifications to the Narrative.
        // However, perhaps we should allow code execution as a
        // capability, and just block Narrative modifications?
        var originalExecute = codeCell.CodeCell.prototype.execute;
        p.execute = function () {
            if (Jupyter.narrative.readonly) {
                alert('Read only mode - execute prohibited');
                return;
            }
            return originalExecute.apply(this, arguments);
        };
    }());

    /*
     * NEW:
     *
     * Hides and shows code cell components based on the current toggle
     * state of the cell, as reflected in the cell metadata
     * (via getCellState).
     */

    // NOTEBOOK

    notebook.Notebook.prototype.eachCell = function (fun) {
        var cells = this.get_cells();
        cells.forEach(function (cell) {
            fun(cell);
        });
    };

    // Patch the Notebook to return the right name
    notebook.Notebook.prototype.get_notebook_name = function () {
        if (!this.metadata.name) {
            this.metadata.name = this.notebook_name;
        }
        return this.metadata.name;
    };

    // Patch the Notebook to not wedge a file extension on a new Narrative name
    notebook.Notebook.prototype.rename = function (new_name) {
        var that = this;
        var parent = nbUtils.url_path_split(this.notebook_path)[0];
        var new_path = nbUtils.url_path_join(parent, new_name);
        return this.contents.rename(this.notebook_path, new_path).then(
            function (json) {
                that.notebook_name = json.name;
                that.notebook_path = json.path;
                that.last_modified = new Date(json.last_modified);
                // that.session.rename_notebook(json.path);
                that.events.trigger('notebook_renamed.Notebook', json);
            }
        );
    };

    // Extend methods.
    (function () {
        var p = notebook.Notebook.prototype;

        var sidecarData = null;

        // insert_cell_at_index wrapper
        // Adds a third argument, "data", which is passed in the
        // "insertedAtIndex.Cell" event to any listeners, esp.
        // notebook extensions for cells. Note that if "data" is absent
        // or falsey, the sidecarData closed-over variable is used. It
        // may be set by insert_cell_below or insert_cell_above if they
        // are called with a similarly new third argument.
        //
        // We use this technique since we do not want to re-implement the
        // underlying method, just wrap it.
        //
        // Note that the cell object created is not extensible, so we can't
        // store this on the cell object itself.
        //
        // Also note that this works because ... js is single threaded and there
        // is no possibility that another call will bump into this value.
        (function () {
            var originalMethod = p.insert_cell_at_index;
            p.insert_cell_at_index = function (type, index, data) {
                var cell = originalMethod.apply(this, arguments);
                var dataToSend = data || sidecarData;
                sidecarData = null;
                this.events.trigger('insertedAtIndex.Cell', {
                    type: type || 'code',
                    index: index,
                    cell: cell,
                    data: dataToSend
                });
                return cell;
            };
        }());

        // insert_cell_below wrapper
        // Accepts a third argument "data" not supported in the original.
        // Since it cannot be passed to the inner method, it is set
        // on the sidecarData variable, which is picked up above.
        // This method always calls insert_cell_at_index to do the
        // actual cell insertion, so is a reliable method of passing this
        // extra argument.
        (function () {
            var originalMethod = p.insert_cell_below;
            p.insert_cell_below = function (type, index, data) {
                sidecarData = data;
                var cell = originalMethod.apply(this, arguments);
                return cell;
            };
        }());
        (function () {
            var originalMethod = p.insert_cell_above;
            p.insert_cell_above = function (type, index, data) {
                sidecarData = data;
                var cell = originalMethod.apply(this, arguments);
                return cell;
            };
        }());
    }());

    // Patch the save widget to skip the 'notebooks' part of the URL when updating
    // after a notebook rename.
    saveWidget.SaveWidget.prototype.update_address_bar = function () {
        var base_url = this.notebook.base_url;
        var path = this.notebook.notebook_path;
        var state = { path: path };
        window.history.replaceState(state, '', nbUtils.url_path_join(
            base_url,
            nbUtils.encode_uri_components(path)));
    };

    // Patch the save widget to take in options at save time
    saveWidget.SaveWidget.prototype.rename_notebook = function (options) {
        // silently fail if a read-only narrative.
        if (Jupyter.narrative.readonly) {
            return;
        }
        options = options || {};
        var that = this;
        var dialog_body = $('<div>').append(
            $('<p>').addClass('rename-message')
            .text(options.message ? options.message : 'Enter a new Narrative name:')
        ).append(
            $('<br>')
        ).append(
            $('<input>').attr('type', 'text').attr('size', '25').addClass('form-control')
            .val(options.notebook.get_notebook_name())
        );
        var d = dialog.modal({
            title: 'Rename Narrative',
            body: dialog_body,
            notebook: options.notebook,
            keyboard_manager: this.keyboard_manager,
            buttons: {
                'OK': {
                    class: 'btn-primary',
                    click: function () {
                        var new_name = d.find('input').val();
                        d.find('.rename-message').text('Renaming and saving...');
                        d.find('input[type="text"]').prop('disabled', true);
                        that.notebook.rename(new_name).then(
                            function () {
                                d.modal('hide');
                                that.notebook.metadata.name = new_name;
                                that.element.find('span.filename').text(new_name);
                                Jupyter.narrative.saveNarrative();
                                if (options.callback) {
                                    options.callback();
                                }
                            },
                            function (error) {
                                d.find('.rename-message').text(error.message || 'Unknown error');
                                d.find('input[type="text"]').prop('disabled', false).focus().select();
                            }
                        );
                        return false;
                    }
                },
                'Cancel': {}
            },
            open: function () {
                /**
                 * Upon ENTER, click the OK button.
                 */
                d.find('input[type="text"]').keydown(function (event) {
                    if (event.which === keyboard.keycodes.enter) {
                        d.find('.btn-primary').first().click();
                        return false;
                    }
                });
                d.find('input[type="text"]').focus().select();
            }
        });
    };
});


text:
May 27 Premarket Briefing: 10 Things You Should Know
U.S. stock futures are tentatively rising as investors digest a big cable-TV deal and debate when the Federal Reserve will raise interest rates.
Nora Morrison
May 27, 2015 7:41 AM EDT
Updated from 6:57 a.m.
NEW YORK (TheStreet) -- Here are 10 things you should know for Wednesday, May 27:
1. -- U.S. stock futures were tentatively rising as investors digested a big cable-TV deal and debated when the Federal Reserve will raise interest rates.
European stocks were back in positive territory on Wednesday, recovering from a three-day decline amid stronger-than-expected German consumer confidence and as deal momentum boosted individual stocks, including Imperial Tobacco (ITYBY) .
Asian markets were mixed. The Hang Seng retreated in Hong Kong, while the Nikkei moved up in Tokyo.
2. -- The economic calendar in the U.S. on Wednesday includes the Mortgage Bankers' Association mortgage application data at 7 a.m. and the comparable-store sales Redbook at 8:55 a.m.
3. -- U.S. stocks on Tuesday tumbled as positive economic news ignited investor fears that the Federal Reserve would raise rates sometime soon.
The Dow Jones Industrial Average (DIA) - Get Report dropped 1.04% to 18,041.54. The S&P 500 (SPY) - Get Report sank 1.03% to 2,104.20. The Nasdaq (QQQ) - Get Report fell 1.11% to 5,032.75.
4. -- The U.S. Federal Trade Commission approved Reynolds American's (RAI) $27 billion merger with Lorillard (LO) , saying that the tie-up of the No. 2 and No. 3 tobacco companies in the U.S. would satisfy antitrust requirements. The companies are selling four cigarette brands -- Reynolds' Winston, Kool and Salem and Lorillard's Maverick -- to Imperial Tobacco (ITYBY) to satisfy regulators. Imperial Tobacco stock was up 2.35% in London trading.
In premarket trading, Lorillard stock was down 0.03%. Reynolds stock was up 2.08%.
5. -- The Internal Revenue Service announced a data breach through which hackers obtained prior tax returns for more than 100,000 people. Through the scheme, fraudsters used already-obtained Social Security numbers and other personal information to look up past returns, and then used the information in those to file new, fraudulent returns and gain large refunds. The IRS paid out almost $50 million before catching on.
The IRS is facing an influx of fake demands for refunds even as its budget has been cut 18% since 2010, adjusted for inflation.
6. -- Investors were still discussing the merits of the $56 billion buyout by Charter Communications (CHTR) - Get Report of Time Warner Cable (TWC) , announced on Tuesday. The cable-TV deal will need to pass regulatory scrutiny, something that the prior deal between Time Warner Cable and Comcast (CMCSA) - Get Report did not withstand. Some consumers are concerned that the deal will mean that cable-TV prices go up.
In premarket trading, Charter stock was sinking by 0.16%, while Time Warner Cable stock was up 0.14% after a 7.3% rise on Tuesday.
7. -- Spam-canner Hormel Foods (HRL) - Get Reportwill buy organic and natural meat companyApplegate Farms for $775 million. Hormel plans to operate Applegate as a standalone unit. The purchase is in line with a consumer trend away from processed foods and toward natural, organic -- and generally more expensive -- foods.
Hormel shares were rising by 4.7% in premarket trading.
8. -- The CEO of disappearing-photo site Snapchat, Evan Spiegel, said that stocks are in a bubble that is driven by persistent low interest rates. Spiegel, who spoke at Re/Code's Code Conference in California, also said that his own company was heading for an IPO. Los Angeles-based Snapchat currently has almost 100 million daily active users.
9. -- New home sales rose by 6% in April after a drop in March, the Commerce Department said. The figures suggest that the economy is bouncing back. Plus, the Standard & Poor's/Case-Shiller 20-city home price index said that March home prices were up 5% from a year ago.
However, some Fedwatchers were concerned by the numbers, which indicate that the economy may be strong enough for the Federal Reserve to raise rates soon.
10. -- The earnings calendar for Wednesday includes DSW (DSW) - Get Report, Michael Kors (KORS) and Toll Brothers (TOL) - Get Report before the opening bell and Costco Wholesale (COST) - Get Report after the market close.
FuturesIndustrial GoodsConsumer ServicesStocksInvestingConsumer StaplesOpinionTechnologyUtilitiesMaterialsFinancial Services

redpajama_set_name: RedPajamaCommonCrawl


RIO DE JANEIRO — There have been cost overruns and complaints about spending billions on a mega-event when teachers have gone unpaid. Critics say upscale areas have been favored at the expense of slum dwellers. A pledge to clean up Rio de Janeiro's polluted bay went unfulfilled, while the promise of law and order now feels like a cruel taunt in the face of rising crime.
But the criticism aside, the 2016 Summer Olympics in Rio have profoundly altered this city of six million, yielding a revitalized port; a new subway line; and a flush of municipal projects, big and small, that had long been on the wish list of city planners.
To many, it has become an article of faith that the modern Olympics are a drain on public coffers, a sop to corporate interests and a vanity project for glory-seeking leaders hoping to burnish their legacies and their nations' standing on the world stage.
Brazil is no different. Born seven years ago in the heady days of an economic boom, these Games were initially seen as a triumphal capstone for a newly ascendant global power. Instead, as the country suffered through its worst recession in decades, the Games became an emblem of government waste and political hubris — and a target for protesters who dogged the Olympic torch relay as it wended its way across the country.
But experts say the Games also served as a powerful catalyst for urban revitalization, spurring infrastructure projects, financed with taxpayer money and private investment, that will enhance the lives of Rio's residents.
Nearly 100 miles of rapid bus lanes have slashed commuting times for thousands of the working poor. Four new tunnels have been built, and a 17-mile light rail system opened in June. A new subway line, the system's first major expansion in decades, began operating four days before the opening ceremony.
The city said it had sped up the construction of more than 400 schools and health clinics in impoverished neighborhoods, part of what the mayor called a revitalization spurred by the Olympics.
Still, critics say the Games have delivered uneven benefits, favoring upscale areas like Barra da Tijuca, the site of the Olympic Village, while ignoring hundreds of poor communities where residents live in jerry-built housing that lacks basic sanitation.
"The Olympics have led to displacement, gentrification and sweet deals for real estate developers and construction companies," said Theresa Williamson, the executive director of Catalytic Communities, an advocacy group for the city's favelas.
But while acknowledging the dire state of Rio's public finances — the underfunded schools and hospitals, the unpaid government salaries and the unmitigated misery of its hilltop favelas — some experts say the Olympics will provide benefits for years to come.
"It's undeniable that the infrastructure that has been built for the Games will benefit the population once the Olympics are over," said Barbara Mattos, an analyst at Moody's, the credit rating agency.
Eduardo Paes, Rio's hard-charging mayor, who has aspirations of higher office, is quick to swat away criticism of the Games, calling the event a once-in-a-generation opportunity to lure investment to a city where fortunes have waned in the nearly six decades since the national capital moved from Rio to Brasília.
He noted that the $12 billion budget for the Games was significantly lower than the expenses of other recent host cities — the roughly $15 billion spent on the 2012 London Games and the $51 billion that Russia lavished on the 2014 Winter Olympics in Sochi.
More important, Mr. Paes said, much of the money came from the private companies that built the Olympic Village and the Olympic golf course, as well as those that renovated the city's port, a project that includes a two-mile waterfront promenade and two new museums.
Over all, he said, the city has built 75,000 units of affordable housing since 2009, although some estimates suggest that nearly as many people, most of them poor, lost their homes to projects related to the Olympics.
Critics dispute some of Mr. Paes's figures, pointing out that cost overruns will most likely bring the final cost of the Games to $20 billion. Others note that the 3,600 apartments that make up the Olympic Village will end up as homes for the rich, and that the golf course, which required filling in protected wetlands, will serve only the wealthy.
The interim president of Brazil, Michel Temer, right, riding last month with the governor of the state of Rio de Janeiro, Luiz Fernando de Souza, in an inaugural event for a new subway line in Rio.
In a sign of the anger over the Games, a media bus was attacked on August 9 in an area torn apart for Olympic projects. But some analysts agree with Mr. Paes that the Games will not leave the city with significant debt.
In a report issued in May, Moody's said that the Games would have a negligible impact on the city's ailing economy but that the $7 billion in transportation-related spending was money well spent.
That assessment stood in stark contrast to the benefits seen in the estimated $11 billion that Brazil spent hosting the 2014 World Cup, which left behind a constellation of 12 new or renovated stadiums, most of which are not used regularly.
Parsing the numbers can be tricky, of course, and Olympic hosts often fiddle with budget categories to conceal the true costs.
Bent Flyvbjerg, an Oxford University economist and the lead researcher on a study that examined Rio's Olympic finances, said the actual amount spent on sports venues was most likely $4.6 billion, 51 percent over budget.
That amount, Mr. Flyvbjerg said, placed Rio somewhere in the middle of host cities that have exceeded their spending projections.
In recent years, Oslo, Boston and Munich, bowing to popular opposition, have dropped their Olympic ambitions. Over the last three decades, nearly every city that has hosted the Games has lost money, and few expect Rio to recoup the billions of dollars spent preparing for an event that lasts just weeks.
The amount of money lost to waste and corruption may never be known. Sérgio Cabral, the former governor who helped land the Olympics, has been accused of demanding millions in bribes. It also remains to be seen whether the 12 Olympic venues intended to become schools or community sports centers will end up as white elephants.
But city officials say the Olympics helped move the needle on infrastructure plans that had languished for years.
In some poor neighborhoods, the Olympics served as a cudgel to speed the overhaul of public clinics that had been plagued by long waits and poor service. At one, in the troubled City of God favela, software now streamlines the triage process, a cheery ombudsman takes complaints and a new app lets supervisors track how long doctors spend with each patient — or whether they take inordinately long lunch breaks.
Then there is Meu Porto Maravilha, or My Wonderful Port, the historic waterfront that for decades was cut off from downtown Rio by a hulking elevated highway, its 19th-century warehouses left to molder. Plans to rehabilitate the port, first put forth in the 1980s, had long been stymied by a lack of money and insufficient political will.
The $2.5 billion rehabilitation, much of it financed through the sale of air rights from adjacent properties and tax incentives to developers, included demolishing the viaduct and funneling traffic through a new three-mile tunnel.
Over the next decade, the developers plan to build 500 apartments that they say will be affordable to residents of a nearby favela. Many of these residents are descendants of the half-million African slaves who first arrived in Brazil at Valongo Wharf. The wharf's recently unearthed foundations are scheduled to become part of a museum that will also include a forgotten slave cemetery.
"If we didn't get the Games, I'm not sure this would have happened in our lifetime," said Alberto Silva, who is in charge of the project.
Since opening in May, the port has been a hit with Brazilians, who crowd the waterfront promenade day and night, drawn by free concerts, food trucks and the opportunity for selfies in front of the Olympic flame.
As she made her way through the elbow-to-elbow throngs, Maria Helana Lima, 49, a house cleaner, said she had initially shared the skepticism of friends who viewed the Games as a colossal waste of money.
"It's hard to get excited about the Olympics when our hospitals are so overcrowded and people can't find jobs," she said. But sitting in the shadow of a new science museum by the Spanish architect Santiago Calatrava, Ms. Lima said she had changed her mind.


text:
Bald Eagle Has Some Sushi
Harriet is the oldest eagle ambassador and arrived at the National Eagle Center in 2000. In 1998, a vehicle collision left her left wing badly dislocated and part of it was subsequently amputated.
Although she was fully adult at the time of her injury, we know that she hatched in 1981. Harriet was banded as an eaglet in her nest in northern Wisconsin. A researcher placed a small aluminum band on her leg, and she lived in the wild for 17 years before her accident in 1998.
Harriet has a feather tuft atop her head that makes her easy to identify. We can't be certain, but suspect that this distinctive feather growth is the result of scar tissue and damage to feather follicles.
As an eagle ambassador with the National Eagle Center, Harriet has made appearances across the country. She's been featured on the Today Show and The Tonight Show with Jay Leno. In 2007, Harriet was in Washington DC to celebrate the removal of the bald eagle from the endangered species list.
Much of Harriet's work over the years has been with veterans. She has visited VA hospitals and been a part of numerous veterans honor ceremonies. Harriet is the eagle featured on the Minnesota Support Our Troops license plate.
Bald Eagle Eating Fish.jpg
eagle bird bald eagle american eagle closeup details feathers beak eye eat eating bird of prey haliaeetus leucocephalus sea eagle southern bald eagle northern bald eagle Harriet national eagle center wabasha minnesota
Birds, Eagle


Hi to all...short question for developers, the code and library in googlecode is update to latest version?
I've just commited a new folder called librariesOK.
Those are the libs we're actually using.
could you please tell me where the libraries are locateted ? I am particularly interested in the code for intercepting the Mavlink messages for vertical speed. My plan is to take the Mavlink VS data with a pro mini or micro and convert it to an analog signal which will be fed to the video TX audio input.
By the way - I noticed that heading information is represented with 1 to 3 digits. In aviation normally three digits are used on PFDs or MFDs. A heading of 5 degrees would be shown as 005, a heading of 15 degrees as 015 and so on. It's just a matter of consistency for representing heading values.
I think that that variometer feature shouldn't be hard to achieve with a mini.
Thanks for pointing the 3 digit standard. It's a none code space cost.
The only drawback regarding the leading zeros is the fact that the OSD will became more clutered.
On leading zeroes; it is because of useable sreen area.
We have made many things different than real aviation HUD-s have. It has a reason.
In a real plane you dont only have the HUD view. In here you see everything through the OSD.
We are happy to help if you still want to achive this!
thanks for reply, Will keep you updated about my project.
Regarding leading zeroes on the heading - let's have a look at it randomly : around 95 % percent of the time you have at least two digits, around 70% of the time you have three digits anyway. The OSD is cluttered, that's an argument. But it is way much easier for our brains to navigate in an OSD if it is clean and consistent. And I can tell you from own experience - a HUD in real aviation is cluttered as well. And the guys designing it spent a lot to make it more readable. The came up with trend vectors and bars instead of plain numbers. What a treat - it's so easy to interpret.
A big improvement would be a transition from digital information (numbers) to bars indicating errors or deviations from zero (for example VS)- that's widely used in real HUD. Absolute numbers often don't count much when it comes to interpretation of information. Just my own experience.
The minimosd is a little limited - I know. But part of the information could in my opinion as well be presented in another way.
Well, i belive you. I am not a real pilot.
We will talk this over with Miguel.
But on RC planes Heading is not very usefool.
That is why we made real heading panel.
I am usually around 20-30° off from the compass, becauseof wind.
So it would be more usefool might be to show real-real heading instead what we have now.
Like it tells you that you are 11° off to the right.
Bars or ladders with low speed/altitude ladder signs/warnings.
The ladders mostly in the center of the field of view like on a stealth plane HUD (human eye has very high resolution but only in a narrow field of view).
quote "Regarding heading orientation IMHO for FPV I think that the most important panel is the Home Arrow :)" yes, I agree.
quote "human eye has very high resolution but only in a narrow field of view" yes, I agree. But movement on a ladder on the side captures your attention, and at a glance you know what is going on without processing this information in your brain in a big way..
One question : what about conditional compiling to free memory space ? Just to push development ahead and nevertheless being able to keep the most common features aboard anytime.
Completly agree, ladders are great. Do you know that Vertical Landing Aid that copter fw as built in horizon panel? My goal was to "at a glance" know if copter is at low altitude.
Conditional compiling is something I've already implemented (sort of).
It will however be difficult to mantain/support versions.
Will the source code be in the user PC installation folder (my current implementation) or "on-line" and downloaded at "compile time".
Will we compile all possible combinations? APM Mission Planner work more or less this way for each plane / copter / rover type. Also if I recall well, Companion9X radio fw application works also this way.
In this case we would need a routine to generate all the hex everytime there is a new version. Also we would need a repository since code.google does no longer support uploading "downloadables".
We have been on this trip for a while now and I guess it will take even more time to achieve this.
hey! thanks for the reply - tried to call and left a message. Were you able to fix this?


text:
Q: image and script link not good because of subfolder I am new to ProcessWire and I have a simple question.
I transferred from being hosted on a server to running form a local site and some images, scripts, and links to pages are not showing up correctly.
The Homepage can be found at "http://localhost/restaurant/release/" and, for example, a relative link to some script is currently something like <script src="/site/templates/scripts/f.js">.
The problem is that, when the browser tries to access this link, it actually gets "http://localhost/site/templates/scripts/f.js"
instead of "http://localhost/restaurant/release/site/templates/scripts/f.js".
How does ProcessWire handle these kinds of links? And how do I fix them?

A: You need to set the base tag in your HTML head:
<base href="http://localhost/restaurant/release">

Use your links as per normal:
<script src="/site/templates/scripts/f.js">

Alternatively, simply omit the leading slash from the script src.

redpajama_set_name: RedPajamaStackExchange


There was a three-vehicle pileup on Aug. 22 on Route 114 in East Hampton, in a construction work area near Cove Hollow Road. At around 1:50 p.m., East Hampton Town police said, Robert J. Foley of Mastic Beach, 38, who was northbound in a 2009 Ford van, rear-ended a 2017 Jeep, forcing it into the 2006 Toyota in front of it.
The Jeep's driver, Harold T. King of East Hampton, 30, complained of neck pain but refused medical attention. The driver of the Toyota, Jan Spoerri of East Hampton, 52, was not hurt, nor was Mr. Foley.
Other recent accidents on local roads included one at the busy intersection of Bluff Road and Atlantic Avenue in Amagansett, where, at 1 p.m. on Aug. 23, a Ford pickup truck hit a 69-year-old bicyclist. John Ryan of East Hampton, 52, the driver of the northbound 2012 truck, told police he was turning left from Atlantic onto Bluff and did not see the oncoming bicyclist, Michael Strauss of Larchmont, N.Y.
Mr. Strauss, who was wearing a helmet, complained of head pain and minor bleeding. He was taken for treatment to Stony Brook University Hospital, a level-one trauma center, and later released.
About 20 minutes later, two cars collided under the train trestle on Stephen Hand's Path in East Hampton. Isabella R. Grimes of Clinton, Conn., 19, in a northbound 2008 Subaru, told East Hampton Town police she was underneath the trestle when a southbound Kia, also underneath it, crossed the double yellow lines and sideswiped her vehicle.
The driver of the 2016 Kia, Arline H. Blake of Sag Harbor, 68, told police she had the right of way. Police, however, blamed both drivers for the collision, saying that Ms. Blake had failed to keep right and Ms. Grimes had not only failed to yield the right of way but tried to pass the Kia under the trestle, sideswiping it.
Ms. Blake complained of back pain and was taken to Stony Brook Southampton Hospital. An eyewitness, Jeff Litzko, corroborated Ms. Blake's version of the event to police. Both vehicles were towed, and neither driver was charged.
Last Thursday at about 10 a.m., an 83-year-old man was involved in a single-car accident after striking a speed sign and then a tree on Stephen Hand's Path in East Hampton, near Barnes Avenue. Police interviewed Paul Hutt of Highland Beach, Fla., who was driving a 2001 Mercedes registered to David A. Becker of New York City, but said he was disoriented and unable to say how the accident occurred. He complained of chest pain and was taken to Stony Brook Southampton Hospital.
Dan Rattiner of Dan's Papers was in a 4:50 p.m. accident Aug. 18 in East Hampton Village, just south of David's Lane by the Presbyterian Church. Mr. Rattiner, 78, told village police he had either fallen asleep or passed out while his 2008 Chevrolet was headed north on Main Street. He woke up, he said, when the car drifted to the right and struck a parked 2014 Jeep, with damage to both vehicles.
Mr. Rattiner told an officer he felt ill and had injured his wrist, and an ambulance transported him to Stony Brook Southampton Hospital.


Projects in the Mining & Industrial using Jacks Winches.
Our range of winches have been used throughout these markets on Mine Sites & various other resource related Installations throughout the world. Please feel free to peruse our gallery which is a small sample of the multitude of successful mining applications we have been proud to be a part of.


text:
Meet Robi: The Interactive Robotic Companion that Speaks Singlish
Meet Robi: The Interactive Robotic Companion that Speaks Singlish Robi by DeAgostini is a build-it-yourself robot that aims to bring families closer together Singapore, 15 June 2016 – Robi, possibly the first ever robot able to speak Singlish, arrived in Singapore today with…
Singaporean start-up to turn South-East Asia's top magazines into "point, snap, pay" experiences
Singaporean start-up to turn South-East Asia's top magazines into "point, snap, pay" experiences · iQNECT partners with C True to launch visual search and m-commerce in 6 leading magazines in Thailand · Readers can access videos, claim offers, and make purchases by…
Singaporean entrepreneur named among 100 Most Creative People in Business 2015 (Fast Company magazine)
Singapore's very own Dinesh Bhatia, CEO of TradeHero, has been named by Fast Company Magazine one of its "100 Most Creative People in Business 2015," for teaching aspiring investors how to make the leap, making financial investment accessible to all. TradeHero, developed in Singapore in 2012,…


toddlers table and chairs wooden china new design home school kindergarten red solid wooden toddler table chairs childrens table and chairs wooden.
toddlers table and chairs wooden table and chair set for sale kids white table set kids kitchen table and chairs little table and chair set table and chair set for toddler table and chairs wood ikea.
toddlers table and chairs wooden desks wooden desk and chair set children child s jr roll top toddler wood toddler table chairs wood.
toddlers table and chairs wooden beneficial small table and chairs table and chairs medium images of table chairs wooden toddler table and chairs wood.
toddlers table and chairs wooden cheap kids table chair chairs kids folding table and chairs set wooden table set for toddlers table cheap kids table and chairs toddler table and chairs wood ikea.
toddlers table and chairs wooden kids table and chair wooden toddler wooden table and chairs uk.
toddlers table and chairs wooden table and chair set for kids table chair for toddler toddler tables and chairs wooden table toddler table and chairs set wood.
toddlers table and chairs wooden kids activity table and chairs kids playroom table and chairs interior design toddler play table childrens table and chairs wooden.
toddlers table and chairs wooden play table for toddlers architecture toddler play tables chair wooden toddler chair play table for toddlers architecture toddler play tables chair intended childrens t.
toddlers table and chairs wooden various table chair sets table chair set table and chair set table and chairs elegant table chair childrens wooden table and chairs australia.
toddlers table and chairs wooden toddler table and chair kids wooden table and chairs medium size of toddler table and chairs childrens table chairs wooden.
toddlers table and chairs wooden table and chairs for toddlers toddler table and chair toddler table and chairs wood toddler table toddler table and chairs wood.
toddlers table and chairs wooden table chair sets amazing interiors 4 toddler wooden table and chairs uk.
toddlers table and chairs wooden kid table and chair kids table and chairs do it yourself home projects from white more kid table and chair childrens table and 4 chairs wooden.
toddlers table and chairs wooden medium size of stunning dining table on chair kids character table and chairs wooden childrens wooden table and chairs cape town.
toddlers table and chairs wooden toddler table and chairs garden table chairs green toddler table chairs wood childrens wooden table and chairs cape town.
toddlers table and chairs wooden kid table chair table and chairs set medium size of wooden table and chair set style kid table chair toddler table and chairs set wood.
toddlers table and chairs wooden table chair set table and chairs table and chairs astonishing kids table and image table chair childrens table chairs wooden.
toddlers table and chairs wooden wooden toddler table wooden toddler table view toddler wooden table and chairs nz.
toddlers table and chairs wooden full size of kitchen table conventional toddler kitchen table set luxury swivel and toddler chair childrens wooden table and chairs australia.
toddlers table and chairs wooden toddler table and chairs wood table chair for toddler desk and chair set for toddlers toddler toddler table and chairs wood wooden toddler table and chairs ikea.
toddlers table and chairs wooden kids furniture table chairs kids table and chairs clearance wood working plans for childrens table and chair set wooden.
toddlers table and chairs wooden build an easy table and chair set for the little kids the set costs about toddler wooden table and chairs uk.
toddlers table and chairs wooden child table and chairs wood home and furniture extraordinary kid table chairs on dining room furniture and chair set kid child table and chair set wooden toddler table.
toddlers table and chairs wooden wood table and chairs table and chairs toddler table and wood table and chairs table and childrens table and 4 chairs wooden.
toddlers table and chairs wooden crayola toddler table and chairs wooden table and chair set toddler table and chair set natural wooden table and chair set toddler table and chair set toddler table an.
toddlers table and chairs wooden toddler table and chairs set gypsy chair wood toddler wooden table and chairs nz.
toddlers table and chairs wooden wood table and chairs sets chairs kids play table and chairs toddler desk and chair wood table and chairs toddler table and chairs set wood.
toddlers table and chairs wooden wood table and chairs wooden table and chair set table and chair sets kid table wood table and chairs childrens wooden table and chairs cape town.
toddlers table and chairs wooden table chair set for toddlers wooden table and chair set toddler table chair set school chair table chair set for toddlers toddler table and chairs wooden.
toddlers table and chairs wooden table wooden kids table study table and cupboard set toddler table and 4 chairs kids plastic desk and chair toddler desk chair kids childrens wooden table and chairs c.
toddlers table and chairs wooden toddler table and chair play with me table and chairs in cherry wooden toddler table and toddler table and chair childrens table and 4 chairs wooden.
toddlers table and chairs wooden table and chair for toddlers wooden table and chairs children wooden chair children s wooden table table and chair for toddlers toddler wooden table and chairs nz.
toddlers table and chairs wooden children table and chairs wood toddler chair and table kids table furniture by fantasia furniture kids children table and chairs wood childrens table and chairs wooden.
toddlers table and chairs wooden trending table chair sets tables and chair sets luxury kids table and chairs kids childrens table and chairs wooden.
toddlers table and chairs wooden table and chairs medium size of astonishing toddler table chair set baby in chairs sets childrens table and chairs wood.
toddlers table and chairs wooden wooden table and chairs set vintage wooden table chair set for dolls house furniture miniature wooden table and chairs toddler table and chairs wood.
toddlers table and chairs wooden wooden toddler table and chairs wood.
toddlers table and chairs wooden table chair sets stunning furniture ingenious children and design with round home ideas toddler table and chairs wood.
toddlers table and chairs wooden child table sets wooden kids table and chairs china best design kids wooden study table chair wooden toddler table and chairs ikea.
toddlers table and chairs wooden toddler table and chairs wood toddler play table and chairs toddler table and chairs wood children toddler table and chairs wooden.
toddlers table and chairs wooden table and chairs set wood kids table chair sets children table and chairs kids table childrens wooden table chairs uk.


Rushing: L, Justin Villanueva 6-39, Keven Yrrizarry 9-37, Naujrye Neal 1-27, Aidan Foyle 4-21, Brendan Tighe 1-8.
Passing: L, Aidan Foyle 11-24-2-140.
Receiving: L, Brendan Tighe 6-74, David Brito 2-54, Kyle Shanahan 3-12.
Rushing: NT, Brent Robinson 7-58; Tyler Alden 1-3; Eli Norton 15-74; Randy Delva 2-50; Jose Soba 10-87; Luke McKenna 3-23.
Receiving: Brent Robinson 1-7; Tyler Alden 3-64; Eli Norton 2-13.
Passing: T, Jay Connolly 13-27-1-254.
Receivng: T, Shane Aylward 7-191.
Rushing: T, Jack Kelly 8-80; Kyle Zervas 9-55.
Rushing: W, Peter Marino 16-127.
Passing: W, Andrew Sullivan 11-18-0-131.
Receiving: W, Benoit 6-74; Peter Marino 1-39, Kyle Kenyon 2-7.
Rushing: P, Charlie Katin 2-38; Brett Lindsay 5-15; Matt Crowley 4-5.
Passing: P, Ian Hoey 11-25-3-203.
Receiving: P, Colby Travis 4-90; Nicholas Milano 4-84; Charlie Katin 1-16; Jake Herrling 1-8; Matt Crowley 1-5.
Braden Lynn 2-23, Parker Landfore 3-45, Edward Mullen 2-11.
Passing: L, Braden Lynn 2-3-0-36.
Receiving: Evan Lyons 1-24, Mike Crory 1-12.
Rushing: GL, Jake Noel 10-138; Benji Hach 14-125; Matthew Gaudette 4-32; Bobby Cronin 1-9; Isaiah Carrasquillo 1-5; Ryan Hickey 1-3.


The HCG Diet is quickly becoming a significant force in the online diet world. "HCG Diet Drops" are the main factor in the HCG Diet that may cause weight reduction. Precisely what is this diet Cheap Air Max 97 Plus , what are these drops and does this system really make it easier for a person to shed pounds? There are several different brand names and websites on the market that promise dieters the moon. If you assume that dieting is simple, you may get a shock when you honestly try to do it. In fact it's very hard to get slimmer. The claims and the real results of this new craze should be worthwhile for us to examine.
The term "Human Chorionic Gonadotropin" is really what is meant from the three letters "HCG." The hormone HCG is located in the standard body. The theory is that HCG helps your whole body lose excess fat–in areas like your thighs, your abdomen, your derriere, and underneath your arms–when you take in very small quantities of the hormone on a regular basis. People suspect that the body is induced to burn saved fat for energy by consuming supplements of HCG. The claim is also made that you're going to digest what you eat more effectively because HCG jump-starts your metabolic systems by influencing the hypothalamus.
Several internet vendors sell the HCG Diet Drops. An example is an internet site offering a 40-day diet plan or a smaller, 21-day supply. The seller claims that you could consistently drop at least one pound per day just by adding HCG Diet Drops to what you consume. The brain evidently has to have that range of time to work on your own metabolism in order to change it in the right direction for fat loss. The price of these weight loss plans is huge. A 21 day supply of HCG Diet Drops will cost you just about fifty dollars. For a couple drops of the HCG dietary supplement you're paying two dollars each and each day.
There is a healthy amount of skepticism surrounding this particular form of dieting. There is no scientific evidence that any quick, easy plan to lose fat and get fit has ever proven to work. That the simplest way to lose weight and keep it off is to eat a healthy diet and get a good level of exercising. If you believe the HCG Drops suppliers, your excess poundage will basically disappear without effort by using the drops. The hormone will make your body actually eat itself, seemingly, according to the vendors. That's rather awful and very bizarre!
The real story is this. You can slim down very fast, and there are a lot of ways to do it. This would be good news if it were not for the fact that the fast diets are unhealthy and can injure your body. And there's not a way to know whether any extra weight that you do happen to lose using the drops will continue to be lost. Once you stop taking them you might gain all that weight right back.
The decision to dose oneself with hormones should be made only in consultation with a physician. Hormone supplements really should be prescribed by a doctor, not obtained off the internet in a desperate endeavor to lose a lot of weight without doing any work. Your physician will tell you whether or not this type of hormone supplementation may be for you and how best to approach your weight loss so that you can remain healthy.
For more atricles on weight loss and dieting take a look at my Muscle Building website now!
Decent health can be associated with regular and trouble absolutely free bowel actions. A healthy person is even expected to transfer their bowels at least at the time a day. Missing to transfer your bowels even for just just one day and you are at danger for so quite a few illness inflicting issues. A colon cleanser that will detoxify your product and get rid of excessive waste could be the method you have been on the lookout for.
A single of the big causes of an harmful technique could be your food plan. Beneficial eating habits procedures can effortlessly be thrown out the window if your give good results schedule or you way of living just does not allow you to take in right. Some most people without the need of finding out it could be consuming so a lot of foodstuff that is unhealthy for them that they may perhaps have even started out to get usual difficulties with constipation.
The sugars from sweets and hormones observed inside of the meat that we consume, can be contributing issues to constipation. We you do not have the self-discipline or power of will to change your taking in behavior. Then it's possible you look into choix therapies, like a colon cleanse to support your overall body cope with getting rid of these pollutants proficiently from your technique.
With colonic irrigations, herbs, and an useful colon cleanser you can rather quite a bit make your colon squeaky thoroughly clean and conserve by yourself the issues of owning to deal with any sickness introduced about a backed-up program.
You can even pick out to go with a pure colon cleanse by adding herbs and significantly more fibre into your diet. This might involve a minimal shift to your food plan or, if you are disciplined good enough, a drastic modify for the more effective. We would advise not only more vegetables and fruits in your diet plan but we would stimulate you to have additional of unprocessed foodstuff as very well.
All of the strategies for an reliable colon cleanse requires a tiny significantly more discipline be since it is commonly not a just one-time thing. This form of treatment generally entail the usage of a colon cleanser through a course of a variety of days to get the full influence.