<commit_before>Class("Restorer", {
    Restorer: function(data) {
        //check if there's something to restore or not
        this.nothingToRestore = false;
        for (var k in app.storage.keys) {
            if (!data[app.storage.currentProject+"_"+k]) {
                this.nothingToRestore = true;
                return;
            }
        }
        this.lights = data[app.storage.currentProject+"_lights"];
        this.meshes = data[app.storage.currentProject+"_meshes"];
        //flags
        this.meshesFlag = (this.meshes.keys.length > 0);
        this.lightsFlag = (this.lights.keys.length > 0); // true/false whether we recovered something or not
        //object loader
        this.loader = new THREE.ObjectLoader();
    },

    restore: function() {
        //if nothing to restore, return
        if (this.nothingToRestore) return;
        //restoring meshes
        for (var i=0; i<this.meshes.total; i++) {
            var k = this.meshes.keys[i];
            //recreating mesh
            var mesh = this.loader.parse(this.meshes.map[k]);
            //every mesh must have castshadow and receive shadow enabled
            mesh.castShadow = true;
            mesh.receiveShadow = true;
            //setting correct flag
            mesh.flag = "mesh";
            //store new mesh in our map
            app.mm.store(mesh.uuid, mesh);
            //add new mesh to the scene and to meshes list
            app.sm.scene.add(app.mm.map.get(mesh.uuid));
            app.mm.meshes.push(app.mm.map.get(mesh.uuid));
            //forcing scene to update itself
            app.sm.update();
            //attach new mesh to transform control
            //app.sm.transformControl.attach(mesh);
            //creating a callback for our mesh
            app.interface.meshEvents.bind(app.mm.map.get(mesh.uuid), "click", function(event) {
                //now only adding this mesh to the transform control
                if (app.sm.lastClicked.uuid == event.target.uuid) return;
                app.sm.deselect();
                //Setting uuid to the scene
                app.sm.uuid = event.target.uuid;
                app.sm.typeClicked = "mesh";
                app.sm.select(event.target, "translate");
            });
            //increasing meshcount
            app.mm.meshCount++;
            //calling addedmesh event
            app.interface.events.meshAdded.dispatch();
        }
        //restoring lights
        for (var j=0; j<this.lights.keys.length; j++) {

        }
        //restoring models
        //restoring sounds
        //updating all materials
        if (this.meshesFlag) {
            var keys_list = app.mm.map.keys.concat();
            if (keys_list.length != 0) {
                var start = +new Date();
                do {
                    app.mm.map.get(keys_list.shift()).material.needsUpdate = true;
                } while (keys_list.length > 0 && (+new Date() - start < 50));
            }
        }
    }
})<commit_msg>we're now able to restore lights<commit_after>Class("Restorer", {
    Restorer: function(data) {
        //check if there's something to restore or not
        this.nothingToRestore = false;
        for (var k in app.storage.keys) {
            if (!data[app.storage.currentProject+"_"+k]) {
                this.nothingToRestore = true;
                return;
            }
        }
        this.lights = data[app.storage.currentProject+"_lights"];
        this.meshes = data[app.storage.currentProject+"_meshes"];
        //flags
        this.meshesFlag = (this.meshes.keys.length > 0);
        this.lightsFlag = (this.lights.keys.length > 0); // true/false whether we recovered something or not
        //object loader
        this.loader = new THREE.ObjectLoader();
    },

    restore: function() {
        //if nothing to restore, return
        if (this.nothingToRestore) return;
        //restoring meshes
        for (var i=0; i<this.meshes.total; i++) {
            var k = this.meshes.keys[i];
            //recreating mesh
            var mesh = this.loader.parse(this.meshes.map[k]);
            //every mesh must have castshadow and receive shadow enabled
            mesh.castShadow = true;
            mesh.receiveShadow = true;
            //setting correct flag
            mesh.flag = "mesh";
            //store new mesh in our map
            app.mm.store(mesh.uuid, mesh);
            //add new mesh to the scene and to meshes list
            app.sm.scene.add(app.mm.map.get(mesh.uuid));
            app.mm.meshes.push(app.mm.map.get(mesh.uuid));
            //forcing scene to update itself
            app.sm.update();
            //attach new mesh to transform control
            //app.sm.transformControl.attach(mesh);
            //creating a callback for our mesh
            app.interface.meshEvents.bind(app.mm.map.get(mesh.uuid), "click", function(event) {
                //now only adding this mesh to the transform control
                if (app.sm.lastClicked.uuid == event.target.uuid) return;
                app.sm.deselect();
                //Setting uuid to the scene
                app.sm.uuid = event.target.uuid;
                app.sm.typeClicked = "mesh";
                app.sm.select(event.target, "translate");
            });
            //increasing meshcount
            app.mm.meshCount++;
            //calling addedmesh event
            app.interface.events.meshAdded.dispatch();
        }
        //restoring lights
        for (var j=0; j<this.lights.total; j++) {
            var k = this.lights.keys[j];
            var l = this.lights.map[k];
            //recreating light, holder, target, helper
            var o = {
                flag: "light",
                holder: (l.holder) ? this.loader.parse(l.holder) : false,
                //helper: (l.helper) ? this.loader.parse(l.helper) : false,
                target: (l.target) ? this.loader.parse(l.target) : false,
                light: (l.light) ? this.loader.parse(l.light) : false
            };
            //setting o.light.flag
            o.light.flag = "light";
            //setting helpers ecc
            if (l.light.object.type == "DirectionalLight") {
                //i have to add helper
                var size = 50;
                o.helper = new THREE.DirectionalLightHelper(o.light, size);
                o.light.castShadow = true;
                o.light.shadowCameraVisible = true;

                o.light.shadowMapWidth = 512;
                o.light.shadowMapHeight = 512;

                var d = 200;
                o.light.shadowCameraLeft = -d;
                o.light.shadowCameraRight = d;
                o.light.shadowCameraTop = d;
                o.light.shadowCameraBottom = -d;
                // #TODO be able to change shadow camera far
                o.light.shadowCameraFar = 1000;
                o.light.shadowDarkness = 0.2;
            } else if (l.light.object.type == "AmbientLight") {
                //we just need to set helper false
                o.helper = false;
            } else if (l.light.object.typ == "PointLight") {
                var sphereSize = 50;
                o.helper = new THREE.PointLightHelper(o.light, sphereSize);

                //every light must cast shadow
                o.light.castShadow = true;
                var d = 200;
                o.light.shadowCameraLeft = -d;
                o.light.shadowCameraRight = d;
                o.light.shadowCameraTop = d;
                o.light.shadowCameraBottom = -d;
                // #TODO be able to change shadow camera far
                o.light.shadowCameraFar = 1000;
                o.light.shadowDarkness = 0.2;
            }
            //we're now ready to add our lights to the scene
            //add light to scene
            app.sm.scene.add(o.light)
            //pushing light into array
            app.lm.lights.push(o.light);
            //storing this light
            app.lm.store(o.light.uuid, o);
            //forcing scene update
            app.sm.update();
            //setting
            app.sm.uuid = o.light.uuid;
            app.sm.typeClicked = "light";
            //adding to transform
            if (o.holder) {
                app.sm.select(o.holder, "translate");
            } else {
                app.sm.select(o.light, "translate");
            }
            //check if this light has helper
            if (o.helper) {
                //adding helper to scene
                app.sm.scene.add(o.helper);
                //ading helper to mesh lists
                app.mm.meshes.push(o.helper);
                //adding click listener to helper
                app.interface.meshEvents.bind(o.helper, "click", function(event) {
                    //now only adding this mesh to the transform control
                    if (app.sm.lastClicked.uuid === event.target.light.uuid) return;
                    app.sm.deselect();
                    //Setting uuid to the scene
                    app.sm.uuid = event.target.light.uuid;
                    app.sm.typeClicked = "light";
                    app.sm.select(event.target.light, "translate");
                });
                //calling addedmesh event
                app.interface.events.meshAdded.dispatch();
            }
            //check if this has target
            if (o.target) {
                //Setting target name
                o.target.name = "Target_"+this.lightCount;
                o.target.flag = "target";
                //add target to the scene
                app.sm.scene.add(o.target);
                //adding target to meshes list
                // #TODO remove this when exporting
                app.mm.meshes.push(o.target);
                //adding click listener to target
                app.interface.meshEvents.bind(o.target, "click", function(event) {
                    if (app.sm.lastClicked.uuid === event.target.uuid) return;
                    app.sm.deselect();
                    app.sm.select(event.target, "translate");
                });
                //calling addedmesh event
                app.interface.events.meshAdded.dispatch();
            }
            //check if we need to use holder
            if (o.holder) {
                //Setting holder name
                o.holder.name = "Holder_"+this.lightCount;
                o.holder.flag = "holder";
                //adding holder to the scene
                app.sm.scene.add(o.holder);
                //adding holder to meshesh list -- do we really need to do this?
                // #TODO remove this when exporting
                app.mm.meshes.push(o.holder);
                //adding click listener to holder
                app.interface.meshEvents.bind(o.holder, "click", function(event) {
                    if (app.sm.lastClicked.uuid === event.target.uuid) return;
                    app.sm.deselect();
                    app.sm.uuid = o.light.uuid;
                    app.sm.typeClicked = "light";
                    app.sm.select(event.target, "translate");
                });
                //calling addedmesh event
                app.interface.events.meshAdded.dispatch();
            }
            //increasing light count
            this.lightCount++;
            //triggering light added event
            app.interface.events.lightAdded.dispatch();
        }
        //restoring models
        //restoring sounds
        //updating all materials
        if (this.meshesFlag) {
            var keys_list = app.mm.map.keys.concat();
            if (keys_list.length != 0) {
                var start = +new Date();
                do {
                    app.mm.map.get(keys_list.shift()).material.needsUpdate = true;
                } while (keys_list.length > 0 && (+new Date() - start < 50));
            }
        }
    }
})<|endoftext|>


<commit_before>import ohm from "https://unpkg.com/ohm-js@15.2.1/dist/ohm.js";

export default class LeoUIExample{
  static async create () {

    var hello =
 lively.notify('hi')}>
        Hi

    var world =

        World

    let description =

    hello.addEventListener('dragstart', dragStart);
    hello.addEventListener('dragend', dragEnd);

    world.addEventListener('drop', drop);

