<commit_before>var options = options || {};  // allows specifications to be added if the variable is already present

function read(URL, callback) {
    /**
    reads the contents of the file at the URL,
    converts it into a string,
    puts the string into a
, and then
    calls the callback function (which has no arguments)
    with "this" equalling the

    */
    var file = new XMLHttpRequest();
    file.open("GET", URL);  // Don't add false as an extra argument (browsers don't like it). (default: asynchronous=true)
    file.onreadystatechange = function () {
        if(file.readyState === 4) {  // Is it done?
            if(file.status === 200 || file.status == 0) {  // Was it successful?
                // file.responseXML might have something
                var container = document.createElement("div");
                container.innerHTML = file.responseText;
                /*
                var tags = container.children;
                for (var index=0; index<tags.length; index++) {
                    var tag = document.createElement(tags[index].tagName);
                    if (tag.tagName != "script") {
                        tag.appendChild(document.createTextNode(tags[index].innerHTML));
                        container.insertBefore(tag, tags[index]);
                        tags[index+1].outerHTML = "";
                    }
                }
                */
                // This is necessary because HTML5 doesn't think script tags and innerHTML should go together (for security reasons).
                var scripts = file.responseText.split(""))));
                            container.insertBefore(scriptTag, container.getElementsByTagName("script")[index-1]);
                            var oldTag = container.getElementsByTagName("script")[index];
                            oldTag.parentNode.removeChild(oldTag);
                        }
                    });
                }
                callback.call(container);  // .call(calling object / value of "this", function arguments (listed individually))  .apply has function arguments in an array
                // You could also use callback(argument(s)) like a normal function, but it wouldn't change the value of "this".
            }
        }
    }
    file.send();
}

function pageJump(ID) {
    /**
    makes a section to jump to certain parts of the page
    */
    document.getElementsByTagName("h1")[0].id = "top";
    var division = document.getElementById(ID);
    var contents = document.createElement("div");
    contents.className = "list";
    contents.innerHTML = "

Jump to:
";
    var sections = division.getElementsByTagName("h2");
    var toTop = document.createElement("a");
    toTop.href = "#top";
    toTop.innerHTML = "To top";
    var listItems = "";  // I need this variable to hold the list items because trying to add
 at the beginning and
 at the end separately causes it to fill in the
 immediately after the
 and omit the real

    for (var index=0; index<sections.length; index++) {  // I would use (var in array), but index exceeds entries.length for no apparent reason
        var inside = sections[index].innerHTML.trim();  // The inner HTML has a bunch of whitespace for no apparent reason.
        sections[index].id = inside;
        listItems += "
" + inside + "
";
        division.insertBefore(toTop.cloneNode(true), division.getElementsByTagName("h2")[index].nextSibling);  // inserts after

        // toTop needs to be cloned so it doesn't keep getting reasigned to the next place (it also needs to have true to clone all children of the node, although it doesn't apply here)
    }
    contents.innerHTML += "
" + listItems + "

";
    division.parentNode.insertBefore(contents, division);  // .insertBefore() only works for the immediate descendants of the parent
}

//This is able to run without waiting for anything else to load.

// makes my custom tag which underlines things
document.createElement("under");
// makes my custom tag which overlines things
document.createElement("over");

// adds the universal formatting
var style = document.createElement("link");
style.rel = "stylesheet";
style.href = "https://coolprogramminguser.github.io/Standards/formatting.css";
document.head.insertBefore(style, document.head.children[0]);

// links a favicon
var faviconNumber = 1;
var icon = document.createElement("link");
icon.rel = "icon";
var circleColors = ["Red", "Yellow", "Green", "Cyan", "Blue", "Magenta"];
icon.href = "https://coolprogramminguser.github.io/Standards/favicons/Red Circle.ico";
document.head.insertBefore(icon, document.head.children[0]);

// cycles the favicon
setInterval(function() {
    icon.href = "https://coolprogramminguser.github.io/Standards/favicons/" + circleColors[faviconNumber] + " Circle.ico";
    faviconNumber = faviconNumber<circleColors.length-1 ? faviconNumber+1 : 0;
}, 1000);

window.addEventListener("load", function() {  // This waits for everything past the script import to load before running.

    // surrounds the  content with a
 tag
    document.body.innerHTML = "
" + document.body.innerHTML + "
";

    // adds a title to the page
    var title = document.createElement("h1");
    title.style.color = "white";
    title.innerHTML = document.title;
    document.body.insertBefore(title, document.body.children[0]);

    // surrounds every list with

    var orderedLists = document.getElementsByTagName("ol");
    var unorderedLists = document.getElementsByTagName("ul");
    for (var index=0; index<orderedLists.length; index++) {
        orderedLists[index].outerHTML = "
" + orderedLists[index].outerHTML + "
";
        orderedLists[index].style.visibility = "visible";
    }
    for (var index=0; index<unorderedLists.length; index++) {
        unorderedLists[index].outerHTML = "
" + unorderedLists[index].outerHTML + "
";
        unorderedLists[index].style.visibility = "visible";
    }

    // interprets condensed tables
    var tables = document.getElementsByClassName("compact");
    for (var counter=0; counter<tables.length; counter++) {
        var table = tables[counter];
        var headings = table.getElementsByTagName("th");
        for (var index=0; index<headings.length; index++) {
            var parent = headings[index].parentNode;
            var newHeadings = headings[index].innerHTML.split("|");
            parent.removeChild(headings[index]);
            newHeadings.forEach(function(heading) {
                parent.innerHTML += "" + heading.trim() + "	";
            });
        }
        var data = table.getElementsByTagName("td");
        for (var index=0; index<data.length; index++) {
            var parent = data[index].parentNode;
            var newData = data[index].innerHTML.split("|");
            parent.removeChild(data[index]);
            newData.forEach(function(item) {
                parent.innerHTML += "" + item.trim() + "	";
            });
        }
        table.style.visibility = "visible";
    }

    // handles the options
    for (var spec in options) {
        switch (spec) {
            case "navigation":
                document.body.style = "margin:0vw 0vh 0vh 15vw; width: 85%;";
                read(options[spec], function() {
                    this.className = "nav";
                    document.body.insertBefore(this, document.body.childNodes[0]);
                });
                break;
        }
    }
});
<commit_msg>made the  favicon smoothly change colors<commit_after>var options = options || {};  // allows specifications to be added if the variable is already present

function read(URL, callback) {
    /**
    reads the contents of the file at the URL,
    converts it into a string,
    puts the string into a
, and then
    calls the callback function (which has no arguments)
    with "this" equalling the

    */
    var file = new XMLHttpRequest();
    file.open("GET", URL);  // Don't add false as an extra argument (browsers don't like it). (default: asynchronous=true)
    file.onreadystatechange = function () {
        if(file.readyState === 4) {  // Is it done?
            if(file.status === 200 || file.status == 0) {  // Was it successful?
                // file.responseXML might have something
                var container = document.createElement("div");
                container.innerHTML = file.responseText;
                /*
                var tags = container.children;
                for (var index=0; index<tags.length; index++) {
                    var tag = document.createElement(tags[index].tagName);
                    if (tag.tagName != "script") {
                        tag.appendChild(document.createTextNode(tags[index].innerHTML));
                        container.insertBefore(tag, tags[index]);
                        tags[index+1].outerHTML = "";
                    }
                }
                */
                // This is necessary because HTML5 doesn't think script tags and innerHTML should go together (for security reasons).
                var scripts = file.responseText.split(""))));
                            container.insertBefore(scriptTag, container.getElementsByTagName("script")[index-1]);
                            var oldTag = container.getElementsByTagName("script")[index];
                            oldTag.parentNode.removeChild(oldTag);
                        }
                    });
                }
                callback.call(container);  // .call(calling object / value of "this", function arguments (listed individually))  .apply has function arguments in an array
                // You could also use callback(argument(s)) like a normal function, but it wouldn't change the value of "this".
            }
        }
    }
    file.send();
}

function pageJump(ID) {
    /**
    makes a section to jump to certain parts of the page
    */
    document.getElementsByTagName("h1")[0].id = "top";
    var division = document.getElementById(ID);
    var contents = document.createElement("div");
    contents.className = "list";
    contents.innerHTML = "

Jump to:
";
    var sections = division.getElementsByTagName("h2");
    var toTop = document.createElement("a");
    toTop.href = "#top";
    toTop.innerHTML = "To top";
    var listItems = "";  // I need this variable to hold the list items because trying to add
 at the beginning and
 at the end separately causes it to fill in the
 immediately after the
 and omit the real

    for (var index=0; index<sections.length; index++) {  // I would use (var in array), but index exceeds entries.length for no apparent reason
        var inside = sections[index].innerHTML.trim();  // The inner HTML has a bunch of whitespace for no apparent reason.
        sections[index].id = inside;
        listItems += "
" + inside + "
";
        division.insertBefore(toTop.cloneNode(true), division.getElementsByTagName("h2")[index].nextSibling);  // inserts after

        // toTop needs to be cloned so it doesn't keep getting reasigned to the next place (it also needs to have true to clone all children of the node, although it doesn't apply here)
    }
    contents.innerHTML += "
" + listItems + "

";
    division.parentNode.insertBefore(contents, division);  // .insertBefore() only works for the immediate descendants of the parent
}

//This is able to run without waiting for anything else to load.

// makes my custom tag which underlines things
document.createElement("under");
// makes my custom tag which overlines things
document.createElement("over");

// adds the universal formatting
var style = document.createElement("link");
style.rel = "stylesheet";
style.href = "https://coolprogramminguser.github.io/Standards/formatting.css";
document.head.insertBefore(style, document.head.children[0]);

// links a favicon
var faviconNumber = 1;
var icon = document.createElement("link");
icon.rel = "icon";
document.head.insertBefore(icon, document.head.children[0]);

// cycles the favicon
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
var color = 0;
context.beginPath();
context.arc(canvas.width/2, canvas.height/2, 64, 0, 2*Math.PI);
setInterval(function() {
    if (color >= 360) {
        color = 0;
    }
    context.fillStyle = "hsl(" + color + ", 100%, 50%)";
    context.fill();
    document.getElementById("icon").href = canvas.toDataURL();
    color++;
}, 20);

