Constraint Editor with Intellisense

by Michael Barros

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/mithril/0.2.3/mithril.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.ui.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootswatch/3.3.6/paper/bootstrap.min.css">
<script src="//bayardrock.github.io/WebIntellisense/src/js/lib/webintellisense-textbox.js"></script>
<script src="//bayardrock.github.io/WebIntellisense/src/js/lib/webintellisense.js"></script>
<div class="container">
  <div class="row">
    <div class="col-xs-12 col-md-4">
      <h5>Specify Optimization Problem</h5>
      <div id="app"></div>
    </div>
  </div>
</div>

CSS

.accordion.panel{
  border: none;
}
::-webkit-input-placeholder{
  font-size: 12px;
}
#main{margin-top: 20px;}
.panel-heading {    
  color: #333;
  background-color: #f5f5f5;
  border-bottom: solid #ddd 1px;
}
.panel{
  border-radius: 0px;
  box-shadow: none;
  border: solid lightgray 1px;
}
span.heading{
  margin-left: 5px;
}
.panel-custom-heading, .panel-custom-footer{
  padding: 5px 10px;
  background: none;
}
.panel-custom-footer{
  padding: 0px;
}
.panel-custom-heading .glyphicon-remove{
  visibility: hidden;
}
.panel-custom-heading:hover .glyphicon-remove{
  visibility: visible;
}
.remove, .add{
  margin-right: 0px;
}
.remove{
  /*margin-right: -15px;*/
  /*margin-right: -5px; */
}
.add{
  color: white;
  background: #2196f3;
  padding: 5px;
  font-size: 9px;
}
.remove{
  color: white;
  background: darkred;
  padding: 5px;
  font-size: 9px;
}
.panel-custom-heading .heading{
  font-family: Consolas;
}

.br-intellisense {
    min-width: 120px;
    max-height: 176px;
    min-height: 22px;
    z-index: 10;
    overflow: auto;
    position: absolute;
    background-color: white;
    border: 1px solid lightgray;
    box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
    padding: 0;
    margin: 5px;
    display: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -webkit-user-select: none;
    user-select: none;
}

.br-documentation {
    min-width: 200px;
    padding: 3px;
    overflow: auto;
    position: absolute;
    z-index: 10;
    background-color: #E7E8EC;
    border: 1px solid #CCCEDB;
    box-shadow: 2px 3px 5px rgba(0,0,0,.2);
    font-family: 'Segoe UI';
    font-size: 10pt;
    white-space: pre-line;
    display: none;
}

.br-listlink {
    font-family: 'Segoe UI';
    font-size: 10pt;
    list-style: none;
    cursor: pointer;
    border: 1px solid white;
    white-space: nowrap;
    overflow: hidden;
}

.br-listlink:hover {
  /* background-color: #FDF4BF; */
  background-color: #d9ecff;
}

.br-selected {
    /* background-color: #FDF4BF; */
 ...

JavaScript

(function() {
    // @param x Array of symbols
    // @return List of Allowed Symbols
    var AllowedSymbols, App, IntelliSenseBox, MaxObjective, Panel, ToggleDiv, validateConstraint;

    AllowedSymbols = function(x) {};

    // returns keycodes of allowed symbols
    validateConstraint = function(constraint) {};

    IntelliSenseBox = {
        view: function(ctrl, props) {
            return m('textarea.form-control', {
                placeholder: 'Ctrl + Space for suggestions',
                value: props.value(),
                onchange: props.handleChange || null,
                onkeypress: props.handleKeyPress || null,
                config: IntelliSenseBox.config(props),
                style: {
                    resize: "vertical"
                }
            });
        },
        config: function(props) {
            return function(el, isInit, ctx) {
                var intellisense;
                if (!isInit) {
                    intellisense = new TextBoxIntellisense(el);
                    intellisense.getDecls().setFilterMode('contains');
                    intellisense.addDeclarationTrigger({
                        keyCode: 190
                    });
                    intellisense.addDeclarationTrigger({
                        keyCode: 32,
                        ctrlKey: true,
                        preventDefault: true
                    });
                    intellisense.onDeclaration(function(item) {
                        return intellisense.setDeclarations(props.data);
                    });
                    return ctx.intellisense = intellisense;
                } else {
                    return ctx.intellisense.onDeclaration(function(item) {
                        return ctx.intellisense.setDeclarations(props.data);
                    });
                }
            };
        }
    };

    MaxObjective = {
        view: function(ctrl, props) {
            return m(".checkbox", m("span", "Maximize...