<commit_before>import Ember from 'ember';
import hbs from 'htmlbars-inline-precompile';
import { moduleForComponent, test } from 'ember-qunit';
import sinon from 'sinon';

const mockStream = {
    actions: {},

    on( actionName, handler ) {
        this.actions[ actionName ] = handler;
    },

    subject: {
        dispose() {
            mockStream.actions = {};
        },

        onCompleted() {}
    }
};

const template = hbs`
    {{#sl-modal as |modal|}}
        {{sl-modal-header
            title="Simple Example"
            ariaLabelledBy=modal.ariaLabelledBy
        }}

        {{#sl-modal-body}}

A simple modal example

        {{/sl-modal-body}}

        {{sl-modal-footer}}
    {{/sl-modal}}
`;

moduleForComponent( 'sl-modal', 'Integration | Component | sl modal', {
    afterEach() {
        this.$( '.modal' ).remove();
        Ember.$( '.modal-backdrop' ).remove();
    },

    integration: true
});

test( 'backdrop property is passed thru to jquery correctly', function( assert ) {
    // we currently only pass thru the backdrop parameter
    const spy = sinon.spy( Ember.$.fn, 'modal' );

    // props passed to bootstrap modal that are not bound to template
    const nonTemplateProps = {
        'keyboard': true,
        'show': false
    };

    // all props set one way
    const template1 = hbs`
        {{#sl-modal
            backdrop=false
        }}
            {{sl-modal-header}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    `;

    // all props set another way
    const template2 = hbs`
        {{#sl-modal
            backdrop=true
        }}
            {{sl-modal-header}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    `;

    // all props allowed to default
    const template3 = hbs`
        {{#sl-modal}}
            {{sl-modal-header}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    `;

    this.render( template1 );

    assert.deepEqual(
        spy.args[0][0],
        Ember.$.extend(
            {
                'backdrop': false
            },
            nonTemplateProps
        ),
        'backdrop is false when set to false'
    );

    this.render( template2 );

    assert.deepEqual(
        spy.args[1][0],
        Ember.$.extend(
            {
                'backdrop': true
            },
            nonTemplateProps
        ),
        'backdrop is true when set to true'
    );

    this.render( template3 );

    assert.deepEqual(
        spy.args[2][0],
        Ember.$.extend(
            {
                'backdrop': true
            },
            nonTemplateProps
        ),
        'backdrop is true by default'
    );

    Ember.$.fn.modal.restore();
});

test( 'Animated property adds fade class', function( assert ) {
    // all props set one way
    const template1 = hbs`
        {{#sl-modal
            animated=false
        }}
            {{sl-modal-header}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    `;

    // all props set another way
    const template2 = hbs`
        {{#sl-modal
            animated=true
        }}
            {{sl-modal-header}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    `;

    // all props allowed to default
    const template3 = hbs`
        {{#sl-modal}}
            {{sl-modal-header}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    `;

    this.render( template1 );
    const $first = this.$( '>:first-child' );

    this.render( template2 );
    const $second = this.$( '>:first-child' );

    this.render( template3 );
    const $third = this.$( '>:first-child' );

    assert.strictEqual(
        $first.filter( ':not(.fade)' ).length,
        1,
        'fade class not present when animated set to false'
    );

    assert.strictEqual(
        $second.filter( '.fade' ).length,
        1,
        'fade class present when animated set to true'
    );

    assert.strictEqual(
        $third.filter( '.fade' ).length,
        1,
        'fade class present when animated not set'
    );
});

test( 'Classes are present', function( assert ) {
    this.render( template );

    assert.ok(
        this.$( '>:first-child' ).hasClass( 'modal' ),
        'Has class modal'
    );
});