window.addEventListener("load", function() {  // This waits for everything past the script import to load before running.

    // surrounds the  content with a
 tag
    document.body.innerHTML = "
" + document.body.innerHTML + "
";

    // adds a title to the page
    var title = document.createElement("h1");
    title.style.color = "white";
    title.innerHTML = document.title;
    document.body.insertBefore(title, document.body.children[0]);

    // surrounds every list with

    var orderedLists = document.getElementsByTagName("ol");
    var unorderedLists = document.getElementsByTagName("ul");
    for (var index=0; index<orderedLists.length; index++) {
        orderedLists[index].outerHTML = "
" + orderedLists[index].outerHTML + "
";
        orderedLists[index].style.visibility = "visible";
    }
    for (var index=0; index<unorderedLists.length; index++) {
        unorderedLists[index].outerHTML = "
" + unorderedLists[index].outerHTML + "
";
        unorderedLists[index].style.visibility = "visible";
    }

    // interprets condensed tables
    var tables = document.getElementsByClassName("compact");
    for (var counter=0; counter<tables.length; counter++) {
        var table = tables[counter];
        var headings = table.getElementsByTagName("th");
        for (var index=0; index<headings.length; index++) {
            var parent = headings[index].parentNode;
            var newHeadings = headings[index].innerHTML.split("|");
            parent.removeChild(headings[index]);
            newHeadings.forEach(function(heading) {
                parent.innerHTML += "" + heading.trim() + "	";
            });
        }
        var data = table.getElementsByTagName("td");
        for (var index=0; index<data.length; index++) {
            var parent = data[index].parentNode;
            var newData = data[index].innerHTML.split("|");
            parent.removeChild(data[index]);
            newData.forEach(function(item) {
                parent.innerHTML += "" + item.trim() + "	";
            });
        }
        table.style.visibility = "visible";
    }

    // handles the options
    for (var spec in options) {
        switch (spec) {
            case "navigation":
                document.body.style = "margin:0vw 0vh 0vh 15vw; width: 85%;";
                read(options[spec], function() {
                    this.className = "nav";
                    document.body.insertBefore(this, document.body.childNodes[0]);
                });
                break;
        }
    }
});
<|endoftext|>


