<commit_before>(function ($) {
   'use strict';

    var igcFile = null;
    var barogramPlot = null;
    var altitudeConversionFactor = 1.0; // Conversion from metres to required units

    function plotBarogram() {
        var nPoints = igcFile.recordTime.length;
        var pressureBarogramData = [];
        var gpsBarogramData = [];
        var j;
        var timestamp;

        for (j = 0; j < nPoints; j++) {
            timestamp = igcFile.recordTime[j].getTime();
            pressureBarogramData.push([timestamp, igcFile.pressureAltitude[j] * altitudeConversionFactor]);
            gpsBarogramData.push([timestamp, igcFile.gpsAltitude[j] * altitudeConversionFactor]);
        }

        var baro = $.plot($('#barogram'), [{
            label: 'Pressure altitude',
            data: pressureBarogramData
        }, {
            label: 'GPS altitude',
            data: gpsBarogramData
        }], {
            axisLabels: {
                show: true
            },
            xaxis: {
                mode: 'time',
                timeformat: '%H:%M',
                axisLabel: 'Time (UTC)'
            },
            yaxis: {
                axisLabel: 'Altitude / ' + $('#altitudeUnits').val()
            },

            crosshair: {
                mode: 'xy'
            }
        });

        return baro;
    }

    function updateTimeline (timeIndex, mapControl) {
        var currentPosition = igcFile.latLong[timeIndex];
        var startPosition = igcFile.latLong[0];
        var distance = L.latLng(currentPosition[0], currentPosition[1]).distanceTo(
            L.latLng(startPosition[0], startPosition[1])) / 1000.0;

        var unitName = $('#altitudeUnits').val();
        $('#timePositionDisplay').text(
            igcFile.recordTime[timeIndex].toUTCString() + ': ' +
            (igcFile.pressureAltitude[timeIndex] * altitudeConversionFactor).toFixed(0) + ' ' +
            unitName + ' (barometric) / ' +
            (igcFile.gpsAltitude[timeIndex] * altitudeConversionFactor).toFixed(0) + ' ' +
            unitName + ' (GPS); ' +
            distance.toFixed(1) + ' km from takeoff'
        );

        mapControl.setTimeMarker(timeIndex);

        barogramPlot.lockCrosshair({
           x: igcFile.recordTime[timeIndex].getTime(),
           y: igcFile.pressureAltitude[timeIndex] * altitudeConversionFactor
        });
    }

    function displayIgc(mapControl) {
        // Display the headers.
        var headerTable = $('#headerInfo tbody');
        headerTable.html('');
        var headerName;
        var headerIndex;
        for (headerIndex = 0; headerIndex < igcFile.headers.length; headerIndex++) {
            headerTable.append(
                $('

').append($('	').text(igcFile.headers[headerIndex].name))
                              .append($('	').text(igcFile.headers[headerIndex].value))
            );
        }

        // Show the task declaration if it is present.
        if (igcFile.task.coordinates.length > 0) {
            $('#task').show();
            var taskList = $('#task ol').first().html('');
            var j;
            for (j = 0; j < igcFile.task.names.length; j++) {
                taskList.append($('

').text(igcFile.task.names[j]));
            }

            mapControl.addTask(igcFile.task.coordinates, igcFile.task.names);
        }
        else {
            $('#task').hide();
        }

        // Reveal the map and graph. We have to do this before
        // setting the zoom level of the map or plotting the graph.
        $('#igcFileDisplay').show();

        mapControl.addTrack(igcFile.latLong);
        barogramPlot = plotBarogram(igcFile);

        $('#timeSlider').prop('max', igcFile.recordTime.length - 1);
        updateTimeline(0, mapControl);
    }

    $(document).ready(function () {
        var mapControl = createMapControl('map');

        $('#fileControl').change(function () {
            if (this.files.length > 0) {
                var reader = new FileReader();
                reader.onload = function(e)  {
                  try {
                      $('#errorMessage').text('');
                      mapControl.reset();
                      $('#timeSlider').val(0);

                      igcFile = parseIGC(this.result);
                      displayIgc(mapControl);
                  } catch (ex) {
                      if (ex instanceof IGCException) {
                          $('#errorMessage').text(ex.message);
                      }
                      else {
                          throw ex;
                      }
                  }
                };
                reader.readAsText(this.files[0]);
            }
        });

        $('#altitudeUnits').change(function () {
            var altitudeUnit = $(this).val();
            if (altitudeUnit === 'feet') {
                altitudeConversionFactor = 3.2808399;
            }
            else {
                altitudeConversionFactor = 1.0;
            }

            if (igcFile !== null) {
                barogramPlot = plotBarogram();
                updateTimeline($('#timeSlider').val(), mapControl);
            }
        });

        // We need to handle the 'change' event for IE, but
        // 'input' for Chrome and Firefox in order to update smoothly
        // as the range input is dragged.
        $('#timeSlider').on('input', function() {
           updateTimeline($(this).val(), mapControl);
        });
        $('#timeSlider').on('change', function() {
           updateTimeline($(this).val(), mapControl);
        });
    });
}(jQuery));
<commit_msg>Clickable graph.<commit_after>(function ($) {
   'use strict';

    var igcFile = null;
    var barogramPlot = null;
    var altitudeConversionFactor = 1.0; // Conversion from metres to required units

    function plotBarogram() {
        var nPoints = igcFile.recordTime.length;
        var pressureBarogramData = [];
        var gpsBarogramData = [];
        var j;
        var timestamp;

        for (j = 0; j < nPoints; j++) {
            timestamp = igcFile.recordTime[j].getTime();
            pressureBarogramData.push([timestamp, igcFile.pressureAltitude[j] * altitudeConversionFactor]);
            gpsBarogramData.push([timestamp, igcFile.gpsAltitude[j] * altitudeConversionFactor]);
        }

        var baro = $.plot($('#barogram'), [{
            label: 'Pressure altitude',
            data: pressureBarogramData
        }, {
            label: 'GPS altitude',
            data: gpsBarogramData
        }], {
            axisLabels: {
                show: true
            },
            xaxis: {
                mode: 'time',
                timeformat: '%H:%M',
                axisLabel: 'Time (UTC)'
            },
            yaxis: {
                axisLabel: 'Altitude / ' + $('#altitudeUnits').val()
            },

            crosshair: {
                mode: 'xy'
            },

            grid: {
                clickable: true,
                autoHighlight: false
            }
        });

        return baro;
    }

    function updateTimeline (timeIndex, mapControl) {
        var currentPosition = igcFile.latLong[timeIndex];
        var startPosition = igcFile.latLong[0];
        var distance = L.latLng(currentPosition[0], currentPosition[1]).distanceTo(
            L.latLng(startPosition[0], startPosition[1])) / 1000.0;

        var unitName = $('#altitudeUnits').val();
        $('#timePositionDisplay').text(
            igcFile.recordTime[timeIndex].toUTCString() + ': ' +
            (igcFile.pressureAltitude[timeIndex] * altitudeConversionFactor).toFixed(0) + ' ' +
            unitName + ' (barometric) / ' +
            (igcFile.gpsAltitude[timeIndex] * altitudeConversionFactor).toFixed(0) + ' ' +
            unitName + ' (GPS); ' +
            distance.toFixed(1) + ' km from takeoff'
        );

        mapControl.setTimeMarker(timeIndex);

        barogramPlot.lockCrosshair({
           x: igcFile.recordTime[timeIndex].getTime(),
           y: igcFile.pressureAltitude[timeIndex] * altitudeConversionFactor
        });
    }

    function displayIgc(mapControl) {
        // Display the headers.
        var headerTable = $('#headerInfo tbody');
        headerTable.html('');
        var headerName;
        var headerIndex;
        for (headerIndex = 0; headerIndex < igcFile.headers.length; headerIndex++) {
            headerTable.append(
                $('

').append($('	').text(igcFile.headers[headerIndex].name))
                              .append($('	').text(igcFile.headers[headerIndex].value))
            );
        }

        // Show the task declaration if it is present.
        if (igcFile.task.coordinates.length > 0) {
            $('#task').show();
            var taskList = $('#task ol').first().html('');
            var j;
            for (j = 0; j < igcFile.task.names.length; j++) {
                taskList.append($('

').text(igcFile.task.names[j]));
            }

            mapControl.addTask(igcFile.task.coordinates, igcFile.task.names);
        }
        else {
            $('#task').hide();
        }

        // Reveal the map and graph. We have to do this before
        // setting the zoom level of the map or plotting the graph.
        $('#igcFileDisplay').show();

        mapControl.addTrack(igcFile.latLong);
        barogramPlot = plotBarogram(igcFile);

        $('#timeSlider').prop('max', igcFile.recordTime.length - 1);
        updateTimeline(0, mapControl);
    }

    $(document).ready(function () {
        var mapControl = createMapControl('map');

        $('#fileControl').change(function () {
            if (this.files.length > 0) {
                var reader = new FileReader();
                reader.onload = function(e)  {
                  try {
                      $('#errorMessage').text('');
                      mapControl.reset();
                      $('#timeSlider').val(0);

                      igcFile = parseIGC(this.result);
                      displayIgc(mapControl);
                  } catch (ex) {
                      if (ex instanceof IGCException) {
                          $('#errorMessage').text(ex.message);
                      }
                      else {
                          throw ex;
                      }
                  }
                };
                reader.readAsText(this.files[0]);
            }
        });

        $('#altitudeUnits').change(function () {
            var altitudeUnit = $(this).val();
            if (altitudeUnit === 'feet') {
                altitudeConversionFactor = 3.2808399;
            }
            else {
                altitudeConversionFactor = 1.0;
            }

            if (igcFile !== null) {
                barogramPlot = plotBarogram();
                updateTimeline($('#timeSlider').val(), mapControl);
            }
        });

        // We need to handle the 'change' event for IE, but
        // 'input' for Chrome and Firefox in order to update smoothly
        // as the range input is dragged.
        $('#timeSlider').on('input', function() {
           updateTimeline($(this).val(), mapControl);
        });
        $('#timeSlider').on('change', function() {
           updateTimeline($(this).val(), mapControl);
        });

         $('#barogram').on('plotclick', function (event, pos, item) {
             console.log('plot click');
             if (item) {
                 updateTimeline(item.dataIndex, mapControl);
                 $('#timeSlider').val(item.dataIndex);
             }
         });
    });
}(jQuery));
<|endoftext|>


<commit_before>// This module defines a reusable data table component using D3.js.
define(function(require) {

  // Load D3 v4 via our custom bundle build output.
  var d3 = require("../d3/d3.min");

  // Configuration.
  var headerBackgroundColor = "lightblue";

  // Constructor function for a data table.
  // Accepts a container `div` DOM element.
  return function Table(div){

    // DOM Elements.
    var tableContainer = d3.select(div),
        tableTitleContainer = tableContainer.append("div")
          .style("font-size", "2em")
          .style("margin-top", "0.5em"),
        tableRoot = tableContainer
          .append("table")
            .attr("class", "table table-bordered"),
        tableHeader = tableRoot
          .append("thead")
            .style("background-color", headerBackgroundColor)
          .append("tr"),
        tableBody = tableRoot
          .append("tbody");

    // Internal variables
    var

        // An array of row objects.
        data,

        // An array of column descriptor objects with properties:
        //  * title - The title of the column to display in the header.
        //  * property - The name of the column property in row objects.
        columns,

        // The human-readable title for the top of the table.
        title;

    // Renders the table.
    function my(){

      // Set the title.
      tableTitleContainer.text(title);

      // Populate the table header.
      var titles = tableHeader.selectAll("th").data(columns);
      titles.exit().remove();
      titles = titles.enter().append("th").merge(titles);
      titles.text(function (d) { return d.title; });

      // Populate the table rows.
      var tr = tableBody.selectAll("tr").data(data);
      tr.exit().remove();
      tr = tr.enter().append("tr").merge(tr);

      // Set the values for each table cell using a nested selection.
      var td = tr.selectAll("td").data(function (row) {
        return columns.map(function (column) {
          return row[column.property];
        });
      });
      td.exit().remove();
      td = td.enter().append("td").merge(td);
      td.text( function (d) { return d; });
    }

    my.data = function (_){
      //return _ ? data = _, my : data;
      if(_){
        data = _;
        return my;
      } else {
        return data;
      }
    };

    my.columns = function (_){
      //return _ ? columns = _, my : columns;
      if(_){
        columns = _;
        return my;
      } else {
        return columns;
      }
    };

    my.title = function (_){
      //return _ ? title = _, my : title;
      if(arguments.length){
        title = _;
        return my;
      } else {
        return title;
      }
    };

    return my;
  }
});
<commit_msg>Refactor table title accessor<commit_after>// This module defines a reusable data table component using D3.js.
define(function(require) {

  // Load D3 v4 via our custom bundle build output.
  var d3 = require("../d3/d3.min");

  // Configuration.
  var headerBackgroundColor = "lightblue";

  // Constructor function for a data table.
  // Accepts a container `div` DOM element.
  return function Table(div){

    // DOM Elements.
    var tableContainer = d3.select(div),
        tableTitleContainer = tableContainer.append("div")
          .style("font-size", "2em")
          .style("margin-top", "0.5em"),
        tableRoot = tableContainer
          .append("table")
            .attr("class", "table table-bordered"),
        tableHeader = tableRoot
          .append("thead")
            .style("background-color", headerBackgroundColor)
          .append("tr"),
        tableBody = tableRoot
          .append("tbody");

    // Internal variables
    var

        // An array of row objects.
        data,

        // An array of column descriptor objects with properties:
        //  * title - The title of the column to display in the header.
        //  * property - The name of the column property in row objects.
        columns,

        // The human-readable title for the top of the table.
        title;

    // Renders the table.
    function my(){

      // Set the title.
      tableTitleContainer.text(title);

      // Populate the table header.
      var titles = tableHeader.selectAll("th").data(columns);
      titles.exit().remove();
      titles = titles.enter().append("th").merge(titles);
      titles.text(function (d) { return d.title; });

      // Populate the table rows.
      var tr = tableBody.selectAll("tr").data(data);
      tr.exit().remove();
      tr = tr.enter().append("tr").merge(tr);

      // Set the values for each table cell using a nested selection.
      var td = tr.selectAll("td").data(function (row) {
        return columns.map(function (column) {
          return row[column.property];
        });
      });
      td.exit().remove();
      td = td.enter().append("td").merge(td);
      td.text( function (d) { return d; });
    }

    my.data = function (_){
      //return _ ? data = _, my : data;
      if(_){
        data = _;
        return my;
      } else {
        return data;
      }
    };

    my.columns = function (_){
      //return _ ? columns = _, my : columns;
      if(_){
        columns = _;
        return my;
      } else {
        return columns;
      }
    };

    my.title = function (_){
      return arguments.length ? (title = _, my) : title;
    };

    return my;
  }
});
<|endoftext|>


<commit_before>import { EditorState, ContentState, Modifier, SelectionState } from 'draft-js';
import regex from '../utils/regex';
import { OrderedMap } from 'immutable';
import syntaxDecorator from '../utils/syntaxDecorator';
import renderDecorator from '../utils/renderDecorator';

const defaultText =
`# Heading
=======
## Sub-heading
-----------
### Another deeper heading

Paragraphs are separated
by a blank line.

\`\`\`bash
$ npm install
$ npm start
\`\`\`

    indentation

Two spaces at the end of a line leave a
line break.

Text attributes _italic_, *italic*, __bold__, **bold**, \`monospace\`, ~~strike~~.

Horizontal rule:
---

img:
![alt text](https://pbs.twimg.com/profile_images/378800000822867536/3f5a00acf72df93528b6bb7cd0a4fd0c.jpeg "Title")

taskList:
- [ ] dick
- [x] fuck

\`\`\`js
const foo = 'bar';
foo.replace(/b/, 'c');
\`\`\`

Bullet list:

  * apples
  * oranges
  * pears
    * apples
    * oranges
    * pears
      * apples
      * oranges
      * pears
        * apples
        * oranges
        * pears

Numbered list:

  1. apples
    1. apples
    2. oranges
    3. pears
      1. apples
      2. oranges
      3. pears
        1. apples
        2. oranges
        3. pears
  2. oranges
  3. pears

| Tables        | Are           | Cool  |
|---------------|:-------------:|-------|
| col 3 is      |    r-l        | $1600 |
| col 2 is      | centered      |   $12 |
| zebra stripes | are neat      |    $1 |

> ar en resnksndf sdpofmopsdmf
sdlknksdnkf
> wofnosidn oi
> oejfosf

> ijewnef
> kneinfie

reist

> sfosdnf
>wnfoefm

A [link](http://example.com).`;

let codeBlockMap = OrderedMap();
let listMap = OrderedMap();
let tableMap = OrderedMap();
let blockQuoteMap = OrderedMap();
const parsedText = defaultText
  .replace(regex.block.codeBlock, (match, p1, p2, p3, offset) => {
    codeBlockMap = codeBlockMap.set(offset.toString(), match.replace(/\n$/, ''));
    return `$$CODEBLOCK__${offset}$$`;
  })
  .replace(regex.block.list, (match, offset) => {
    listMap = listMap.set(offset.toString(), match.replace(/\n$/, ''));
    return `$$LIST__${offset}$$`;
  })
  .replace(regex.block.table, (match, offset) => {
    tableMap = tableMap.set(offset.toString(), match.replace(/\n$/, ''));
    return `$$TABLE__${offset}$$`;
  })
  .replace(regex.block.blockquote, (match, offset) => {
    blockQuoteMap = blockQuoteMap.set(offset.toString(), match.replace(/\n$/, ''));
    return `$$BLOCKQUITE__${offset}$$`;
  });

const defaultContent = ContentState.createFromText(parsedText);

const tokenHackRegexes = [
  {
    withoutGroup: /\$\$BLOCKQUITE__\d+\$\$/g,
    withGroup: /\$\$BLOCKQUITE__(\d+)\$\$/g,
    mapObject: blockQuoteMap
  },
  {
    withoutGroup: /\$\$LIST__\d+\$\$/g,
    withGroup: /\$\$LIST__(\d+)\$\$/g,
    mapObject: listMap
  },
  {
    withoutGroup: /\$\$CODEBLOCK__\d+\$\$/g,
    withGroup: /\$\$CODEBLOCK__(\d+)\$\$/g,
    mapObject: codeBlockMap
  },
  {
    withoutGroup: /\$\$TABLE__\d+\$\$/g,
    withGroup: /\$\$TABLE__(\d+)\$\$/g,
    mapObject: tableMap
  },
];

let parsedContent = defaultContent;

tokenHackRegexes
  .forEach(re => {
    defaultContent.getBlockMap()
      .filter(block => block.getText().match(new RegExp(re.withoutGroup)))
      .forEach(block => {
        const text = block.getText();
        const match = new RegExp(re.withGroup).exec(text);
        parsedContent = Modifier.replaceText(
          parsedContent,
          SelectionState.createEmpty(block.getKey()).set('focusOffset', text.length),
          regex.mapObject.get(match[1])
        );
      });
  });
/* ---------------------------------- */

export default {
  editor: {
    editorState: EditorState.createWithContent(parsedContent, syntaxDecorator),
    viewEditorState: EditorState.createWithContent(parsedContent, renderDecorator),
  },
};
<commit_msg>fix name issue<commit_after>import { EditorState, ContentState, Modifier, SelectionState } from 'draft-js';
import regex from '../utils/regex';
import { OrderedMap } from 'immutable';
import syntaxDecorator from '../utils/syntaxDecorator';
import renderDecorator from '../utils/renderDecorator';

const defaultText =
`# Heading
=======
## Sub-heading
-----------
### Another deeper heading

Paragraphs are separated
by a blank line.

\`\`\`bash
$ npm install
$ npm start
\`\`\`

    indentation

Two spaces at the end of a line leave a
line break.

Text attributes _italic_, *italic*, __bold__, **bold**, \`monospace\`, ~~strike~~.

Horizontal rule:
---

img:
![alt text](https://pbs.twimg.com/profile_images/378800000822867536/3f5a00acf72df93528b6bb7cd0a4fd0c.jpeg "Title")

taskList:
- [ ] dick
- [x] fuck

\`\`\`js
const foo = 'bar';
foo.replace(/b/, 'c');
\`\`\`

Bullet list:

  * apples
  * oranges
  * pears
    * apples
    * oranges
    * pears
      * apples
      * oranges
      * pears
        * apples
        * oranges
        * pears

Numbered list:

  1. apples
    1. apples
    2. oranges
    3. pears
      1. apples
      2. oranges
      3. pears
        1. apples
        2. oranges
        3. pears
  2. oranges
  3. pears

| Tables        | Are           | Cool  |
|---------------|:-------------:|-------|
| col 3 is      |    r-l        | $1600 |
| col 2 is      | centered      |   $12 |
| zebra stripes | are neat      |    $1 |

> ar en resnksndf sdpofmopsdmf
sdlknksdnkf
> wofnosidn oi
> oejfosf

> ijewnef
> kneinfie

reist

> sfosdnf
>wnfoefm

A [link](http://example.com).`;

let codeBlockMap = OrderedMap();
let listMap = OrderedMap();
let tableMap = OrderedMap();
let blockQuoteMap = OrderedMap();
const parsedText = defaultText
  .replace(regex.block.codeBlock, (match, p1, p2, p3, offset) => {
    codeBlockMap = codeBlockMap.set(offset.toString(), match.replace(/\n$/, ''));
    return `$$CODEBLOCK__${offset}$$`;
  })
  .replace(regex.block.list, (match, offset) => {
    listMap = listMap.set(offset.toString(), match.replace(/\n$/, ''));
    return `$$LIST__${offset}$$`;
  })
  .replace(regex.block.table, (match, offset) => {
    tableMap = tableMap.set(offset.toString(), match.replace(/\n$/, ''));
    return `$$TABLE__${offset}$$`;
  })
  .replace(regex.block.blockquote, (match, offset) => {
    blockQuoteMap = blockQuoteMap.set(offset.toString(), match.replace(/\n$/, ''));
    return `$$BLOCKQUITE__${offset}$$`;
  });

const defaultContent = ContentState.createFromText(parsedText);

const tokenHackRegexes = [
  {
    withoutGroup: /\$\$BLOCKQUITE__\d+\$\$/g,
    withGroup: /\$\$BLOCKQUITE__(\d+)\$\$/g,
    mapObject: blockQuoteMap
  },
  {
    withoutGroup: /\$\$LIST__\d+\$\$/g,
    withGroup: /\$\$LIST__(\d+)\$\$/g,
    mapObject: listMap
  },
  {
    withoutGroup: /\$\$CODEBLOCK__\d+\$\$/g,
    withGroup: /\$\$CODEBLOCK__(\d+)\$\$/g,
    mapObject: codeBlockMap
  },
  {
    withoutGroup: /\$\$TABLE__\d+\$\$/g,
    withGroup: /\$\$TABLE__(\d+)\$\$/g,
    mapObject: tableMap
  },
];

let parsedContent = defaultContent;

tokenHackRegexes
  .forEach(re => {
    defaultContent.getBlockMap()
      .filter(block => block.getText().match(new RegExp(re.withoutGroup)))
      .forEach(block => {
        const text = block.getText();
        const match = new RegExp(re.withGroup).exec(text);
        parsedContent = Modifier.replaceText(
          parsedContent,
          SelectionState.createEmpty(block.getKey()).set('focusOffset', text.length),
          re.mapObject.get(match[1])
        );
      });
  });
/* ---------------------------------- */

export default {
  editor: {
    editorState: EditorState.createWithContent(parsedContent, syntaxDecorator),
    viewEditorState: EditorState.createWithContent(parsedContent, renderDecorator),
  },
};
<|endoftext|>


<commit_before>(function ($) {
   'use strict';

    var igcFile = null;
    var barogramPlot = null;
    var altitudeConversionFactor = 1.0; // Conversion from metres to required units

    function plotBarogram() {
        var nPoints = igcFile.recordTime.length;
        var pressureBarogramData = [];
        var gpsBarogramData = [];
        var j;
        var timestamp;

        for (j = 0; j < nPoints; j++) {
            timestamp = igcFile.recordTime[j].getTime();
            pressureBarogramData.push([timestamp, igcFile.pressureAltitude[j] * altitudeConversionFactor]);
            gpsBarogramData.push([timestamp, igcFile.gpsAltitude[j] * altitudeConversionFactor]);
        }

        var baro = $.plot($('#barogram'), [{
            label: 'Pressure altitude',
            data: pressureBarogramData
        }, {
            label: 'GPS altitude',
            data: gpsBarogramData
        }], {
            axisLabels: {
                show: true
            },
            xaxis: {
                mode: 'time',
                timeformat: '%H:%M',
                axisLabel: 'Time (UTC)'
            },
            yaxis: {
                axisLabel: 'Altitude / ' + $('#altitudeUnits').val()
            },

            crosshair: {
                mode: 'x'
            }
        });

        return baro;
    }

    function displayIgc(mapControl) {
        // Display the headers.
        var headerTable = $('#headerInfo tbody');
        headerTable.html('');
        var headerName;
        var headerIndex;
        for (headerIndex = 0; headerIndex < igcFile.headers.length; headerIndex++) {
            headerTable.append(
                $('

').append($('	').text(igcFile.headers[headerIndex].name))
                              .append($('	').text(igcFile.headers[headerIndex].value))
            );
        }

        // Show the task declaration if it is present.
        if (igcFile.task.coordinates.length > 0) {
            $('#task').show();
            var taskList = $('#task ol').first().html('');
            var j;
            for (j = 0; j < igcFile.task.names.length; j++) {
                taskList.append($('

').text(igcFile.task.names[j]));
            }

            mapControl.addTask(igcFile.task.coordinates, igcFile.task.names);
        }
        else {
            $('#task').hide();
        }

        // Reveal the map and graph. We have to do this before
        // setting the zoom level of the map or plotting the graph.
        $('#igcFileDisplay').show();

        mapControl.addTrack(igcFile.latLong);
        barogramPlot = plotBarogram(igcFile);

        $('#timeSlider').prop('max', igcFile.recordTime.length - 1);
        updateTimeline(0, mapControl);
    }

    function updateTimeline (timeIndex, mapControl) {
        var currentPosition = igcFile.latLong[timeIndex];
        var startPosition = igcFile.latLong[0];
        var distance = L.latLng(currentPosition[0], currentPosition[1]).distanceTo(
            L.latLng(startPosition[0], startPosition[1])) / 1000.0;

        var unitName = $('#altitudeUnits').val();
        $('#timePositionDisplay').text(
            igcFile.recordTime[timeIndex].toUTCString() + ': ' +
            (igcFile.pressureAltitude[timeIndex] * altitudeConversionFactor).toFixed(0) + ' ' +
            unitName + ' (barometric) / ' +
            (igcFile.gpsAltitude[timeIndex] * altitudeConversionFactor).toFixed(0) + ' ' +
            unitName + ' (GPS); ' +
            distance.toFixed(1) + ' km from takeoff'
        );

        mapControl.setTimeMarker(timeIndex);

        barogramPlot.lockCrosshair({
           x: igcFile.recordTime[timeIndex].getTime(),
           y: 1.0
        });
    }

    $(document).ready(function () {
        var mapControl = createMapControl('map');

        $('#fileControl').change(function () {
            if (this.files.length > 0) {
                var reader = new FileReader();
                reader.onload = function(e)  {
                  try {
                      $('#errorMessage').text('');
                      mapControl.reset();
                      $('#timeSlider').val(0);

                      igcFile = parseIGC(this.result);
                      displayIgc(mapControl);
                  } catch (ex) {
                      if (ex instanceof IGCException) {
                          $('#errorMessage').text(ex.message);
                      }
                      else {
                          throw ex;
                      }
                  }
                };
                reader.readAsText(this.files[0]);
            }
        });

        $('#altitudeUnits').change(function () {
            var altitudeUnit = $(this).val();
            if (altitudeUnit === 'feet') {
                altitudeConversionFactor = 3.2808399;
            }
            else {
                altitudeConversionFactor = 1.0;
            }

            if (igcFile !== null) {
                barogramPlot = plotBarogram();
                updateTimeline($('#timeSlider').val(), mapControl);
            }
        });

        // We need to handle the 'change' event for IE, but
        // 'input' for Chrome and Firefox in order to update smoothly
        // as the range input is dragged.
        $('#timeSlider').on('input', function() {
           updateTimeline($(this).val(), mapControl);
        });
        $('#timeSlider').on('change', function() {
           updateTimeline($(this).val(), mapControl);
        });
    });
}(jQuery));
<commit_msg>Fix JSLint warning.<commit_after>(function ($) {
   'use strict';

    var igcFile = null;
    var barogramPlot = null;
    var altitudeConversionFactor = 1.0; // Conversion from metres to required units

    function plotBarogram() {
        var nPoints = igcFile.recordTime.length;
        var pressureBarogramData = [];
        var gpsBarogramData = [];
        var j;
        var timestamp;

        for (j = 0; j < nPoints; j++) {
            timestamp = igcFile.recordTime[j].getTime();
            pressureBarogramData.push([timestamp, igcFile.pressureAltitude[j] * altitudeConversionFactor]);
            gpsBarogramData.push([timestamp, igcFile.gpsAltitude[j] * altitudeConversionFactor]);
        }

        var baro = $.plot($('#barogram'), [{
            label: 'Pressure altitude',
            data: pressureBarogramData
        }, {
            label: 'GPS altitude',
            data: gpsBarogramData
        }], {
            axisLabels: {
                show: true
            },
            xaxis: {
                mode: 'time',
                timeformat: '%H:%M',
                axisLabel: 'Time (UTC)'
            },
            yaxis: {
                axisLabel: 'Altitude / ' + $('#altitudeUnits').val()
            },

            crosshair: {
                mode: 'x'
            }
        });

        return baro;
    }

    function updateTimeline (timeIndex, mapControl) {
        var currentPosition = igcFile.latLong[timeIndex];
        var startPosition = igcFile.latLong[0];
        var distance = L.latLng(currentPosition[0], currentPosition[1]).distanceTo(
            L.latLng(startPosition[0], startPosition[1])) / 1000.0;

        var unitName = $('#altitudeUnits').val();
        $('#timePositionDisplay').text(
            igcFile.recordTime[timeIndex].toUTCString() + ': ' +
            (igcFile.pressureAltitude[timeIndex] * altitudeConversionFactor).toFixed(0) + ' ' +
            unitName + ' (barometric) / ' +
            (igcFile.gpsAltitude[timeIndex] * altitudeConversionFactor).toFixed(0) + ' ' +
            unitName + ' (GPS); ' +
            distance.toFixed(1) + ' km from takeoff'
        );

        mapControl.setTimeMarker(timeIndex);

        barogramPlot.lockCrosshair({
           x: igcFile.recordTime[timeIndex].getTime(),
           y: 1.0
        });
    }

    function displayIgc(mapControl) {
        // Display the headers.
        var headerTable = $('#headerInfo tbody');
        headerTable.html('');
        var headerName;
        var headerIndex;
        for (headerIndex = 0; headerIndex < igcFile.headers.length; headerIndex++) {
            headerTable.append(
                $('

').append($('	').text(igcFile.headers[headerIndex].name))
                              .append($('	').text(igcFile.headers[headerIndex].value))
            );
        }

        // Show the task declaration if it is present.
        if (igcFile.task.coordinates.length > 0) {
            $('#task').show();
            var taskList = $('#task ol').first().html('');
            var j;
            for (j = 0; j < igcFile.task.names.length; j++) {
                taskList.append($('

').text(igcFile.task.names[j]));
            }

            mapControl.addTask(igcFile.task.coordinates, igcFile.task.names);
        }
        else {
            $('#task').hide();
        }

        // Reveal the map and graph. We have to do this before
        // setting the zoom level of the map or plotting the graph.
        $('#igcFileDisplay').show();

        mapControl.addTrack(igcFile.latLong);
        barogramPlot = plotBarogram(igcFile);

        $('#timeSlider').prop('max', igcFile.recordTime.length - 1);
        updateTimeline(0, mapControl);
    }

    $(document).ready(function () {
        var mapControl = createMapControl('map');

        $('#fileControl').change(function () {
            if (this.files.length > 0) {
                var reader = new FileReader();
                reader.onload = function(e)  {
                  try {
                      $('#errorMessage').text('');
                      mapControl.reset();
                      $('#timeSlider').val(0);

                      igcFile = parseIGC(this.result);
                      displayIgc(mapControl);
                  } catch (ex) {
                      if (ex instanceof IGCException) {
                          $('#errorMessage').text(ex.message);
                      }
                      else {
                          throw ex;
                      }
                  }
                };
                reader.readAsText(this.files[0]);
            }
        });

        $('#altitudeUnits').change(function () {
            var altitudeUnit = $(this).val();
            if (altitudeUnit === 'feet') {
                altitudeConversionFactor = 3.2808399;
            }
            else {
                altitudeConversionFactor = 1.0;
            }

            if (igcFile !== null) {
                barogramPlot = plotBarogram();
                updateTimeline($('#timeSlider').val(), mapControl);
            }
        });

        // We need to handle the 'change' event for IE, but
        // 'input' for Chrome and Firefox in order to update smoothly
        // as the range input is dragged.
        $('#timeSlider').on('input', function() {
           updateTimeline($(this).val(), mapControl);
        });
        $('#timeSlider').on('change', function() {
           updateTimeline($(this).val(), mapControl);
        });
    });
}(jQuery));
<|endoftext|>


<commit_before>define(function(require, exports, module) {
    main.consumes = [
        "editors", "ui", "settings", "tabManager", "ace", "menus", "commands",
        "console", "ace.status"
    ];
    main.provides = ["immediate"];
    return main;

    function main(options, imports, register) {
        var editors   = imports.editors;
        var tabs      = imports.tabManager;
        var ui        = imports.ui;
        var menus     = imports.menus;
        var commands  = imports.commands;
        var c9console = imports.console;
        var aceHandle = imports.ace;
        var aceStatus = imports["ace.status"];

        var Repl     = require("plugins/c9.ide.ace.repl/repl").Repl;
        var markup   = require("text!./immediate.xml");

        var counter  = 0;

        /***** Initialization *****/

        var extensions = [];

        var handle = editors.register("immediate", "Immediate Window",
                                      Immediate, extensions);
        var emit   = handle.getEmitter();

        var replTypes = {}; //Shared across Immediate windows
        var theme;

        handle.on("load", function(){
            handle.addElement(
                tabs.getElement("mnuEditors").appendChild(
                    new ui.item({
                        caption : "New Immediate Window",
                        onclick : function(e){
                            tabs.open({
                                active     : true,
                                pane       : this.parentNode.pane,
                                editorType : "immediate"
                            }, function(){});
                        }
                    })
                )
            );

            menus.addItemByPath("Window/New Immediate Window", new ui.item({
                onclick : function(){
                    tabs.open({
                        active     : true,
                        pane       : this.parentNode.pane,
                        editorType : "immediate"
                    }, function(){});
                }
            }), 31, handle);

            commands.addCommand({
                name    : "showimmediate",
                group   : "Panels",
                exec    : function (editor) {
                    // Search for the output pane
                    if (search()) return;

                    // If not found show the console
                    c9console.show();

                    // Search again
                    if (search()) return;

                    // Else open the output panel in the console
                    tabs.open({
                        editorType : "immediate",
                        active     : true,
                        pane        : c9console.getPanes()[0],
                    }, function(){});
                }
            }, handle);

            // Insert some CSS
            ui.insertCss(require("text!./style.css"), options.staticPrefix, handle);
        });

        //Search through pages
        function search(){
            return !tabs.getTabs().every(function(tab){
                if (tab.editorType == "immediate") {
                    tabs.focusTab(tab);
                    return false;
                }
                return true;
            });
        }

        function Immediate(){
            var Baseclass = editors.findEditor("ace");

            var deps   = main.consumes.splice(0, main.consumes.length - 1);
            var plugin = new Baseclass(true, [], deps);
            // var emit   = plugin.getEmitter();

            var ddType, btnClear, ace, menu;

            plugin.on("draw", function(e){
                aceStatus.draw();

                // Create UI elements
                ui.insertMarkup(e.tab, markup, plugin);

                ddType    = plugin.getElement("ddType");
                btnClear  = plugin.getElement("btnClear");
                menu      = plugin.getElement("menu");

                ace = plugin.ace;

                ace.setOption("printMargin", false);
                ace.setOption("scrollPastEnd", 0);
                ace.setOption("showFoldWidgets", false);
                ace.setOption("highlightActiveLine", false);
                ace.setOption("highlightGutterLine", false);
                // ace.setOption("fontSize", 11);
                // ace.container.style.lineHeight = "17px";

                e.htmlNode.className += " immediate";

                ddType.on("afterchange", function(){
                    if (currentDocument)
                        currentDocument.getSession().changeType(ddType.selectedType);
                });
                btnClear.on("click", function(){
                    plugin.clear();
                    btnClear.blur();
                });

                for (var type in replTypes){
                    var t = replTypes[type];
                    addType(t.caption, type, t.plugin);
                }

                handle.on("addEvaluator", function(e){
                    addType(e.caption, e.id, e.plugin);
                });

                menu.on("itemclick", function(e) {
                    var value = e.relatedNode.getAttribute("value");
                    ddType.setType(value);
                });

                function update(e){
                    if (e && !e.value)
                        return;
                    var items = menu.childNodes;
                    var value = ddType.selectedType || items[0].value;
                    var selectedItem;
                    items.forEach(function(item){
                        var selected = item.value == value ? true :  false;
                        if (selected) selectedItem = item;
                        item.setAttribute("selected", selected);
                    });

                    ddType.setType(value);
                }

                ddType.setAttribute("submenu", menu);
                ddType.setType = function (type) {
                    if (type == ddType.selectedType || !replTypes[type])
                        return;
                    ddType.selectedType = type;
                    ddType.setAttribute("caption", replTypes[type].caption);
                    ddType.dispatchEvent("afterchange");
                };

                function setTheme(e){
                    theme = e.theme;
                    if (!theme) return;

                    btnClear.parentNode.$ext.className = "bar-status "
                        + (theme.isDark ? "ace_dark" : "");

                }

                aceHandle.on("themeChange", setTheme, plugin);
                setTheme({theme: aceHandle.theme});

                menu.on("prop.visible", update);
                update();
            });

            /***** Method *****/

            function addType(caption, value, plugin){
                var item = menu.appendChild(new ui.item({
                    caption : caption,
                    value   : value,
                    type    : "radio"
                }));

                plugin.addElement(item);
            }

            function setActiveEvaluator(value){
                ddType.setAttribute("value", value);
            }

            // Set the tab in loading state - later this could be the output block
            // currentDocument.tab.className.add("loading");
            // settings.save();

            /***** Lifecycle *****/

            plugin.on("load", function(){
            });

            var currentDocument;
            plugin.on("documentLoad", function(e){
                var doc     = e.doc;
                var session = doc.getSession();

                doc.undoManager.on("change", function(e){
                    if (!doc.undoManager.isAtBookmark())
                        doc.undoManager.bookmark();
                });

                doc.title = "Immediate";

                if (session.repl) return;

                session.changeType = function(type){
                    handle.findEvaluator(type, function(type, evaluator){
                        session.type = type;

                        if (!session.repl) {
                            session.repl = new Repl(session.session, {
                                mode      : evaluator.mode,
                                evaluator : evaluator,
                                message   : evaluator.message
                            });

                            if (currentDocument
                              && currentDocument.getSession() == session)
                                session.repl.attach(ace);
                        }
                        else {
                            session.repl.setEvaluator(evaluator);
                            session.repl.session.setMode(evaluator.mode);
                        }
                    });
                };

                doc.value = "";

                session.changeType(session.type || ddType.selectedType);
            });
            plugin.on("documentActivate", function(e){
                currentDocument = e.doc;
                var session = e.doc.getSession();

                if (session.type) {
                    ddType.setType(session.type);
                }

                if (session.repl)
                    session.repl.attach(ace);
            });
            plugin.on("documentUnload", function(e){
                var session = e.doc.getSession();
                if (session.repl)
                    session.repl.detach();
                // TODO: this breaks moving repl between splits
                // delete session.repl;
            });
            plugin.on("getState", function(e){
                // @todo at one for each value container
                e.state.type      = e.doc.getSession().type;
            });
            plugin.on("setState", function(e){
                if (e.state.type) {
                    e.doc.getSession().type = e.state.type;
                    ddType.setType(e.state.type);
                }
            });
            plugin.on("clear", function(){
            });
            plugin.on("focus", function(){
            });
            plugin.on("enable", function(){
            });
            plugin.on("disable", function(){
            });
            plugin.on("unload", function(){
            });

            /***** Register and define API *****/

            /**
             * Immediate Pane for Cloud9 IDE
             * @class immediate.Immediate
             * @extends Editor
             */
            /**
             * The type of editor. Use this to create an immediate pane using
             * {@link tabManager#openEditor} or {@link editors#createEditor}.
             * @property {"immediate"} type
             * @readonly
             */
            plugin.freezePublicAPI({
                /**
                 *
                 */
                setActiveEvaluator : setActiveEvaluator
            });

            plugin.load("immediate" + counter++);

            return plugin;
        }

        /**
         * The immediate handle, provides an API for adding
         * {@link Evaluator evaluators} to the immediate panes.
         * An evaluator is a plugin that can take the expressions from the
         * multi-line REPL and return resuls. The results can be
         * rendered as HTML and are fully interactive.
         *
         * This is the object you get when you request the immediate service
         * in your plugin.
         *
         * Example:
         *
         *     define(function(require, exports, module) {
         *         main.consumes = ["immediate", "Plugin"];
         *         main.provides = ["myplugin"];
         *         return main;
         *
         *         function main(options, imports, register) {
         *             var immediate = imports.immediate;
         *             var plugin    = new imports.Plugin("Your Name", main.consumes);
         *
         *             plugin.on("load", function(){
         *                 var evaluator = {
         *                     mode        : "ace/mode/go",
         *                     message     : "",
         *                     canEvaluate : function(str) { return str.trim() ? true : false; },
         *                     evaluate    : function(expression, cell, done) {
         *
         *                         executeCommand(expression, function(result){
         *                             cell.addWidget({
         *                                 html       : "
"
         *                                     + result + "
",
         *                                 coverLine  : true,
         *                                 fixedWidth : true
         *                             });
         *
         *                             done();
         *                         });
         *
         *                     }
         *                 };
         *
         *                 immediate.addEvaluator("Go Language", "go", evaluator, plugin);
         *             });
         *         });
         *     });
         *
         *
         * @class immediate
         * @extends Plugin
         * @singleton
         */
        handle.freezePublicAPI({
            _events : [
                /**
                 * Fires when an evaluator is added.
                 * @event addEvaluator
                 * @param {Object}              e
                 * @param {String}              e.caption     The caption of the evaluator.
                 * @param {String}              e.id          The unique identifier of the evaluator.
                 * @param {Evaluator} e.evaluator   The evaluator.
                 * @param {Plugin}              e.plugin      The plugin responsible for adding the evaluator.
                 */
                "addEvaluator",
                /**
                 * Fires when an evaluator is removed.
                 * @event removeEvaluator
                 * @param {Object}              e
                 * @param {String}              e.caption     The caption of the evaluator.
                 * @param {String}              e.id          The unique identifier of the evaluator.
                 * @param {Evaluator} e.evaluator   The evaluator.
                 * @param {Plugin}              e.plugin      The plugin responsible for adding the evaluator.
                 */
                "removeEvaluator"
            ],

            /**
             * Adds a new evaluator to all immediate panes. The user is able
             * to choose the evaluator from a dropdown in the UI of the
             * immediate pane.
             * @param {String}              caption     The caption in the dropdown.
             * @param {String}              id          The unique identifier of this evaluator.
             * @param {Evaluator} evaluator   The evaluator for your runtime.
             * @param {Plugin}              plugin      The plugin responsible for adding the evaluator.
             * @fires addEvaluator
             */
            addEvaluator : function(caption, id, evaluator, plugin){
                if (replTypes[id])
                    throw new Error("An evaluator is already registered with "
                        + "the id '" + id + "'");

                replTypes[id] = {
                    caption   : caption,
                    id        : id,
                    evaluator : evaluator,
                    plugin    : plugin
                };
                emit("addEvaluator", replTypes[id]);

                plugin.addOther(function(){
                    handle.removeEvaluator(id);
                });
            },

            /**
             * Retrieves an evaluator based on it's id. When the evaluator is
             * not yet registered, the callback will be returned when the
             * evaluator is registered.
             * @param {String}              id                  The id of the evaluator to retrieve.
             * @param {Function}            callback            Called when the evaluator is available.
             * @param {Error}               callback.id         The id of the requested evaluator.
             * @param {Evaluator} callback.evaluator  The evaluator requested.
             */
            findEvaluator : function(id, callback){
                if (!id || !replTypes[id]) {
                    handle.on("addEvaluator", function wait(e){
                        if (!id || e.id == id)
                            callback(e.id, replTypes[e.id].evaluator);

                        handle.off("addEvaluator", wait);
                    });
                }
                else {
                    callback(id, replTypes[id].evaluator);
                }
            },

            /**
             * Removes an evaluator from all immediate panes.
             * @param {String} id  The unique identifier of the evaluator to remove.
             */
            removeEvaluator : function(id){
                emit("removeEvaluator", replTypes[id]);
                delete replTypes[id];
            }
        });

        register(null, {
            immediate: handle
        });
    }
});<commit_msg>Make sure apf doesnt disallow selection<commit_after>define(function(require, exports, module) {
    main.consumes = [
        "editors", "ui", "settings", "tabManager", "ace", "menus", "commands",
        "console", "ace.status"
    ];
    main.provides = ["immediate"];
    return main;

    function main(options, imports, register) {
        var editors   = imports.editors;
        var tabs      = imports.tabManager;
        var ui        = imports.ui;
        var menus     = imports.menus;
        var commands  = imports.commands;
        var c9console = imports.console;
        var aceHandle = imports.ace;
        var aceStatus = imports["ace.status"];

        var Repl     = require("plugins/c9.ide.ace.repl/repl").Repl;
        var markup   = require("text!./immediate.xml");

        var counter  = 0;

        /***** Initialization *****/

        var extensions = [];

        var handle = editors.register("immediate", "Immediate Window",
                                      Immediate, extensions);
        var emit   = handle.getEmitter();

        var replTypes = {}; //Shared across Immediate windows
        var theme;

        handle.on("load", function(){
            handle.addElement(
                tabs.getElement("mnuEditors").appendChild(
                    new ui.item({
                        caption : "New Immediate Window",
                        onclick : function(e){
                            tabs.open({
                                active     : true,
                                pane       : this.parentNode.pane,
                                editorType : "immediate"
                            }, function(){});
                        }
                    })
                )
            );

            menus.addItemByPath("Window/New Immediate Window", new ui.item({
                onclick : function(){
                    tabs.open({
                        active     : true,
                        pane       : this.parentNode.pane,
                        editorType : "immediate"
                    }, function(){});
                }
            }), 31, handle);

            commands.addCommand({
                name    : "showimmediate",
                group   : "Panels",
                exec    : function (editor) {
                    // Search for the output pane
                    if (search()) return;

                    // If not found show the console
                    c9console.show();

                    // Search again
                    if (search()) return;

                    // Else open the output panel in the console
                    tabs.open({
                        editorType : "immediate",
                        active     : true,
                        pane        : c9console.getPanes()[0],
                    }, function(){});
                }
            }, handle);

            // Insert some CSS
            ui.insertCss(require("text!./style.css"), options.staticPrefix, handle);
        });

        //Search through pages
        function search(){
            return !tabs.getTabs().every(function(tab){
                if (tab.editorType == "immediate") {
                    tabs.focusTab(tab);
                    return false;
                }
                return true;
            });
        }

        function Immediate(){
            var Baseclass = editors.findEditor("ace");

            var deps   = main.consumes.splice(0, main.consumes.length - 1);
            var plugin = new Baseclass(true, [], deps);
            // var emit   = plugin.getEmitter();

            var ddType, btnClear, ace, menu;

            plugin.on("draw", function(e){
                aceStatus.draw();

                // Create UI elements
                ui.insertMarkup(e.tab, markup, plugin);

                ddType    = plugin.getElement("ddType");
                btnClear  = plugin.getElement("btnClear");
                menu      = plugin.getElement("menu");

                ace = plugin.ace;

                ace.setOption("printMargin", false);
                ace.setOption("scrollPastEnd", 0);
                ace.setOption("showFoldWidgets", false);
                ace.setOption("highlightActiveLine", false);
                ace.setOption("highlightGutterLine", false);
                // ace.setOption("fontSize", 11);
                // ace.container.style.lineHeight = "17px";

                e.htmlNode.className += " immediate";

                // Allow Selection (APF)
                e.tab.textselect = true;

                ddType.on("afterchange", function(){
                    if (currentDocument)
                        currentDocument.getSession().changeType(ddType.selectedType);
                });
                btnClear.on("click", function(){
                    plugin.clear();
                    btnClear.blur();
                });

                for (var type in replTypes){
                    var t = replTypes[type];
                    addType(t.caption, type, t.plugin);
                }

                handle.on("addEvaluator", function(e){
                    addType(e.caption, e.id, e.plugin);
                });

                menu.on("itemclick", function(e) {
                    var value = e.relatedNode.getAttribute("value");
                    ddType.setType(value);
                });

                function update(e){
                    if (e && !e.value)
                        return;
                    var items = menu.childNodes;
                    var value = ddType.selectedType || items[0].value;
                    var selectedItem;
                    items.forEach(function(item){
                        var selected = item.value == value ? true :  false;
                        if (selected) selectedItem = item;
                        item.setAttribute("selected", selected);
                    });

                    ddType.setType(value);
                }

                ddType.setAttribute("submenu", menu);
                ddType.setType = function (type) {
                    if (type == ddType.selectedType || !replTypes[type])
                        return;
                    ddType.selectedType = type;
                    ddType.setAttribute("caption", replTypes[type].caption);
                    ddType.dispatchEvent("afterchange");
                };

                function setTheme(e){
                    theme = e.theme;
                    if (!theme) return;

                    btnClear.parentNode.$ext.className = "bar-status "
                        + (theme.isDark ? "ace_dark" : "");

                }

                aceHandle.on("themeChange", setTheme, plugin);
                setTheme({theme: aceHandle.theme});

                menu.on("prop.visible", update);
                update();
            });

            /***** Method *****/

            function addType(caption, value, plugin){
                var item = menu.appendChild(new ui.item({
                    caption : caption,
                    value   : value,
                    type    : "radio"
                }));

                plugin.addElement(item);
            }

            function setActiveEvaluator(value){
                ddType.setAttribute("value", value);
            }

            // Set the tab in loading state - later this could be the output block
            // currentDocument.tab.className.add("loading");
            // settings.save();

            /***** Lifecycle *****/

            plugin.on("load", function(){
            });

            var currentDocument;
            plugin.on("documentLoad", function(e){
                var doc     = e.doc;
                var session = doc.getSession();

                doc.undoManager.on("change", function(e){
                    if (!doc.undoManager.isAtBookmark())
                        doc.undoManager.bookmark();
                });

                doc.title = "Immediate";

                if (session.repl) return;

                session.changeType = function(type){
                    handle.findEvaluator(type, function(type, evaluator){
                        session.type = type;

                        if (!session.repl) {
                            session.repl = new Repl(session.session, {
                                mode      : evaluator.mode,
                                evaluator : evaluator,
                                message   : evaluator.message
                            });

                            if (currentDocument
                              && currentDocument.getSession() == session)
                                session.repl.attach(ace);
                        }
                        else {
                            session.repl.setEvaluator(evaluator);
                            session.repl.session.setMode(evaluator.mode);
                        }
                    });
                };

                doc.value = "";

                session.changeType(session.type || ddType.selectedType);
            });
            plugin.on("documentActivate", function(e){
                currentDocument = e.doc;
                var session = e.doc.getSession();

                if (session.type) {
                    ddType.setType(session.type);
                }

                if (session.repl)
                    session.repl.attach(ace);
            });
            plugin.on("documentUnload", function(e){
                var session = e.doc.getSession();
                if (session.repl)
                    session.repl.detach();
                // TODO: this breaks moving repl between splits
                // delete session.repl;
            });
            plugin.on("getState", function(e){
                // @todo at one for each value container
                e.state.type      = e.doc.getSession().type;
            });
            plugin.on("setState", function(e){
                if (e.state.type) {
                    e.doc.getSession().type = e.state.type;
                    ddType.setType(e.state.type);
                }
            });
            plugin.on("clear", function(){
            });
            plugin.on("focus", function(){
            });
            plugin.on("enable", function(){
            });
            plugin.on("disable", function(){
            });
            plugin.on("unload", function(){
            });

            /***** Register and define API *****/

            /**
             * Immediate Pane for Cloud9 IDE
             * @class immediate.Immediate
             * @extends Editor
             */
            /**
             * The type of editor. Use this to create an immediate pane using
             * {@link tabManager#openEditor} or {@link editors#createEditor}.
             * @property {"immediate"} type
             * @readonly
             */
            plugin.freezePublicAPI({
                /**
                 *
                 */
                setActiveEvaluator : setActiveEvaluator
            });

            plugin.load("immediate" + counter++);

            return plugin;
        }

        /**
         * The immediate handle, provides an API for adding
         * {@link Evaluator evaluators} to the immediate panes.
         * An evaluator is a plugin that can take the expressions from the
         * multi-line REPL and return resuls. The results can be
         * rendered as HTML and are fully interactive.
         *
         * This is the object you get when you request the immediate service
         * in your plugin.
         *
         * Example:
         *
         *     define(function(require, exports, module) {
         *         main.consumes = ["immediate", "Plugin"];
         *         main.provides = ["myplugin"];
         *         return main;
         *
         *         function main(options, imports, register) {
         *             var immediate = imports.immediate;
         *             var plugin    = new imports.Plugin("Your Name", main.consumes);
         *
         *             plugin.on("load", function(){
         *                 var evaluator = {
         *                     mode        : "ace/mode/go",
         *                     message     : "",
         *                     canEvaluate : function(str) { return str.trim() ? true : false; },
         *                     evaluate    : function(expression, cell, done) {
         *
         *                         executeCommand(expression, function(result){
         *                             cell.addWidget({
         *                                 html       : "
"
         *                                     + result + "
",
         *                                 coverLine  : true,
         *                                 fixedWidth : true
         *                             });
         *
         *                             done();
         *                         });
         *
         *                     }
         *                 };
         *
         *                 immediate.addEvaluator("Go Language", "go", evaluator, plugin);
         *             });
         *         });
         *     });
         *
         *
         * @class immediate
         * @extends Plugin
         * @singleton
         */
        handle.freezePublicAPI({
            _events : [
                /**
                 * Fires when an evaluator is added.
                 * @event addEvaluator
                 * @param {Object}              e
                 * @param {String}              e.caption     The caption of the evaluator.
                 * @param {String}              e.id          The unique identifier of the evaluator.
                 * @param {Evaluator} e.evaluator   The evaluator.
                 * @param {Plugin}              e.plugin      The plugin responsible for adding the evaluator.
                 */
                "addEvaluator",
                /**
                 * Fires when an evaluator is removed.
                 * @event removeEvaluator
                 * @param {Object}              e
                 * @param {String}              e.caption     The caption of the evaluator.
                 * @param {String}              e.id          The unique identifier of the evaluator.
                 * @param {Evaluator} e.evaluator   The evaluator.
                 * @param {Plugin}              e.plugin      The plugin responsible for adding the evaluator.
                 */
                "removeEvaluator"
            ],

            /**
             * Adds a new evaluator to all immediate panes. The user is able
             * to choose the evaluator from a dropdown in the UI of the
             * immediate pane.
             * @param {String}              caption     The caption in the dropdown.
             * @param {String}              id          The unique identifier of this evaluator.
             * @param {Evaluator} evaluator   The evaluator for your runtime.
             * @param {Plugin}              plugin      The plugin responsible for adding the evaluator.
             * @fires addEvaluator
             */
            addEvaluator : function(caption, id, evaluator, plugin){
                if (replTypes[id])
                    throw new Error("An evaluator is already registered with "
                        + "the id '" + id + "'");

                replTypes[id] = {
                    caption   : caption,
                    id        : id,
                    evaluator : evaluator,
                    plugin    : plugin
                };
                emit("addEvaluator", replTypes[id]);

                plugin.addOther(function(){
                    handle.removeEvaluator(id);
                });
            },

            /**
             * Retrieves an evaluator based on it's id. When the evaluator is
             * not yet registered, the callback will be returned when the
             * evaluator is registered.
             * @param {String}              id                  The id of the evaluator to retrieve.
             * @param {Function}            callback            Called when the evaluator is available.
             * @param {Error}               callback.id         The id of the requested evaluator.
             * @param {Evaluator} callback.evaluator  The evaluator requested.
             */
            findEvaluator : function(id, callback){
                if (!id || !replTypes[id]) {
                    handle.on("addEvaluator", function wait(e){
                        if (!id || e.id == id)
                            callback(e.id, replTypes[e.id].evaluator);

                        handle.off("addEvaluator", wait);
                    });
                }
                else {
                    callback(id, replTypes[id].evaluator);
                }
            },

            /**
             * Removes an evaluator from all immediate panes.
             * @param {String} id  The unique identifier of the evaluator to remove.
             */
            removeEvaluator : function(id){
                emit("removeEvaluator", replTypes[id]);
                delete replTypes[id];
            }
        });

        register(null, {
            immediate: handle
        });
    }
});<|endoftext|>