test( 'Listeners are setup and firing appropriately', function( assert ) {
    assert.expect( 4 );

    const beforeShowDone = assert.async();
    const afterShowDone = assert.async();
    const beforeHideDone = assert.async();
    const afterHideDone = assert.async();

    const beforeShow = () =>  {
        assert.ok(
            true,
            'beforeShow was triggered'
        );

        beforeShowDone();
    };

    const afterShow = () => {
        assert.ok(
            true,
            'afterShow was triggered'
        );

        afterShowDone();
    };

    const beforeHide = () => {
        assert.ok(
            true,
            'beforeHide was triggered'
        );

        beforeHideDone();
    };

    const afterHide = () => {
        assert.ok(
            true,
            'afterHide was triggered'
        );

        afterHideDone();
    };

    this.on( 'beforeShow', beforeShow );
    this.on( 'afterShow', afterShow );
    this.on( 'beforeHide', beforeHide );
    this.on( 'afterHide', afterHide );

    this.render( hbs`
        {{#sl-modal name="testing"
            beforeShow="beforeShow"
            afterShow="afterShow"
            beforeHide="beforeHide"
            afterHide="afterHide"
         }}
            {{sl-modal-header}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    Ember.run( () => {
        this.$( '>:first-child' ).modal( 'show' );
        this.$( '>:first-child' ).modal( 'hide' );
    });

    this.hideModal = false;
});

test( 'Property isOpen is set appropriately', function( assert ) {
    this.set( 'isOpen' );

    this.render( hbs`
        {{#sl-modal isOpen=isOpen}}
            {{sl-modal-header title="Simple Example"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    Ember.run( () => {
        this.$( '>:first-child' ).trigger( 'shown.bs.modal' );
    });

    assert.strictEqual(
        this.get( 'isOpen' ),
        true,
        'isOpen was set to true when modal show event was triggered'
    );

    Ember.run( () => {
        this.$( '>:first-child' ).trigger( 'hidden.bs.modal' );
    });

    assert.strictEqual(
        this.get( 'isOpen' ),
        false,
        'isOpen was set to false when modal close event was triggered'
    );
});

test( 'Closing of modal using close button works', function( assert ) {
    assert.expect( 1 );
    const closeDone = assert.async();

    const modalClosed = () => {
        assert.ok(
            true,
            'Modal was closed'
        );
        closeDone();
    };

    this.on( 'modalClosed', modalClosed );

    this.render( hbs`
        {{#sl-modal afterHide="modalClosed"}}
            {{sl-modal-header title="Simple Example"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    Ember.run( () => {
        this.$( '>:first-child' ).modal( 'show' );
        this.$( '>:first-child' ).find( '.close' ).click();
    });

});

test( 'ariaDescribedBy attribute binding', function( assert ) {
    const describedBy = 'targetId';

    this.set( 'ariaDescribedBy', describedBy );

    this.render( hbs`
        {{#sl-modal ariaDescribedBy=ariaDescribedBy}}
            {{sl-modal-header title="Simple Example"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    assert.strictEqual(
        this.$( '>:first-child' ).attr( 'aria-describedby' ),
        describedBy
    );
});

test( 'aria-hidden is true', function( assert ) {
    this.render( template );

    assert.strictEqual(
        this.$( '>:first-child' ).attr( 'aria-hidden' ),
        'true'
    );
});

test( 'aria-labelledby is set', function( assert ) {
    this.render( template );

    assert.strictEqual(
        this.$( '>:first-child' ).attr( 'aria-labelledby' ),
        this.$( '>:first-child' ).find( '.modal-title' ).prop( 'id' ),
        '"aria-labelledby" points to correct element'
    );
});

test( 'Component responds to "hide" stream action', function( assert ) {
    this.set( 'stream', mockStream );
    this.set( 'hide', sinon.spy() );

    this.render( hbs`
        {{#sl-modal stream=stream hide=hide}}
            {{sl-modal-header title="Simple Example"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    mockStream.actions[ 'hide' ]();

    assert.ok(
        this.get( 'hide' ).calledOnce,
        'hide() was triggered successfully'
    );
});

test( 'Component responds to "show" stream action', function( assert ) {
    this.set( 'stream', mockStream );
    this.set( 'show', sinon.spy() );

    this.render( hbs`
        {{#sl-modal stream=stream show=show}}
            {{sl-modal-header title="Simple Example"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    mockStream.actions[ 'show' ]();

    assert.ok(
        this.get( 'show' ).calledOnce,
        'hide() was triggered successfully'
    );
});

test( 'Components do not cross-contaminate', function( assert ) {
    const spyModal = sinon.spy( Ember.$.fn, 'modal' );
    const spyOn = sinon.spy( Ember.$.fn, 'on' );

    this.render( hbs`
        {{#sl-modal}}
            {{sl-modal-header title="Simple Example 1"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    const $first = this.$( '>:first-child' );

    assert.deepEqual(
        spyModal.thisValues.map( ( i ) => i.get( 0 ) ),
        spyModal.thisValues.map( (   ) => $first.get( 0 ) ),
        'First modal attaches to the proper element ($.fn.modal)'
    );

    assert.deepEqual(
        spyOn.thisValues.map( ( i ) => i.get( 0 ) ),
        spyOn.thisValues.map( (   ) => $first.get( 0 ) ),
        'First modal attaches to the proper element ($.fn.on)'
    );

    spyModal.reset();
    spyOn.reset();

    this.render( hbs`
        {{#sl-modal}}
            {{sl-modal-header title="Simple Example 2"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    const $second = this.$( '>:first-child' );

    assert.deepEqual(
        spyModal.thisValues.map( ( i ) => i.get( 0 ) ),
        spyModal.thisValues.map( (   ) => $second.get( 0 ) ),
        'Second modal attaches to the proper element ($.fn.modal)'
    );

    assert.deepEqual(
        spyOn.thisValues.map( ( i ) => i.get( 0 ) ),
        spyOn.thisValues.map( (   ) => $second.get( 0 ) ),
        'Second modal attaches to the proper element ($.fn.on)'
    );

    spyModal.reset();
    spyOn.reset();

    $second.modal( 'show' );

    assert.deepEqual(
        spyModal.thisValues.map( ( i ) => i.get( 0 ) ),
        spyModal.thisValues.map( (   ) => $second.get( 0 ) ),
        'Second modal acts on the proper dom element (1/2)'
    );

    spyModal.reset();

    $second.modal( 'hide' );

    assert.deepEqual(
        spyModal.thisValues.map( ( i ) => i.get( 0 ) ),
        spyModal.thisValues.map( (   ) => $second.get( 0 ) ),
        'Second modal acts on the proper dom element (2/2)'
    );

    Ember.$.fn.modal.restore();
    Ember.$.fn.on.restore();
});
<commit_msg>slimmed down some templates to only what was required; based on Aziz' suggestion<commit_after>import Ember from 'ember';
import hbs from 'htmlbars-inline-precompile';
import { moduleForComponent, test } from 'ember-qunit';
import sinon from 'sinon';

const mockStream = {
    actions: {},

    on( actionName, handler ) {
        this.actions[ actionName ] = handler;
    },

    subject: {
        dispose() {
            mockStream.actions = {};
        },

        onCompleted() {}
    }
};

const template = hbs`
    {{#sl-modal as |modal|}}
        {{sl-modal-header
            title="Simple Example"
            ariaLabelledBy=modal.ariaLabelledBy
        }}

        {{#sl-modal-body}}

A simple modal example

        {{/sl-modal-body}}

        {{sl-modal-footer}}
    {{/sl-modal}}
`;

moduleForComponent( 'sl-modal', 'Integration | Component | sl modal', {
    afterEach() {
        this.$( '.modal' ).remove();
        Ember.$( '.modal-backdrop' ).remove();
    },

    integration: true
});

test( 'backdrop property is passed thru to jquery correctly', function( assert ) {
    // we currently only pass thru the backdrop parameter
    const spy = sinon.spy( Ember.$.fn, 'modal' );

    // props passed to bootstrap modal that are not bound to template
    const nonTemplateProps = {
        'keyboard': true,
        'show': false
    };

    // all props set one way
    const template1 = hbs`
        {{#sl-modal
            backdrop=false
        }}

        {{/sl-modal}}
    `;

    // all props set another way
    const template2 = hbs`
        {{#sl-modal
            backdrop=true
        }}

        {{/sl-modal}}
    `;

    // all props allowed to default
    const template3 = hbs`
        {{#sl-modal}}

        {{/sl-modal}}
    `;

    this.render( template1 );

    assert.deepEqual(
        spy.args[0][0],
        Ember.$.extend(
            {
                'backdrop': false
            },
            nonTemplateProps
        ),
        'backdrop is false when set to false'
    );

    this.render( template2 );

    assert.deepEqual(
        spy.args[1][0],
        Ember.$.extend(
            {
                'backdrop': true
            },
            nonTemplateProps
        ),
        'backdrop is true when set to true'
    );

    this.render( template3 );

    assert.deepEqual(
        spy.args[2][0],
        Ember.$.extend(
            {
                'backdrop': true
            },
            nonTemplateProps
        ),
        'backdrop is true by default'
    );

    Ember.$.fn.modal.restore();
});

test( 'Animated property adds fade class', function( assert ) {
    // all props set one way
    const template1 = hbs`
        {{#sl-modal
            animated=false
        }}

        {{/sl-modal}}
    `;

    // all props set another way
    const template2 = hbs`
        {{#sl-modal
            animated=true
        }}

        {{/sl-modal}}
    `;

    // all props allowed to default
    const template3 = hbs`
        {{#sl-modal}}

        {{/sl-modal}}
    `;

    this.render( template1 );
    const $first = this.$( '>:first-child' );

    this.render( template2 );
    const $second = this.$( '>:first-child' );

    this.render( template3 );
    const $third = this.$( '>:first-child' );

    assert.strictEqual(
        $first.filter( ':not(.fade)' ).length,
        1,
        'fade class not present when animated set to false'
    );

    assert.strictEqual(
        $second.filter( '.fade' ).length,
        1,
        'fade class present when animated set to true'
    );

    assert.strictEqual(
        $third.filter( '.fade' ).length,
        1,
        'fade class present when animated not set'
    );
});

test( 'Classes are present', function( assert ) {
    this.render( template );

    assert.ok(
        this.$( '>:first-child' ).hasClass( 'modal' ),
        'Has class modal'
    );
});

test( 'Listeners are setup and firing appropriately', function( assert ) {
    assert.expect( 4 );

    const beforeShowDone = assert.async();
    const afterShowDone = assert.async();
    const beforeHideDone = assert.async();
    const afterHideDone = assert.async();

    const beforeShow = () =>  {
        assert.ok(
            true,
            'beforeShow was triggered'
        );

        beforeShowDone();
    };

    const afterShow = () => {
        assert.ok(
            true,
            'afterShow was triggered'
        );

        afterShowDone();
    };

    const beforeHide = () => {
        assert.ok(
            true,
            'beforeHide was triggered'
        );

        beforeHideDone();
    };

    const afterHide = () => {
        assert.ok(
            true,
            'afterHide was triggered'
        );

        afterHideDone();
    };

    this.on( 'beforeShow', beforeShow );
    this.on( 'afterShow', afterShow );
    this.on( 'beforeHide', beforeHide );
    this.on( 'afterHide', afterHide );

    this.render( hbs`
        {{#sl-modal name="testing"
            beforeShow="beforeShow"
            afterShow="afterShow"
            beforeHide="beforeHide"
            afterHide="afterHide"
         }}
            {{sl-modal-header}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    Ember.run( () => {
        this.$( '>:first-child' ).modal( 'show' );
        this.$( '>:first-child' ).modal( 'hide' );
    });

    this.hideModal = false;
});

test( 'Property isOpen is set appropriately', function( assert ) {
    this.set( 'isOpen' );

    this.render( hbs`
        {{#sl-modal isOpen=isOpen}}
            {{sl-modal-header title="Simple Example"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    Ember.run( () => {
        this.$( '>:first-child' ).trigger( 'shown.bs.modal' );
    });

    assert.strictEqual(
        this.get( 'isOpen' ),
        true,
        'isOpen was set to true when modal show event was triggered'
    );

    Ember.run( () => {
        this.$( '>:first-child' ).trigger( 'hidden.bs.modal' );
    });

    assert.strictEqual(
        this.get( 'isOpen' ),
        false,
        'isOpen was set to false when modal close event was triggered'
    );
});

test( 'Closing of modal using close button works', function( assert ) {
    assert.expect( 1 );
    const closeDone = assert.async();

    const modalClosed = () => {
        assert.ok(
            true,
            'Modal was closed'
        );
        closeDone();
    };

    this.on( 'modalClosed', modalClosed );

    this.render( hbs`
        {{#sl-modal afterHide="modalClosed"}}
            {{sl-modal-header title="Simple Example"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    Ember.run( () => {
        this.$( '>:first-child' ).modal( 'show' );
        this.$( '>:first-child' ).find( '.close' ).click();
    });

});

test( 'ariaDescribedBy attribute binding', function( assert ) {
    const describedBy = 'targetId';

    this.set( 'ariaDescribedBy', describedBy );

    this.render( hbs`
        {{#sl-modal ariaDescribedBy=ariaDescribedBy}}
            {{sl-modal-header title="Simple Example"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    assert.strictEqual(
        this.$( '>:first-child' ).attr( 'aria-describedby' ),
        describedBy
    );
});

test( 'aria-hidden is true', function( assert ) {
    this.render( template );

    assert.strictEqual(
        this.$( '>:first-child' ).attr( 'aria-hidden' ),
        'true'
    );
});

test( 'aria-labelledby is set', function( assert ) {
    this.render( template );

    assert.strictEqual(
        this.$( '>:first-child' ).attr( 'aria-labelledby' ),
        this.$( '>:first-child' ).find( '.modal-title' ).prop( 'id' ),
        '"aria-labelledby" points to correct element'
    );
});

test( 'Component responds to "hide" stream action', function( assert ) {
    this.set( 'stream', mockStream );
    this.set( 'hide', sinon.spy() );

    this.render( hbs`
        {{#sl-modal stream=stream hide=hide}}
            {{sl-modal-header title="Simple Example"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    mockStream.actions[ 'hide' ]();

    assert.ok(
        this.get( 'hide' ).calledOnce,
        'hide() was triggered successfully'
    );
});

test( 'Component responds to "show" stream action', function( assert ) {
    this.set( 'stream', mockStream );
    this.set( 'show', sinon.spy() );

    this.render( hbs`
        {{#sl-modal stream=stream show=show}}
            {{sl-modal-header title="Simple Example"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    mockStream.actions[ 'show' ]();

    assert.ok(
        this.get( 'show' ).calledOnce,
        'hide() was triggered successfully'
    );
});

test( 'Components do not cross-contaminate', function( assert ) {
    const spyModal = sinon.spy( Ember.$.fn, 'modal' );
    const spyOn = sinon.spy( Ember.$.fn, 'on' );

    this.render( hbs`
        {{#sl-modal}}
            {{sl-modal-header title="Simple Example 1"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    const $first = this.$( '>:first-child' );

    assert.deepEqual(
        spyModal.thisValues.map( ( i ) => i.get( 0 ) ),
        spyModal.thisValues.map( (   ) => $first.get( 0 ) ),
        'First modal attaches to the proper element ($.fn.modal)'
    );

    assert.deepEqual(
        spyOn.thisValues.map( ( i ) => i.get( 0 ) ),
        spyOn.thisValues.map( (   ) => $first.get( 0 ) ),
        'First modal attaches to the proper element ($.fn.on)'
    );

    spyModal.reset();
    spyOn.reset();

    this.render( hbs`
        {{#sl-modal}}
            {{sl-modal-header title="Simple Example 2"}}

            {{#sl-modal-body}}

A simple modal example

            {{/sl-modal-body}}

            {{sl-modal-footer}}
        {{/sl-modal}}
    ` );

    const $second = this.$( '>:first-child' );

    assert.deepEqual(
        spyModal.thisValues.map( ( i ) => i.get( 0 ) ),
        spyModal.thisValues.map( (   ) => $second.get( 0 ) ),
        'Second modal attaches to the proper element ($.fn.modal)'
    );

    assert.deepEqual(
        spyOn.thisValues.map( ( i ) => i.get( 0 ) ),
        spyOn.thisValues.map( (   ) => $second.get( 0 ) ),
        'Second modal attaches to the proper element ($.fn.on)'
    );

    spyModal.reset();
    spyOn.reset();

    $second.modal( 'show' );

    assert.deepEqual(
        spyModal.thisValues.map( ( i ) => i.get( 0 ) ),
        spyModal.thisValues.map( (   ) => $second.get( 0 ) ),
        'Second modal acts on the proper dom element (1/2)'
    );

    spyModal.reset();

    $second.modal( 'hide' );

    assert.deepEqual(
        spyModal.thisValues.map( ( i ) => i.get( 0 ) ),
        spyModal.thisValues.map( (   ) => $second.get( 0 ) ),
        'Second modal acts on the proper dom element (2/2)'
    );

    Ember.$.fn.modal.restore();
    Ember.$.fn.on.restore();
});
<|endoftext|>


<commit_before>var connection = new WebSocket('ws://192.168.50.1:9876');

$(".dispenser").each(parse_button($(this)));

$(".dispenser").click(function() {
  connection.onopen(send_asking_socket("ask_dispenser", "#data_window", "#detail_window", "" + $(this).children(".id_dispenser").text()));
});

$("#network_request").click(function() {
  connection.onopen(send_asking_socket("ask_network", "#data_window", "#network_window"));
});

$("#data_request_from_network").click(function() {
  connection.onopen(send_asking_socket("ask_full_update", "#network_window", "#data_window"));
});

$("#data_request_from_detail").click(function() {
  connection.onopen(send_asking_socket("ask_full_update", "#detail_window", "#data_window"));
});

connection.onmessage = function(event) {
  on_receive(event.data);
};

function on_receive(data){
  var msg = JSON.parse(data);
  switch (msg.type) {
    case "detail_answer":
    setDetailWindow(msg.id, msg.filling, msg.battery, msg.date);
    break;
    case "update":
    setUpdateButton(msg.id, msg.filling, msg.battery);
    break;
    case "dirty_alert":
    for (var count = 0 ; count < msg.dirty_dispenser.length ; count ++){
      window.alert("the dispenser number " + msg.dirty_dispenser[count] + " is dirty");
    }
    break;
    case "network_answer":
    setNetworkWindow(msg.sleep_time, msg.wake_up_time, msg.cycle_time);
    break;
    default:
    window.alert("c'est la merde, on recoit des types chelous");
  }
}

function send_asking_socket (type, current_window, new_window){
  var data_send = new Object();
  data_send.data.type = type;

  if(arguments[3] !== undefined) {
    data_send.data.id = "" + arguments[3];
  }

  var string = JSON.stringify(data_send);
  connection.send(string);
  $(current_window).css('display','none');
  $(new_window).css('display','block');
}

function setDetailWindow(id, filling, battery, date){
  window.alert("Detail Window not in beta version");
}

function setNetworkWindow(sleep, wake_up, cycle){
  window.alert("Network Window not in beta version");
}

function setUpdateButton(id_updated, new_filling, new_battery){
  var id_button = "#button_" + id_updated;
  $(id_button).children(".filling_dispenser").text(new_filling);
  $(id_button).children(".battery_dispenser").text(new_battery);
  parse_button(id_button);
}

function parse_button(current_button){
  var filling = parseInt($(current_button).children('.filling_dispenser').text());
  var battery = parseInt($(current_button).children('.battery_dispenser').text());

  if(filling < 20 || battery < 20){
    $(current_button).css('background-color','orange');
    if (filling < 5) {
      $(current_button).css('background-color','red');
      issue_called("Dispenser "+ $(current_button).children('.id_dispenser').text() + " is nearly empty \n");
    } else if (battery < 1) {
      $(current_button).css('background-color','red');
      issue_called("Dispenser "+ $(current_button).children('.id_dispenser').text() + " battery is nearly empty\n");
    }
  }
}

function issue_called(text_for_alert){
  window.alert(text_for_alert);
}
<commit_msg><commit_after>var connection = new WebSocket('ws://192.168.50.1:9876');

function on_receive(data){
  var msg = JSON.parse(data);
  switch (msg.type) {
    case "detail_answer":
    setDetailWindow(msg.id, msg.filling, msg.battery, msg.date);
    break;
    case "update":
    setUpdateButton(msg.id, msg.filling, msg.battery);
    break;
    case "dirty_alert":
    for (var count = 0 ; count < msg.dirty_dispenser.length ; count ++){
      window.alert("the dispenser number " + msg.dirty_dispenser[count] + " is dirty");
    }
    break;
    case "network_answer":
    setNetworkWindow(msg.sleep_time, msg.wake_up_time, msg.cycle_time);
    break;
    default:
    window.alert("c'est la merde, on recoit des types chelous");
  }
}

function send_asking_socket (type, current_window, new_window){
  var data_send = new Object();
  data_send.data.type = type;

  if(arguments[3] !== undefined) {
    data_send.data.id = "" + arguments[3];
  }

  var string = JSON.stringify(data_send);
  connection.send(string);
  $(current_window).css('display','none');
  $(new_window).css('display','block');
}

function setDetailWindow(id, filling, battery, date){
  window.alert("Detail Window not in beta version");
}

function setNetworkWindow(sleep, wake_up, cycle){
  window.alert("Network Window not in beta version");
}

function setUpdateButton(id_updated, new_filling, new_battery){
  var id_button = "#button_" + id_updated;
  $(id_button).children(".filling_dispenser").text(new_filling);
  $(id_button).children(".battery_dispenser").text(new_battery);
  parse_button(id_button);
}

function parse_button(current_button){
  var filling = parseInt($(current_button).children('.filling_dispenser').text());
  var battery = parseInt($(current_button).children('.battery_dispenser').text());

  if(filling < 20 || battery < 20){
    $(current_button).css('background-color','orange');
    if (filling < 5) {
      $(current_button).css('background-color','red');
      issue_called("Dispenser "+ $(current_button).children('.id_dispenser').text() + " is nearly empty \n");
    } else if (battery < 1) {
      $(current_button).css('background-color','red');
      issue_called("Dispenser "+ $(current_button).children('.id_dispenser').text() + " battery is nearly empty\n");
    }
  }
}

function issue_called(text_for_alert){
  window.alert(text_for_alert);
}

$(".dispenser").each(parse_button($(this)));

$(".dispenser").click(function() {
  connection.onopen(send_asking_socket("ask_dispenser", "#data_window", "#detail_window", "" + $(this).children(".id_dispenser").text()));
});

$("#network_request").click(function() {
  connection.onopen(send_asking_socket("ask_network", "#data_window", "#network_window"));
});

$("#data_request_from_network").click(function() {
  connection.onopen(send_asking_socket("ask_full_update", "#network_window", "#data_window"));
});

$("#data_request_from_detail").click(function() {
  connection.onopen(send_asking_socket("ask_full_update", "#detail_window", "#data_window"));
});

connection.onmessage = function(event) {
  on_receive(event.data);
};
<|endoftext|>


<commit_before>'use strict';

function migrate(key, value) {
    switch (key) {
        case '!':
            return invert(module.exports(value));
        case '&':
            return module.exports(value);
        case '|':
            var f = module.exports(value);
            if (f[0] === 'all') {
                f[0] = 'any';
                return f;
            } else {
                return ['any', module.exports(value)];
            }
        case '^':
            throw new Error('can\'t migrate ^ (XOR) filters');
        default:
            if (typeof value !== 'object') {
                return ['==', key, value];
            } else if (Array.isArray(value)) {
                return ['in', key].concat(value);
            } else if (Object.keys(value).length > 1) {
                throw new Error('can\'t migrate complex filter ' + JSON.stringify(value));
            } else {
                var k = Object.keys(value)[0],
                    v = value[k];
                if (k === 'in' || k === '!in') {
                    return [k, key].concat(v);
                } else {
                    return [k, key, v];
                }
            }
    }
}

function invert(filter6) {
    if (filter6[0] === 'all') {
        return ['any'].concat(filter6.slice(1).map(invert));
    } else {
        filter6[0] = {
            '==': '!=',
            '!=': '==',
            '<': '>=',
            '<=': '>',
            '>': '<=',
            '>=': '<',
            'in': '!in',
            '!in': 'in',
            'any': 'none',
            'none': 'any'
        }[filter6[0]];
        return filter6;
    }
}

module.exports = function(filter5) {
    var filters6 = [];

    for (var key in filter5) {
        filters6.push(migrate(key, filter5[key]));
    }

    if (filters6.length === 1)
        return filters6[0];

    filters6.unshift('all');
    return filters6;
};
<commit_msg>Satisfy jshint<commit_after>'use strict';

function migrate(key, value) {
    switch (key) {
        case '!':
            return invert(module.exports(value));
        case '&':
            return module.exports(value);
        case '|':
            var f = module.exports(value);
            if (f[0] === 'all') {
                f[0] = 'any';
                return f;
            } else {
                return ['any', module.exports(value)];
            }
            break;
        case '^':
            throw new Error('can\'t migrate ^ (XOR) filters');
        default:
            if (typeof value !== 'object') {
                return ['==', key, value];
            } else if (Array.isArray(value)) {
                return ['in', key].concat(value);
            } else if (Object.keys(value).length > 1) {
                throw new Error('can\'t migrate complex filter ' + JSON.stringify(value));
            } else {
                var k = Object.keys(value)[0],
                    v = value[k];
                if (k === 'in' || k === '!in') {
                    return [k, key].concat(v);
                } else {
                    return [k, key, v];
                }
            }
    }
}

function invert(filter6) {
    if (filter6[0] === 'all') {
        return ['any'].concat(filter6.slice(1).map(invert));
    } else {
        filter6[0] = {
            '==': '!=',
            '!=': '==',
            '<': '>=',
            '<=': '>',
            '>': '<=',
            '>=': '<',
            'in': '!in',
            '!in': 'in',
            'any': 'none',
            'none': 'any'
        }[filter6[0]];
        return filter6;
    }
}

module.exports = function(filter5) {
    var filters6 = [];

    for (var key in filter5) {
        filters6.push(migrate(key, filter5[key]));
    }

    if (filters6.length === 1)
        return filters6[0];

    filters6.unshift('all');
    return filters6;
};
<|endoftext|>


<commit_before>'use strict';
var express = require('express');
var bodyParser = require('body-parser');

var nrdb = require('./nrdb-local');
var formatting = require('./formatting');
// A list of common card shorthands and their corresponding full names
var shorthands = require('./shorthands.json');
// Regex generated from the shorthand keys to be used in find/replace
// Only matches whole words
var shorthandRegExp = new RegExp(
    Object.keys(shorthands).reduce((pv, cv, ci, a) => {
        var o = pv;
        if (ci !== 0) {
            o += '\\b|\\b';
        }
        o += cv;
        if (ci === a.length - 1) {
            o += '\\b';
        }
        return o;
    }, '\\b')
);

var messages = {
    noHits: {text: "The run is successful but you access 0 cards of that name."},
    invalidDeck: {text: "Search for a decklist by it's netrunnerdb link or ID number."}
};
var port = process.env.PORT || 3000;
var token = process.env.TOKEN || '';

var app = express();
app.use(bodyParser.urlencoded({extended: false}));

var initpromise = nrdb.init();

function findSearchStrings(text) {
    var cardFinder = new RegExp('.*?\\[(.*?)\\]', 'g'),
        searches = [],
        i = cardFinder.exec(text);
    while (i) {
        searches.push(i[1]);
        i = cardFinder.exec(text);
    }
    return searches;
}

function findCards(searches) {
    var promises = [], i;
    searches.forEach((search, i) => {
        promises[i] = nrdb.getCardByTitle(search);
    });
    return new Promise((resolve, reject) => {
        Promise.all(promises).then((cards) => {
            resolve(cards.filter((e) => {
                return e;
            }));
        }, reject);
    });
}

app.post('/decklist', (req, res) => {
    // if (!req.body.token || req.body.token !== token) {
    //     return res.sendStatus(401);
    // }
    if (req.body.trigger_word) {
        req.body.text = req.body.text.replace(new RegExp('^' + req.body.trigger_word + '\\s*', 'i'), '');
    }
    var match = req.body.text.match(/(\d+)/);
    if (match) {
        var id = match[1];
        nrdb.getDecklist(id).then((decklist) => {
            res.json(formatting.formatDecklist(decklist));
        }, () => {
            res.json(messages.noHits);
        });
    } else {
        res.json(messages.invalidDeck);
    }
});

app.post('/', (req, res) => {
    // if (!req.body.token || req.body.token !== token) {
    //     return res.sendStatus(401);
    // }
    var response = {};
    var searches = [];
    if (!req.body || Object.keys(req.body).length === 0) {
        return res.sendStatus(400);
    }

    if (req.body.user_name === 'slackbot') {
        return res.sendStatus(200);
    }

    if (req.body.command) {
        searches[0] = req.body.text;
        response = messages.noHits;
    } else if (req.body.trigger_word) {
        response = messages.noHits;
        searches[0] = req.body.text.replace(new RegExp('^' + req.body.trigger_word + '\\s*', 'i'), '');
    } else {
        searches = findSearchStrings(req.body.text);
    }
    if (searches && searches.length > 0) {
        var match = searches[0].match(/(?:netrunnerdb.com\/\w\w\/decklist\/)(\d+)/);
        if (match) {
            var id = match[1];
            nrdb.getDecklist(id).then((decklist) => {
                res.json(formatting.formatDecklist(decklist));
            }, () => {
                res.send(messages.noHits);
            });
        } else {
            searches.forEach((search, i) => {
                searches[i] = search.toLowerCase().replace(shorthandRegExp, (sh) => {
                    return shorthands[sh];
                });
            });
            initpromise.then(() => {
                findCards(searches).then((results) => {
                    var o = formatting.formatCards(results);
                    if (o.text !== '') {
                        res.json(o);
                    } else {
                        res.json(response);
                    }
                }, (err) => {
                    console.log(err);
                    res.sendStatus(500);
                });
            }, (err) => {
                console.log(err);
                res.sendStatus(500);
            });
        }
    } else {
        res.send('');
    }
});

app.listen(port);
console.info('Express listening on port ' + port);

module.exports = {app: app, findSearchStrings: findSearchStrings, findCards: findCards};

<commit_msg>Made additional error message for decklists<commit_after>'use strict';
var express = require('express');
var bodyParser = require('body-parser');

var nrdb = require('./nrdb-local');
var formatting = require('./formatting');
// A list of common card shorthands and their corresponding full names
var shorthands = require('./shorthands.json');
// Regex generated from the shorthand keys to be used in find/replace
// Only matches whole words
var shorthandRegExp = new RegExp(
    Object.keys(shorthands).reduce((pv, cv, ci, a) => {
        var o = pv;
        if (ci !== 0) {
            o += '\\b|\\b';
        }
        o += cv;
        if (ci === a.length - 1) {
            o += '\\b';
        }
        return o;
    }, '\\b')
);

var messages = {
    noCardHits: {
        response_type: "ephemeral",
        text: "The run is successful but you access 0 cards of that name."
    },
    noDeckHits: {
        response_type: "ephemeral",
        text: "The archetype of that deck is _\u200bnon-existant\u200b_."
    },
    invalidDeck: {
        response_type: "ephemeral",
        text: "Search for a decklist by it's netrunnerdb link or ID number.\ne.g. _\u200b[netrunnerdb\u200b.com/en/decklist/]1234[/psycoscorch]\u200b_"
    }
};
var port = process.env.PORT || 3000;
var token = process.env.TOKEN || '';

var app = express();
app.use(bodyParser.urlencoded({extended: false}));

var initpromise = nrdb.init();

function findSearchStrings(text) {
    var cardFinder = new RegExp('.*?\\[(.*?)\\]', 'g'),
        searches = [],
        i = cardFinder.exec(text);
    while (i) {
        searches.push(i[1]);
        i = cardFinder.exec(text);
    }
    return searches;
}

function findCards(searches) {
    var promises = [], i;
    searches.forEach((search, i) => {
        promises[i] = nrdb.getCardByTitle(search);
    });
    return new Promise((resolve, reject) => {
        Promise.all(promises).then((cards) => {
            resolve(cards.filter((e) => {
                return e;
            }));
        }, reject);
    });
}

app.post('/decklist', (req, res) => {
    // if (!req.body.token || req.body.token !== token) {
    //     return res.sendStatus(401);
    // }
    if (req.body.trigger_word) {
        req.body.text = req.body.text.replace(new RegExp('^' + req.body.trigger_word + '\\s*', 'i'), '');
    }
    var match = req.body.text.match(/(\d+)/);
    if (match) {
        var id = match[1];
        nrdb.getDecklist(id).then((decklist) => {
            res.json(formatting.formatDecklist(decklist));
        }, () => {
            res.json(messages.noDeckHits);
        });
    } else {
        res.json(messages.invalidDeck);
    }
});

app.post('/', (req, res) => {
    // if (!req.body.token || req.body.token !== token) {
    //     return res.sendStatus(401);
    // }
    var response = {};
    var searches = [];
    if (!req.body || Object.keys(req.body).length === 0) {
        return res.sendStatus(400);
    }

    if (req.body.user_name === 'slackbot') {
        return res.sendStatus(200);
    }

    if (req.body.command) {
        searches[0] = req.body.text;
        response = messages.noCardHits;
    } else if (req.body.trigger_word) {
        response = messages.noCardHits;
        searches[0] = req.body.text.replace(new RegExp('^' + req.body.trigger_word + '\\s*', 'i'), '');
    } else {
        searches = findSearchStrings(req.body.text);
    }
    if (searches && searches.length > 0) {
        var match = searches[0].match(/(?:netrunnerdb.com\/\w\w\/decklist\/)(\d+)/);
        if (match) {
            var id = match[1];
            nrdb.getDecklist(id).then((decklist) => {
                res.json(formatting.formatDecklist(decklist));
            }, () => {
                res.send(messages.noDeckHits);
            });
        } else {
            searches.forEach((search, i) => {
                searches[i] = search.toLowerCase().replace(shorthandRegExp, (sh) => {
                    return shorthands[sh];
                });
            });
            initpromise.then(() => {
                findCards(searches).then((results) => {
                    var o = formatting.formatCards(results);
                    if (o.text !== '') {
                        res.json(o);
                    } else {
                        res.json(response);
                    }
                }, (err) => {
                    console.log(err);
                    res.sendStatus(500);
                });
            }, (err) => {
                console.log(err);
                res.sendStatus(500);
            });
        }
    } else {
        res.send('');
    }
});

app.listen(port);
console.info('Express listening on port ' + port);

module.exports = {app: app, findSearchStrings: findSearchStrings, findCards: findCards};

<|endoftext|>


<commit_before>var path = require('path');

function _includePaths (basePath) {
  if (basePath) {
    return [
      basePath + '/app',
      basePath + '/candela.js',
      basePath + '/components',
      basePath + '/shim',
      basePath + '/test',
      basePath + '/util',
      basePath + '/VisComponent'
    ];
  } else {
    return [
      /\/node_modules\/candela\//
    ]
  }
}

function addNMPath(packages, paths) {
  if (!Array.isArray(packages)) {
    packages = [packages];
  }

  return packages.map(function (package) {
    return new RegExp('/node_modules/' + package + '/')
  }).concat(paths);
}

module.exports = function (config, basePath) {
  var includePaths = _includePaths(basePath);

  // Install empty module and module.loaders entries if missing.
  config.module = config.module || {};
  config.module.loaders = config.module.loaders || [];

  // Prepend the Candela loaders.
  config.module.loaders = [
    {
      test: /\.js$/,
      loader: 'babel-loader',
      query: {
        presets: ['es2015']
      },
      include: includePaths
    },
    {
      test: /\.jpe?g$|\.gif$|\.png$|\.woff$|\.wav$|\.mp3$|\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$|\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
      loader: 'url-loader',
      include: addNMPath(['font-awesome', 'bootstrap'], includePaths)
    },
    {
      test: /\.csv$/,
      loader: 'raw-loader',
      include: includePaths
    },
    {
      test: /\.html$/,
      loader: 'html-loader?attrs=img:src',
      include: includePaths
    },
    {
      test: /\.styl$/,
      loaders: ['style-loader', 'css-loader', 'stylus-loader'],
      include: includePaths
    },
    {
      test: /\.css$/,
      loaders: ['style-loader', 'css-loader'],
      include: addNMPath('lineupjs', includePaths)
    },
    {
      test: /\.scss$/,
      loaders: ['style-loader', 'css-loader', 'sass-loader'],
      include: addNMPath('UpSet', includePaths)
    },
    {
      test: /\.jade$/,
      loaders: ['jade-loader'],
      include: includePaths
    },
    {
      test: /\.json$/,
      loaders: ['json-loader', 'strip-json-comments-loader'],
      include: addNMPath('datalib', includePaths)
    }
  ].concat(config.module.loaders);

  config.resolve = config.resolve || {};
  config.resolve.alias = config.resolve.alias || {};
  config.resolve.alias['font-awesome-webpack$'] = path.resolve(basePath || '.', 'shim', 'font-awesome-webpack.shim.js');

  return config;
};
<commit_msg>build(webpack): exclude existing loaders from affecting node_modules/candela<commit_after>var path = require('path');

function _includePaths (basePath) {
  if (basePath) {
    return [
      basePath + '/app',
      basePath + '/candela.js',
      basePath + '/components',
      basePath + '/shim',
      basePath + '/test',
      basePath + '/util',
      basePath + '/VisComponent'
    ];
  } else {
    return [
      /\/node_modules\/candela\//
    ]
  }
}

function addNMPath(packages, paths) {
  if (!Array.isArray(packages)) {
    packages = [packages];
  }

  return packages.map(function (package) {
    return new RegExp('/node_modules/' + package + '/')
  }).concat(paths);
}

module.exports = function (config, basePath, options) {
  var includePaths = _includePaths(basePath);

  options = options || {};

  // By default, exclude the existing loaders from affecting
  // node_modules/candela. This prevents double application of loaders if they
  // are specified in the client project without any include or exclude
  // directives.
  var exclude = options.excludeCandelaNM === undefined || options.excludeCandelaNM;

  // Install empty module and module.loaders entries if missing.
  config.module = config.module || {};
  config.module.loaders = config.module.loaders || [];

  // Exclude the base paths from having existing loaders applied to them.
  if (exclude) {
    config.modules.loaders = config.modules.loaders || [];
    config.modules.loaders.forEach(function (loader) {
      loader.exclude = (loader.exclude || []).concat(includePaths);
    });
  }

  // Prepend the Candela loaders.
  config.module.loaders = [
    {
      test: /\.js$/,
      loader: 'babel-loader',
      query: {
        presets: ['es2015']
      },
      include: includePaths
    },
    {
      test: /\.jpe?g$|\.gif$|\.png$|\.woff$|\.wav$|\.mp3$|\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$|\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
      loader: 'url-loader',
      include: addNMPath(['font-awesome', 'bootstrap'], includePaths)
    },
    {
      test: /\.csv$/,
      loader: 'raw-loader',
      include: includePaths
    },
    {
      test: /\.html$/,
      loader: 'html-loader?attrs=img:src',
      include: includePaths
    },
    {
      test: /\.styl$/,
      loaders: ['style-loader', 'css-loader', 'stylus-loader'],
      include: includePaths
    },
    {
      test: /\.css$/,
      loaders: ['style-loader', 'css-loader'],
      include: addNMPath('lineupjs', includePaths)
    },
    {
      test: /\.scss$/,
      loaders: ['style-loader', 'css-loader', 'sass-loader'],
      include: addNMPath('UpSet', includePaths)
    },
    {
      test: /\.jade$/,
      loaders: ['jade-loader'],
      include: includePaths
    },
    {
      test: /\.json$/,
      loaders: ['json-loader', 'strip-json-comments-loader'],
      include: addNMPath('datalib', includePaths)
    }
  ].concat(config.module.loaders);

  config.resolve = config.resolve || {};
  config.resolve.alias = config.resolve.alias || {};
  config.resolve.alias['font-awesome-webpack$'] = path.resolve(basePath || '.', 'shim', 'font-awesome-webpack.shim.js');

  return config;
};
<|endoftext|>


<commit_before>// React batches all mutations that happen in a single
// event tick into a single reconcile. We can do the same
// thing for requestAnimationFrame(). This means you can
// have a ton of different tweens for very little cost, as
// they will coalesce into a single reconcile.
var _requestAnimationFrame = window.requestAnimationFrame;

window.requestAnimationFrame = function(func) {
  return _requestAnimationFrame(function() {
    // This is the magic that does it. Note: this was
    // exported in my custom build of React; it is not
    // available in the prebuilt versions yet.
    React.Updates.batchedUpdates(func);
  });
};<commit_msg>more hacks on ReactUpdates<commit_after>// React batches all mutations that happen in a single
// event tick into a single reconcile. We can do the same
// thing for requestAnimationFrame(). This means you can
// have a ton of different tweens for very little cost, as
// they will coalesce into a single reconcile.
var _requestAnimationFrame = window.requestAnimationFrame;

// Completely take over the ReactUpdates system.

var batchedUpdates = React.Updates.batchedUpdates;

React.Updates.batchedUpdates = function(func) {
  func();
};

window.requestAnimationFrame = function(func) {
  return _requestAnimationFrame(function() {
    // This is the magic that does it. Note: this was
    // exported in my custom build of React; it is not
    // available in the prebuilt versions yet.
    batchedUpdates(func);
  });
};<|endoftext|>


<commit_before>var jspm = require('jspm')

if (process.env.NODE_ENV === 'production')
{
  console.log('Executing deploy script')
  jspm.install(true, {})
    .then(function(){
      return jspm.dlLoader()
    })
    .then(function() {
      return jspm.bundleSFX('app/main', 'build.js', {sourceMaps: false, inject: false, minify: true})
    })
    .then(function(){
      console.log('Deploy finished')
      process.exit(0)
  })
}
<commit_msg>Added informative messages<commit_after>var jspm = require('jspm')

if (process.env.NODE_ENV === 'production')
{
  console.log('Executing deploy script')
  jspm.install(true, {})
    .then(function(){
      console.log("Dl downloading")
      return jspm.dlLoader()
    })
    .then(function() {
      console.log("Bundle creation")
      return jspm.bundleSFX('app/main', 'build.js', {sourceMaps: false, inject: false, minify: true})
    })
    .then(function(){
      console.log('Deploy finished')
      process.exit(0)
  })
}
<|endoftext|>


<commit_before>/* global describe, expect, it */
'use strict';

(function (self)
{
    function createOutput(compatibilities)
    {
        function appendLengths(name, char)
        {
            result += '\n' + padRight(name, 4);
            compatibilities.forEach(
                function (compatibility)
                {
                    var content;
                    try
                    {
                        content = JScrewIt.encode(char, false, compatibility).length;
                    }
                    catch (e)
                    {
                        content = 'ERROR';
                    }
                    result += padLeft(content, 8);
                }
            );
        }

        function appendLengthsRange(min, max, namer)
        {
            namer = namer || function () { return '`' + String.fromCharCode(charCode) + '`'; };
            for (var charCode = min; charCode <= max; ++charCode)
            {
                var name = namer(charCode);
                var char = String.fromCharCode(charCode);
                appendLengths(name, char);
            }
        }

        var result = '     ';
        compatibilities.forEach(
            function (compatibility)
            {
                result += padBoth(compatibility, 8);
            }
        );
        result = result.replace(/ +$/, '');
        result += '\n    ' + new Array(compatibilities.length + 1).join(' -------');
        var C0_CONTROL_CODE_NAMES =
        [
            'NUL',  'SOH',  'STX',  'ETX',  'EOT',  'ENQ',  'ACK',  'BEL',
            'BS',   'HT',   'LF',   'VT',   'FF',   'CR',   'SO',   'SI',
            'DLE',  'DC1',  'DC2',  'DC3',  'DC4',  'NAK',  'SYN',  'ETB',
            'CAN',  'EM',   'SUB',  'ESC',  'FS',   'GS',   'RS',   'US'
        ];
        appendLengthsRange(0, 31, function (charCode) { return C0_CONTROL_CODE_NAMES[charCode]; });
        appendLengthsRange(32, 126);
        appendLengths('DEL', '\x7f');
        var C1_CONTROL_CODE_NAMES =
        [
            'PAD',  'HOP',  'BPH',  'NBH',  'IND',  'NEL',  'SSA',  'ESA',
            'HTS',  'HTJ',  'VTS',  'PLD',  'PLU',  'RI',   'SS2',  'SS3',
            'DCS',  'PU1',  'PU2',  'STS',  'CCH',  'MW',   'SPA',  'EPA',
            'SOS',  'SGCI', 'SCI',  'CSI',  'ST',   'OSC',  'PM',   'APC'
        ];
        appendLengthsRange(
            128,
            159,
            function (charCode) { return C1_CONTROL_CODE_NAMES[charCode - 0x80]; }
        );
        appendLengths('NBSP', '\xa0');
        appendLengthsRange(161, 172);
        appendLengths('SHY', '\xad');
        appendLengthsRange(174, 255);
        appendLengths('`♥`', '♥');
        return result;
    }

    function describeTest(compatibility)
    {
        describe(
            'encodes with ' + compatibility + ' compatibility',
            function ()
            {
                var code;
                for (code = 0; code < 256; ++code)
                {
                    test(code, compatibility);
                }
                for (; code < 0x00010000; code <<= 1)
                {
                    test(code + 33, compatibility);
                }
            }
        );
    }

    function getAvailableFeatures()
    {
        var result = JScrewIt.FEATURE_INFOS.AUTO.includes;
        return result;
    }

    function init(env)
    {
        JScrewIt = (env || self).JScrewIt;
    }

    function padBoth(str, length)
    {
        str += '';
        var result = padRight(padLeft(str, length + str.length >> 1), length);
        return result;
    }

    function padLeft(str, length)
    {
        str += '';
        var result = new Array(length - str.length + 1).join(' ') + str;
        return result;
    }

    function padRight(str, length)
    {
        str += '';
        var result = str + new Array(length - str.length + 1).join(' ');
        return result;
    }

    function run()
    {
        describe(
            'JScrewIt.encode',
            function()
            {
                describeTest('DEFAULT');
                if (JScrewIt.areFeaturesAvailable('COMPACT'))
                {
                    describeTest('COMPACT');
                }
                if (JScrewIt.areFeaturesAvailable('NO_IE'))
                {
                    describeTest('NO_IE');
                }
                describeTest('AUTO');
                it(
                    'throws a ReferenceError for incompatible features',
                    function ()
                    {
                        var fn =
                            function () { JScrewIt.encode('', false, ['NO_IE_SRC', 'IE_SRC']); };
                        expect(fn).toThrow(new ReferenceError('Incompatible features'));
                    }
                );
            }
        );
        describe(
            'JScrewIt.areFeaturesCompatible',
            function()
            {
                it(
                    'returns true for compatible features',
                    function ()
                    {
                        var compatible = JScrewIt.areFeaturesCompatible(['FILL', 'SELF']);
                        expect(compatible).toBe(true);
                    }
                );
                it(
                    'returns false for incompatible features',
                    function ()
                    {
                        var compatible = JScrewIt.areFeaturesCompatible(['CHROME_SRC', 'IE_SRC']);
                        expect(compatible).toBe(false);
                    }
                );
            }
        );
        describe(
            'JScrewIt.FEATURE_INFOS',
            function()
            {
                describe(
                    'contains correct information',
                    function ()
                    {
                        it(
                            'for the DEFAULT feature',
                            function ()
                            {
                                var info = JScrewIt.FEATURE_INFOS.DEFAULT;
                                expect(info.available).toBe(true);
                                expect(info.includes.length).toBe(0);
                                expect(info.excludes.length).toBe(0);
                            }
                        );
                        it(
                            'for the AUTO feature',
                            function ()
                            {
                                var info = JScrewIt.FEATURE_INFOS.AUTO;
                                expect(info.available).toBe(true);
                                expect(info.includes.length).toBeGreaterThan(0);
                                expect(info.excludes.length).toBe(0);
                            }
                        );
                        it(
                            'for the CHROME_SRC feature',
                            function ()
                            {
                                var info = JScrewIt.FEATURE_INFOS.CHROME_SRC;
                                expect(info.includes).toContain('NO_IE_SRC');
                                expect(info.excludes).toContain('FF_SAFARI_SRC');
                            }
                        );
                    }
                );
                describe(
                    'contains only well-formed obejcts:',
                    function ()
                    {
                        var features = Object.getOwnPropertyNames(JScrewIt.FEATURE_INFOS);
                        features.forEach(
                            function (feature)
                            {
                                it(
                                    feature,
                                    function ()
                                    {
                                        var info = JScrewIt.FEATURE_INFOS[feature];
                                        expect(typeof info).toBe('object');
                                        expect(info.name).toBe(feature);
                                        var available = info.available;
                                        expect(typeof available).toBe('boolean');
                                        expect(available).toBe(
                                            JScrewIt.areFeaturesAvailable(feature)
                                        );
                                        expect(Array.isArray(info.includes)).toBeTruthy();
                                        var excludes = info.excludes;
                                        expect(Array.isArray(excludes)).toBeTruthy();
                                        expect(typeof info.description).toBe('string');
                                        excludes.forEach(
                                            function (exclude)
                                            {
                                                var info = JScrewIt.FEATURE_INFOS[exclude];
                                                expect(info.excludes).toContain(feature);
                                            }
                                        );
                                    }
                                );
                            }
                        );
                    }
                );
            }
        );
    }

    function test(charCode, compatibility)
    {
        var char = String.fromCharCode(charCode);
        var desc =
            charCode >= 0x7f && charCode <= 0xa0 || charCode === 0xad ?
            '"\\u00' + charCode.toString(16) + '"' : JSON.stringify(char);
        it(
            desc,
            function ()
            {
                var encoding = JScrewIt.encode(char, false, compatibility);
                expect(eval(encoding)).toBe(char);
                expect(encoding).toMatch(/^[!+()[\]]*$/);
                if (compatibility !== 'DEFAULT')
                {
                    expect(encoding.length).not.toBeGreaterThan(JScrewIt.encode(char).length);
                }
            }
        );
    }

    var JScrewIt;

    self.TestSuite =
    {
        createOutput: createOutput,
        getAvailableFeatures: getAvailableFeatures,
        init: init,
        run: run
    };

})(typeof exports === 'undefined' ? self : exports);
<commit_msg>Added test case for unknown feature<commit_after>/* global describe, expect, it */
'use strict';

(function (self)
{
    function createOutput(compatibilities)
    {
        function appendLengths(name, char)
        {
            result += '\n' + padRight(name, 4);
            compatibilities.forEach(
                function (compatibility)
                {
                    var content;
                    try
                    {
                        content = JScrewIt.encode(char, false, compatibility).length;
                    }
                    catch (e)
                    {
                        content = 'ERROR';
                    }
                    result += padLeft(content, 8);
                }
            );
        }

        function appendLengthsRange(min, max, namer)
        {
            namer = namer || function () { return '`' + String.fromCharCode(charCode) + '`'; };
            for (var charCode = min; charCode <= max; ++charCode)
            {
                var name = namer(charCode);
                var char = String.fromCharCode(charCode);
                appendLengths(name, char);
            }
        }

        var result = '     ';
        compatibilities.forEach(
            function (compatibility)
            {
                result += padBoth(compatibility, 8);
            }
        );
        result = result.replace(/ +$/, '');
        result += '\n    ' + Array(compatibilities.length + 1).join(' -------');
        var C0_CONTROL_CODE_NAMES =
        [
            'NUL',  'SOH',  'STX',  'ETX',  'EOT',  'ENQ',  'ACK',  'BEL',
            'BS',   'HT',   'LF',   'VT',   'FF',   'CR',   'SO',   'SI',
            'DLE',  'DC1',  'DC2',  'DC3',  'DC4',  'NAK',  'SYN',  'ETB',
            'CAN',  'EM',   'SUB',  'ESC',  'FS',   'GS',   'RS',   'US'
        ];
        appendLengthsRange(0, 31, function (charCode) { return C0_CONTROL_CODE_NAMES[charCode]; });
        appendLengthsRange(32, 126);
        appendLengths('DEL', '\x7f');
        var C1_CONTROL_CODE_NAMES =
        [
            'PAD',  'HOP',  'BPH',  'NBH',  'IND',  'NEL',  'SSA',  'ESA',
            'HTS',  'HTJ',  'VTS',  'PLD',  'PLU',  'RI',   'SS2',  'SS3',
            'DCS',  'PU1',  'PU2',  'STS',  'CCH',  'MW',   'SPA',  'EPA',
            'SOS',  'SGCI', 'SCI',  'CSI',  'ST',   'OSC',  'PM',   'APC'
        ];
        appendLengthsRange(
            128,
            159,
            function (charCode) { return C1_CONTROL_CODE_NAMES[charCode - 0x80]; }
        );
        appendLengths('NBSP', '\xa0');
        appendLengthsRange(161, 172);
        appendLengths('SHY', '\xad');
        appendLengthsRange(174, 255);
        appendLengths('`♥`', '♥');
        return result;
    }

    function describeTest(compatibility)
    {
        describe(
            'encodes with ' + compatibility + ' compatibility',
            function ()
            {
                var code;
                for (code = 0; code < 256; ++code)
                {
                    test(code, compatibility);
                }
                for (; code < 0x00010000; code <<= 1)
                {
                    test(code + 33, compatibility);
                }
            }
        );
    }

    function getAvailableFeatures()
    {
        var result = JScrewIt.FEATURE_INFOS.AUTO.includes;
        return result;
    }

    function init(env)
    {
        JScrewIt = (env || self).JScrewIt;
    }

    function padBoth(str, length)
    {
        str += '';
        var result = padRight(padLeft(str, length + str.length >> 1), length);
        return result;
    }

    function padLeft(str, length)
    {
        str += '';
        var result = Array(length - str.length + 1).join(' ') + str;
        return result;
    }

    function padRight(str, length)
    {
        str += '';
        var result = str + Array(length - str.length + 1).join(' ');
        return result;
    }

    function run()
    {
        describe(
            'JScrewIt.encode',
            function()
            {
                describeTest('DEFAULT');
                if (JScrewIt.areFeaturesAvailable('COMPACT'))
                {
                    describeTest('COMPACT');
                }
                if (JScrewIt.areFeaturesAvailable('NO_IE'))
                {
                    describeTest('NO_IE');
                }
                describeTest('AUTO');
                it(
                    'throws a ReferenceError for incompatible features',
                    function ()
                    {
                        var fn =
                            function () { JScrewIt.encode('', false, ['NO_IE_SRC', 'IE_SRC']); };
                        expect(fn).toThrow(ReferenceError('Incompatible features'));
                    }
                );
            }
        );
        describe(
            'JScrewIt.areFeaturesCompatible',
            function()
            {
                it(
                    'returns true for compatible features',
                    function ()
                    {
                        var compatible = JScrewIt.areFeaturesCompatible(['FILL', 'SELF']);
                        expect(compatible).toBe(true);
                    }
                );
                it(
                    'returns false for incompatible features',
                    function ()
                    {
                        var compatible = JScrewIt.areFeaturesCompatible(['CHROME_SRC', 'IE_SRC']);
                        expect(compatible).toBe(false);
                    }
                );
                it(
                    'throws a ReferenceError for unknown features',
                    function ()
                    {
                        var fn = function () { JScrewIt.areFeaturesCompatible(['???']); };
                        expect(fn).toThrow(ReferenceError('Unknown feature "???"'));
                    }
                );
            }
        );
        describe(
            'JScrewIt.FEATURE_INFOS',
            function()
            {
                describe(
                    'contains correct information',
                    function ()
                    {
                        it(
                            'for the DEFAULT feature',
                            function ()
                            {
                                var info = JScrewIt.FEATURE_INFOS.DEFAULT;
                                expect(info.available).toBe(true);
                                expect(info.includes.length).toBe(0);
                                expect(info.excludes.length).toBe(0);
                            }
                        );
                        it(
                            'for the AUTO feature',
                            function ()
                            {
                                var info = JScrewIt.FEATURE_INFOS.AUTO;
                                expect(info.available).toBe(true);
                                expect(info.includes.length).toBeGreaterThan(0);
                                expect(info.excludes.length).toBe(0);
                            }
                        );
                        it(
                            'for the CHROME_SRC feature',
                            function ()
                            {
                                var info = JScrewIt.FEATURE_INFOS.CHROME_SRC;
                                expect(info.includes).toContain('NO_IE_SRC');
                                expect(info.excludes).toContain('FF_SAFARI_SRC');
                            }
                        );
                    }
                );
                describe(
                    'contains only well-formed obejcts:',
                    function ()
                    {
                        var features = Object.getOwnPropertyNames(JScrewIt.FEATURE_INFOS);
                        features.forEach(
                            function (feature)
                            {
                                it(
                                    feature,
                                    function ()
                                    {
                                        var info = JScrewIt.FEATURE_INFOS[feature];
                                        expect(typeof info).toBe('object');
                                        expect(info.name).toBe(feature);
                                        var available = info.available;
                                        expect(typeof available).toBe('boolean');
                                        expect(available).toBe(
                                            JScrewIt.areFeaturesAvailable(feature)
                                        );
                                        expect(Array.isArray(info.includes)).toBeTruthy();
                                        var excludes = info.excludes;
                                        expect(Array.isArray(excludes)).toBeTruthy();
                                        expect(typeof info.description).toBe('string');
                                        excludes.forEach(
                                            function (exclude)
                                            {
                                                var info = JScrewIt.FEATURE_INFOS[exclude];
                                                expect(info.excludes).toContain(feature);
                                            }
                                        );
                                    }
                                );
                            }
                        );
                    }
                );
            }
        );
    }

    function test(charCode, compatibility)
    {
        var char = String.fromCharCode(charCode);
        var desc =
            charCode >= 0x7f && charCode <= 0xa0 || charCode === 0xad ?
            '"\\u00' + charCode.toString(16) + '"' : JSON.stringify(char);
        it(
            desc,
            function ()
            {
                var encoding = JScrewIt.encode(char, false, compatibility);
                expect(eval(encoding)).toBe(char);
                expect(encoding).toMatch(/^[!+()[\]]*$/);
                if (compatibility !== 'DEFAULT')
                {
                    expect(encoding.length).not.toBeGreaterThan(JScrewIt.encode(char).length);
                }
            }
        );
    }

    var JScrewIt;

    self.TestSuite =
    {
        createOutput: createOutput,
        getAvailableFeatures: getAvailableFeatures,
        init: init,
        run: run
    };

})(typeof exports === 'undefined' ? self : exports);
<|endoftext|>


<commit_before>/**
 * @overview ccm component for real time  Forum
 * @author Tea Kless <tea.kless@web.de>, 2017
 * @license The MIT License (MIT)
 */

( function () {

  var ccm_version = '9.0.0';
  var ccm_url     = 'https://akless.github.io/ccm/version/ccm-9.0.0.min.js';

  var component_name = 'question';
  var component_obj  = {
    name: component_name,

    config: {
      templates: {
        "main": {
          "class": "container",
          "inner": [
            {
              "id": "answers_view",
              "inner": [
                {
                  "class": "question",
                  "inner": [
                    {
                      "class": "row",
                      "inner": {
                        "class": "question-title col-md-10",
                        "inner": {
                          "tag": "h3",
                          "inner": [
                             "%title% ",
                            {
                              "tag": "small",
                              "inner": "%signatur%"
                            }
                          ]
                        }
                      }
                    },
                    {
                      "class": "row",
                      "inner": [
                        {
                          "class": "voting col-md-1"
                        },
                        {
                          "class": "question col-md-11",
                          "inner": {
                            "tag": "blockquote",
                            "inner": {
                              "tag": "p",
                              "inner": [
                                "%question%",
                                {
                                  "tag": "footer",
                                  "inner": "footer"
                                }
                              ]
                            }
                          }
                        }
                      ]
                    }
                  ]
                },
                {
                  "tag": "hr"
                },
                {
                  "id": "answers"
                },

                {
                  "id": "new-answer",
                  "inner": [
                    {
                      "tag": "h4",
                      "inner": "Your Answer"
                    },
                    {
                      "id": "editor"
                    },
                    {
                      "id": "new",
                      "class": "row",
                      "inner": {
                        "tag": "button",
                        "class": "btn btn-primary",
                        "type": "submit",
                        "inner": "Post Answer",
                        "onclick": "%new_answer%"
                      }
                    }
                  ]

                }
              ]
            }
          ]
        },

        "answer": {
          "inner": [
            {
              "class": "answer row",
              "inner": [
                {
                  "class": "voting-area col-md-1 col-sx-12",
                  "inner": [
                    {
                      "class": "voting-overview col-sx-6 col-md-12"
                    },
                    {
                      "class": "answer-accepted col-sx-6 col-md-12",
                      "inner": {
                        "tag": "span",
                        "class": "glyphicon glyphicon-ok",
                        "oncklick": "%accepted%"
                      }
                    }
                  ]
                },
                {
                  "class": "answer-overview col-md-11 col-sx-12",
                  "inner": [
                    "%answer%",
                    {
                      "tag": "blockquote",
                      "class": "blockquote-reverse",
                      "inner": {
                        "tag": "footer",
                        "inner": "%signatur%"
                      }
                    }
                  ]
                }
              ]
            },
            {
              "tag": "hr"
            }
          ]

        },

        "voting_overview": {
          "class": "voting_overview row",
          "inner": [
            {
              "class": "col-md-12",
              "inner": "%get_voting%"
            },
            {
              "class": "col-md-12",
              "inner": "votes"
            }
          ]
        }
      },

      data: {
        store: [ 'ccm.store', '../question/datastore.json' ],
        key: "1"
      },
      user:  [ 'ccm.instance', 'https://akless.github.io/ccm-components/user/ccm.user.min.js', { logged_in: true, 'guest.user': 'tmeskh2s' } ],
      style: [ 'ccm.load', '../question/style.css' ],
      editor: [ 'ccm.component', 'https://tkless.github.io/ccm-components/editor/ccm.editor.js',
        { 'settings.modules.toolbar': [
            [{ 'size': ['small', false, 'large', 'huge'] }],  // custom dropdown
            ['bold', 'italic', 'underline'],        // toggled buttons
            ['blockquote', 'code-block'],

            [{ 'header': 1 }, { 'header': 2 }],               // custom button values
            [{ 'list': 'ordered'}, { 'list': 'bullet' }],
            [{ 'script': 'sub'}, { 'script': 'super' }],      // superscript/subscript
            [{ 'indent': '-1'}, { 'indent': '+1' }],          // outdent/indent

            [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
            [{ 'align': [] }]
        ] }
      ],
      voting: [ "ccm.component", "https://tkless.github.io/ccm-components/voting/ccm.voting.js", {
        data: {
          store: [ 'ccm.store', 'https://tkless.github.io/ccm-components/voting/voting_datastore.js' ]
        }
      } ],
      bootstrap: [ 'ccm.load', 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css' ]
    },

    Instance: function () {
      var self = this;
      var editor;
      var dataset;

      this.init = function ( callback ) {

        // listen to change event of ccm realtime datastore => (re)render own content
        self.data.store.onChange = function ( question ) {
          dataset = question;
          self.start();
        };

        callback();
      };

      this.start = function ( callback ) {

        self.ccm.helper.dataset( self.data.store, self.data.key, function ( question ) {
          dataset = question;
        } );

        renderQuestion();
        renderAnswers();
        renderEditor();

        function renderQuestion() {

          self.ccm.helper.setContent( self.element, self.ccm.helper.protect( self.ccm.helper.html( self.templates.main, {
            title: dataset.title,
            signatur: "posted " + dataset.date,
            question: dataset.content,
            new_answer: function () { newAnswer(); }
          })));

          if ( !self.user || !self.user.isLoggedIn() )
            return;

          var user = self.user.data().user;

          if ( user === dataset.user ) {
            self.voting.instance( dataset.voting, function (instance) {
              var voting_elem = self.ccm.helper.html( self.templates.voting_overview, {
                get_voting: instance.getVoting()
              } );

              self.element.querySelector( '.voting' ).appendChild( voting_elem );
            } );
          }
          else
            renderVoting( self.element.querySelector( '.voting' ), dataset.voting );

        }

        function renderAnswers() {
          self.element.querySelector( '#answers').innerHTML = '';

          dataset.answers.map ( renderAnswer );

          function answerAccepted( answer ) {

            if ( self.user.data().user === dataset.user ) return;

            // has user already accepted ?
            if ( answer.accepted === true )
              answer.accepted = '';
            // not accepted
            else {
              self.element.querySelector( '.glyphicon-ok' ).classList.add( 'accepted' );
              answer.accepted = true;
            }

            // update dataset for rendering => (re)render accepted answer
            self.data.store.set( dataset, function () { renderAnswers() } );
          }
        }

        function renderAnswer( answer ) {

          // generate on-the-fly element
          var answer_elem = self.ccm.helper.html( self.templates.answer, {
            answer: answer.content,
            signatur: answer.user + ' ' + answer.date,
            accepted: function () { answerAccepted( answer ); }
          } );

          // prepend element to DOM
          self.ccm.helper.prepend( self.element.querySelector( '#answers' ), answer_elem );

          // render accepted answer green
          if ( answer.accepted === true )
            self.element.querySelector( '.glyphicon-ok' ).classList.add( 'accepted' );

          renderVoting( answer_elem.querySelector( '.voting-overview' ), answer.voting );
        }

        function renderEditor() {
          if (!self.user || !self.user.isLoggedIn()) return;

          var user = self.user.data().user;

          self.editor.start( { root: self.element.querySelector( '#editor' ) }, function (instance) {
            if (user !== dataset.user) {
              editor = instance;
            }
            else {
              editor = instance;
              editor.get().enable( false );
            }
          } );
        }

        function renderVoting( element, voting ) {
          if ( !self.user ) return;
          self.voting.start( voting, function ( voting_inst ) {
            element.appendChild( voting_inst.root );
          } );

        }

        function newAnswer() {

          self.user.login( function () {
            var user = self.user.data().user;

            // only not question author can be able to create new answer
            if ( user !== dataset.user ) {
              dataset.answers.push(
                {
                  "date": getDateTime(),
                  "user": user,
                  "content": editor.get().root.innerHTML,
                  "voting": { }
                }

              );

              // update dataset for rendering => (re)render accepted answer
              self.data.store.set( dataset, function () { renderAnswers(); } );
            }

          } );
        }

        function getDateTime() {

          var today = new Date();
          var dd    = today.getDate();
          var mm    = today.getMonth();
          var yyyy  = today.getFullYear();
          var hour  = today.getHours();
          var min   = today.getMinutes();

          var monat = ["Januar", "Februar", "März", "April", "Mai", "Juni","Juli", "August", "September", "Oktober", "November", "Dezember"];

          if ( dd < 10 ) dd = '0' + dd;

          if ( hour < 10 ) hour = '0' + hour;
          if ( min  < 10 ) min  = '0' + min;

          return dd + ' ' + monat[ mm].substring(0, 3) + '. '  + yyyy + ' ' + hour + ':' + min;

        }

        if ( callback ) callback();
      };
    }
  };

  var namespace = window.ccm && ccm.components[ component_name ]; if ( namespace ) { if ( namespace.ccm_version ) ccm_version = namespace.ccm_version; if ( namespace.ccm_url ) ccm_url = namespace.ccm_url; }
  if ( !window.ccm || !ccm[ ccm_version ] ) { var tag = document.createElement( 'script' ); document.head.appendChild( tag ); tag.onload = register; tag.src = ccm_url; } else register();
  function register() { ccm[ ccm_version ].component( component_obj ); }
}() );
<commit_msg>compatibility to ccm v9.2.0<commit_after>/**
 * @overview ccm component for real time  Forum
 * @author Tea Kless <tea.kless@web.de>, 2017
 * @license The MIT License (MIT)
 */

( function () {

  var filename = "ccm.question.js";

  var ccm_version = '9.2.0';
  var ccm_url     = 'https://akless.github.io/ccm/version/ccm-9.2.0.min.js';

  var component_name = 'question';
  var component_obj  = {
    name: component_name,

    config: {
      templates: {
        "main": {
          "class": "container",
          "inner": [
            {
              "id": "answers_view",
              "inner": [
                {
                  "class": "question",
                  "inner": [
                    {
                      "class": "row",
                      "inner": {
                        "class": "question-title col-md-10",
                        "inner": {
                          "tag": "h3",
                          "inner": [
                             "%title% ",
                            {
                              "tag": "small",
                              "inner": "%signatur%"
                            }
                          ]
                        }
                      }
                    },
                    {
                      "class": "row",
                      "inner": [
                        {
                          "class": "voting col-md-1"
                        },
                        {
                          "class": "question col-md-11",
                          "inner": {
                            "tag": "blockquote",
                            "inner": {
                              "tag": "p",
                              "inner": [
                                "%question%",
                                {
                                  "tag": "footer",
                                  "inner": "footer"
                                }
                              ]
                            }
                          }
                        }
                      ]
                    }
                  ]
                },
                {
                  "tag": "hr"
                },
                {
                  "id": "answers"
                },

                {
                  "id": "new-answer",
                  "inner": [
                    {
                      "tag": "h4",
                      "inner": "Your Answer"
                    },
                    {
                      "id": "editor"
                    },
                    {
                      "id": "new",
                      "class": "row",
                      "inner": {
                        "tag": "button",
                        "class": "btn btn-primary",
                        "type": "submit",
                        "inner": "Post Answer",
                        "onclick": "%new_answer%"
                      }
                    }
                  ]

                }
              ]
            }
          ]
        },

        "answer": {
          "inner": [
            {
              "class": "answer row",
              "inner": [
                {
                  "class": "voting-area col-md-1 col-sx-12",
                  "inner": [
                    {
                      "class": "voting-overview col-sx-6 col-md-12"
                    },
                    {
                      "class": "answer-accepted col-sx-6 col-md-12",
                      "inner": {
                        "tag": "span",
                        "class": "glyphicon glyphicon-ok",
                        "oncklick": "%accepted%"
                      }
                    }
                  ]
                },
                {
                  "class": "answer-overview col-md-11 col-sx-12",
                  "inner": [
                    "%answer%",
                    {
                      "tag": "blockquote",
                      "class": "blockquote-reverse",
                      "inner": {
                        "tag": "footer",
                        "inner": "%signatur%"
                      }
                    }
                  ]
                }
              ]
            },
            {
              "tag": "hr"
            }
          ]

        },

        "voting_overview": {
          "class": "voting_overview row",
          "inner": [
            {
              "class": "col-md-12",
              "inner": "%get_voting%"
            },
            {
              "class": "col-md-12",
              "inner": "votes"
            }
          ]
        }
      },

      data: {
        store: [ 'ccm.store', '../question/datastore.json' ],
        key: "1"
      },
      user:  [ 'ccm.instance', 'https://akless.github.io/ccm-components/user/ccm.user.min.js', { logged_in: true, 'guest.user': 'tmeskh2s' } ],
      style: [ 'ccm.load', '../question/style.css' ],
      editor: [ 'ccm.component', 'https://tkless.github.io/ccm-components/editor/ccm.editor.js',
        { 'settings.modules.toolbar': [
            [{ 'size': ['small', false, 'large', 'huge'] }],  // custom dropdown
            ['bold', 'italic', 'underline'],        // toggled buttons
            ['blockquote', 'code-block'],

            [{ 'header': 1 }, { 'header': 2 }],               // custom button values
            [{ 'list': 'ordered'}, { 'list': 'bullet' }],
            [{ 'script': 'sub'}, { 'script': 'super' }],      // superscript/subscript
            [{ 'indent': '-1'}, { 'indent': '+1' }],          // outdent/indent

            [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
            [{ 'align': [] }]
        ] }
      ],
      voting: [ "ccm.component", "https://tkless.github.io/ccm-components/voting/ccm.voting.js", {
        data: {
          store: [ 'ccm.store', 'https://tkless.github.io/ccm-components/voting/voting_datastore.js' ]
        }
      } ],
      bootstrap: [ 'ccm.load', 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css' ]
    },

    Instance: function () {
      var self = this;
      var editor;
      var dataset;

      this.init = function ( callback ) {

        // listen to change event of ccm realtime datastore => (re)render own content
        self.data.store.onChange = function ( question ) {
          dataset = question;
          self.start();
        };

        callback();
      };

      this.start = function ( callback ) {

        self.ccm.helper.dataset( self.data.store, self.data.key, function ( question ) {
          dataset = question;
        } );

        renderQuestion();
        renderAnswers();
        renderEditor();

        function renderQuestion() {

          self.ccm.helper.setContent( self.element, self.ccm.helper.protect( self.ccm.helper.html( self.templates.main, {
            title: dataset.title,
            signatur: "posted " + dataset.date,
            question: dataset.content,
            new_answer: function () { newAnswer(); }
          })));

          if ( !self.user || !self.user.isLoggedIn() )
            return;

          var user = self.user.data().user;

          if ( user === dataset.user ) {
            self.voting.instance( dataset.voting, function (instance) {
              var voting_elem = self.ccm.helper.html( self.templates.voting_overview, {
                get_voting: instance.getVoting()
              } );

              self.element.querySelector( '.voting' ).appendChild( voting_elem );
            } );
          }
          else
            renderVoting( self.element.querySelector( '.voting' ), dataset.voting );

        }

        function renderAnswers() {
          self.element.querySelector( '#answers').innerHTML = '';

          dataset.answers.map ( renderAnswer );

          function answerAccepted( answer ) {

            if ( self.user.data().user === dataset.user ) return;

            // has user already accepted ?
            if ( answer.accepted === true )
              answer.accepted = '';
            // not accepted
            else {
              self.element.querySelector( '.glyphicon-ok' ).classList.add( 'accepted' );
              answer.accepted = true;
            }

            // update dataset for rendering => (re)render accepted answer
            self.data.store.set( dataset, function () { renderAnswers() } );
          }
        }

        function renderAnswer( answer ) {

          // generate on-the-fly element
          var answer_elem = self.ccm.helper.html( self.templates.answer, {
            answer: answer.content,
            signatur: answer.user + ' ' + answer.date,
            accepted: function () { answerAccepted( answer ); }
          } );

          // prepend element to DOM
          self.ccm.helper.prepend( self.element.querySelector( '#answers' ), answer_elem );

          // render accepted answer green
          if ( answer.accepted === true )
            self.element.querySelector( '.glyphicon-ok' ).classList.add( 'accepted' );

          renderVoting( answer_elem.querySelector( '.voting-overview' ), answer.voting );
        }

        function renderEditor() {
          if (!self.user || !self.user.isLoggedIn()) return;

          var user = self.user.data().user;

          self.editor.start( { root: self.element.querySelector( '#editor' ) }, function (instance) {
            if (user !== dataset.user) {
              editor = instance;
            }
            else {
              editor = instance;
              editor.get().enable( false );
            }
          } );
        }

        function renderVoting( element, voting ) {
          if ( !self.user ) return;
          self.voting.start( voting, function ( voting_inst ) {
            element.appendChild( voting_inst.root );
          } );

        }

        function newAnswer() {

          self.user.login( function () {
            var user = self.user.data().user;

            // only not question author can be able to create new answer
            if ( user !== dataset.user ) {
              dataset.answers.push(
                {
                  "date": getDateTime(),
                  "user": user,
                  "content": editor.get().root.innerHTML,
                  "voting": { }
                }

              );

              // update dataset for rendering => (re)render accepted answer
              self.data.store.set( dataset, function () { renderAnswers(); } );
            }

          } );
        }

        function getDateTime() {

          var today = new Date();
          var dd    = today.getDate();
          var mm    = today.getMonth();
          var yyyy  = today.getFullYear();
          var hour  = today.getHours();
          var min   = today.getMinutes();

          var monat = ["Januar", "Februar", "März", "April", "Mai", "Juni","Juli", "August", "September", "Oktober", "November", "Dezember"];

          if ( dd < 10 ) dd = '0' + dd;

          if ( hour < 10 ) hour = '0' + hour;
          if ( min  < 10 ) min  = '0' + min;

          return dd + ' ' + monat[ mm].substring(0, 3) + '. '  + yyyy + ' ' + hour + ':' + min;

        }

        if ( callback ) callback();
      };
    }
  };

  if ( window.ccm && window.ccm.files ) window.ccm.files[ filename ] = component_obj;
  var namespace = window.ccm && ccm.components[ component_name ]; if ( namespace ) { if ( namespace.ccm_version ) ccm_version = namespace.ccm_version; if ( namespace.ccm_url ) ccm_url = namespace.ccm_url; }
  if ( !window.ccm || !ccm[ ccm_version ] ) { var tag = document.createElement( 'script' ); document.head.appendChild( tag ); tag.onload = register; tag.src = ccm_url; } else register();
  function register() { ccm[ ccm_version ].component( component_obj ); }
}() );
<|endoftext|>