<commit_before>define(
  'ephox.snooker.api.TableOperations',

  [
    'ephox.compass.Arr',
    'ephox.peanut.Fun',
    'ephox.perhaps.Option',
    'ephox.scullion.Struct',
    'ephox.snooker.api.Generators',
    'ephox.snooker.api.Structs',
    'ephox.snooker.api.TableContent',
    'ephox.snooker.api.TableLookup',
    'ephox.snooker.model.DetailsList',
    'ephox.snooker.model.RunOperation',
    'ephox.snooker.model.TableMerge',
    'ephox.snooker.model.Transitions',
    'ephox.snooker.model.Warehouse',
    'ephox.snooker.operate.MergingOperations',
    'ephox.snooker.operate.ModificationOperations',
    'ephox.snooker.operate.TransformOperations',
    'ephox.snooker.resize.Adjustments',
    'ephox.sugar.api.Remove',
    'global!parseInt'
  ],

  function (Arr, Fun, Option, Struct, Generators, Structs, TableContent, TableLookup, DetailsList, RunOperation, TableMerge, Transitions, Warehouse, MergingOperations, ModificationOperations, TransformOperations, Adjustments, Remove, parseInt) {
    var prune = function (table) {
      var cells = TableLookup.cells(table);
      if (cells.length === 0) Remove.remove(table);
    };

    var outcome = Struct.immutable('grid', 'cursor');

    var elementFromGrid = function (grid, row, column) {
      return findIn(grid, row, column).orThunk(function () {
        return findIn(grid, 0, 0);
      });
    };

    var findIn = function (grid, row, column) {
      return Option.from(grid[row]).bind(function (r) {
        return Option.from(r[column]);
      });
    };

    var bundle = function (grid, row, column) {
      return outcome(grid, findIn(grid, row, column));
    };

    var insertRowBefore = function (grid, detail, comparator, genWrappers) {
      var example = detail.row();
      var targetIndex = detail.row();
      var newGrid = ModificationOperations.insertRowAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, targetIndex, detail.column());
    };

    var insertRowAfter = function (grid, detail, comparator, genWrappers) {
      var example = detail.row();
      var targetIndex = detail.row() + detail.rowspan();
      var newGrid = ModificationOperations.insertRowAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, targetIndex, detail.column());
    };

    var insertColumnAfter = function (grid, detail, comparator, genWrappers) {
      var example = detail.column();
      var targetIndex = detail.column() + detail.colspan();
      var newGrid = ModificationOperations.insertColumnAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, detail.row(), targetIndex);
    };

    var insertColumnBefore = function (grid, detail, comparator, genWrappers) {
      var example = detail.column();
      var targetIndex = detail.column();
      var newGrid = ModificationOperations.insertColumnAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, detail.row(), targetIndex);
    };

    var makeRowHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid = TransformOperations.replaceRow(grid, detail.row(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };

    var makeColumnHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid = TransformOperations.replaceColumn(grid, detail.column(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };

    var unmakeRowHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid =  TransformOperations.replaceRow(grid, detail.row(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };

    var unmakeColumnHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid = TransformOperations.replaceColumn(grid, detail.column(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };

    var eraseColumn = function (grid, detail, comparator, _genWrappers) {
      var newGrid = ModificationOperations.deleteColumnAt(grid, detail.column());
      var cursor = elementFromGrid(newGrid, detail.row(), detail.column());
      return outcome(newGrid, cursor);
    };

    var eraseRow = function (grid, detail, comparator, _genWrappers) {
      var newGrid = ModificationOperations.deleteRowAt(grid, detail.row());
      var cursor = elementFromGrid(newGrid, detail.row(), detail.column());
      return outcome(newGrid, cursor);
    };

    var mergeCells = function (grid, mergable, comparator, _genWrappers) {
      var cells = mergable.cells();
      TableContent.merge(cells);
      var newGrid = MergingOperations.merge(grid, mergable.bounds(), comparator, Fun.constant(cells[0]));
      return outcome(newGrid, Option.from(cells[0]));
    };

    var unmergeCells = function (grid, unmergable, comparator, genWrappers) {
      var newGrid = Arr.foldr(unmergable, function (b, cell) {
        return MergingOperations.unmerge(b, cell, comparator, genWrappers.combine(cell));
      }, grid);
      return outcome(newGrid, Option.from(unmergable[0]));
    };

    var pasteCells = function (grid, pasteDetails, comparator, genWrappers) {
      var gridify = function (table, generators) {
        var list = DetailsList.fromTable(table);
        var wh = Warehouse.generate(list);
        return Transitions.toGrid(wh, generators);
      };
      var gridB = gridify(pasteDetails.clipboard(), pasteDetails.generators());
      var startAddress = Structs.address(pasteDetails.row(), pasteDetails.column());
      var mergedGrid = TableMerge.merge(startAddress, grid, gridB, pasteDetails.generators(), comparator);
      return mergedGrid.fold(function () {
        return outcome(grid, Option.some(pasteDetails.element()));
      }, function (nuGrid) {
        var cursor = elementFromGrid(nuGrid, pasteDetails.row(), pasteDetails.column());
        return outcome(nuGrid, cursor);
      });
    };

    // Only column modifications force a resizing. Everything else just tries to preserve the table as is.
    var resize = Adjustments.adjustWidthTo;

    return {
      insertRowBefore: RunOperation.run(insertRowBefore, RunOperation.onCell, Fun.noop, Fun.noop, Generators.modification),
      insertRowAfter:  RunOperation.run(insertRowAfter, RunOperation.onCell, Fun.noop, Fun.noop, Generators.modification),
      insertColumnBefore:  RunOperation.run(insertColumnBefore, RunOperation.onCell, resize, Fun.noop, Generators.modification),
      insertColumnAfter:  RunOperation.run(insertColumnAfter, RunOperation.onCell, resize, Fun.noop, Generators.modification),
      eraseColumn:  RunOperation.run(eraseColumn, RunOperation.onCell, resize, prune, Generators.modification),
      eraseRow:  RunOperation.run(eraseRow, RunOperation.onCell, Fun.noop, prune, Generators.modification),
      makeColumnHeader:  RunOperation.run(makeColumnHeader, RunOperation.onCell, Fun.noop, Fun.noop, Generators.transform('row', 'th')),
      unmakeColumnHeader:  RunOperation.run(unmakeColumnHeader, RunOperation.onCell, Fun.noop, Fun.noop, Generators.transform(null, 'td')),
      makeRowHeader:  RunOperation.run(makeRowHeader, RunOperation.onCell, Fun.noop, Fun.noop, Generators.transform('col', 'th')),
      unmakeRowHeader:  RunOperation.run(unmakeRowHeader, RunOperation.onCell, Fun.noop, Fun.noop, Generators.transform(null, 'td')),
      mergeCells: RunOperation.run(mergeCells, RunOperation.onMergable, Fun.noop, Fun.noop, Generators.merging),
      unmergeCells: RunOperation.run(unmergeCells, RunOperation.onUnmergable, resize, Fun.noop, Generators.merging),
      pasteCells: RunOperation.run(pasteCells, RunOperation.onPaste, resize, Fun.noop, Generators.modification)
    };
  }
);
<commit_msg>TBIO-4190: wire up the api for split cell into columns<commit_after>define(
  'ephox.snooker.api.TableOperations',

  [
    'ephox.compass.Arr',
    'ephox.peanut.Fun',
    'ephox.perhaps.Option',
    'ephox.scullion.Struct',
    'ephox.snooker.api.Generators',
    'ephox.snooker.api.Structs',
    'ephox.snooker.api.TableContent',
    'ephox.snooker.api.TableLookup',
    'ephox.snooker.model.DetailsList',
    'ephox.snooker.model.RunOperation',
    'ephox.snooker.model.TableMerge',
    'ephox.snooker.model.Transitions',
    'ephox.snooker.model.Warehouse',
    'ephox.snooker.operate.MergingOperations',
    'ephox.snooker.operate.ModificationOperations',
    'ephox.snooker.operate.TransformOperations',
    'ephox.snooker.resize.Adjustments',
    'ephox.sugar.api.Remove',
    'global!parseInt'
  ],

  function (Arr, Fun, Option, Struct, Generators, Structs, TableContent, TableLookup, DetailsList, RunOperation, TableMerge, Transitions, Warehouse, MergingOperations, ModificationOperations, TransformOperations, Adjustments, Remove, parseInt) {
    var prune = function (table) {
      var cells = TableLookup.cells(table);
      if (cells.length === 0) Remove.remove(table);
    };

    var outcome = Struct.immutable('grid', 'cursor');

    var elementFromGrid = function (grid, row, column) {
      return findIn(grid, row, column).orThunk(function () {
        return findIn(grid, 0, 0);
      });
    };

    var findIn = function (grid, row, column) {
      return Option.from(grid[row]).bind(function (r) {
        return Option.from(r[column]);
      });
    };

    var bundle = function (grid, row, column) {
      return outcome(grid, findIn(grid, row, column));
    };

    var insertRowBefore = function (grid, detail, comparator, genWrappers) {
      var example = detail.row();
      var targetIndex = detail.row();
      var newGrid = ModificationOperations.insertRowAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, targetIndex, detail.column());
    };

    var insertRowAfter = function (grid, detail, comparator, genWrappers) {
      var example = detail.row();
      var targetIndex = detail.row() + detail.rowspan();
      var newGrid = ModificationOperations.insertRowAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, targetIndex, detail.column());
    };

    var insertColumnAfter = function (grid, detail, comparator, genWrappers) {
      var example = detail.column();
      var targetIndex = detail.column() + detail.colspan();
      var newGrid = ModificationOperations.insertColumnAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, detail.row(), targetIndex);
    };

    var insertColumnBefore = function (grid, detail, comparator, genWrappers) {
      var example = detail.column();
      var targetIndex = detail.column();
      var newGrid = ModificationOperations.insertColumnAt(grid, targetIndex, example, comparator, genWrappers.getOrInit);
      return bundle(newGrid, detail.row(), targetIndex);
    };

    var makeRowHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid = TransformOperations.replaceRow(grid, detail.row(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };

    var makeColumnHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid = TransformOperations.replaceColumn(grid, detail.column(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };

    var unmakeRowHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid =  TransformOperations.replaceRow(grid, detail.row(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };

    var unmakeColumnHeader = function (grid, detail, comparator, genWrappers) {
      var newGrid = TransformOperations.replaceColumn(grid, detail.column(), comparator, genWrappers.replaceOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };

    var splitCellIntoColumns = function (grid, detail, comparator, genWrappers) {
      var newGrid = ModificationOperations.splitCellIntoColumns(grid, detail.row(), detail.column(), comparator, genWrappers.getOrInit);
      return bundle(newGrid, detail.row(), detail.column());
    };

    var eraseColumn = function (grid, detail, comparator, _genWrappers) {
      var newGrid = ModificationOperations.deleteColumnAt(grid, detail.column());
      var cursor = elementFromGrid(newGrid, detail.row(), detail.column());
      return outcome(newGrid, cursor);
    };

    var eraseRow = function (grid, detail, comparator, _genWrappers) {
      var newGrid = ModificationOperations.deleteRowAt(grid, detail.row());
      var cursor = elementFromGrid(newGrid, detail.row(), detail.column());
      return outcome(newGrid, cursor);
    };

    var mergeCells = function (grid, mergable, comparator, _genWrappers) {
      var cells = mergable.cells();
      TableContent.merge(cells);
      var newGrid = MergingOperations.merge(grid, mergable.bounds(), comparator, Fun.constant(cells[0]));
      return outcome(newGrid, Option.from(cells[0]));
    };

    var unmergeCells = function (grid, unmergable, comparator, genWrappers) {
      var newGrid = Arr.foldr(unmergable, function (b, cell) {
        return MergingOperations.unmerge(b, cell, comparator, genWrappers.combine(cell));
      }, grid);
      return outcome(newGrid, Option.from(unmergable[0]));
    };

    var pasteCells = function (grid, pasteDetails, comparator, genWrappers) {
      var gridify = function (table, generators) {
        var list = DetailsList.fromTable(table);
        var wh = Warehouse.generate(list);
        return Transitions.toGrid(wh, generators);
      };
      var gridB = gridify(pasteDetails.clipboard(), pasteDetails.generators());
      var startAddress = Structs.address(pasteDetails.row(), pasteDetails.column());
      var mergedGrid = TableMerge.merge(startAddress, grid, gridB, pasteDetails.generators(), comparator);
      return mergedGrid.fold(function () {
        return outcome(grid, Option.some(pasteDetails.element()));
      }, function (nuGrid) {
        var cursor = elementFromGrid(nuGrid, pasteDetails.row(), pasteDetails.column());
        return outcome(nuGrid, cursor);
      });
    };

    // Only column modifications force a resizing. Everything else just tries to preserve the table as is.
    var resize = Adjustments.adjustWidthTo;

    return {
      insertRowBefore: RunOperation.run(insertRowBefore, RunOperation.onCell, Fun.noop, Fun.noop, Generators.modification),
      insertRowAfter:  RunOperation.run(insertRowAfter, RunOperation.onCell, Fun.noop, Fun.noop, Generators.modification),
      insertColumnBefore:  RunOperation.run(insertColumnBefore, RunOperation.onCell, resize, Fun.noop, Generators.modification),
      insertColumnAfter:  RunOperation.run(insertColumnAfter, RunOperation.onCell, resize, Fun.noop, Generators.modification),
      splitCellIntoColumns:  RunOperation.run(splitCellIntoColumns, RunOperation.onCell, resize, Fun.noop, Generators.modification),
      eraseColumn:  RunOperation.run(eraseColumn, RunOperation.onCell, resize, prune, Generators.modification),
      eraseRow:  RunOperation.run(eraseRow, RunOperation.onCell, Fun.noop, prune, Generators.modification),
      makeColumnHeader:  RunOperation.run(makeColumnHeader, RunOperation.onCell, Fun.noop, Fun.noop, Generators.transform('row', 'th')),
      unmakeColumnHeader:  RunOperation.run(unmakeColumnHeader, RunOperation.onCell, Fun.noop, Fun.noop, Generators.transform(null, 'td')),
      makeRowHeader:  RunOperation.run(makeRowHeader, RunOperation.onCell, Fun.noop, Fun.noop, Generators.transform('col', 'th')),
      unmakeRowHeader:  RunOperation.run(unmakeRowHeader, RunOperation.onCell, Fun.noop, Fun.noop, Generators.transform(null, 'td')),
      mergeCells: RunOperation.run(mergeCells, RunOperation.onMergable, Fun.noop, Fun.noop, Generators.merging),
      unmergeCells: RunOperation.run(unmergeCells, RunOperation.onUnmergable, resize, Fun.noop, Generators.merging),
      pasteCells: RunOperation.run(pasteCells, RunOperation.onPaste, resize, Fun.noop, Generators.modification)
    };
  }
);
<|endoftext|>


<commit_before>'use strict';

import chemspider from 'https://www.lactame.com/lib/chemspider-json-api/0.0.3/chemspider-json-api.js';
import util from 'src/util/util';

module.exports = {
    search(term) {
        return chemspider.search({
            searchOptions: {
                searchOptions: {
                    QueryText: term
                }
            },
            resultOptions: {
                serfilter: 'Compound[Mol|Name|Synonyms]'
            }
        }).then(data => data.map(fromChemspider));
    }
};

function fromChemspider(chemspider) {
    var entry = {
        $content: {
            general: {
                molfile: chemspider.Mol,
                description: chemspider.Name
            }
        },
        id: util.getNextUniqueId(true),
        source: 'chemspider'
    };

    const name = entry.$content.general.name =  [];
    const identifier = entry.$content.identifier = {};
    const cas = identifier.cas = [];
    const synonyms = chemspider.Synonyms;
    for (let i = 0; i < synonyms.length; i++) {
        const synonym = synonyms[i];
        if (isReliableSynonym(synonym)) {
            name.push({
                value: synonym.Name,
                language: synonym.LangID
            });
        }
        if(isReliableCas(synonym)) {
            cas.push({
                value: synonym.Name
            });
        }
    }
    return entry;
}

function isReliableCas(synonym) {
    return synonym.Reliability >= 4 && synonym.LangID === 'en' && synonym.SynonymType == 2;
}

function isReliableSynonym(synonym) {
    return synonym.Reliability >= 4 && synonym.SynonymType == 5 && synonym.LangID === 'en';
}<commit_msg>chemspider search: add chemspider ID<commit_after>'use strict';

import chemspider from 'https://www.lactame.com/lib/chemspider-json-api/0.0.3/chemspider-json-api.js';
import util from 'src/util/util';

module.exports = {
    search(term) {
        return chemspider.search({
            searchOptions: {
                searchOptions: {
                    QueryText: term
                }
            },
            resultOptions: {
                serfilter: 'Compound[Mol|Name|Synonyms|CSID]'
            }
        }).then(data => data.map(fromChemspider));
    }
};

function fromChemspider(chemspider) {
    var entry = {
        $content: {
            general: {
                molfile: chemspider.Mol,
                description: chemspider.Name
            }
        },
        id: util.getNextUniqueId(true),
        source: 'chemspider'
    };

    const name = entry.$content.general.name =  [];
    const identifier = entry.$content.identifier = {};
    const cas = identifier.cas = [];
    const CSID = identifier.chemSpiderID = [];
    const synonyms = chemspider.Synonyms;
    for (let i = 0; i < synonyms.length; i++) {
        const synonym = synonyms[i];
        if (isReliableSynonym(synonym)) {
            name.push({
                value: synonym.Name,
                language: synonym.LangID
            });
        }
        if(isReliableCas(synonym)) {
            cas.push({
                value: synonym.Name
            });
        }
    }
    if(chemspider.CSID) {
        CSID.push({value: chemspider.CSID});
    }
    return entry;
}

function isReliableCas(synonym) {
    return synonym.Reliability >= 4 && synonym.LangID === 'en' && synonym.SynonymType == 2;
}

function isReliableSynonym(synonym) {
    return synonym.Reliability >= 4 && synonym.SynonymType == 5 && synonym.LangID === 'en';
}<|endoftext|>


<commit_before>
/*!
 * Rah_textile_bar
 *
 * @author Jukka Svahn
 */

(function($, len, createRange, duplicate){

    var opt = {}, is = {}, form = {}, words = {}, lines = {};

    var methods = {

        /**
         * Initialize
         */

        init : function() {
            this.click(function(e) {
                e.preventDefault();

                $.each(this.attributes, function(index, attr)
                {
                    if (attr.name.indexOf('data-') === 0)
                    {
                        opt[attr.name.substr(5)] = attr.value;
                    }
                });

                opt.field = $($(this).attr('href'));
                opt.field.focus();
                opt.selection = methods.caret.apply(opt.field);

                words = { start : 0, end : 0, text : [] };
                lines = { start : 0, end : 0, text : [] };

                var i = 0, ls = 0, le = 0;

                $.each(opt.field.val().split(/\r\n|\r|\n/), function(index, line){

                    if (ls > opt.selection.end)
                    {
                        return;
                    }

                    le = ls+line.length;

                    if (le >= opt.selection.start)
                    {
                        if (!lines.text[0])
                        {
                            lines.start = ls;
                        }

                        lines.text.push(line);
                        lines.end = le;
                    }

                    ls = le+1;

                    $.each(line.split(' '), function(index, w) {

                        if (i > opt.selection.end)
                        {
                            return;
                        }

                        if (i+w.length >= opt.selection.start)
                        {
                            if (!words.text[0])
                            {
                                words.start = i;
                            }

                            words.text.push(w);
                            words.end = i+w.length;
                        }

                        i += w.length+1;
                    });
                });

                opt.selection.char_before = (
                    opt.selection.start < 1 ?
                        '' : opt.field.val().substr(opt.selection.start-1, 1)
                );

                is.empty = (!opt.selection.text);
                is.whitespace = (!is.empty && !$.trim(opt.selection.text));
                is.inline = (opt.selection.text.indexOf("\n") == -1);

                is.linefirst = (
                    opt.selection.start < 1 ||
                    opt.selection.char_before == "\n" ||
                    opt.selection.char_before == "\r"
                );

                var offset = lines.end;
                var c = opt.field.val();

                is.paragraph = (
                    c.indexOf("\n\n", offset) >= 0 ||
                    c.indexOf("\r\n\r\n", offset) >= 0
                );

                is.block = (
                    !is.paragraph &&
                    c.indexOf("\n", offset) >= 0 ||
                    c.indexOf("\r\n", offset) >= 0
                );

                if (!format[opt.callback])
                {
                    return;
                }

                var f = format[opt.callback]();

                if (f)
                {
                    opt.field.val(f);
                }

                methods.caret.apply(opt.field, [{
                    start : opt.selection.end,
                    end : opt.selection.end
                }]);
            });
        },

        /*!
         * Caret code based on jCaret
         * @author C. F., Wong (Cloudgen)
         * @link http://code.google.com/p/jcaret/
         *
         * Copyright (c) 2010 C. F., Wong (http://cloudgen.w0ng.hk)
         * Licensed under the MIT License:
         * http://www.opensource.org/licenses/mit-license.php
         */

        caret : function(options)
        {
            var start, end, t = this[0];

            if (
                typeof options === "object" &&
                typeof options.start === "number" &&
                typeof options.end === "number"
            )
            {
                start = options.start;
                end = options.end;
            }

            if (typeof start != "undefined")
            {
                if ($.type(this[0].createTextRange) !== 'undefined')
                {
                    var selRange = this[0].createTextRange();
                    selRange.collapse(true);
                    selRange.moveStart('character', start);
                    selRange.moveEnd('character', end-start);
                    selRange.select();
                }
                else if ($.type(this[0].selectionStart) !== 'undefined')
                {
                    this[0].selectionStart = start;
                    this[0].selectionEnd = end;
                }

                this[0].focus();
                return this;
            }

            else
            {
                if ($.type(this[0].createTextRange) !== 'undefined')
                {
                    var selection = document.selection;

                    if (this[0].tagName.toLowerCase() != "textarea")
                    {
                        var val = this.val(),
                        range = selection[createRange]()[duplicate]();
                        range.moveEnd("character", val[len]);
                        var s = (range.text == "" ? val[len]:val.lastIndexOf(range.text));
                        range = selection[createRange]()[duplicate]();
                        range.moveStart("character", -val[len]);
                        var e = range.text[len];
                    }
                    else
                    {
                        var range = selection[createRange](),
                        stored_range = range[duplicate]();
                        stored_range.moveToElementText(this[0]);
                        stored_range.setEndPoint('EndToEnd', range);
                        var s = stored_range.text[len] - range.text[len],
                        e = s + range.text[len]
                    }
                }
                else if ($.type(this[0].selectionStart) !== 'undefined')
                {
                    var s = t.selectionStart,
                    e = t.selectionEnd;
                }

                return {
                    start : s,
                    end : e,
                    text : t.value.substring(s,e)
                };
            }
        }
    };

    /**
     * Replaces a selection with Textile markup.
     *
     * @param {string}  string
     * @param {integer} start
     * @param {integer} end
     */

    var insert = function(string, start, end)
    {
        if(typeof start === "undefined")
        {
            start = opt.selection.start;
        }

        if(typeof end === "undefined")
        {
            end = opt.selection.end;
        }

        opt.field.val(opt.field.val().substring(0, start) + string + opt.field.val().substring(end));
        opt.selection.end = start + string.length;
    };

    /**
     * Formatting methods.
     */

    var format =
    {
        /**
         * Formats a code block.
         */

        code : function()
        {
            if ((is.linefirst && is.empty) || !is.inline)
            {
                insert(
                    'bc. ' + $.trim(lines.text.join("\n")),
                    lines.start,
                    lines.end
                );

                return;
            }

            format.inline();
        },

        /**
         * Formats a list such as <ul> and <ol>.
         */

        list : function()
        {
            var out = [];

            $.each(lines.text, function(key, line) {
                out.push(((is.linefirst && is.empty) || $.trim(line) ? opt.bullet + ' ' : '') + line);
            });

            out = out.join("\n");
            insert(out, lines.start, lines.end);
            opt.selection.end = lines.start + out.length;
        },

        /**
         * Formats simple inline tags.
         *
         * Works for elements such as <strong>, <bold>,
         * <em>, <ins>, <del>.
         */

        inline : function()
        {
            if (is.empty && words.text.length == 1)
            {
                opt.selection.start = words.start;
                opt.selection.end = words.end;
                opt.selection.text = words.text.join(' ');
            }

            var r = !is.whitespace && is.inline ?
                opt.before + opt.selection.text + opt.after :
                opt.selection.text + opt.before + opt.after;

            insert(r);
        },

        /**
         * Formats a heading.
         */

        heading : function()
        {
            var line = lines.text.join("\n");
            var s = line.substr(0,3);

            if (jQuery.inArray(s, ['h1.', 'h2.', 'h3.', 'h4.', 'h5.', 'h6.']) >= 0)
            {
                s = s == 'h6.' ? 1 : parseInt(s.substr(1,1)) + 1;
                insert(s, lines.start+1, lines.start+2);
                opt.selection.end = lines.start+line.length;
                return;
            }

            insert(
                opt.level +'. ' + line + (!is.paragraph ? "\n\n" : ''),
                lines.start,
                lines.end
            );
        },

        /**
         * Formats a block.
         */

        block : function()
        {
            insert(
                opt['tag'] +'. ' + $.trim(lines.text.join("\n")) +
                (!is.paragraph ? "\n\n" : ''),
                lines.start,
                lines.end
            );
        },

        /**
         * Formats an image.
         *
         * @todo Not implemented
         */

        image : function()
        {
        },

        /**
         * Formats a link.
         */

        link : function()
        {
            var text = opt.selection.text;
            var link = 'http://';

            if (is.empty && words.text.length == 1)
            {
                opt.selection.start = words.start;
                opt.selection.end = words.end;
                text = words.text.join(' ');
            }

            if (text.indexOf('http://') == 0 || text.indexOf('https://') == 0)
            {
                link = text;
                text = '$';
            }

            else if(text.indexOf('www.') == 0)
            {
                link = 'http://'+text;
                text = '$';
            }

            insert('"' + text + '":'+link);
        },

        /**
         * Formats an acronym.
         */

        acronym : function()
        {
            var text = opt.selection.text;
            var abc = 'ABC';

            if (is.empty)
            {
                if(words.text.length == 1 && words.text[0].length >= 3 && /[:lower:]/.test(words.text[0]) === false)
                {
                    abc = words.text[0];
                }
                else
                {
                    text = words.text.join(' ');
                }

                opt.selection.start = words.start;
                opt.selection.end = words.end;
            }

            insert(abc+'('+text+')');
        }
    };

    $.fn.rah_textile_bar = function (method, options)
    {
        if ($.type(method) !== 'string' || $.type(methods[method]) !== 'function')
        {
            options = method;
            method = 'init';
        }

        return methods[method].call(this, options);
    };

})(jQuery, 'length', 'createRange', 'duplicate');<commit_msg>Updated header comments.<commit_after>/**
 * Dense - Device pixel ratio aware images
 *
 * @link    https://github.com/gocom/cotton.js
 * @license MIT
 */

/*
 * Copyright (C) 2013 Jukka Svahn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

(function($, len, createRange, duplicate){

    var opt = {}, is = {}, form = {}, words = {}, lines = {};

    var methods = {

        /**
         * Initialize
         */

        init : function() {
            this.click(function(e) {
                e.preventDefault();

                $.each(this.attributes, function(index, attr)
                {
                    if (attr.name.indexOf('data-') === 0)
                    {
                        opt[attr.name.substr(5)] = attr.value;
                    }
                });

                opt.field = $($(this).attr('href'));
                opt.field.focus();
                opt.selection = methods.caret.apply(opt.field);

                words = { start : 0, end : 0, text : [] };
                lines = { start : 0, end : 0, text : [] };

                var i = 0, ls = 0, le = 0;

                $.each(opt.field.val().split(/\r\n|\r|\n/), function(index, line){

                    if (ls > opt.selection.end)
                    {
                        return;
                    }

                    le = ls+line.length;

                    if (le >= opt.selection.start)
                    {
                        if (!lines.text[0])
                        {
                            lines.start = ls;
                        }

                        lines.text.push(line);
                        lines.end = le;
                    }

                    ls = le+1;

                    $.each(line.split(' '), function(index, w) {

                        if (i > opt.selection.end)
                        {
                            return;
                        }

                        if (i+w.length >= opt.selection.start)
                        {
                            if (!words.text[0])
                            {
                                words.start = i;
                            }

                            words.text.push(w);
                            words.end = i+w.length;
                        }

                        i += w.length+1;
                    });
                });

                opt.selection.char_before = (
                    opt.selection.start < 1 ?
                        '' : opt.field.val().substr(opt.selection.start-1, 1)
                );

                is.empty = (!opt.selection.text);
                is.whitespace = (!is.empty && !$.trim(opt.selection.text));
                is.inline = (opt.selection.text.indexOf("\n") == -1);

                is.linefirst = (
                    opt.selection.start < 1 ||
                    opt.selection.char_before == "\n" ||
                    opt.selection.char_before == "\r"
                );

                var offset = lines.end;
                var c = opt.field.val();

                is.paragraph = (
                    c.indexOf("\n\n", offset) >= 0 ||
                    c.indexOf("\r\n\r\n", offset) >= 0
                );

                is.block = (
                    !is.paragraph &&
                    c.indexOf("\n", offset) >= 0 ||
                    c.indexOf("\r\n", offset) >= 0
                );

                if (!format[opt.callback])
                {
                    return;
                }

                var f = format[opt.callback]();

                if (f)
                {
                    opt.field.val(f);
                }

                methods.caret.apply(opt.field, [{
                    start : opt.selection.end,
                    end : opt.selection.end
                }]);
            });
        },

        /*!
         * Caret code based on jCaret
         * @author C. F., Wong (Cloudgen)
         * @link http://code.google.com/p/jcaret/
         *
         * Copyright (c) 2010 C. F., Wong (http://cloudgen.w0ng.hk)
         * Licensed under the MIT License:
         * http://www.opensource.org/licenses/mit-license.php
         */

        caret : function(options)
        {
            var start, end, t = this[0];

            if (
                typeof options === "object" &&
                typeof options.start === "number" &&
                typeof options.end === "number"
            )
            {
                start = options.start;
                end = options.end;
            }

            if (typeof start != "undefined")
            {
                if ($.type(this[0].createTextRange) !== 'undefined')
                {
                    var selRange = this[0].createTextRange();
                    selRange.collapse(true);
                    selRange.moveStart('character', start);
                    selRange.moveEnd('character', end-start);
                    selRange.select();
                }
                else if ($.type(this[0].selectionStart) !== 'undefined')
                {
                    this[0].selectionStart = start;
                    this[0].selectionEnd = end;
                }

                this[0].focus();
                return this;
            }

            else
            {
                if ($.type(this[0].createTextRange) !== 'undefined')
                {
                    var selection = document.selection;

                    if (this[0].tagName.toLowerCase() != "textarea")
                    {
                        var val = this.val(),
                        range = selection[createRange]()[duplicate]();
                        range.moveEnd("character", val[len]);
                        var s = (range.text == "" ? val[len]:val.lastIndexOf(range.text));
                        range = selection[createRange]()[duplicate]();
                        range.moveStart("character", -val[len]);
                        var e = range.text[len];
                    }
                    else
                    {
                        var range = selection[createRange](),
                        stored_range = range[duplicate]();
                        stored_range.moveToElementText(this[0]);
                        stored_range.setEndPoint('EndToEnd', range);
                        var s = stored_range.text[len] - range.text[len],
                        e = s + range.text[len]
                    }
                }
                else if ($.type(this[0].selectionStart) !== 'undefined')
                {
                    var s = t.selectionStart,
                    e = t.selectionEnd;
                }

                return {
                    start : s,
                    end : e,
                    text : t.value.substring(s,e)
                };
            }
        }
    };

    /**
     * Replaces a selection with Textile markup.
     *
     * @param {string}  string
     * @param {integer} start
     * @param {integer} end
     */

    var insert = function(string, start, end)
    {
        if(typeof start === "undefined")
        {
            start = opt.selection.start;
        }

        if(typeof end === "undefined")
        {
            end = opt.selection.end;
        }

        opt.field.val(opt.field.val().substring(0, start) + string + opt.field.val().substring(end));
        opt.selection.end = start + string.length;
    };

    /**
     * Formatting methods.
     */

    var format =
    {
        /**
         * Formats a code block.
         */

        code : function()
        {
            if ((is.linefirst && is.empty) || !is.inline)
            {
                insert(
                    'bc. ' + $.trim(lines.text.join("\n")),
                    lines.start,
                    lines.end
                );

                return;
            }

            format.inline();
        },

        /**
         * Formats a list such as <ul> and <ol>.
         */

        list : function()
        {
            var out = [];

            $.each(lines.text, function(key, line) {
                out.push(((is.linefirst && is.empty) || $.trim(line) ? opt.bullet + ' ' : '') + line);
            });

            out = out.join("\n");
            insert(out, lines.start, lines.end);
            opt.selection.end = lines.start + out.length;
        },

        /**
         * Formats simple inline tags.
         *
         * Works for elements such as <strong>, <bold>,
         * <em>, <ins>, <del>.
         */

        inline : function()
        {
            if (is.empty && words.text.length == 1)
            {
                opt.selection.start = words.start;
                opt.selection.end = words.end;
                opt.selection.text = words.text.join(' ');
            }

            var r = !is.whitespace && is.inline ?
                opt.before + opt.selection.text + opt.after :
                opt.selection.text + opt.before + opt.after;

            insert(r);
        },

        /**
         * Formats a heading.
         */

        heading : function()
        {
            var line = lines.text.join("\n");
            var s = line.substr(0,3);

            if (jQuery.inArray(s, ['h1.', 'h2.', 'h3.', 'h4.', 'h5.', 'h6.']) >= 0)
            {
                s = s == 'h6.' ? 1 : parseInt(s.substr(1,1)) + 1;
                insert(s, lines.start+1, lines.start+2);
                opt.selection.end = lines.start+line.length;
                return;
            }

            insert(
                opt.level +'. ' + line + (!is.paragraph ? "\n\n" : ''),
                lines.start,
                lines.end
            );
        },

        /**
         * Formats a block.
         */

        block : function()
        {
            insert(
                opt['tag'] +'. ' + $.trim(lines.text.join("\n")) +
                (!is.paragraph ? "\n\n" : ''),
                lines.start,
                lines.end
            );
        },

        /**
         * Formats an image.
         *
         * @todo Not implemented
         */

        image : function()
        {
        },

        /**
         * Formats a link.
         */

        link : function()
        {
            var text = opt.selection.text;
            var link = 'http://';

            if (is.empty && words.text.length == 1)
            {
                opt.selection.start = words.start;
                opt.selection.end = words.end;
                text = words.text.join(' ');
            }

            if (text.indexOf('http://') == 0 || text.indexOf('https://') == 0)
            {
                link = text;
                text = '$';
            }

            else if(text.indexOf('www.') == 0)
            {
                link = 'http://'+text;
                text = '$';
            }

            insert('"' + text + '":'+link);
        },

        /**
         * Formats an acronym.
         */

        acronym : function()
        {
            var text = opt.selection.text;
            var abc = 'ABC';

            if (is.empty)
            {
                if(words.text.length == 1 && words.text[0].length >= 3 && /[:lower:]/.test(words.text[0]) === false)
                {
                    abc = words.text[0];
                }
                else
                {
                    text = words.text.join(' ');
                }

                opt.selection.start = words.start;
                opt.selection.end = words.end;
            }

            insert(abc+'('+text+')');
        }
    };

    $.fn.rah_textile_bar = function (method, options)
    {
        if ($.type(method) !== 'string' || $.type(methods[method]) !== 'function')
        {
            options = method;
            method = 'init';
        }

        return methods[method].call(this, options);
    };

})(jQuery, 'length', 'createRange', 'duplicate');<|endoftext|>