    var g = ohm.grammar('Academic { \n  Exp = \n    AcademicQuery \n \n  AcademicQuery = Attribute Comparator Value -- simpleQuery \n    | ("And" | "Or") "(" AcademicQuery "," AcademicQuery ")" -- complexQuery \n    | "Composite(" CompositeQuery ")" -- compositeQuery \n \n  CompositeQuery = CompositeAttribute Comparator Value -- simpleCompositeQuery \n    | ("And" | "Or") "(" CompositeQuery "," CompositeQuery ")" -- complexCompositeQuery \n \n  Comparator = \n    PartialComparator "="? \n  PartialComparator = \n    "=" | "<" | ">" \n \n  Attribute (an attribute) = \n    letter letter? letter? \n  CompositeAttribute = \n    Attribute "." Attribute \n \n \n  Value (a value) = \n    "\'" alnum* "\'" -- string \n    | Number \n    | Date \n    | ( "[" | "(" ) Number "," Number ( "]" | ")" ) -- numberRange \n    | ( "[" | "(" ) Date "," Date ( "]" | ")" ) -- dateRange \n \n  Number = \n    digit+ \n  Date = \n    "\'" digit digit digit digit "-" digit digit "-" digit digit "\'" \n}');

    lively.notify(g.match("Composite(And(AA.AuN='mike smith',AA.AfN='harvard university'))").succeeded(), "Composite(And(AA.AuN='mike smith',AA.AfN='harvard university'))");
    lively.notify(g.match("And(AA.AuN='mike smith',AA.AfN='harvard university')").succeeded(), "And(AA.AuN='mike smith',AA.AfN='harvard university')");

    // TODO: Add Semantics

    function dragStart(event) {
      description.innerHTML = "dragging";
      event.dataTransfer.setData("element", event.target.id);
    }

    function dragEnd(event) {
      description.innerHTML = "";
    }

    function drop(event) {
      event.preventDefault();
      var data = event.dataTransfer.getData("element");
      console.log("Datatransfer Types" + event.dataTransfer.types);
      event.target.appendChild(lively.query(this, '#'+data))
    }

    return

            Title

            Author

            Year

            <input value='something'></input>

                  Name

                  <input value='name'></input>

                  Institution

                  <input value='inst'></input>

            <input value='2001'></input>

  }
}<commit_msg>add first semantics<commit_after>import ohm from "https://unpkg.com/ohm-js@15.2.1/dist/ohm.js";

export default class LeoUIExample{
  static async create () {

    var hello =
 lively.notify('hi')}>
        Hi

    var world =

        World

    let description =

    hello.addEventListener('dragstart', dragStart);
    hello.addEventListener('dragend', dragEnd);

    world.addEventListener('drop', drop);

    var g = ohm.grammar('Academic { \n  Exp = \n    AcademicQuery \n \n  AcademicQuery = Attribute Comparator Value -- simple \n    | ("And" | "Or") "(" AcademicQuery "," AcademicQuery ")" -- complex \n    | "Composite(" CompositeQuery ")" -- composite \n \n  CompositeQuery = CompositeAttribute Comparator Value -- simple \n    | ("And" | "Or") "(" CompositeQuery "," CompositeQuery ")" -- complex \n \n  Comparator = \n    PartialComparator "="? \n  PartialComparator = \n    "=" | "<" | ">" \n \n  Attribute (an attribute) = \n    letter letter? letter? \n  CompositeAttribute = \n    Attribute "." Attribute \n \n \n  Value (a value) = \n    "\'" alnum* "\'" -- string \n    | Number \n    | Date \n    | ( "[" | "(" ) Number "," Number ( "]" | ")" ) -- numberRange \n    | ( "[" | "(" ) Date "," Date ( "]" | ")" ) -- dateRange \n \n  Number = \n    digit+ \n  Date = \n    "\'" digit digit digit digit "-" digit digit "-" digit digit "\'" \n}');

    /*lively.notify(g.match("Composite(And(AA.AuN='mike smith',AA.AfN='harvard university'))").succeeded(), "Composite(And(AA.AuN='mike smith',AA.AfN='harvard university'))");
    lively.notify(g.match("And(AA.AuN='mike smith',AA.AfN='harvard university')").succeeded(), "And(AA.AuN='mike smith',AA.AfN='harvard university')");*/

    //var queryObject = {};

    var s = g.createSemantics();

    s.addOperation(
      'interpret', {
        Exp: function(e) {
          return e.interpret();
        },

        AcademicQuery_simple: function(attr, comp, val) {
          var attribute = attr.interpret();
          //var comparator = comp.interpret();
          //var value = val.interpret();
          return { [attribute]: {
            "comparator": "a",//comparator,
            "value": "b"//value,
          }}
        },
        AcademicQuery_complex: function(conj, x, left, y, right, z) {
          var conjunction = conj.interpret();

          return {conjunction: [
            left.interpret(),
            right.interpret()
          ]}
        },

        Attribute: function(a, b, c) {
          var array = [a.interpret(), b.interpret(), c.interpret()];
          return array.join('');
        },

        letter: function(a) {
          return a.sourceString;
        }
      }
    )

    var r = g.match("A = 'e'")
    var n = s(r)
    lively.notify("A = 'e'", n.interpret());

    function dragStart(event) {
      description.innerHTML = "dragging";
      event.dataTransfer.setData("element", event.target.id);
    }

    function dragEnd(event) {
      description.innerHTML = "";
    }

    function drop(event) {
      event.preventDefault();
      var data = event.dataTransfer.getData("element");
      console.log("Datatransfer Types" + event.dataTransfer.types);
      event.target.appendChild(lively.query(this, '#'+data))
    }

    return

            Title

            Author

            Year

            <input value='something'></input>

                  Name

                  <input value='name'></input>

                  Institution

                  <input value='inst'></input>

            <input value='2001'></input>

  }
}<|endoftext|>


<commit_before>describe("me.Camera2d", function () {

    beforeAll(function () {
        // update position so that it's not just 0
        me.game.viewport.move(100, 100);
    });

    it("convert between local and World coords without transforms", function () {
        var result = new me.Vector2d();
        // convert to word coordinates
        me.game.viewport.localToWorld(250, 150, result);
        // convert back to local coordinates
        me.game.viewport.worldToLocal(result.x, result.y, result);

        expect( result.x ).toBeCloseTo(250);
        expect( result.y ).toBeCloseTo(150);
    });

    it("convert between local and World coords with transforms", function () {
        var result = new me.Vector2d();

        // rotate the viewport
        me.game.viewport.currentTransform.rotate(0.5);

        // convert to word coordinates
        me.game.viewport.localToWorld(250, 150, result);
        // convert back to local coordinates
        me.game.viewport.worldToLocal(result.x, result.y, result);

        expect( result.x ).toBeCloseTo(250);
        expect( result.y ).toBeCloseTo(150);
    });
});
<commit_msg>fix Jasmine test<commit_after>describe("me.Camera2d", function () {

    beforeEach(function () {
        // update position so that it's not just 0
        me.game.viewport.move(100, 100);
    });

    afterEach(function () {
        // move back to default 0,0 position
        me.game.viewport.moveTo(0, 0);
    });

    it("convert between local and World coords without transforms", function () {
        var result = new me.Vector2d();
        // convert to word coordinates
        me.game.viewport.localToWorld(250, 150, result);
        // convert back to local coordinates
        me.game.viewport.worldToLocal(result.x, result.y, result);

        expect( result.x ).toBeCloseTo(250);
        expect( result.y ).toBeCloseTo(150);
    });

    it("convert between local and World coords with transforms", function () {
        var result = new me.Vector2d();

        // rotate the viewport
        me.game.viewport.currentTransform.rotate(0.5);

        // convert to word coordinates
        me.game.viewport.localToWorld(250, 150, result);
        // convert back to local coordinates
        me.game.viewport.worldToLocal(result.x, result.y, result);

        expect( result.x ).toBeCloseTo(250);
        expect( result.y ).toBeCloseTo(150);
    });
});
<|endoftext|>


<commit_before>/*global define*/

var gettext = gettext || function (text) {
    'use strict';
    return text;
};