<commit_before>'use strict';

var express = require('express');
var router = express.Router();

/**
 * Home page
 */
router.get('/', function (req, res, next) {

  res.render('yard/index');

});

/**
 * Docs page
 */
router.get('/docs', function (req, res, next) {

  res.render('yard/docs/index', {

    main: {

      title : 'Hawk.so Docs',
      description : 'Hawk.so is a clever and easy-to-use error tracker. It helps improve your applications. To learn how to start using Hawk..'

    }

  });

});

module.exports = router;
<commit_msg>Update meta<commit_after>'use strict';

var express = require('express');
var router = express.Router();

/**
 * Home page
 */
router.get('/', function (req, res, next) {

  res.render('yard/index');

});

/**
 * Docs page
 */
router.get('/docs', function (req, res, next) {

  res.render('yard/docs/index', {

    meta : {

      title : 'Platform documentation',
      description : 'Hawk.so is a clever and easy-to-use error tracker. It helps improve your applications.\nTo learn how to start using Hawk..'

    }

  });

});

module.exports = router;
<|endoftext|>


<commit_before>/**
 * GitHub Buttons on the homepage
 * Adapted from https://github.com/mdo/github-buttons/
 * Copyright 2014 Mark Otto. Released under Apache 2.0.
 */

var user = "warpech",
  repo = "jquery-handsontable",
  head = document.getElementsByTagName('head')[0];

// Add commas to numbers
function addCommas(n) {
  return String(n).replace(/(\d)(?=(\d{3})+$)/g, '$1,')
}

function jsonp(path) {
  var el = document.createElement('script');
  el.src = path + '?callback=callback';
  head.insertBefore(el, head.firstChild);
}

function callback(obj) {
  var watchCount = document.getElementById("githubWatch").querySelector(".gh-count");
  var forkCount = document.getElementById("githubFork").querySelector(".gh-count");
  watchCount.innerHTML = addCommas(obj.data.watchers);
  forkCount.innerHTML = addCommas(obj.data.forks);
  watchCount.style.display = 'block';
  forkCount.style.display = 'block';
}

$(function () {
  jsonp('https://api.github.com/repos/' + user + '/' + repo);
});<commit_msg>only show the numbers if request was successful<commit_after>/**
 * GitHub Buttons on the homepage
 * Adapted from https://github.com/mdo/github-buttons/
 * Copyright 2014 Mark Otto. Released under Apache 2.0.
 */

var user = "warpech",
  repo = "jquery-handsontable",
  head = document.getElementsByTagName('head')[0];

// Add commas to numbers
function addCommas(n) {
  return String(n).replace(/(\d)(?=(\d{3})+$)/g, '$1,')
}

function jsonp(path) {
  var el = document.createElement('script');
  el.src = path + '?callback=callback';
  head.insertBefore(el, head.firstChild);
}

function callback(obj) {
  if(obj.data.watchers) {
    var watchCount = document.getElementById("githubWatch").querySelector(".gh-count");
    var forkCount = document.getElementById("githubFork").querySelector(".gh-count");
    watchCount.innerHTML = addCommas(obj.data.watchers);
    forkCount.innerHTML = addCommas(obj.data.forks);
    watchCount.style.display = 'block';
    forkCount.style.display = 'block';
  }
}

$(function () {
  jsonp('https://api.github.com/repos/' + user + '/' + repo);
});<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @providesModule commitRelayModernMutation
 * @flow
 * @format
 */

'use strict';

const RelayDeclarativeMutationConfig = require('RelayDeclarativeMutationConfig');

const invariant = require('invariant');
const isRelayModernEnvironment = require('isRelayModernEnvironment');
const warning = require('warning');

import type {Disposable, Variables} from '../util/RelayRuntimeTypes';
import type {DeclarativeMutationConfig} from 'RelayDeclarativeMutationConfig';
import type {GraphQLTaggedNode} from 'RelayModernGraphQLTag';
import type {PayloadError, UploadableMap} from 'RelayNetworkTypes';
import type {Environment, SelectorStoreUpdater} from 'RelayStoreTypes';

export type MutationConfig<T> = {|
  configs?: Array<DeclarativeMutationConfig>,
  mutation: GraphQLTaggedNode,
  variables: Variables,
  uploadables?: UploadableMap,
  onCompleted?: ?(response: T, errors: ?Array<PayloadError>) => void,
  onError?: ?(error: Error) => void,
  optimisticUpdater?: ?SelectorStoreUpdater,
  optimisticResponse?: Object,
  updater?: ?SelectorStoreUpdater,
|};

/**
 * Higher-level helper function to execute a mutation against a specific
 * environment.
 */