define(['jquery', 'underscore', 'backbone', 'codemirror', 'djangohint',
      'codemirror/mode/htmlmixed/htmlmixed',
      'codemirror/addon/display/fullscreen'
    ], function($, _, Backbone, CodeMirror) {
    'use strict';

    $.noConflict(true);

    var ScribbleEditor = Backbone.View.extend({
        id: 'scribbleEditorContainer',
        tagName: 'div',
        initialize: function () {
            var self = this;
            this.visible = false;
            this.rendering = false;
            this.errorLine = null;
            this.controls = {};
            this.current = {};
            this.needsSave = false;
            this.needsDraft = false;
            this.scribbles = $('.scribble-wrapper.with-controls');
            this.editorOptions = {
                mode: "text/html",
                tabMode: "indent",
                lineNumbers: true,
                extraKeys: {
                  "F11": function(cm) {
                    cm.setOption("fullScreen", !cm.getOption("fullScreen"));
                  },
                  "Esc": function(cm) {
                    if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
                  },
                  'Tab': 'autocomplete'
                }
                };
            CodeMirror.commands.autocomplete = function (editor) {
                CodeMirror.showHint(editor, CodeMirror.djangoHint);
            };
        },
        events: {
            'click .controls .closed': 'close',
            'click .controls .save': 'submitSave',
            'click .controls .draft': 'createDraft',
            'click .controls .discard': 'deleteDraft'
        },
        render: function () {
            var self = this;
            if (this.scribbles.length > 0) {
                this.buildControls();
                $('body').append(this.$el);
                this.editor = new CodeMirror(document.getElementById(this.id), this.editorOptions);
                this.editor.on("change", function (editor, change) {
                    self.needsSave = true;
                    self.controls.save.removeClass('inactive');
                    self.needsDraft = true;
                    self.controls.draft.removeClass('inactive');
                    self.submitPreview();
                });
                this.editor.selector = this.id;
                // Bind editor to the scribbles
                this.scribbles.each(function (i, elem) {
                    // Bind event handlers for each scribble
                    $(elem).click(function (e) {
                        // Allow click to follow links inside of scribble content
                        if (e.target.nodeName !== 'A') {
                            self.open($(this));
                        }
                    });
                });
            }
        },
        buildControls: function () {
            // Build control bar
            var footerControls = $('

').addClass('controls');
            // Close button
            this.controls.close = $('' + gettext('Close') + '')
                .attr({title: gettext('Close')})
                .addClass('closed');
            // Save button
            this.controls.save = $('' + gettext('Save') + '')
                .attr({title: gettext('Save')})
                .addClass('save inactive');
            this.controls.draft = $('' + gettext('Save Draft') + '')
                .attr({title: gettext('Save as Draft')})
                .addClass('draft inactive');
            this.controls.discard = $('' + gettext('Discard') + '')
                .attr({title: gettext('Discard Draft')})
                .addClass('discard inactive');
            // Error message
            this.controls.errors = $('')
                .addClass('error-msg');
            // Status message
            this.controls.status = $('')
                .addClass('status-msg');
            // Fullscreen instructions
            this.controls.fullscreen = $('
' + gettext('Press') +
            '' + gettext('F11') + '' +
            gettext('to enter/exit Fullscreen edit') + '
')
            .addClass('fullscreen')
            footerControls.append(
                this.controls.status,
                this.controls.errors,
                this.controls.close,
                this.controls.discard,
                this.controls.draft,
                this.controls.save
                this.controls.fullscreen
            );
            this.$el.append(footerControls);
        },
        open: function (scribble) {
            var self = this;
            if (this.visible) {
                this.close();
            }
            this.current.content = $('.scribble-content.original', scribble);
            this.current.preview = $('.scribble-content.preview', scribble);
            this.current.form = $('.scribble-form', scribble);
            this.current.can_save = this.current.form.data('save');
            this.current.can_delete = this.current.form.data('delete');
            this.$el.show();
            this.trigger('open');
            if (this.current.can_save) {
                this.controls.save.show();
                this.editor.setOption('readOnly', false);
                this.editor.setValue($('[name$=content]', this.current.form).val());
                this.restoreDraft();
            } else {
                this.controls.save.hide();
                this.editor.setOption('readOnly', true);
                this.editor.setValue(gettext('You do not have permission to edit this content.'));
            }
            this.$el.animate({height: '300px'}, 500, function () {self.editor.focus(); });
            this.visible = true;
            // Start background draft saving
            var checkDraft = function () {
                if (self.needsDraft) {
                    self.createDraft();
                }
            };
            this.backgroundDraft = setInterval(checkDraft, 3000);
        },
        close: function () {
            this.current.preview.hide();
            this.current.content.show();
            this.current = {};
            this.editor.setValue('');
            this.$el.animate({height: 0}, 500);
            this.visible = false;
            if (this.backgroundDraft) {
                clearInterval(this.backgroundDraft);
            }
            this.trigger('close');
        },
        submitPreview: function (force) {
            var self = this;
            if (this.current.form && (force || (!this.rendering && !this.editor.getOption('readOnly')))) {
                this.rendering = true;
                // Submit the form and display the preview
                $.post(
                    this.current.form.attr('action'),
                    this.getFormData(),
                    function (response) {
                        if (response.valid) {
                            CodeMirror.update_variables(response.variables);
                        }
                        self.renderPreview(response);
                    },
                    'json'
                ).error(function (jqXHR, textStatus, errorThrown) {
                    var msg = 'Server response was "' + errorThrown + '"';
                    self.setError(msg);
                }).complete(function () {
                    self.rendering = false;
                });
            }
        },
        renderPreview: function (response) {
            var self = this;
            if (this.visible) {
                if (this.errorLine !== null) {
                    this.editor.removeLineClass(this.errorLine, "background", "activeline");
                }
                this.controls.errors.html('');
                this.valid = response.valid;
                if (response.valid) {
                    this.current.preview.html(response.html);
                    this.current.preview.show();
                    this.current.content.hide();
                    this.controls.save.removeClass('inactive');
                } else {
                    this.setError(response.error.message, response.error.line - 1);
                }
            }
        },
        setError: function (msg, line) {
            if (typeof line !== 'undefined' && line !== null) {
                this.errorLine = line;
                this.editor.addLineClass(this.errorLine, "background", "activeline");
            }
            this.controls.errors.html('' + gettext('Error:') + ' ' + msg);
            this.valid = false;
            this.controls.save.addClass('inactive');
        },
        getFormData: function () {
            var result = {},
                prefix = '',
                self = this;
            if (this.current.form) {
                prefix = this.current.form.data('prefix');
                $(':input', this.current.form).each(function (i, input) {
                    var inputName = $(input).attr('name').replace(prefix + '-', ''),
                        inputValue = $(input).val();
                    if (inputName === 'content') {
                        result[inputName] = self.editor.getValue();
                    } else {
                        result[inputName] = inputValue;
                    }
                });
            }
            return result;
        },
        submitSave: function () {
            var self = this;
            if (this.current.form && this.valid) {
                // Submit the form and change current content
                $.post(
                    this.current.form.data('save'),
                    this.getFormData(),
                    function (response) {
                        self.renderSave(response);
                    },
                    'json'
                ).error(function (jqXHR, textStatus, errorThrown) {
                    var msg = gettext('Server response was') + '"' + errorThrown + '"';
                    self.setError(msg);
                });
            }
        },
        renderSave: function (response) {
            if (response.valid) {
                this.needsSave = false;
                this.controls.save.addClass('inactive');
                this.current.form.data('save', response.url);
                this.current.content.html(this.current.preview.html());
                $('[name$=content]', this.current.form).val(this.editor.getValue());
                this.deleteDraft();
                this.close();
            } else if (response.error) {
                this.setError(response.error.message);
            }
        },
        createDraft: function () {
            var scribble = null,
                path = window.location.pathname,
                slug = '';
            if (this.current.form) {
                // Check for localstorage and fallback to cookie
                scribble = this.editor.getValue();
                slug = this.current.form.data('prefix');
                if (typeof localStorage !== 'undefined' && localStorage !== null) {
                    localStorage[path + slug] = scribble;
                } else {
                    document.cookie = encodeURIComponent(slug) + '=' + encodeURIComponent(scribble) + ';' + 'path=' + path;
                }
                this.needsDraft = false;
                this.controls.draft.addClass('inactive');
                this.controls.discard.removeClass('inactive');
                this.setStatus(gettext('Draft saved...'));
            }
        },
        restoreDraft: function () {
            var scribble = null,
                path = window.location.pathname,
                slug = '',
                i,
                key,
                value,
                cookies = document.cookie.split(";"),
                cookieName;
            if (this.current.form) {
                // Check for localstorage and fallback to cookie
                slug = this.current.form.data('prefix');
                if (typeof localStorage !== 'undefined' && localStorage !== null) {
                    scribble = localStorage[path + slug];
                } else {
                    for (i = 0; i < cookies.length; i += 1) {
                        key = cookies[i].substr(0, cookies[i].indexOf("="));
                        value = cookies[i].substr(cookies[i].indexOf("=") + 1);
                        key = decodeURIComponent(key.replace(/\+/g, " "));
                        if (key === cookieName) {
                            scribble = decodeURIComponent(value.replace(/\+/g, " "));
                            break;
                        }
                    }
                }
                if (scribble) {
                    this.editor.setValue(scribble);
                    this.submitPreview(true);
                    this.needsDraft = false;
                    this.controls.draft.addClass('inactive');
                    this.controls.discard.removeClass('inactive');
                    this.setStatus(gettext('Restored content from a draft...'));
                }
            }
        },
        deleteDraft: function () {
            var path = window.location.pathname,
                slug = '',
                yesterday = new Date();
            this.editor.setValue($('[name$=content]', this.current.form).val());
            yesterday.setDate(yesterday.getDate() - 1);
            if (this.current.form) {
                // Check for localstorage and fallback to cookie
                slug = this.current.form.data('prefix');
                if (typeof localStorage !== 'undefined' && localStorage !== null) {
                    localStorage.removeItem(path + slug);
                } else {
                    document.cookie = encodeURIComponent(slug) + '=' + encodeURIComponent('') +
                        ';expires=' + yesterday.toUTCString() + ';path=' + path;
                }
                this.needsDraft = true;
                this.controls.draft.removeClass('inactive');
                this.controls.discard.addClass('inactive');
                this.setStatus(gettext('Restored original content...'));
            }
        },
        setStatus: function (msg) {
            var self = this;
            // Append status message
            this.controls.status.fadeIn(500);
            this.controls.status.html(msg);
            // Callback to fade out the message
            setTimeout(function () {
                self.controls.status.fadeOut(500, function () {
                    self.controls.status.html("");
                });
            }, 2000);
        },
        destroy: function () {
            this.undelegateEvents();
            this.remove();
        }
    });

    return ScribbleEditor;
});
<commit_msg>Removed code for fullscreen addon.  This branch should be limited to the addition of selenium testing.<commit_after>/*global define*/

var gettext = gettext || function (text) {
    'use strict';
    return text;
};

define(['jquery', 'underscore', 'backbone', 'codemirror', 'djangohint',
      'codemirror/mode/htmlmixed/htmlmixed'
    ], function($, _, Backbone, CodeMirror) {
    'use strict';

    $.noConflict(true);

    var ScribbleEditor = Backbone.View.extend({
        id: 'scribbleEditorContainer',
        tagName: 'div',
        initialize: function () {
            var self = this;
            this.visible = false;
            this.rendering = false;
            this.errorLine = null;
            this.controls = {};
            this.current = {};
            this.needsSave = false;
            this.needsDraft = false;
            this.scribbles = $('.scribble-wrapper.with-controls');
            this.editorOptions = {
                mode: "text/html",
                tabMode: "indent",
                lineNumbers: true,
                extraKeys: {
                  'Tab': 'autocomplete'
                }
                };
            CodeMirror.commands.autocomplete = function (editor) {
                CodeMirror.showHint(editor, CodeMirror.djangoHint);
            };
        },
        events: {
            'click .controls .closed': 'close',
            'click .controls .save': 'submitSave',
            'click .controls .draft': 'createDraft',
            'click .controls .discard': 'deleteDraft'
        },
        render: function () {
            var self = this;
            if (this.scribbles.length > 0) {
                this.buildControls();
                $('body').append(this.$el);
                this.editor = new CodeMirror(document.getElementById(this.id), this.editorOptions);
                this.editor.on("change", function (editor, change) {
                    self.needsSave = true;
                    self.controls.save.removeClass('inactive');
                    self.needsDraft = true;
                    self.controls.draft.removeClass('inactive');
                    self.submitPreview();
                });
                this.editor.selector = this.id;
                // Bind editor to the scribbles
                this.scribbles.each(function (i, elem) {
                    // Bind event handlers for each scribble
                    $(elem).click(function (e) {
                        // Allow click to follow links inside of scribble content
                        if (e.target.nodeName !== 'A') {
                            self.open($(this));
                        }
                    });
                });
            }
        },
        buildControls: function () {
            // Build control bar
            var footerControls = $('

').addClass('controls');
            // Close button
            this.controls.close = $('' + gettext('Close') + '')
                .attr({title: gettext('Close')})
                .addClass('closed');
            // Save button
            this.controls.save = $('' + gettext('Save') + '')
                .attr({title: gettext('Save')})
                .addClass('save inactive');
            this.controls.draft = $('' + gettext('Save Draft') + '')
                .attr({title: gettext('Save as Draft')})
                .addClass('draft inactive');
            this.controls.discard = $('' + gettext('Discard') + '')
                .attr({title: gettext('Discard Draft')})
                .addClass('discard inactive');
            // Error message
            this.controls.errors = $('')
                .addClass('error-msg');
            // Status message
            this.controls.status = $('')
                .addClass('status-msg');
            footerControls.append(
                this.controls.status,
                this.controls.errors,
                this.controls.close,
                this.controls.discard,
                this.controls.draft,
                this.controls.save
            );
            this.$el.append(footerControls);
        },
        open: function (scribble) {
            var self = this;
            if (this.visible) {
                this.close();
            }
            this.current.content = $('.scribble-content.original', scribble);
            this.current.preview = $('.scribble-content.preview', scribble);
            this.current.form = $('.scribble-form', scribble);
            this.current.can_save = this.current.form.data('save');
            this.current.can_delete = this.current.form.data('delete');
            this.$el.show();
            this.trigger('open');
            if (this.current.can_save) {
                this.controls.save.show();
                this.editor.setOption('readOnly', false);
                this.editor.setValue($('[name$=content]', this.current.form).val());
                this.restoreDraft();
            } else {
                this.controls.save.hide();
                this.editor.setOption('readOnly', true);
                this.editor.setValue(gettext('You do not have permission to edit this content.'));
            }
            this.$el.animate({height: '300px'}, 500, function () {self.editor.focus(); });
            this.visible = true;
            // Start background draft saving
            var checkDraft = function () {
                if (self.needsDraft) {
                    self.createDraft();
                }
            };
            this.backgroundDraft = setInterval(checkDraft, 3000);
        },
        close: function () {
            this.current.preview.hide();
            this.current.content.show();
            this.current = {};
            this.editor.setValue('');
            this.$el.animate({height: 0}, 500);
            this.visible = false;
            if (this.backgroundDraft) {
                clearInterval(this.backgroundDraft);
            }
            this.trigger('close');
        },
        submitPreview: function (force) {
            var self = this;
            if (this.current.form && (force || (!this.rendering && !this.editor.getOption('readOnly')))) {
                this.rendering = true;
                // Submit the form and display the preview
                $.post(
                    this.current.form.attr('action'),
                    this.getFormData(),
                    function (response) {
                        if (response.valid) {
                            CodeMirror.update_variables(response.variables);
                        }
                        self.renderPreview(response);
                    },
                    'json'
                ).error(function (jqXHR, textStatus, errorThrown) {
                    var msg = 'Server response was "' + errorThrown + '"';
                    self.setError(msg);
                }).complete(function () {
                    self.rendering = false;
                });
            }
        },
        renderPreview: function (response) {
            var self = this;
            if (this.visible) {
                if (this.errorLine !== null) {
                    this.editor.removeLineClass(this.errorLine, "background", "activeline");
                }
                this.controls.errors.html('');
                this.valid = response.valid;
                if (response.valid) {
                    this.current.preview.html(response.html);
                    this.current.preview.show();
                    this.current.content.hide();
                    this.controls.save.removeClass('inactive');
                } else {
                    this.setError(response.error.message, response.error.line - 1);
                }
            }
        },
        setError: function (msg, line) {
            if (typeof line !== 'undefined' && line !== null) {
                this.errorLine = line;
                this.editor.addLineClass(this.errorLine, "background", "activeline");
            }
            this.controls.errors.html('' + gettext('Error:') + ' ' + msg);
            this.valid = false;
            this.controls.save.addClass('inactive');
        },
        getFormData: function () {
            var result = {},
                prefix = '',
                self = this;
            if (this.current.form) {
                prefix = this.current.form.data('prefix');
                $(':input', this.current.form).each(function (i, input) {
                    var inputName = $(input).attr('name').replace(prefix + '-', ''),
                        inputValue = $(input).val();
                    if (inputName === 'content') {
                        result[inputName] = self.editor.getValue();
                    } else {
                        result[inputName] = inputValue;
                    }
                });
            }
            return result;
        },
        submitSave: function () {
            var self = this;
            if (this.current.form && this.valid) {
                // Submit the form and change current content
                $.post(
                    this.current.form.data('save'),
                    this.getFormData(),
                    function (response) {
                        self.renderSave(response);
                    },
                    'json'
                ).error(function (jqXHR, textStatus, errorThrown) {
                    var msg = gettext('Server response was') + '"' + errorThrown + '"';
                    self.setError(msg);
                });
            }
        },
        renderSave: function (response) {
            if (response.valid) {
                this.needsSave = false;
                this.controls.save.addClass('inactive');
                this.current.form.data('save', response.url);
                this.current.content.html(this.current.preview.html());
                $('[name$=content]', this.current.form).val(this.editor.getValue());
                this.deleteDraft();
                this.close();
            } else if (response.error) {
                this.setError(response.error.message);
            }
        },
        createDraft: function () {
            var scribble = null,
                path = window.location.pathname,
                slug = '';
            if (this.current.form) {
                // Check for localstorage and fallback to cookie
                scribble = this.editor.getValue();
                slug = this.current.form.data('prefix');
                if (typeof localStorage !== 'undefined' && localStorage !== null) {
                    localStorage[path + slug] = scribble;
                } else {
                    document.cookie = encodeURIComponent(slug) + '=' + encodeURIComponent(scribble) + ';' + 'path=' + path;
                }
                this.needsDraft = false;
                this.controls.draft.addClass('inactive');
                this.controls.discard.removeClass('inactive');
                this.setStatus(gettext('Draft saved...'));
            }
        },
        restoreDraft: function () {
            var scribble = null,
                path = window.location.pathname,
                slug = '',
                i,
                key,
                value,
                cookies = document.cookie.split(";"),
                cookieName;
            if (this.current.form) {
                // Check for localstorage and fallback to cookie
                slug = this.current.form.data('prefix');
                if (typeof localStorage !== 'undefined' && localStorage !== null) {
                    scribble = localStorage[path + slug];
                } else {
                    for (i = 0; i < cookies.length; i += 1) {
                        key = cookies[i].substr(0, cookies[i].indexOf("="));
                        value = cookies[i].substr(cookies[i].indexOf("=") + 1);
                        key = decodeURIComponent(key.replace(/\+/g, " "));
                        if (key === cookieName) {
                            scribble = decodeURIComponent(value.replace(/\+/g, " "));
                            break;
                        }
                    }
                }
                if (scribble) {
                    this.editor.setValue(scribble);
                    this.submitPreview(true);
                    this.needsDraft = false;
                    this.controls.draft.addClass('inactive');
                    this.controls.discard.removeClass('inactive');
                    this.setStatus(gettext('Restored content from a draft...'));
                }
            }
        },
        deleteDraft: function () {
            var path = window.location.pathname,
                slug = '',
                yesterday = new Date();
            this.editor.setValue($('[name$=content]', this.current.form).val());
            yesterday.setDate(yesterday.getDate() - 1);
            if (this.current.form) {
                // Check for localstorage and fallback to cookie
                slug = this.current.form.data('prefix');
                if (typeof localStorage !== 'undefined' && localStorage !== null) {
                    localStorage.removeItem(path + slug);
                } else {
                    document.cookie = encodeURIComponent(slug) + '=' + encodeURIComponent('') +
                        ';expires=' + yesterday.toUTCString() + ';path=' + path;
                }
                this.needsDraft = true;
                this.controls.draft.removeClass('inactive');
                this.controls.discard.addClass('inactive');
                this.setStatus(gettext('Restored original content...'));
            }
        },
        setStatus: function (msg) {
            var self = this;
            // Append status message
            this.controls.status.fadeIn(500);
            this.controls.status.html(msg);
            // Callback to fade out the message
            setTimeout(function () {
                self.controls.status.fadeOut(500, function () {
                    self.controls.status.html("");
                });
            }, 2000);
        },
        destroy: function () {
            this.undelegateEvents();
            this.remove();
        }
    });

    return ScribbleEditor;
});
<|endoftext|>


<commit_before>/**
 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const file = require('gulp-file');
const fs = require('fs-extra');
const gulp = require('gulp');
const gulpWatch = require('gulp-watch');
const {
  endBuildStep,
  mkdirSync,
  printNobuildHelp,
  toPromise,
} = require('./helpers');
const {buildExtensions, extensions} = require('./extension-helpers');
const {jsifyCssAsync} = require('./jsify-css');
const {maybeUpdatePackages} = require('./update-packages');

/**
 * Entry point for 'gulp css'
 * @return {!Promise}
 */
async function css() {
  maybeUpdatePackages();
  printNobuildHelp();
  return compileCss();
}

const cssEntryPoints = [
  {
    path: 'ampdoc.css',
    outJs: 'ampdoc.css.js',
    outCss: 'v0.css',
  },
  {
    path: 'ampshared.css',
    outJs: 'ampshared.css.js',
    outCss: 'v0.css',
    append: true,
  },
  {
    path: 'video-autoplay.css',
    outJs: 'video-autoplay.css.js',
    outCss: 'video-autoplay-out.css',
  },
];

/**
 * Compile all the css and drop in the build folder
 * @param {boolean} watch
 * @param {boolean=} opt_compileAll
 * @return {!Promise}
 */
function compileCss(watch, opt_compileAll) {
  if (watch) {
    gulpWatch('css/**/*.css', function() {
      compileCss();
    });
  }

  /**
   * Writes CSS to build folder
   *
   * @param {string} css
   * @param {string} jsFilename
   * @param {string} cssFilename
   * @param {boolean} append append CSS to existing file
   * @return {Promise}
   */
  function writeCss(css, jsFilename, cssFilename, append) {
    return toPromise(
      // cssText is hardcoded in AmpCodingConvention.java
      file(jsFilename, 'export const cssText = ' + JSON.stringify(css), {
        src: true,
      })
        .pipe(gulp.dest('build'))
        .on('end', function() {
          mkdirSync('build');
          mkdirSync('build/css');
          if (append) {
            fs.appendFileSync(`build/css/${cssFilename}`, css);
          } else {
            fs.writeFileSync(`build/css/${cssFilename}`, css);
          }
        })
    );
  }

  /**
   * @param {string} path
   * @param {string} outJs
   * @param {string} outCss
   * @param {boolean} append
   */
  function writeCssEntryPoint(path, outJs, outCss, append) {
    return jsifyCssAsync(`css/${path}`).then(css =>
      writeCss(css, outJs, outCss, append)
    );
  }

  const startTime = Date.now();

  // Used by `gulp unit --local_changes` to map CSS files to JS files.
  fs.writeFileSync('EXTENSIONS_CSS_MAP', JSON.stringify(extensions));

  let promise = Promise.resolve();

  cssEntryPoints.forEach(entryPoint => {
    const {path, outJs, outCss, append} = entryPoint;
    promise = promise.then(() =>
      writeCssEntryPoint(path, outJs, outCss, append)
    );
  });

  return promise
    .then(() =>
      buildExtensions({
        compileOnlyCss: true,
        compileAll: opt_compileAll,
      })
    )
    .then(() => {
      endBuildStep('Recompiled all CSS files into', 'build/', startTime);
    });
}

module.exports = {
  css,
  compileCss,
  cssEntryPoints,
};

css.description = 'Recompile css to build directory';
<commit_msg>Add explanatory comment (#22728)<commit_after>/**
 * Copyright 2019 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const file = require('gulp-file');
const fs = require('fs-extra');
const gulp = require('gulp');
const gulpWatch = require('gulp-watch');
const {
  endBuildStep,
  mkdirSync,
  printNobuildHelp,
  toPromise,
} = require('./helpers');
const {buildExtensions, extensions} = require('./extension-helpers');
const {jsifyCssAsync} = require('./jsify-css');
const {maybeUpdatePackages} = require('./update-packages');

/**
 * Entry point for 'gulp css'
 * @return {!Promise}
 */
async function css() {
  maybeUpdatePackages();
  printNobuildHelp();
  return compileCss();
}

const cssEntryPoints = [
  {
    path: 'ampdoc.css',
    outJs: 'ampdoc.css.js',
    outCss: 'v0.css',
  },
  {
    path: 'ampshared.css',
    outJs: 'ampshared.css.js',
    outCss: 'v0.css',
    append: true,
  },
  {
    path: 'video-autoplay.css',
    outJs: 'video-autoplay.css.js',
    // When the .css.js files are imported, the .js extension is omitted
    // e.g. '../../build/file.css' attempts to load 'build/file.css.js'
    // but if a file which matches without the .js extension, it will
    // be preferred. We should rename the out.css to have a different name
    // than the JS file to avoid loading CSS as JS
    outCss: 'video-autoplay-out.css',
  },
];

/**
 * Compile all the css and drop in the build folder
 * @param {boolean} watch
 * @param {boolean=} opt_compileAll
 * @return {!Promise}
 */
function compileCss(watch, opt_compileAll) {
  if (watch) {
    gulpWatch('css/**/*.css', function() {
      compileCss();
    });
  }

  /**
   * Writes CSS to build folder
   *
   * @param {string} css
   * @param {string} jsFilename
   * @param {string} cssFilename
   * @param {boolean} append append CSS to existing file
   * @return {Promise}
   */
  function writeCss(css, jsFilename, cssFilename, append) {
    return toPromise(
      // cssText is hardcoded in AmpCodingConvention.java
      file(jsFilename, 'export const cssText = ' + JSON.stringify(css), {
        src: true,
      })
        .pipe(gulp.dest('build'))
        .on('end', function() {
          mkdirSync('build');
          mkdirSync('build/css');
          if (append) {
            fs.appendFileSync(`build/css/${cssFilename}`, css);
          } else {
            fs.writeFileSync(`build/css/${cssFilename}`, css);
          }
        })
    );
  }

  /**
   * @param {string} path
   * @param {string} outJs
   * @param {string} outCss
   * @param {boolean} append
   */
  function writeCssEntryPoint(path, outJs, outCss, append) {
    return jsifyCssAsync(`css/${path}`).then(css =>
      writeCss(css, outJs, outCss, append)
    );
  }

  const startTime = Date.now();

  // Used by `gulp unit --local_changes` to map CSS files to JS files.
  fs.writeFileSync('EXTENSIONS_CSS_MAP', JSON.stringify(extensions));

  let promise = Promise.resolve();

  cssEntryPoints.forEach(entryPoint => {
    const {path, outJs, outCss, append} = entryPoint;
    promise = promise.then(() =>
      writeCssEntryPoint(path, outJs, outCss, append)
    );
  });

  return promise
    .then(() =>
      buildExtensions({
        compileOnlyCss: true,
        compileAll: opt_compileAll,
      })
    )
    .then(() => {
      endBuildStep('Recompiled all CSS files into', 'build/', startTime);
    });
}

module.exports = {
  css,
  compileCss,
  cssEntryPoints,
};

css.description = 'Recompile css to build directory';
<|endoftext|>


<commit_before>
var Scoreboard = (function () {
    var board = {};

    var table_div_id = null;
    var table = null;
    var table_header = null;
    var hostname = null;

    var ci_results = null;
    var ci_accounts = null;
    var user_filter = null;

    var row_cache = {};

    var spinner = null;
    var overlay = null;
    var opaque_overlay = null;

    var hide_overlay = function () {
        spinner.stop();
        overlay.remove();
        opaque_overlay.remove();
    }

    var show_overlay = function () {
        overlay = $(document.createElement('div'));
        overlay.addClass('overlay_clear');
        overlay.appendTo(document.body);
        opaque_overlay = $(document.createElement('div'));
        opaque_overlay.addClass('overlay_opaque');
        opaque_overlay.appendTo(document.body);
        title = $(document.createElement('div'));
        title.addClass('overlay_title');
        title.html('Building results...');
        title.appendTo(overlay);

        var opts = {
            lines: 20, // The number of lines to draw
            length: 35, // The length of each line
            width: 10, // The line thickness
            radius: 45, // The radius of the inner circle
            corners: 1, // Corner roundness (0..1)
            rotate: 0, // The rotation offset
            direction: 1, // 1: clockwise, -1: counterclockwise
            color: '#000', // #rgb or #rrggbb or array of colors
            speed: 1, // Rounds per second
            trail: 60, // Afterglow percentage
            shadow: true, // Whether to render a shadow
            hwaccel: true, // Whether to use hardware acceleration
            className: 'spinner', // The CSS class to assign to the spinner
            zIndex: 2e9, // The z-index (defaults to 2000000000)
            top: '50%', // Top position relative to parent
            left: '50%' // Left position relative to parent
        };
        spinner = new Spinner(opts).spin();
        $(spinner.el).appendTo(overlay);

    }

    var gather_data_and_build = function () {
        show_overlay();
        $.ajax({
            type: 'get',
            url: 'results',
            data: window.location.search.substring(1),
            success: function(data) {
                ci_results = JSON.parse(data);
                get_ci_accounts()
            }
        });
    };

    var get_ci_accounts = function () {
        $.ajax({
            type: 'get',
            url: 'ci-accounts',
            success: function(data) {
                parse_accounts(data);
                build_table();
            }
        });
    }

    var find_ci_in_list = function (ci, list) {
        for (var i = 0; i < list.length; i++) {
            if (ci == list[i]._id) {
                return list[i];
            }
        }
    }

    var parse_accounts = function (ci_accounts_raw) {
        var all_ci_accounts = JSON.parse(ci_accounts_raw);
        var ci_account_objs = {};
        ci_accounts = [];

        // Filter if there is a user url param
        var user_param = get_param_by_name('user')
        user_filter = []
        if (user_param != '') {
            user_filter = user_param.replace(/\s+/g, '').split(',')
        }

        for (var patchset in ci_results) {
            for (var ci in ci_results[patchset].results) {
                if (user_filter.length > 0 && user_filter.indexOf(ci) == -1) {
                    continue;
                }

                if (!(ci in ci_account_objs)) {
                    ci_account_objs[ci] = true;
                    ci_accounts.push(find_ci_in_list(ci, all_ci_accounts));
                }
            }
        }
    }

    var ci_account_header = function (user_name, user_name_pretty) {
        return user_name_pretty + '
 (' + user_name + ')';
    };

    var create_header = function () {
        td = $(document.createElement('td'));
        td.addClass('pretty_table_header');
        return td;
    };

    var create_filler = function (td) {
        if (!td) td = $(document.createElement('td'));
        td.addClass('no_result');
        td.html('&nbsp');
        return td;
    };

    var add_header = function (header_title) {
        var td = create_header();
        td.html(header_title);
        td.appendTo(table_header);
    };

    var set_result = function(cell, result) {
        var cell_class = null;

        switch (result) {
            case 'SUCCESS':
                cell_class = 'success';
                break;
            case 'FAILURE':
            case 'ERROR':
            case 'NOT_REGISTERED':
            case 'ABORTED':
                cell_class = 'fail';
                break;
            case 'MERGE FAILED':
            case 'UNKNOWN':
            default:
                cell_class = 'unknown';
                break;
        }

        cell.removeClass().addClass(cell_class);
        cell.html(result);
    };

    var add_on_click_url = function(element, url) {
        element.on('click', (function () {
            // closures are weird.. scope the url so each on click is using
            // the right one and not just the last url handled by the loop
            var review_url = url;
            return function () {
                window.open(review_url, '_blank');
            }
        })());
    };

    var handle_patchset = function(patchset) {
        var result_row = null;
        var ci_index = null;
        // console.log(JSON.stringify(result));
        var review_id_patchset = patchset._id;

        // add a new row for the review number + patchset
        result_row = $(document.createElement('tr'));
        result_row.appendTo(table);
        var label = create_header();
        label.html(review_id_patchset);
        label.appendTo(result_row);
        var review_patchset_split = review_id_patchset.split(',');
        var url = "https://review.openstack.org/#/c/" + review_patchset_split[0] + "/" + review_patchset_split[1];
        add_on_click_url(label, url);
        label.prop('title', url);

        for (var i = 0; i < ci_accounts.length; i++) {
            var ci_account = ci_accounts[i];
            var td = $(document.createElement('td'));
            if (ci_account._id in patchset.results) {
                var result = patchset.results[ci_account._id];
                add_on_click_url(td, url)
                td.prop('title', url);
                set_result(td, result);
            }
            else {
                td = create_filler(td);
            }
            td.appendTo(result_row);
        }
    }

    var build_table = function () {
        table = $(document.createElement('table'));
        table.addClass('pretty_table');
        table.attr('cellspacing', 0);
        table_container = $('#' + table_div_id);
        table_container.addClass('scoreboard_container');
        table.appendTo(table_container);

        // build a table header that will (by the time
        // we're done) have row for each ci account name
        table_header = $(document.createElement('tr'));
        create_header().appendTo(table_header); // spacer box
        table_header.appendTo(table);

        for (var i = 0; i < ci_accounts.length; i++) {
            var ci = ci_accounts[i]
            add_header(ci_account_header(ci._id, ci.user_name_pretty));
        }

        // TODO: maybe process some of this in a worker thread?
        // It might be nice if we can build a model and then render it
        // all in one go instead of modifying the DOM so much...
        //
        // For now we will handle a single result at a time (later on
        // we could maybe stream/pull incremental updates so the page
        // is 'live').
        //
        // This will add each result into the table and then yield
        // the main thread so the browser can render, handle events,
        // and generally not lock up and be angry with us. It still
        // takes a while to actually build out the table, but at least
        // it will be more exciting to watch all the results pop up
        // on the screen instead of just blank page.
        var index = 0;
        var num_results = ci_results.length;
        (function handle_patchset_wrapper() {
            if (index < num_results) {
                handle_patchset(ci_results[index]);
                index++;
                window.setTimeout(handle_patchset_wrapper, 0);
            } else {
                hide_overlay();
            }
        })();
    };

    var add_input_to_form = function (form, input_type, label_text, input_name, starting_val) {
        var label = $('').text(label_text + ":");
        var input = $('<input/>').attr({type: input_type, id: input_name, name: input_name});
        input.appendTo(label);
        if (starting_val) {
            input.val(starting_val);
        }
        label.appendTo(form);
        return input;
    }

    var get_param_by_name = function (name) {
        name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
        var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
            results = regex.exec(window.location.search);
        return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
    }

    board.show_query_box = function (host, container) {
        var qb_container = $('#' + container);
        qb_container.addClass('query_box_container');

        // create a div inside the container to hold the form stuff
        qb_div = $(document.createElement('div'));
        qb_div.addClass('query_box');
        qb_div.appendTo(qb_container);

        var title = $(document.createElement('div'));
        title.html('3rd Party CI Scoreboard');
        title.addClass('query_box_title');
        title.appendTo(qb_div);

        var current_project = get_param_by_name('project');
        var current_user = get_param_by_name('user');
        var current_timeframe = get_param_by_name('timeframe');
        var start_date = get_param_by_name('start');
        var end_date = get_param_by_name('end');

        var form = $(document.createElement('form'));

        add_input_to_form(form, 'text', 'Project Name', 'project', current_project);
        add_input_to_form(form, 'text', 'CI Account Username', 'user', current_user);
        add_input_to_form(form, 'text', 'Timeframe (hours)', 'timeframe', current_timeframe);
        add_input_to_form(form, 'date', 'Start Date', 'start', start_date);
        add_input_to_form(form, 'date', 'End Date', 'end', end_date);
        // TODO: Implement the "start" and "count" filters so we can do pagination

        submit_button = $('<input/>', { type:'submit', value:'GO!'});
        submit_button.appendTo(form);
        form.submit(function(){
            location.href = '/' + $(this).serialize();
        });

        form.appendTo(qb_div);
    }

    board.build = function (host, container) {
        hostname = host;
        table_div_id = container;
        gather_data_and_build();
    };

    return board;
})();<commit_msg>Add a score/summary of the search<commit_after>
var Scoreboard = (function () {
    var board = {};

    var table_div_id = null;
    var table = null;
    var table_header = null;
    var hostname = null;

    var ci_results = null;
    var ci_accounts = null;
    var user_filter = null;

    var row_cache = {};

    var spinner = null;
    var overlay = null;
    var opaque_overlay = null;

    var score = {};

    var hide_overlay = function () {
        spinner.stop();
        overlay.remove();
        opaque_overlay.remove();
    }

    var show_overlay = function () {
        overlay = $(document.createElement('div'));
        overlay.addClass('overlay_clear');
        overlay.appendTo(document.body);
        opaque_overlay = $(document.createElement('div'));
        opaque_overlay.addClass('overlay_opaque');
        opaque_overlay.appendTo(document.body);
        title = $(document.createElement('div'));
        title.addClass('overlay_title');
        title.html('Building results...');
        title.appendTo(overlay);

        var opts = {
            lines: 20, // The number of lines to draw
            length: 35, // The length of each line
            width: 10, // The line thickness
            radius: 45, // The radius of the inner circle
            corners: 1, // Corner roundness (0..1)
            rotate: 0, // The rotation offset
            direction: 1, // 1: clockwise, -1: counterclockwise
            color: '#000', // #rgb or #rrggbb or array of colors
            speed: 1, // Rounds per second
            trail: 60, // Afterglow percentage
            shadow: true, // Whether to render a shadow
            hwaccel: true, // Whether to use hardware acceleration
            className: 'spinner', // The CSS class to assign to the spinner
            zIndex: 2e9, // The z-index (defaults to 2000000000)
            top: '50%', // Top position relative to parent
            left: '50%' // Left position relative to parent
        };
        spinner = new Spinner(opts).spin();
        $(spinner.el).appendTo(overlay);

    }

    var gather_data_and_build = function () {
        show_overlay();
        $.ajax({
            type: 'get',
            url: 'results',
            data: window.location.search.substring(1),
            success: function(data) {
                ci_results = JSON.parse(data);
                get_ci_accounts()
            }
        });
    };

    var get_ci_accounts = function () {
        $.ajax({
            type: 'get',
            url: 'ci-accounts',
            success: function(data) {
                parse_accounts(data);
                build_table();
            }
        });
    }

    var find_ci_in_list = function (ci, list) {
        for (var i = 0; i < list.length; i++) {
            if (ci == list[i]._id) {
                return list[i];
            }
        }
    }

    var parse_accounts = function (ci_accounts_raw) {
        var all_ci_accounts = JSON.parse(ci_accounts_raw);
        var ci_account_objs = {};
        ci_accounts = [];

        // Filter if there is a user url param
        var user_param = get_param_by_name('user')
        user_filter = []
        if (user_param != '') {
            user_filter = user_param.replace(/\s+/g, '').split(',')
        }

        for (var patchset in ci_results) {
            for (var ci in ci_results[patchset].results) {
                if (user_filter.length > 0 && user_filter.indexOf(ci) == -1) {
                    continue;
                }

                if (!(ci in ci_account_objs)) {
                    ci_account_objs[ci] = true;
                    ci_accounts.push(find_ci_in_list(ci, all_ci_accounts));
                }
            }
        }
    }

    var ci_account_header = function (user_name, user_name_pretty) {
        return user_name_pretty + '
 (' + user_name + ')';
    };

    var create_header = function () {
        td = $(document.createElement('td'));
        td.addClass('pretty_table_header');
        return td;
    };

    var create_filler = function (td) {
        if (!td) td = $(document.createElement('td'));
        td.addClass('no_result');
        td.html('&nbsp');
        return td;
    };

    var add_header = function (header_title) {
        var td = create_header();
        td.html(header_title);
        td.appendTo(table_header);
    };

    var set_result = function(cell, result, ci_account) {
        var cell_class = null;
        var count = null;

        switch (result) {
            case 'SUCCESS':
                cell_class = 'success';
                break;
            case 'FAILURE':
            case 'ERROR':
            case 'NOT_REGISTERED':
            case 'ABORTED':
                cell_class = 'fail';
                break;
            case 'MERGE FAILED':
            case 'UNKNOWN':
            default:
                cell_class = 'unknown';
                break;
        }

        var result_type = cell_class.toUpperCase();

        if (!score[result_type]) {
            score[result_type] = {}
        }

        score[result_type][ci_account] = score[result_type][ci_account] || 0
        count = score[result_type][ci_account] + 1
        score[result_type][ci_account] = count

        cell.removeClass().addClass(cell_class);
        cell.html(result);
    };

    var add_on_click_url = function(element, url) {
        element.on('click', (function () {
            // closures are weird.. scope the url so each on click is using
            // the right one and not just the last url handled by the loop
            var review_url = url;
            return function () {
                window.open(review_url, '_blank');
            }
        })());
    };

    var handle_patchset = function(patchset) {
        var result_row = null;
        var ci_index = null;
        // console.log(JSON.stringify(result));
        var review_id_patchset = patchset._id;

        // add a new row for the review number + patchset
        result_row = $(document.createElement('tr'));
        result_row.appendTo(table);
        var label = create_header();
        label.html(review_id_patchset);
        label.appendTo(result_row);
        var review_patchset_split = review_id_patchset.split(',');
        var url = "https://review.openstack.org/#/c/" + review_patchset_split[0] + "/" + review_patchset_split[1];
        add_on_click_url(label, url);
        label.prop('title', url);

        for (var i = 0; i < ci_accounts.length; i++) {
            var ci_account = ci_accounts[i];
            var td = $(document.createElement('td'));
            if (ci_account._id in patchset.results) {
                var result = patchset.results[ci_account._id];
                add_on_click_url(td, url)
                td.prop('title', url);
                set_result(td, result, ci_account._id);
            }
            else {
                td = create_filler(td);
            }
            td.appendTo(result_row);
        }
    }

    var build_table = function () {
        table = $(document.createElement('table'));
        table.addClass('pretty_table');
        table.attr('cellspacing', 0);
        table_container = $('#' + table_div_id);
        table_container.addClass('scoreboard_container');
        table.appendTo(table_container);

        // build a table header that will (by the time
        // we're done) have row for each ci account name
        table_header = $(document.createElement('tr'));
        table_header.addClass('table_header');
        create_header().appendTo(table_header); // spacer box
        table_header.appendTo(table);

        for (var i = 0; i < ci_accounts.length; i++) {
            var ci = ci_accounts[i]
            add_header(ci_account_header(ci._id, ci.user_name_pretty));
        }

        // TODO: maybe process some of this in a worker thread?
        // It might be nice if we can build a model and then render it
        // all in one go instead of modifying the DOM so much...
        //
        // For now we will handle a single result at a time (later on
        // we could maybe stream/pull incremental updates so the page
        // is 'live').
        //
        // This will add each result into the table and then yield
        // the main thread so the browser can render, handle events,
        // and generally not lock up and be angry with us. It still
        // takes a while to actually build out the table, but at least
        // it will be more exciting to watch all the results pop up
        // on the screen instead of just blank page.
        var index = 0;
        var num_results = ci_results.length;
        (function handle_patchset_wrapper() {
            if (index < num_results) {
                handle_patchset(ci_results[index]);
                index++;
                window.setTimeout(handle_patchset_wrapper, 0);
            } else {
                build_score();
                hide_overlay();
            }
        })();
    };

    var build_score = function () {
        var score_row = null;
        var label = null;

        var scores = Object.keys(score);

        for (var i = 0; i < scores.length; i++) {
            var result_type = scores[i];
            score_row = $(document.createElement('tr'));

            label = create_header();
            label.html(result_type);
            label.appendTo(score_row);

            for (var j = 0; j < ci_accounts.length; j++) {
                var ci = ci_accounts[j]

                label = create_header();
                label.html(score[result_type][ci._id] || 0);
                label.appendTo(score_row);
            }
            $(score_row).insertAfter($('table tr.table_header'));
        }
    };

    var add_input_to_form = function (form, input_type, label_text, input_name, starting_val) {
        var label = $('').text(label_text + ":");
        var input = $('<input/>').attr({type: input_type, id: input_name, name: input_name});
        input.appendTo(label);
        if (starting_val) {
            input.val(starting_val);
        }
        label.appendTo(form);
        return input;
    }

    var get_param_by_name = function (name) {
        name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
        var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
            results = regex.exec(window.location.search);
        return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
    }

    board.show_query_box = function (host, container) {
        var qb_container = $('#' + container);
        qb_container.addClass('query_box_container');

        // create a div inside the container to hold the form stuff
        qb_div = $(document.createElement('div'));
        qb_div.addClass('query_box');
        qb_div.appendTo(qb_container);

        var title = $(document.createElement('div'));
        title.html('3rd Party CI Scoreboard');
        title.addClass('query_box_title');
        title.appendTo(qb_div);

        var current_project = get_param_by_name('project');
        var current_user = get_param_by_name('user');
        var current_timeframe = get_param_by_name('timeframe');
        var start_date = get_param_by_name('start');
        var end_date = get_param_by_name('end');

        var form = $(document.createElement('form'));

        add_input_to_form(form, 'text', 'Project Name', 'project', current_project);
        add_input_to_form(form, 'text', 'CI Account Username', 'user', current_user);
        add_input_to_form(form, 'text', 'Timeframe (hours)', 'timeframe', current_timeframe);
        add_input_to_form(form, 'date', 'Start Date', 'start', start_date);
        add_input_to_form(form, 'date', 'End Date', 'end', end_date);
        // TODO: Implement the "start" and "count" filters so we can do pagination

        submit_button = $('<input/>', { type:'submit', value:'GO!'});
        submit_button.appendTo(form);
        form.submit(function(){
            location.href = '/' + $(this).serialize();
        });

        form.appendTo(qb_div);
    }

    board.build = function (host, container) {
        hostname = host;
        table_div_id = container;
        gather_data_and_build();
    };

    return board;
})();<|endoftext|>


<commit_before>var expect = require('chai').expect;
var auth0 = require('../src');
var Auth0 = require('../src/Auth0');

var ArgumentError = require('../src/exceptions').ArgumentError;
var domains = require('../src/constants').DOMAINS_BY_REGION;

describe('Auth0 module', function () {

    it('should return an instance of Auth0 when the token is valid', function () {
      var options = { token: 'abcdefg' };
      var client = null;

      try {
        client = auth0(options);

        expect(client).to.be.an('Object');
        expect(client).to.be.an.instanceOf(Auth0);
      } catch (err) {
        done(err);
      }
    });

    it('should not allow providing both domain and region', function () {
      var options = {
        token: 'token',
        domain: domains.eu,
        region: 'eu'
      };
      var client = auth0.bind(null, options);

      expect(client).to.throw(ArgumentError, 'Cannot provide both region and domain');
    });

    it('should error when a wrong region is provided', function () {
      var options = {
        token: 'token',
        region: 'xy'
      };
      var client = auth0.bind(null, options);

      expect(client).to.throw(ArgumentError);
    });

    it('should not error when a valid region is provided', function () {
      var options = {
        token: 'token',
        region: 'eu'
      };
      var client = auth0.bind(null, options);

      expect(client).not.to.throw();
    });

    it('should take US as the default region when none is provided', function () {
      var client = new auth0({ token: 'token' });

      expect(client.region).to.equal('us');
    });

    it('should allow regions to be in uppercase or mixed-case', function () {
      var options = {
        token: 'token',
        region: 'EU'
      };
      var client = auth0.bind(null, options);

      expect(client).not.to.throw();
    });
});
<commit_msg>Improve Auth0 module tests<commit_after>var expect = require('chai').expect;
var auth0 = require('../src');
var Auth0 = require('../src/Auth0');

var ArgumentError = require('../src/exceptions').ArgumentError;
var domains = require('../src/constants').DOMAINS_BY_REGION;

describe('Auth0 module', function () {

    it('should raise an error when no options object is provided', function () {
      expect(auth0).to.throw(ArgumentError, 'Auth0 SDK options must be an object');
    });

    it('should raise an error when the token is not valid', function () {
      var client = auth0.bind(null, { token: '' });

      expect(client).to.throw(ArgumentError, 'An access token must be provided');
    });

    it('should return an instance of Auth0 when the token is valid', function () {
      var options = { token: 'abcdefg' };
      var client = auth0(options);

      expect(client).to.be.an('Object');
      expect(client).to.be.an.instanceOf(Auth0);
    });

    it('should not allow providing both domain and region', function () {
      var options = {
        token: 'token',
        domain: domains.eu,
        region: 'eu'
      };
      var client = auth0.bind(null, options);

      expect(client).to.throw(ArgumentError, 'Cannot provide both region and domain');
    });

    it('should raise an error when a wrong region is provided', function () {
      var options = {
        token: 'token',
        region: 'xy'
      };
      var client = auth0.bind(null, options);

      expect(client).to.throw(ArgumentError);
    });

    it('should not throw errors when a valid region is provided', function () {
      var options = {
        token: 'token',
        region: 'eu'
      };
      var client = auth0.bind(null, options);

      expect(client).not.to.throw();
    });

    it('should take US as the default region when none is provided', function () {
      var client = new auth0({ token: 'token' });

      expect(client.region).to.equal('us');
    });

    it('should allow regions to be in uppercase or mixed-case', function () {
      var options = {
        token: 'token',
        region: 'EU'
      };
      var client = auth0.bind(null, options);

      expect(client).not.to.throw();
    });
});
<|endoftext|>


<commit_before>Package.describe({
  summary: "The dynamic stylesheet language."
});

var less = require('less');
var fs = require('fs');
var path = require('path');
var Future = require(path.join('fibers', 'future'));

Package.register_extension(
  "less", function (bundle, source_path, serve_path, where) {
    serve_path = serve_path + '.css';

    var contents = fs.readFileSync(source_path, 'utf8');

    try {
      var css = Future.wrap(less.render)(contents, {
        paths: [path.resolve(source_path, '..')] // for @import
      }).wait();
      bundle.add_resource({
        type: "css",
        path: serve_path,
        data: new Buffer(css),
        where: where
      });
    } catch (e) {
      bundle.error(source_path + ": Less compiler error: " + e.message);
    }
  }
);

Package.on_test(function (api) {
  api.use('test-helpers');
  api.add_files(['less_tests.less', 'less_tests.js'], 'client');
});
<commit_msg>Switch less back to fully synchronous, now that the NPM module supports it.<commit_after>Package.describe({
  summary: "The dynamic stylesheet language."
});

var less = require('less');
var fs = require('fs');
var path = require('path');

Package.register_extension(
  "less", function (bundle, source_path, serve_path, where) {
    serve_path = serve_path + '.css';

    var contents = fs.readFileSync(source_path, 'utf8');

    try {
      less.render(contents.toString('utf8'), {
        // Use fs.readFileSync to process @imports. This is the bundler, so
        // that's not going to cause concurrency issues, and it means that (a)
        // we don't have to use Futures and (b) errors thrown by bugs in less
        // actually get caught.
        syncImport: true,
        paths: [path.resolve(source_path, '..')] // for @import
      }, function (err, css) {
        if (err) {
          bundle.error(source_path + ": Less compiler error: " + err.message);
          return;
        }

        bundle.add_resource({
          type: "css",
          path: serve_path,
          data: new Buffer(css),
          where: where
        });
      });
    } catch (e) {
      // less.render() is supposed to report any errors via its
      // callback. But sometimes, it throws them instead. This is
      // probably a bug in less. Be prepared for either behavior.
      bundle.error(source_path + ": Less compiler error: " + e.message);
    }
  }
);

Package.on_test(function (api) {
  api.use('test-helpers');
  api.add_files(['less_tests.less', 'less_tests.js'], 'client');
});
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({

  attributeBindings: [],
  type: 'checkbox',

  setup: function () {

    // if this get action, do action when checkbox is clicked.
    // else, assume that it binds to value, and set to change value on change event

    this.$('.ui.checkbox').checkbox({
      onChange: Ember.run.bind(this, this.onChange)
    });

  }.on('didInsertElement'),

  onChange: function () {
    var value;

    if (this.type === 'radio') {
      var radioGroup = document.getElementsByName(this.get('name'));
      for (var i = 0; i < radioGroup.length; i++) {
        if (radioGroup[i].checked) {
          value = radioGroup[i].id;
        }
      }
    }

    if (this.get('action')) {
      this.sendAction('action', value);

    } else {
      this.set('value', value);
    }

  }

});
<commit_msg>More flexible ui-checkbox - will need some testing<commit_after>import Ember from 'ember';

export default Ember.Component.extend({

  attributeBindings: [],
  type: 'checkbox',

  typeof_checked: function () {
    var checked = this.get('attrs.checked');

    if (checked && checked.value) {

      if (checked.value instanceof Array) {
        return 'array';

      } else if (checked.value instanceof Object) {
        // TODO: Support for objects not implemented
        return 'object';

      } else if (typeof checked.value === 'boolean') {
        return 'boolean';

      } else if (checked.value instanceof String) {
        return 'string';

      } else {
        console.warn('Could not find checked typeof');
      }
    }

  }.property('checked'),

  should_be_checked: function () {
    var value = this.get('value');
    var checked = this.get('checked');
    var typeofChecked = this.get('typeof_checked');
    var shouldBeChecked;

    switch (typeofChecked) {
      case 'array':
        shouldBeChecked = (checked.indexOf(value) > -1);
        break;

      case 'object':
        // TODO: Not implemented
        console.error('Not implemented.');
        return;

      case 'boolean':
        shouldBeChecked = !!checked;
        break;

      case 'string':
        shouldBeChecked = (checked === value);
        break;

      default:
        break;
    }
    console.log('should_be_checked:' + shouldBeChecked);
    return shouldBeChecked;

  }.property('checked'),

  setup: function () {

    // if this get action, do action when checkbox is clicked.
    // else, assume that it binds to value, and set to change value on change event

    this.$('.ui.checkbox').checkbox({
      onChange: Ember.run.bind(this, this.onChange)
    });

    if (this.get('should_be_checked')) {
      this.$('.ui.checkbox').checkbox('check');
    }

  }.on('didInsertElement'),

  updateUi: function () {
    console.log('updateUi:start');
    var operation = this.get('should_be_checked') ? 'check' : 'uncheck';
    console.log('updateUi:' + operation);
    this.$('.ui.checkbox').checkbox(operation);

  }.observes('should_be_checked'),

  setChecked: function () {
    var value = this.get('value');
    var checked = this.$('.ui.checkbox').checkbox('is checked');

    if (!this.get('attrs.checked')) {
      return;
    }

    if (this.get('attrs.checked').value instanceof Array) {
      if (checked) {
        this.get('checked').addObject(value);

      } else {
        this.get('checked').removeObject(value);
      }

    } else if (this.get('attrs.checked').value instanceof Object) {
      // Not implemented

    } else if (this.get('attrs.checked').value instanceof Boolean) {
      if (checked) {
        this.set('checked', true);

      } else {
        this.set('checked', false);
      }

    } else if (this.get('attrs.checked').value instanceof String) {
      if (checked) {
        this.set('checked', value);

      } else {
        this.set('checked', '');
      }

    } else {
        this.set('checked', value || checked);
    }

  },

  onChange: function () {
    var name = this.get('name');
    var value = this.get('value');
    var checked = this.$('.ui.checkbox').checkbox('is checked');
    var operation;

    if (this.type === 'radio') {
      var radioGroup = document.getElementsByName(this.get('name'));
      for (var i = 0; i < radioGroup.length; i++) {
        if (radioGroup[i].checked) {
          value = radioGroup[i].id;
        }
      }
    }

    console.log('doing som work');

    if (this.get('attrs.action')) {
      this.sendAction('action', value);

    } else if (1 === 2) {

    } else {
      this.setChecked();
    }

  }

});
<|endoftext|>


<commit_before>import getOffset from 'dom-helpers/query/offset';
import requestAnimationFrame from 'dom-helpers/util/requestAnimationFrame';
import React from 'react';
import mountable from 'react-prop-types/lib/mountable';

import Affix from './Affix';
import addEventListener from './utils/addEventListener';
import getContainer from './utils/getContainer';
import getDocumentHeight from './utils/getDocumentHeight';
import ownerDocument from './utils/ownerDocument';
import ownerWindow from './utils/ownerWindow';

/**
 * The `<AutoAffix/>` component wraps `<Affix/>` to automatically calculate
 * offsets in many common cases.
 */
class AutoAffix extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      offsetTop: null,
      offsetBottom: null,
      width: null
    };
  }

  componentDidMount() {
    this._isMounted = true;

    this._windowScrollListener = addEventListener(
      ownerWindow(this), 'scroll', () => this.onWindowScroll()
    );
    this._documentClickListener = addEventListener(
      ownerDocument(this), 'click', () => this.onDocumentClick()
    );

    this.onUpdate();
  }

  componentWillReceiveProps() {
    this._needPositionUpdate = true;
  }

  componentDidUpdate() {
    if (this._needPositionUpdate) {
      this._needPositionUpdate = false;
      this.onUpdate();
    }
  }

  componentWillUnmount() {
    this._isMounted = false;

    if (this._windowScrollListener) {
      this._windowScrollListener.remove();
    }
    if (this._documentClickListener) {
      this._documentClickListener.remove();
    }
  }

  onWindowScroll() {
    this.onUpdate();
  }

  onDocumentClick() {
    requestAnimationFrame(() => this.onUpdate());
  }

  onUpdate() {
    if (!this._isMounted) {
      return;
    }

    const {top: offsetTop, width} = getOffset(this.refs.positioner);

    const container = getContainer(this.props.container);
    let offsetBottom;
    if (container) {
      const documentHeight = getDocumentHeight(ownerDocument(this));
      const {top, height} = getOffset(container);
      offsetBottom = documentHeight - top - height;
    } else {
      offsetBottom = null;
    }

    this.updateState(offsetTop, offsetBottom, width);
  }

  updateState(offsetTop, offsetBottom, width) {
    if (
      offsetTop === this.state.offsetTop &&
      offsetBottom === this.state.offsetBottom &&
      width === this.state.width
    ) {
      return;
    }

    this.setState({offsetTop, offsetBottom, width});
  }

  render() {
    const {container, autoWidth, viewportOffsetTop, children, ...props} =
      this.props;
    const {offsetTop, offsetBottom, width} = this.state;

    const effectiveOffsetTop = Math.max(offsetTop, viewportOffsetTop || 0);

    let {affixStyle, bottomStyle} = this.props;
    if (autoWidth) {
      affixStyle = {width, ...affixStyle};
      bottomStyle = {width, ...bottomStyle};
    }

    return (

        <Affix
          offsetTop={effectiveOffsetTop}
          viewportOffsetTop={viewportOffsetTop}
          offsetBottom={offsetBottom}
          affixStyle={affixStyle}
          bottomStyle={bottomStyle}
          {...props}
        >
          {children}
        </Affix>

    );
  }
}

AutoAffix.propTypes = {
  ...Affix.propTypes,
  /**
   * The logical container node or component for determining offset from bottom
   * of viewport, or a function that returns it
   */
  container: React.PropTypes.oneOfType([
    mountable,
    React.PropTypes.func
  ]),
  /**
   * Automatically set width when affixed
   */
  autoWidth: React.PropTypes.bool
};

// This intentionally doesn't inherit default props from `<Affix>`, so that the
// auto-calculated offsets can apply.
AutoAffix.defaultProps = {
  autoWidth: true
};

export default AutoAffix;
<commit_msg>[changed] Friendlier default for AutoAffix<commit_after>import getOffset from 'dom-helpers/query/offset';
import requestAnimationFrame from 'dom-helpers/util/requestAnimationFrame';
import React from 'react';
import mountable from 'react-prop-types/lib/mountable';

import Affix from './Affix';
import addEventListener from './utils/addEventListener';
import getContainer from './utils/getContainer';
import getDocumentHeight from './utils/getDocumentHeight';
import ownerDocument from './utils/ownerDocument';
import ownerWindow from './utils/ownerWindow';

/**
 * The `<AutoAffix/>` component wraps `<Affix/>` to automatically calculate
 * offsets in many common cases.
 */
class AutoAffix extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      offsetTop: null,
      offsetBottom: null,
      width: null
    };
  }

  componentDidMount() {
    this._isMounted = true;

    this._windowScrollListener = addEventListener(
      ownerWindow(this), 'scroll', () => this.onWindowScroll()
    );
    this._documentClickListener = addEventListener(
      ownerDocument(this), 'click', () => this.onDocumentClick()
    );

    this.onUpdate();
  }

  componentWillReceiveProps() {
    this._needPositionUpdate = true;
  }

  componentDidUpdate() {
    if (this._needPositionUpdate) {
      this._needPositionUpdate = false;
      this.onUpdate();
    }
  }

  componentWillUnmount() {
    this._isMounted = false;

    if (this._windowScrollListener) {
      this._windowScrollListener.remove();
    }
    if (this._documentClickListener) {
      this._documentClickListener.remove();
    }
  }

  onWindowScroll() {
    this.onUpdate();
  }

  onDocumentClick() {
    requestAnimationFrame(() => this.onUpdate());
  }

  onUpdate() {
    if (!this._isMounted) {
      return;
    }

    const {top: offsetTop, width} = getOffset(this.refs.positioner);

    const container = getContainer(this.props.container);
    let offsetBottom;
    if (container) {
      const documentHeight = getDocumentHeight(ownerDocument(this));
      const {top, height} = getOffset(container);
      offsetBottom = documentHeight - top - height;
    } else {
      offsetBottom = null;
    }

    this.updateState(offsetTop, offsetBottom, width);
  }

  updateState(offsetTop, offsetBottom, width) {
    if (
      offsetTop === this.state.offsetTop &&
      offsetBottom === this.state.offsetBottom &&
      width === this.state.width
    ) {
      return;
    }

    this.setState({offsetTop, offsetBottom, width});
  }

  render() {
    const {container, autoWidth, viewportOffsetTop, children, ...props} =
      this.props;
    const {offsetTop, offsetBottom, width} = this.state;

    const effectiveOffsetTop = Math.max(offsetTop, viewportOffsetTop || 0);

    let {affixStyle, bottomStyle} = this.props;
    if (autoWidth) {
      affixStyle = {width, ...affixStyle};
      bottomStyle = {width, ...bottomStyle};
    }

    return (

        <Affix
          offsetTop={effectiveOffsetTop}
          viewportOffsetTop={viewportOffsetTop}
          offsetBottom={offsetBottom}
          affixStyle={affixStyle}
          bottomStyle={bottomStyle}
          {...props}
        >
          {children}
        </Affix>

    );
  }
}

AutoAffix.propTypes = {
  ...Affix.propTypes,
  /**
   * The logical container node or component for determining offset from bottom
   * of viewport, or a function that returns it
   */
  container: React.PropTypes.oneOfType([
    mountable,
    React.PropTypes.func
  ]),
  /**
   * Automatically set width when affixed
   */
  autoWidth: React.PropTypes.bool
};

// This intentionally doesn't inherit default props from `<Affix>`, so that the
// auto-calculated offsets can apply.
AutoAffix.defaultProps = {
  viewportOffsetTop: 0,
  autoWidth: true
};

export default AutoAffix;
<|endoftext|>