function commitRelayModernMutation<T>(
  /* $FlowFixMe(>=0.55.0 site=www) This comment suppresses an error found when
   * Flow v0.55 was deployed. To see the error delete this comment and run
   * Flow. */
  environment: Environment,
  config: MutationConfig<T>,
): Disposable {
  invariant(
    isRelayModernEnvironment(environment),
    'commitRelayModernMutation: expect `environment` to be an instance of ' +
      '`RelayModernEnvironment`.',
  );
  const {createOperationSelector, getRequest} = environment.unstable_internal;
  const mutation = getRequest(config.mutation);
  if (mutation.operationKind !== 'mutation') {
    throw new Error('commitRelayModernMutation: Expected mutation operation');
  }
  let {optimisticResponse, optimisticUpdater, updater} = config;
  const {configs, onError, variables, uploadables} = config;
  const operation = createOperationSelector(mutation, variables);
  // TODO: remove this check after we fix flow.
  if (typeof optimisticResponse === 'function') {
    optimisticResponse = optimisticResponse();
    warning(
      false,
      'commitRelayModernMutation: Expected `optimisticResponse` to be an object, ' +
        'received a function.',
    );
  }
  if (
    optimisticResponse &&
    mutation.fragment.selections &&
    mutation.fragment.selections.length === 1 &&
    mutation.fragment.selections[0].kind === 'LinkedField'
  ) {
    const mutationRoot = mutation.fragment.selections[0].name;
    warning(
      optimisticResponse[mutationRoot],
      'commitRelayModernMutation: Expected `optimisticResponse` to be wrapped ' +
        'in mutation name `%s`',
      mutationRoot,
    );
  }
  if (configs) {
    ({optimisticUpdater, updater} = RelayDeclarativeMutationConfig.convert(
      configs,
      mutation,
      optimisticUpdater,
      updater,
    ));
  }
  return environment
    .executeMutation({
      operation,
      optimisticResponse,
      optimisticUpdater,
      updater,
      uploadables,
    })
    .subscribeLegacy({
      onNext: payload => {
        // NOTE: commitRelayModernMutation has a non-standard use of
        // onCompleted() by calling it on every next value. It may be called
        // multiple times if a network request produces multiple responses.
        const {onCompleted} = config;
        if (onCompleted) {
          const snapshot = environment.lookup(operation.fragment);
          onCompleted((snapshot.data: $FlowFixMe), payload.response.errors);
        }
      },
      onError,
    });
}

module.exports = commitRelayModernMutation;
<commit_msg>remove unused flow suppression<commit_after>/**
 * Copyright (c) 2013-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @providesModule commitRelayModernMutation
 * @flow
 * @format
 */

'use strict';

const RelayDeclarativeMutationConfig = require('RelayDeclarativeMutationConfig');

const invariant = require('invariant');
const isRelayModernEnvironment = require('isRelayModernEnvironment');
const warning = require('warning');

import type {Disposable, Variables} from '../util/RelayRuntimeTypes';
import type {DeclarativeMutationConfig} from 'RelayDeclarativeMutationConfig';
import type {GraphQLTaggedNode} from 'RelayModernGraphQLTag';
import type {PayloadError, UploadableMap} from 'RelayNetworkTypes';
import type {Environment, SelectorStoreUpdater} from 'RelayStoreTypes';

export type MutationConfig<T> = {|
  configs?: Array<DeclarativeMutationConfig>,
  mutation: GraphQLTaggedNode,
  variables: Variables,
  uploadables?: UploadableMap,
  onCompleted?: ?(response: T, errors: ?Array<PayloadError>) => void,
  onError?: ?(error: Error) => void,
  optimisticUpdater?: ?SelectorStoreUpdater,
  optimisticResponse?: Object,
  updater?: ?SelectorStoreUpdater,
|};

/**
 * Higher-level helper function to execute a mutation against a specific
 * environment.
 */
function commitRelayModernMutation<T>(
  environment: Environment,
  config: MutationConfig<T>,
): Disposable {
  invariant(
    isRelayModernEnvironment(environment),
    'commitRelayModernMutation: expect `environment` to be an instance of ' +
      '`RelayModernEnvironment`.',
  );
  const {createOperationSelector, getRequest} = environment.unstable_internal;
  const mutation = getRequest(config.mutation);
  if (mutation.operationKind !== 'mutation') {
    throw new Error('commitRelayModernMutation: Expected mutation operation');
  }
  let {optimisticResponse, optimisticUpdater, updater} = config;
  const {configs, onError, variables, uploadables} = config;
  const operation = createOperationSelector(mutation, variables);
  // TODO: remove this check after we fix flow.
  if (typeof optimisticResponse === 'function') {
    optimisticResponse = optimisticResponse();
    warning(
      false,
      'commitRelayModernMutation: Expected `optimisticResponse` to be an object, ' +
        'received a function.',
    );
  }
  if (
    optimisticResponse &&
    mutation.fragment.selections &&
    mutation.fragment.selections.length === 1 &&
    mutation.fragment.selections[0].kind === 'LinkedField'
  ) {
    const mutationRoot = mutation.fragment.selections[0].name;
    warning(
      optimisticResponse[mutationRoot],
      'commitRelayModernMutation: Expected `optimisticResponse` to be wrapped ' +
        'in mutation name `%s`',
      mutationRoot,
    );
  }
  if (configs) {
    ({optimisticUpdater, updater} = RelayDeclarativeMutationConfig.convert(
      configs,
      mutation,
      optimisticUpdater,
      updater,
    ));
  }
  return environment
    .executeMutation({
      operation,
      optimisticResponse,
      optimisticUpdater,
      updater,
      uploadables,
    })
    .subscribeLegacy({
      onNext: payload => {
        // NOTE: commitRelayModernMutation has a non-standard use of
        // onCompleted() by calling it on every next value. It may be called
        // multiple times if a network request produces multiple responses.
        const {onCompleted} = config;
        if (onCompleted) {
          const snapshot = environment.lookup(operation.fragment);
          onCompleted((snapshot.data: $FlowFixMe), payload.response.errors);
        }
      },
      onError,
    });
}

module.exports = commitRelayModernMutation;
<|endoftext|>


<commit_before>import { VDOM, Widget } from 'cx/ui';
import { isFocused } from 'cx/util';

import marked from 'marked';
import {getStyles} from './styling';

export class Task extends Widget {

    init() {
        if (this.bind)
            this.task = {bind: this.bind};

        super.init();
    }

    declareData() {
        super.declareData(...arguments, {
            task: undefined,
            styles: undefined
        })
    }

    render(context, instance, key) {
        return <TaskCmp key={key} instance={instance}/>
    }
}

class TaskCmp extends VDOM.Component {

    constructor(props) {
        super(props);

        this.state = {
            edit: false,
            scrollHeight: null
        };

        this.dom = {};
    }

    render() {
        let {instance} = this.props;
        let {widget, data} = instance;
        let {CSS} = widget;

        let className = CSS.block("task", {}, {
            edit: this.state.edit,
            completed: !!data.task.completed
        });

        return
 {
                        this.dom.el = el
                    }}
                    tabIndex={0}
                    onClick={::this.onClick}
                    onTouchStart={::this.onTouchStart}
                    onDoubleClick={e=>{this.toggleEditMode()}}>
            { !this.state.edit && this.renderContent() }
            { this.state.edit && this.renderEditor() }

    }

    renderContent() {
        var {data, widget} = this.props.instance;
        var html = data.task.name ? marked(data.task.name) : '

';

        var styles = getStyles(data.task.name, data.styles);

        return [
            <input key="check" type="checkbox"
                   checked={!!data.task.completed}
                   onChange={::this.onCheck}
                   tabIndex={-1}
                   onClick={e=> {
                       e.preventDefault();
                       e.stopPropagation();
                   }}/>,

]
    }

    renderEditor() {
        var {data} = this.props.instance;
        var style = {};
        if (this.state.scrollHeight) {
            style.height = `${this.state.scrollHeight}px`;
        }
        return <textarea defaultValue={data.task.name}
                         onMouseDown={e=>{e.stopPropagation();}}
                         onKeyDown={::this.onEditorKeyDown}
                         ref={c=> {
                             this.dom.editor = c;
                         }}
                         style={style}
                         rows={1}
                         onBlur={::this.onEditorBlur}
                         onChange={::this.onChange}
        />
    }

    onCheck(e) {
        e.preventDefault();
        e.stopPropagation();
        this.setCompleted(e.target.checked);
    }

    setCompleted(completed = true) {
        let {instance} = this.props;
        let {data} = instance;

        instance.set('task', {
            ...data.task,
            completed: completed,
            completedDate: new Date().toISOString()
        });
    }

    onKeyDown(e) {
        let {instance} = this.props;
        let {data, widget} = instance;

        switch (e.keyCode) {
            case 13:
            case 73: // i (insert)
            case 65: // a (append)
                e.stopPropagation();
                e.preventDefault()
                this.toggleEditMode();
                break;

            case 32:
            case 88: // x
                this.setCompleted(!data.task.completed);
                break;

            default:
                if (widget.onKeyDown)
                    widget.onKeyDown(e, instance);
                break;
        }
    }

    save(e) {
        let {instance} = this.props;
        let {data} = instance;

        var task = {
            ...data.task,
            name: e.target.value,
            lastChange: new Date().toISOString()
        };

        delete task.isNew;

        instance.set('task', task);
    }

    onEditorKeyDown(e) {
        let {instance} = this.props;
        let {data} = instance;

        switch (e.keyCode) {
            case 13:
                e.stopPropagation();
                if (e.ctrlKey) {
                    this.save(e);
                    this.toggleEditMode();
                }
                break;

            case 27:
                this.save(e);
                this.toggleEditMode();
                break;

            default:
                e.stopPropagation()
                break;
        }
    }

    onEditorBlur(e) {
        this.save(e);
        this.setState({
            edit: false
        });
    }

    onChange(e) {
        this.componentDidUpdate();
    }

    onClick(e) {
        e.preventDefault();
        e.stopPropagation();
    }

    onTouchStart(e) {
        if (!this.state.edit && isFocused(this.dom.el)) {
            this.toggleEditMode();
            e.stopPropagation();
            e.preventDefault();
        }
    }

    toggleEditMode() {
        var change = {
            edit: !this.state.edit
        };

        if (change.edit)
            change.scrollHeight = null;

        this.setState(change, () => {
            if (this.state.edit)
                this.dom.editor.focus();
            else
                this.dom.el.focus();
        })
    }

    componentDidMount() {
        this.props.instance.parent.toggleEditMode = ::this.toggleEditMode;
        let {instance} = this.props;
        let {store, data} = instance;

        if (this.dom.el.parentNode.parentNode.parentNode.contains(document.activeElement))
            this.toggleEditMode();

        if (data.task.id == store.get('activeTaskId'))
            setTimeout(()=> {
                this.dom.el.focus();
            }, 10);
    }

    componentDidUpdate() {
        if (this.state.edit) {
            this.dom.editor.style.width = `${this.dom.editor.scrollWidth}px`;
            if (this.dom.editor.scrollHeight > this.dom.editor.offsetHeight) {
                this.setState({
                    scrollHeight: Math.ceil(this.dom.editor.scrollHeight)
                });
            }
        }
    }
}
<commit_msg>fix: prevented event propagation on `task done action`<commit_after>import { VDOM, Widget } from 'cx/ui';
import { isFocused } from 'cx/util';

import marked from 'marked';
import {getStyles} from './styling';

export class Task extends Widget {

    init() {
        if (this.bind)
            this.task = {bind: this.bind};

        super.init();
    }

    declareData() {
        super.declareData(...arguments, {
            task: undefined,
            styles: undefined
        })
    }

    render(context, instance, key) {
        return <TaskCmp key={key} instance={instance}/>
    }
}

class TaskCmp extends VDOM.Component {

    constructor(props) {
        super(props);

        this.state = {
            edit: false,
            scrollHeight: null
        };

        this.dom = {};
    }

    render() {
        let {instance} = this.props;
        let {widget, data} = instance;
        let {CSS} = widget;

        let className = CSS.block("task", {}, {
            edit: this.state.edit,
            completed: !!data.task.completed
        });

        return
 {
                        this.dom.el = el
                    }}
                    tabIndex={0}
                    onClick={::this.onClick}
                    onTouchStart={::this.onTouchStart}
                    onDoubleClick={e=>{this.toggleEditMode()}}>
            { !this.state.edit && this.renderContent() }
            { this.state.edit && this.renderEditor() }

    }

    renderContent() {
        var {data, widget} = this.props.instance;
        var html = data.task.name ? marked(data.task.name) : '

';

        var styles = getStyles(data.task.name, data.styles);

        return [
            <input key="check" type="checkbox"
                   checked={!!data.task.completed}
                   onChange={::this.onCheck}
                   tabIndex={-1}
                   onClick={e=> {
                       e.preventDefault();
                       e.stopPropagation();
                   }}/>,

]
    }

    renderEditor() {
        var {data} = this.props.instance;
        var style = {};
        if (this.state.scrollHeight) {
            style.height = `${this.state.scrollHeight}px`;
        }
        return <textarea defaultValue={data.task.name}
                         onMouseDown={e=>{e.stopPropagation();}}
                         onKeyDown={::this.onEditorKeyDown}
                         ref={c=> {
                             this.dom.editor = c;
                         }}
                         style={style}
                         rows={1}
                         onBlur={::this.onEditorBlur}
                         onChange={::this.onChange}
        />
    }

    onCheck(e) {
        e.preventDefault();
        e.stopPropagation();
        this.setCompleted(e.target.checked);
    }

    setCompleted(completed = true) {
        let {instance} = this.props;
        let {data} = instance;

        instance.set('task', {
            ...data.task,
            completed: completed,
            completedDate: new Date().toISOString()
        });
    }

    onKeyDown(e) {
        let {instance} = this.props;
        let {data, widget} = instance;

        switch (e.keyCode) {
            case 13:
            case 73: // i (insert)
            case 65: // a (append)
                e.stopPropagation();
                e.preventDefault()
                this.toggleEditMode();
                break;

            case 32:
            case 88: // x
                e.stopPropagation();
                e.preventDefault();
                this.setCompleted(!data.task.completed);
                break;

            default:
                if (widget.onKeyDown)
                    widget.onKeyDown(e, instance);
                break;
        }
    }

    save(e) {
        let {instance} = this.props;
        let {data} = instance;

        var task = {
            ...data.task,
            name: e.target.value,
            lastChange: new Date().toISOString()
        };

        delete task.isNew;

        instance.set('task', task);
    }

    onEditorKeyDown(e) {
        let {instance} = this.props;
        let {data} = instance;

        switch (e.keyCode) {
            case 13:
                e.stopPropagation();
                if (e.ctrlKey) {
                    this.save(e);
                    this.toggleEditMode();
                }
                break;

            case 27:
                this.save(e);
                this.toggleEditMode();
                break;

            default:
                e.stopPropagation()
                break;
        }
    }

    onEditorBlur(e) {
        this.save(e);
        this.setState({
            edit: false
        });
    }

    onChange(e) {
        this.componentDidUpdate();
    }

    onClick(e) {
        e.preventDefault();
        e.stopPropagation();
    }

    onTouchStart(e) {
        if (!this.state.edit && isFocused(this.dom.el)) {
            this.toggleEditMode();
            e.stopPropagation();
            e.preventDefault();
        }
    }

    toggleEditMode() {
        var change = {
            edit: !this.state.edit
        };

        if (change.edit)
            change.scrollHeight = null;

        this.setState(change, () => {
            if (this.state.edit)
                this.dom.editor.focus();
            else
                this.dom.el.focus();
        })
    }

    componentDidMount() {
        this.props.instance.parent.toggleEditMode = ::this.toggleEditMode;
        let {instance} = this.props;
        let {store, data} = instance;

        if (this.dom.el.parentNode.parentNode.parentNode.contains(document.activeElement))
            this.toggleEditMode();

        if (data.task.id == store.get('activeTaskId'))
            setTimeout(()=> {
                this.dom.el.focus();
            }, 10);
    }

    componentDidUpdate() {
        if (this.state.edit) {
            this.dom.editor.style.width = `${this.dom.editor.scrollWidth}px`;
            if (this.dom.editor.scrollHeight > this.dom.editor.offsetHeight) {
                this.setState({
                    scrollHeight: Math.ceil(this.dom.editor.scrollHeight)
                });
            }
        }
    }
}
<|endoftext|>


<commit_before>const PropTypes = require('prop-types');
const React = require('react');

import { withTheme } from './Theme';
const Button = require('./Button');
const Icon = require('./Icon');
const MXFocusTrap = require('../components/MXFocusTrap');

const _merge = require('lodash/merge');

const { themeShape } = require('../constants/App');

const StyleUtils = require('../utils/Style');
const { deprecatePrimaryColor, deprecatePropWithMessage } = require('../utils/Deprecation');

class Modal extends React.Component {
  static propTypes = {
    'aria-describedby': PropTypes.string,
    'aria-label': PropTypes.string,
    'aria-labelledby': PropTypes.string,
    buttons: PropTypes.arrayOf(PropTypes.shape({
      actionText: PropTypes.string,
      className: PropTypes.string,
      isActive: PropTypes.bool,
      icon: PropTypes.string,
      label: PropTypes.string,
      onClick: PropTypes.func,
      primaryColor: PropTypes.string,
      style: PropTypes.object,
      type: PropTypes.oneOf(['primary', 'secondary'])
    })),
    color: PropTypes.string,
    contentStyle: PropTypes.object,
    focusOnLoad: PropTypes.bool,
    focusTrapProps: PropTypes.object,
    footerContent: PropTypes.node,
    footerStyle: PropTypes.object,
    isRelative: PropTypes.bool,
    onRequestClose: PropTypes.func,
    showCloseIcon: PropTypes.bool,
    showFooter: PropTypes.bool,
    showScrim: PropTypes.bool,
    showTitleBar: PropTypes.bool,
    style: PropTypes.object,
    styles: PropTypes.object,
    theme: themeShape,
    title: PropTypes.string,
    tooltip: PropTypes.string,
    tooltipLabel: PropTypes.string,
    tooltipTitle: PropTypes.string
  };

  static defaultProps = {
    'aria-label': '',
    buttons: [],
    focusOnLoad: true,
    focusTrapProps: {},
    isRelative: false,
    showCloseIcon: true,
    showFooter: false,
    showScrim: true,
    showTitleBar: false,
    title: '',
    tooltip: null,
    tooltipLabel: '',
    tooltipTitle: null
  };

  state = {
    showTooltip: false
  };

  componentDidMount () {
    deprecatePrimaryColor(this.props, 'color');
    deprecatePropWithMessage(
      this.props,
      'isOpen',
      'Please handle Modal opening from its parent.',
      'modal'
    );

    if (this.props.focusOnLoad) this._modalContent.focus();
  }

  _handleTooltipToggle = (show) => {
    this.setState({
      showTooltip: show
    });
  };

  _renderTitleBar = (styles) => {
    if (this.props.showTitleBar) {
      return (

          {this.props.title}

      );
    } else {
      return null;
    }
  };

  _renderFooter = (styles, theme) => {
    if (this.props.showFooter) {
      return (

          {this._renderTooltipIconAndLabel(styles, theme)}
          {this._renderFooterContent(styles)}

            {this.props.buttons.map((button, i) => {
              return (
                <Button
                  actionText={button.actionText}
                  className={'mx-modal-button ' + button.className}
                  icon={button.icon}
                  isActive={button.isActive}
                  key={button.type + i}
                  onClick={button.onClick}
                  style={Object.assign({}, styles.button, button.style)}
                  theme={theme}
                  type={button.type}
                >
                  {button.label}
                </Button>
              );
            })}

      );
    } else {
      return null;
    }
  };

  _renderFooterContent = (styles) => {
    return (

        {this.props.footerContent}

    );
  };

  _renderTooltip = (styles, theme) => {
    if (this.state.showTooltip) {
      return (

            {this.props.tooltipTitle}

            {this.props.tooltip}

      );
    } else {
      return null;
    }
  };

  _renderTooltipIconAndLabel = (styles, theme) => {
    if (this.props.tooltip) {
      return (

          <Icon
            className='mx-modal-tooltip-label-icon'
            elementProps={{
              onMouseOut: this._handleTooltipToggle.bind(null, false),
              onMouseOver: this._handleTooltipToggle.bind(null, true)
            }}
            size={18}
            style={{ color: theme.Colors.PRIMARY }}
            type='info'
          />

            {this.props.tooltipLabel}

      );
    } else {
      return null;
    }
  };

  render () {
    const theme = StyleUtils.mergeTheme(this.props.theme, this.props.color);
    const styles = this.styles(theme);
    const mergedFocusTrapProps = {
      focusTrapOptions: {
        clickOutsideDeactivates: true
      },
      ...this.props.focusTrapProps
    };

    return (
      <MXFocusTrap {...mergedFocusTrapProps}>

            {this._renderTitleBar(styles)}

 this._modalContent = ref}
              style={Object.assign({}, styles.content, this.props.contentStyle)}
              tabIndex={0}
            >
              {this.props.children}
              {this._renderTooltip(styles, theme)}

            {this._renderFooter(styles, theme)}
            {this.props.showCloseIcon && (
              <button
                aria-label='Close Modal'
                onClick={this.props.onRequestClose}
                onKeyUp={e => e.keyCode === 13 && this.props.onRequestClose()}
                role='button'
                style={styles.close}
                tabIndex={0}
              >
                <Icon
                  className='mx-modal-close'
                  size={24}
                  style={styles.closeIcon}
                  type='close-solid'
                />
              </button>
            )}

      </MXFocusTrap>
    );
  }

  styles = theme => {
    return _merge({}, {
      scrim: {
        zIndex: 1000,
        position: 'fixed',
        top: 0,
        right: 0,
        bottom: 0,
        left: 0,
        textAlign: 'center'
      },
      relative: {
        position: 'absolute'
      },
      overlay: {
        backgroundColor: this.props.showScrim ? theme.Colors.SCRIM : 'transparent'
      },
      close: {
        position: 'absolute',
        top: 0,
        right: 0,
        margin: '-12px -12px 0 0',
        cursor: 'pointer',
        border: 'none',
        backgroundColor: 'transparent'
      },
      closeIcon: {
        color: theme.Colors.GRAY_700
      },
      container: {
        fontFamily: theme.FontFamily,
        boxSizing: 'border-box',
        position: 'relative',
        zIndex: 1001,
        backgroundColor: theme.Colors.WHITE,
        boxShadow: theme.ShadowHigh,
        borderRadius: 2,
        top: 20,
        maxWidth: 'calc(100% - 40px)',
        display: 'inline-block',
        textAlign: 'left'
      },
      titleBar: {
        backgroundColor: theme.Colors.GRAY_100,
        borderTopLeftRadius: 2,
        borderTopRightRadius: 2,
        padding: '15px 20px',
        color: theme.Colors.GRAY_500,
        fontSize: theme.FontSizes.SMALL,
        textTransform: 'uppercase',
        letterSpacing: 1
      },
      content: {
        position: 'relative',
        maxHeight: 'calc(100% - 140px)',
        overflow: 'auto'
      },
      footer: {
        backgroundColor: theme.Colors.GRAY_100,
        borderBottomLeftRadius: 2,
        borderBottomRightRadius: 2,
        padding: '10px 20px',
        display: 'flex',
        justifyContent: 'space-between'
      },
      footerContent: {
        padding: '5px 0',
        textAlign: 'left'
      },
      tooltipLabel: {
        padding: '5px 0'
      },
      tooltipLabelText: {
        fontSize: theme.FontSizes.SMALL
      },
      tooltip: {
        backgroundColor: theme.Colors.GRAY_100,
        borderColor: theme.Colors.GRAY_300,
        borderStyle: 'solid',
        borderWidth: 1,
        boxSizing: 'border-box',
        bottom: 10,
        left: 10,
        position: 'absolute',
        width: 250,
        maxWidth: '100%',
        padding: 10
      },
      tooltipTitle: {
        fontSize: theme.FontSizes.MEDIUM,
        marginBottom: 5
      },
      tooltipContent: {
        color: theme.Colors.GRAY_500,
        fontSize: theme.FontSizes.SMALL,
        lineHeight: '1.5em',
        textAlign: 'left'
      },
      buttons: {
        textAlign: 'right'
      },
      button: {
        marginLeft: 5
      },
      small: {
        width: 400,
        textAlign: 'center'
      }
    }, this.props.styles);
  };
}

module.exports = withTheme(Modal);
<commit_msg>Adds role prop<commit_after>const PropTypes = require('prop-types');
const React = require('react');

import { withTheme } from './Theme';
const Button = require('./Button');
const Icon = require('./Icon');
const MXFocusTrap = require('../components/MXFocusTrap');

const _merge = require('lodash/merge');

const { themeShape } = require('../constants/App');

const StyleUtils = require('../utils/Style');
const { deprecatePrimaryColor, deprecatePropWithMessage } = require('../utils/Deprecation');

class Modal extends React.Component {
  static propTypes = {
    'aria-describedby': PropTypes.string,
    'aria-label': PropTypes.string,
    'aria-labelledby': PropTypes.string,
    buttons: PropTypes.arrayOf(PropTypes.shape({
      actionText: PropTypes.string,
      className: PropTypes.string,
      isActive: PropTypes.bool,
      icon: PropTypes.string,
      label: PropTypes.string,
      onClick: PropTypes.func,
      primaryColor: PropTypes.string,
      style: PropTypes.object,
      type: PropTypes.oneOf(['primary', 'secondary'])
    })),
    color: PropTypes.string,
    contentStyle: PropTypes.object,
    focusOnLoad: PropTypes.bool,
    focusTrapProps: PropTypes.object,
    footerContent: PropTypes.node,
    footerStyle: PropTypes.object,
    isRelative: PropTypes.bool,
    onRequestClose: PropTypes.func,
    role: PropTypes.string,
    showCloseIcon: PropTypes.bool,
    showFooter: PropTypes.bool,
    showScrim: PropTypes.bool,
    showTitleBar: PropTypes.bool,
    style: PropTypes.object,
    styles: PropTypes.object,
    theme: themeShape,
    title: PropTypes.string,
    tooltip: PropTypes.string,
    tooltipLabel: PropTypes.string,
    tooltipTitle: PropTypes.string
  };

  static defaultProps = {
    'aria-label': '',
    buttons: [],
    focusOnLoad: true,
    focusTrapProps: {},
    isRelative: false,
    role: 'dialog',
    showCloseIcon: true,
    showFooter: false,
    showScrim: true,
    showTitleBar: false,
    title: '',
    tooltip: null,
    tooltipLabel: '',
    tooltipTitle: null
  };

  state = {
    showTooltip: false
  };

  componentDidMount () {
    deprecatePrimaryColor(this.props, 'color');
    deprecatePropWithMessage(
      this.props,
      'isOpen',
      'Please handle Modal opening from its parent.',
      'modal'
    );

    if (this.props.focusOnLoad) this._modalContent.focus();
  }

  _handleTooltipToggle = (show) => {
    this.setState({
      showTooltip: show
    });
  };

  _renderTitleBar = (styles) => {
    if (this.props.showTitleBar) {
      return (

          {this.props.title}

      );
    } else {
      return null;
    }
  };

  _renderFooter = (styles, theme) => {
    if (this.props.showFooter) {
      return (

          {this._renderTooltipIconAndLabel(styles, theme)}
          {this._renderFooterContent(styles)}

            {this.props.buttons.map((button, i) => {
              return (
                <Button
                  actionText={button.actionText}
                  className={'mx-modal-button ' + button.className}
                  icon={button.icon}
                  isActive={button.isActive}
                  key={button.type + i}
                  onClick={button.onClick}
                  style={Object.assign({}, styles.button, button.style)}
                  theme={theme}
                  type={button.type}
                >
                  {button.label}
                </Button>
              );
            })}

      );
    } else {
      return null;
    }
  };

  _renderFooterContent = (styles) => {
    return (

        {this.props.footerContent}

    );
  };

  _renderTooltip = (styles, theme) => {
    if (this.state.showTooltip) {
      return (

            {this.props.tooltipTitle}

            {this.props.tooltip}

      );
    } else {
      return null;
    }
  };

  _renderTooltipIconAndLabel = (styles, theme) => {
    if (this.props.tooltip) {
      return (

          <Icon
            className='mx-modal-tooltip-label-icon'
            elementProps={{
              onMouseOut: this._handleTooltipToggle.bind(null, false),
              onMouseOver: this._handleTooltipToggle.bind(null, true)
            }}
            size={18}
            style={{ color: theme.Colors.PRIMARY }}
            type='info'
          />

            {this.props.tooltipLabel}

      );
    } else {
      return null;
    }
  };

  render () {
    const theme = StyleUtils.mergeTheme(this.props.theme, this.props.color);
    const styles = this.styles(theme);
    const mergedFocusTrapProps = {
      focusTrapOptions: {
        clickOutsideDeactivates: true
      },
      ...this.props.focusTrapProps
    };

    return (
      <MXFocusTrap {...mergedFocusTrapProps}>

            {this._renderTitleBar(styles)}

 this._modalContent = ref}
              role={this.props.role}
              style={Object.assign({}, styles.content, this.props.contentStyle)}
              tabIndex={0}
            >
              {this.props.children}
              {this._renderTooltip(styles, theme)}

            {this._renderFooter(styles, theme)}
            {this.props.showCloseIcon && (
              <button
                aria-label='Close Modal'
                onClick={this.props.onRequestClose}
                onKeyUp={e => e.keyCode === 13 && this.props.onRequestClose()}
                role='button'
                style={styles.close}
                tabIndex={0}
              >
                <Icon
                  className='mx-modal-close'
                  size={24}
                  style={styles.closeIcon}
                  type='close-solid'
                />
              </button>
            )}

      </MXFocusTrap>
    );
  }

  styles = theme => {
    return _merge({}, {
      scrim: {
        zIndex: 1000,
        position: 'fixed',
        top: 0,
        right: 0,
        bottom: 0,
        left: 0,
        textAlign: 'center'
      },
      relative: {
        position: 'absolute'
      },
      overlay: {
        backgroundColor: this.props.showScrim ? theme.Colors.SCRIM : 'transparent'
      },
      close: {
        position: 'absolute',
        top: 0,
        right: 0,
        margin: '-12px -12px 0 0',
        cursor: 'pointer',
        border: 'none',
        backgroundColor: 'transparent'
      },
      closeIcon: {
        color: theme.Colors.GRAY_700
      },
      container: {
        fontFamily: theme.FontFamily,
        boxSizing: 'border-box',
        position: 'relative',
        zIndex: 1001,
        backgroundColor: theme.Colors.WHITE,
        boxShadow: theme.ShadowHigh,
        borderRadius: 2,
        top: 20,
        maxWidth: 'calc(100% - 40px)',
        display: 'inline-block',
        textAlign: 'left'
      },
      titleBar: {
        backgroundColor: theme.Colors.GRAY_100,
        borderTopLeftRadius: 2,
        borderTopRightRadius: 2,
        padding: '15px 20px',
        color: theme.Colors.GRAY_500,
        fontSize: theme.FontSizes.SMALL,
        textTransform: 'uppercase',
        letterSpacing: 1
      },
      content: {
        position: 'relative',
        maxHeight: 'calc(100% - 140px)',
        overflow: 'auto'
      },
      footer: {
        backgroundColor: theme.Colors.GRAY_100,
        borderBottomLeftRadius: 2,
        borderBottomRightRadius: 2,
        padding: '10px 20px',
        display: 'flex',
        justifyContent: 'space-between'
      },
      footerContent: {
        padding: '5px 0',
        textAlign: 'left'
      },
      tooltipLabel: {
        padding: '5px 0'
      },
      tooltipLabelText: {
        fontSize: theme.FontSizes.SMALL
      },
      tooltip: {
        backgroundColor: theme.Colors.GRAY_100,
        borderColor: theme.Colors.GRAY_300,
        borderStyle: 'solid',
        borderWidth: 1,
        boxSizing: 'border-box',
        bottom: 10,
        left: 10,
        position: 'absolute',
        width: 250,
        maxWidth: '100%',
        padding: 10
      },
      tooltipTitle: {
        fontSize: theme.FontSizes.MEDIUM,
        marginBottom: 5
      },
      tooltipContent: {
        color: theme.Colors.GRAY_500,
        fontSize: theme.FontSizes.SMALL,
        lineHeight: '1.5em',
        textAlign: 'left'
      },
      buttons: {
        textAlign: 'right'
      },
      button: {
        marginLeft: 5
      },
      small: {
        width: 400,
        textAlign: 'center'
      }
    }, this.props.styles);
  };
}

module.exports = withTheme(Modal);
<|endoftext|>