<commit_before>/*globals vmxApi:true,  spyOn: true, beforeEach: true, it: true, describe: true, expect:true*/

describe("vmxApi", function() {
  'use strict';
  var hand_dets_neg,face_dets_neg;
  var hand_dets_pos,face_dets_pos;
  var face_params_neg,hand_params_neg;
  var face_params_pos,hand_params_pos;
  var empty_params;
  var default_config;
  var DefaultConfig;
  beforeEach(function() {
    //Before eachtest, we set up some useful face_params.
    vmxApi.reset();
    hand_dets_pos = [
      {
        bb: {
          0: 391.48,
          1: 542.64,
          2: 612.87,
          3: 627.4,
        },
        cls: "hand",
        image: "data:image/jpeg;base64,/9j/4AAQSk",
        score: 1,
      }
    ];

    face_dets_pos = [
      {
        bb: {
          0: 391.48,
          1: 542.64,
          2: 612.87,
          3: 627.4,
        },
        cls: "face",
        image: "data:image/jpeg;base64,/9j/4AAQSk",
        score: 1,
      }
    ];
    hand_dets_neg = [
      {
        bb: {
          0: 391.48,
          1: 542.64,
          2: 612.87,
          3: 627.4,
        },
        cls: "hand",
        image: "data:image/jpeg;base64,/9j/4AAQSk",
        score: -0.994451,
      }
    ];

    face_dets_neg = [
      {
        bb: {
          0: 391.48,
          1: 542.64,
          2: 612.87,
          3: 627.4,
        },
        cls: "face",
        image: "data:image/jpeg;base64,/9j/4AAQSk",
        score: -0.994451,
      }
    ];

    face_params_neg ={
      detections: face_dets_neg,
      connectionId: 'foo',
    };

    hand_params_neg ={
      detections: hand_dets_neg,
      connectionId: 'bar',
    };
    face_params_pos ={
      detections: face_dets_pos,
      connectionId: 'foo',
    };

    hand_params_pos ={
      detections: hand_dets_pos,
      connectionId: 'bar',
    };

    empty_params = {};
    DefaultConfig = function(){
     return {
       minScore : 0.01,
       minTime : 1000*60*5, //5 minutes;
     };
    };
    default_config = new DefaultConfig();
  });

  it("should not reject tautologies", function() {
    expect(3).toEqual(3);
  });

  it("should accept detections from the server", function(){
    expect(vmxApi.processServerResponse(face_params_pos)).toBeTruthy();
  });

  it("should not allow any params to everDetected()", function(){
    var err = {name:"Too many parameters", message: "This functin takes no params!"};
    expect(function(){vmxApi('face').everDetected("anything");}).toThrow(err);
  });

  it("should not find any detections if nothing's been processed", function(){
    expect(vmxApi('face').everDetected()).toBe(false);
  });

  it("should find detections it has processed", function(){
    vmxApi.processServerResponse(face_params_pos);
    expect(vmxApi('face')).toBeTruthy();
  });

  it("should be able to fully reset itself", function(){
    //This test should probably be more robust
    vmxApi.processServerResponse(face_params_pos);
    expect(vmxApi('face')).toBeTruthy();
    vmxApi.reset();
    expect(vmxApi('face').everDetected()).toBe(false);
    expect(vmxApi('face').everDetected()).toBe(false);
  });

  it("should know if it's ever seen a model", function(){
    vmxApi.processServerResponse(face_params_pos);
    expect(vmxApi('face')).toBeTruthy();
    expect(vmxApi('face').everDetected()).toBe(true);
  });

  describe("onEnter", function() {
    it("should fire when it sees a detection with minimum score", function(){
      var toBeSpied = {
        callback                : function(){},
        callback_sanity_checker : function(){},
      };

      spyOn(toBeSpied,'callback');
      spyOn(toBeSpied,'callback_sanity_checker');

      vmxApi('hand').onEnter(toBeSpied.callback, empty_params, default_config);

      vmxApi.processServerResponse(hand_params_pos);

      expect(toBeSpied.callback)
            .toHaveBeenCalled();

      expect(toBeSpied.callback_sanity_checker)
            .not.toHaveBeenCalled();
    });
    it("should should handle time thresholds correctly", function(){
      var toBeSpied = {
        callback                : function(){},
        callback_sanity_checker : function(){},
      };

      var now = (new Date()).getTime();
      var fakeTime = now;
      spyOn(Date.prototype,'getTime').andCallFake(function(){
        return fakeTime;
      });

      spyOn(toBeSpied,'callback');
      spyOn(toBeSpied,'callback_sanity_checker');

      vmxApi('hand').onEnter(toBeSpied.callback, empty_params, default_config);

      expect(toBeSpied.callback)
            .not.toHaveBeenCalled();

      vmxApi.processServerResponse(hand_params_pos);
      expect(toBeSpied.callback)
            .toHaveBeenCalled();
      expect(toBeSpied.callback.callCount).toBe(1);

      fakeTime += 1000;
      vmxApi.processServerResponse(hand_params_pos);
      expect(toBeSpied.callback.callCount).toBe(1);
      // Lets make a hundred fake positives 1second apart
      for(var y = 0; y<100; ++y){
        fakeTime += 1000;
        vmxApi.processServerResponse(hand_params_pos);
        expect(toBeSpied.callback.callCount).toBe(1);
      }

      // Lets make a hundred fake positives 10 minutes apart
      for(var x = 2; x<100; ++x){
        fakeTime += 1000 * 60 * 10;
        vmxApi.processServerResponse(hand_params_pos);
        expect(toBeSpied.callback.callCount).toBe(x);
      }

    });
  });

  describe("onLeave", function() {
    it("should onLeave function when something leaves", function(){
      var toBeSpied = {
        callback  : function(){},
      };
      spyOn(toBeSpied,'callback');

      var config = new DefaultConfig();
      //Something has to be gone for ten minutes
      config.minTime = 1000 * 60 * 10;
      config.minScore = 0;

      var now = (new Date()).getTime();
      var fakeTime = now;
      spyOn(Date.prototype,'getTime').andCallFake(function(){
        return fakeTime;
      });

      vmxApi('hand').onLeave(toBeSpied.callback, empty_params, config);
      // Send server a positive so the leave function can fire
      vmxApi.processServerResponse(hand_params_pos);
      expect(toBeSpied.callback)
            .not.toHaveBeenCalled();

      // bumptime by a minute
      fakeTime += 1000 * 60;

      // Send it a negative
      vmxApi.processServerResponse(hand_params_neg);
      expect(toBeSpied.callback)
            .not.toHaveBeenCalled();

      // wait another ten minutes
      fakeTime += 1000 * 60 * 10;

      // send another negative
      vmxApi.processServerResponse(hand_params_neg);
      expect(toBeSpied.callback)
            .toHaveBeenCalled();

    });
  });

});
<commit_msg>removing trailing commas<commit_after>/*globals vmxApi:true,  spyOn: true, beforeEach: true, it: true, describe: true, expect:true*/

describe("vmxApi", function() {
  'use strict';
  var hand_dets_neg,face_dets_neg;
  var hand_dets_pos,face_dets_pos;
  var face_params_neg,hand_params_neg;
  var face_params_pos,hand_params_pos;
  var empty_params;
  var default_config;
  var DefaultConfig;
  beforeEach(function() {
    //Before eachtest, we set up some useful face_params.
    vmxApi.reset();
    hand_dets_pos = [
      {
        bb: {
          0: 391.48,
          1: 542.64,
          2: 612.87,
          3: 627.4
        },
        cls: "hand",
        image: "data:image/jpeg;base64,/9j/4AAQSk",
        score: 1
      }
    ];

    face_dets_pos = [
      {
        bb: {
          0: 391.48,
          1: 542.64,
          2: 612.87,
          3: 627.4
        },
        cls: "face",
        image: "data:image/jpeg;base64,/9j/4AAQSk",
        score: 1
      }
    ];
    hand_dets_neg = [
      {
        bb: {
          0: 391.48,
          1: 542.64,
          2: 612.87,
          3: 627.4
        },
        cls: "hand",
        image: "data:image/jpeg;base64,/9j/4AAQSk",
        score: -0.994451
      }
    ];

    face_dets_neg = [
      {
        bb: {
          0: 391.48,
          1: 542.64,
          2: 612.87,
          3: 627.4
        },
        cls: "face",
        image: "data:image/jpeg;base64,/9j/4AAQSk",
        score: -0.994451
      }
    ];

    face_params_neg ={
      detections: face_dets_neg,
      connectionId: 'foo'
    };

    hand_params_neg ={
      detections: hand_dets_neg,
      connectionId: 'bar'
    };
    face_params_pos ={
      detections: face_dets_pos,
      connectionId: 'foo'
    };

    hand_params_pos ={
      detections: hand_dets_pos,
      connectionId: 'bar'
    };

    empty_params = {};
    DefaultConfig = function(){
     return {
       minScore : 0.01,
       minTime : 1000*60*5 //5 minutes;
     };
    };
    default_config = new DefaultConfig();
  });

  it("should not reject tautologies", function() {
    expect(3).toEqual(3);
  });

  it("should accept detections from the server", function(){
    expect(vmxApi.processServerResponse(face_params_pos)).toBeTruthy();
  });

  it("should not allow any params to everDetected()", function(){
    var err = {name:"Too many parameters", message: "This functin takes no params!"};
    expect(function(){vmxApi('face').everDetected("anything");}).toThrow(err);
  });

  it("should not find any detections if nothing's been processed", function(){
    expect(vmxApi('face').everDetected()).toBe(false);
  });

  it("should find detections it has processed", function(){
    vmxApi.processServerResponse(face_params_pos);
    expect(vmxApi('face')).toBeTruthy();
  });

  it("should be able to fully reset itself", function(){
    //This test should probably be more robust
    vmxApi.processServerResponse(face_params_pos);
    expect(vmxApi('face')).toBeTruthy();
    vmxApi.reset();
    expect(vmxApi('face').everDetected()).toBe(false);
    expect(vmxApi('face').everDetected()).toBe(false);
  });

  it("should know if it's ever seen a model", function(){
    vmxApi.processServerResponse(face_params_pos);
    expect(vmxApi('face')).toBeTruthy();
    expect(vmxApi('face').everDetected()).toBe(true);
  });

  describe("onEnter", function() {
    it("should fire when it sees a detection with minimum score", function(){
      var toBeSpied = {
        callback                : function(){},
        callback_sanity_checker : function(){}
      };

      spyOn(toBeSpied,'callback');
      spyOn(toBeSpied,'callback_sanity_checker');

      vmxApi('hand').onEnter(toBeSpied.callback, empty_params, default_config);

      vmxApi.processServerResponse(hand_params_pos);

      expect(toBeSpied.callback)
            .toHaveBeenCalled();

      expect(toBeSpied.callback_sanity_checker)
            .not.toHaveBeenCalled();
    });
    it("should should handle time thresholds correctly", function(){
      var toBeSpied = {
        callback                : function(){},
        callback_sanity_checker : function(){}
      };

      var now = (new Date()).getTime();
      var fakeTime = now;
      spyOn(Date.prototype,'getTime').andCallFake(function(){
        return fakeTime;
      });

      spyOn(toBeSpied,'callback');
      spyOn(toBeSpied,'callback_sanity_checker');

      vmxApi('hand').onEnter(toBeSpied.callback, empty_params, default_config);

      expect(toBeSpied.callback)
            .not.toHaveBeenCalled();

      vmxApi.processServerResponse(hand_params_pos);
      expect(toBeSpied.callback)
            .toHaveBeenCalled();
      expect(toBeSpied.callback.callCount).toBe(1);

      fakeTime += 1000;
      vmxApi.processServerResponse(hand_params_pos);
      expect(toBeSpied.callback.callCount).toBe(1);
      // Lets make a hundred fake positives 1second apart
      for(var y = 0; y<100; ++y){
        fakeTime += 1000;
        vmxApi.processServerResponse(hand_params_pos);
        expect(toBeSpied.callback.callCount).toBe(1);
      }

      // Lets make a hundred fake positives 10 minutes apart
      for(var x = 2; x<100; ++x){
        fakeTime += 1000 * 60 * 10;
        vmxApi.processServerResponse(hand_params_pos);
        expect(toBeSpied.callback.callCount).toBe(x);
      }

    });
  });

  describe("onLeave", function() {
    it("should onLeave function when something leaves", function(){
      var toBeSpied = {
        callback  : function(){}
      };
      spyOn(toBeSpied,'callback');

      var config = new DefaultConfig();
      //Something has to be gone for ten minutes
      config.minTime = 1000 * 60 * 10;
      config.minScore = 0;

      var now = (new Date()).getTime();
      var fakeTime = now;
      spyOn(Date.prototype,'getTime').andCallFake(function(){
        return fakeTime;
      });

      vmxApi('hand').onLeave(toBeSpied.callback, empty_params, config);
      // Send server a positive so the leave function can fire
      vmxApi.processServerResponse(hand_params_pos);
      expect(toBeSpied.callback)
            .not.toHaveBeenCalled();

      // bumptime by a minute
      fakeTime += 1000 * 60;

      // Send it a negative
      vmxApi.processServerResponse(hand_params_neg);
      expect(toBeSpied.callback)
            .not.toHaveBeenCalled();

      // wait another ten minutes
      fakeTime += 1000 * 60 * 10;

      // send another negative
      vmxApi.processServerResponse(hand_params_neg);
      expect(toBeSpied.callback)
            .toHaveBeenCalled();

    });
  });

});
<|endoftext|>


<commit_before>({
    block : 'page',
    title : 'Showcase',
    mods : { theme : 'islands' },
    head : [
        {
            elem : 'conditional-comment',
            condition : '> IE 8',
            msieOnly : false,
            content : { elem : 'css', url : '_showcase.css' }
        },
        {
            elem : 'conditional-comment',
            condition : '<= IE 8',
            content : { elem : 'css', url : '_showcase.ie.css' }
        }
    ],
    scripts : [{ elem : 'js', url : '_showcase.js' }],
    content : [
        {
            block : 'table',
            content : [
                {
                    elem : 'row',
                    content : [
                        {
                            elem : 'cell',
                            content : {
                                block : 'button',
                                mods : { theme : 'islands', size : 's' },
                                text : 'size S'
                            }
                        },
                        {
                            elem : 'cell',
                            content : {
                                block : 'checkbox-group',
                                name : 'islands',
                                mods : { theme : 'islands', size : 'l' },
                                val : [ 2, 4 ],
                                options : [
                                    { val : 1, text : 'Small' },
                                    { val : 2, text : 'Normal' },
                                    { val : 3, text : 'Big', disabled : true },
                                    { val : 4, text : 'Beautiful', disabled : true }
                                ]
                            }
                        },
                        {
                            elem : 'cell',
                            content : [
                                {
                                    block : 'input',
                                    mods : { theme : 'islands', 'has-clear' : true, size : 'l' },
                                    val : 'Find images',
                                    placeholder : 'type a question'
                                },
                                {
                                    block : 'menu',
                                    mods : { mode : 'radio', theme : 'islands', size : 'l', custom : true },
                                    val : 3,
                                    content : [
                                        {
                                            block : 'menu-item',
                                            val : 1,
                                            content : 'Show on the site'
                                        },
                                        {
                                            block : 'menu-item',
                                            val : 2,
                                            content : 'Cached version'
                                        },
                                        {
                                            block : 'menu-item',
                                            val : 3,
                                            content : 'Search in your pocket'
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            elem : 'cell',
                            content : {
                                block : 'select',
                                mods : { mode : 'check', theme : 'islands', size : 'l' },
                                name : 'select',
                                text : 'Language',
                                options : [
                                    { val : 1, text : 'Русский' },
                                    { val : 2, text : 'English' },
                                    { val : 3, text : 'Deutsch' },
                                    { val : 4, text : 'Português' },
                                    { val : 5, text : '中國' }
                                ]
                            }
                        }
                    ]
                },
                {
                    elem : 'row',
                    content : [
                        {
                            elem : 'cell',
                            content : {
                                block : 'button',
                                mods : { theme : 'islands', size : 'm', view : 'action' },
                                text : 'Action'
                            }
                        },
                        {
                            elem : 'cell',
                            content : [
                                {
                                    block : 'radio-group',
                                    name : 'islands-radios-1',
                                    mods : { theme : 'islands', size : 'l' },
                                    val : 2,
                                    options : [
                                        { val : 1, text : 'Radio is off' },
                                        { val : 2, text : 'Radio is on' }
                                    ]
                                },
                                { tag : 'br' },
                                {
                                    block : 'radio-group',
                                    name : 'islands-radios-2',
                                    mods : { theme : 'islands', size : 'l' },
                                    val : 2,
                                    options : [
                                        { val : 1, text : 'No, you can\'t', disabled : true },
                                        { val : 2, text : 'You have no choice', disabled : true }
                                    ]
                                }
                            ]
                        },
                        {
                            block: 'test2',
                            js: true
                        },
                        {
                            elem : 'cell',
                            content : [
                                {
                                    block : 'radio-group',
                                    name : 'islands-button',
                                    mods : { theme : 'islands', size : 'l', type : 'button' },
                                    val : 2,
                                    options : [
                                        { val : 1, text : 'Black & white' },
                                        { val : 2, text : 'Colored' },
                                        { val : 3, text : 'Any colors' }
                                    ]
                                },
                                {
                                    block : 'spin-container',
                                    content : ['s', 'm', 'l', 'xl'].map(function(size) {
                                        return {
                                            block : 'spin',
                                            mods : { theme : 'islands', size : size, visible : true }
                                        };
                                    })
                                },
                                {
                                    block: 'progressbar-example',
                                    js: true,
                                    content: [{
                                        block : 'button',
                                        mods : {
                                            theme : 'islands',
                                            size : 's',
                                            togglable : 'check',
                                            checked : true
                                        },
                                        text : 'Pause'
                                    },
                                    {
                                        block : 'progressbar',
                                        mods : { theme : 'islands' },
                                        val : 25
                                    }]
                                }
                            ]
                        },
                        {
                            elem : 'cell',
                            content : {
                                block : 'select',
                                mods : { mode : 'radio-check', theme : 'islands', size : 'l' },
                                name : 'select-radio',
                                text : 'Your mood',
                                options : [
                                    { val : 1, text : 'Bed' },
                                    { val : 2, text : 'Normal' },
                                    { val : 3, text : 'Great!' }
                                ]
                            }
                        }
                    ]
                },
                {
                    elem : 'row',
                    content : [
                        {
                            elem : 'cell',
                            content : {
                                block : 'button',
                                mods : { theme : 'islands', size : 'l', togglable : 'check' },
                                text : 'Togglable'
                            }

                        },
                        {
                            elem : 'cell',
                            content : [
                                {
                                    block : 'attach',
                                    mods : { theme : 'islands', size : 'l' },
                                    button : {
                                        block : 'button',
                                        mods : { theme : 'islands', size : 'l' },
                                        icon : { block : 'icon', mods : { action : 'download' } },
                                        text : 'Load image'
                                    },
                                    noFileText : 'file is not selected'
                                }
                            ]
                        },
                        {
                            elem : 'cell',
                            content : {
                                block : 'textarea',
                                mods : { theme : 'islands', size : 'l' },
                                val : 'Write a review',
                                placeholder : 'nothing to say'
                            }
                        },
                        {
                            elem : 'cell',
                            content : {
                                block : 'test',
                                js : true,
                                content : [
                                    {
                                        block : 'link',
                                        mods : { theme : 'islands', size : 'l', pseudo : true },
                                        content : 'Open your mind'
                                    },
                                    {
                                        block : 'modal',
                                        mods : { theme : 'islands', autoclosable : true },
                                        content : [
                                            {
                                                block : 'text',
                                                content : 'Your mind was opened!'
                                            },
                                            '(Click outside the box to close)'
                                        ]
                                    }
                                ]
                            }
                        }
                    ]
                }
            ]
        }
    ]
})
<commit_msg>Fix typos in showcase<commit_after>({
    block : 'page',
    title : 'Showcase',
    mods : { theme : 'islands' },
    head : [
        {
            elem : 'conditional-comment',
            condition : '> IE 8',
            msieOnly : false,
            content : { elem : 'css', url : '_showcase.css' }
        },
        {
            elem : 'conditional-comment',
            condition : '<= IE 8',
            content : { elem : 'css', url : '_showcase.ie.css' }
        }
    ],
    scripts : [{ elem : 'js', url : '_showcase.js' }],
    content : [
        {
            block : 'table',
            content : [
                {
                    elem : 'row',
                    content : [
                        {
                            elem : 'cell',
                            content : {
                                block : 'button',
                                mods : { theme : 'islands', size : 's' },
                                text : 'size S'
                            }
                        },
                        {
                            elem : 'cell',
                            content : {
                                block : 'checkbox-group',
                                name : 'islands',
                                mods : { theme : 'islands', size : 'l' },
                                val : [ 2, 4 ],
                                options : [
                                    { val : 1, text : 'Small' },
                                    { val : 2, text : 'Normal' },
                                    { val : 3, text : 'Big', disabled : true },
                                    { val : 4, text : 'Beautiful', disabled : true }
                                ]
                            }
                        },
                        {
                            elem : 'cell',
                            content : [
                                {
                                    block : 'input',
                                    mods : { theme : 'islands', 'has-clear' : true, size : 'l' },
                                    val : 'Find images',
                                    placeholder : 'type a question'
                                },
                                {
                                    block : 'menu',
                                    mods : { mode : 'radio', theme : 'islands', size : 'l', custom : true },
                                    val : 3,
                                    content : [
                                        {
                                            block : 'menu-item',
                                            val : 1,
                                            content : 'Show on the site'
                                        },
                                        {
                                            block : 'menu-item',
                                            val : 2,
                                            content : 'Cached version'
                                        },
                                        {
                                            block : 'menu-item',
                                            val : 3,
                                            content : 'Search in your pocket'
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            elem : 'cell',
                            content : {
                                block : 'select',
                                mods : { mode : 'check', theme : 'islands', size : 'l' },
                                name : 'select',
                                text : 'Language',
                                options : [
                                    { val : 1, text : 'Русский' },
                                    { val : 2, text : 'English' },
                                    { val : 3, text : 'Deutsch' },
                                    { val : 4, text : 'Português' },
                                    { val : 5, text : '中國' }
                                ]
                            }
                        }
                    ]
                },
                {
                    elem : 'row',
                    content : [
                        {
                            elem : 'cell',
                            content : {
                                block : 'button',
                                mods : { theme : 'islands', size : 'm', view : 'action' },
                                text : 'Action'
                            }
                        },
                        {
                            elem : 'cell',
                            content : [
                                {
                                    block : 'radio-group',
                                    name : 'islands-radios-1',
                                    mods : { theme : 'islands', size : 'l' },
                                    val : 2,
                                    options : [
                                        { val : 1, text : 'Radio is off' },
                                        { val : 2, text : 'Radio is on' }
                                    ]
                                },
                                { tag : 'br' },
                                {
                                    block : 'radio-group',
                                    name : 'islands-radios-2',
                                    mods : { theme : 'islands', size : 'l' },
                                    val : 2,
                                    options : [
                                        { val : 1, text : 'No, you can\'t', disabled : true },
                                        { val : 2, text : 'You have no choice', disabled : true }
                                    ]
                                }
                            ]
                        },
                        {
                            block: 'test2',
                            js: true
                        },
                        {
                            elem : 'cell',
                            content : [
                                {
                                    block : 'radio-group',
                                    name : 'islands-button',
                                    mods : { theme : 'islands', size : 'l', type : 'button' },
                                    val : 2,
                                    options : [
                                        { val : 1, text : 'Black & white' },
                                        { val : 2, text : 'Colored' },
                                        { val : 3, text : 'Any colors' }
                                    ]
                                },
                                {
                                    block : 'spin-container',
                                    content : ['s', 'm', 'l', 'xl'].map(function(size) {
                                        return {
                                            block : 'spin',
                                            mods : { theme : 'islands', size : size, visible : true }
                                        };
                                    })
                                },
                                {
                                    block: 'progressbar-example',
                                    js: true,
                                    content: [{
                                        block : 'button',
                                        mods : {
                                            theme : 'islands',
                                            size : 's',
                                            togglable : 'check',
                                            checked : true
                                        },
                                        text : 'Pause'
                                    },
                                    {
                                        block : 'progressbar',
                                        mods : { theme : 'islands' },
                                        val : 25
                                    }]
                                }
                            ]
                        },
                        {
                            elem : 'cell',
                            content : {
                                block : 'select',
                                mods : { mode : 'radio-check', theme : 'islands', size : 'l' },
                                name : 'select-radio',
                                text : 'Your mood',
                                options : [
                                    { val : 1, text : 'Bad' },
                                    { val : 2, text : 'Normal' },
                                    { val : 3, text : 'Great!' }
                                ]
                            }
                        }
                    ]
                },
                {
                    elem : 'row',
                    content : [
                        {
                            elem : 'cell',
                            content : {
                                block : 'button',
                                mods : { theme : 'islands', size : 'l', togglable : 'check' },
                                text : 'Togglable'
                            }

                        },
                        {
                            elem : 'cell',
                            content : [
                                {
                                    block : 'attach',
                                    mods : { theme : 'islands', size : 'l' },
                                    button : {
                                        block : 'button',
                                        mods : { theme : 'islands', size : 'l' },
                                        icon : { block : 'icon', mods : { action : 'download' } },
                                        text : 'Load image'
                                    },
                                    noFileText : 'file is not selected'
                                }
                            ]
                        },
                        {
                            elem : 'cell',
                            content : {
                                block : 'textarea',
                                mods : { theme : 'islands', size : 'l' },
                                val : 'Write a review',
                                placeholder : 'nothing to say'
                            }
                        },
                        {
                            elem : 'cell',
                            content : {
                                block : 'test',
                                js : true,
                                content : [
                                    {
                                        block : 'link',
                                        mods : { theme : 'islands', size : 'l', pseudo : true },
                                        content : 'Open your mind'
                                    },
                                    {
                                        block : 'modal',
                                        mods : { theme : 'islands', autoclosable : true },
                                        content : [
                                            {
                                                block : 'text',
                                                content : 'Your mind was opened!'
                                            },
                                            '(Click outside the box to close)'
                                        ]
                                    }
                                ]
                            }
                        }
                    ]
                }
            ]
        }
    ]
})
<|endoftext|>


<commit_before>/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF licenses this file
 * to you 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.
 */
require(["jquery", "sakai/sakai.api.core"], function($, sakai){

    /**
     * @name sakai_global.carousel
     *
     * @class carousel
     *
     * @description
     *
     * @version 0.0.1
     * @param {String} tuid Unique id of the widget
     * @param {Boolean} showSettings Show the settings of the widget or not
     */
    sakai_global.carousel = function(tuid, showSettings){

        /////////////////////////////
        // Configuration variables //
        /////////////////////////////

        // Containers
        var carouselContainer = "#carousel_container";

        // Templates
        var carouselSingleColumnTemplate = "carousel_single_column_template";

        /////////////////////
        // RENDER PREVIEWS //
        /////////////////////

        var renderImagePreview = function(contentURL, lastModified){
            var json = {
                "contentURL": "/p/" + contentURL + "?_=" + lastModified,
                "sakai": sakai,
                "maxwidth": "350",
                "height": "200px"
            }
            return "";
        };

        var isJwPlayerSupportedVideo = function(mimeType){
            supported = false;
            if (mimeType.substring(0, 6) === "video/") {
                var mimeSuffix = mimeType.substring(6);
                if (mimeSuffix === "x-flv" || mimeSuffix === "mp4" || mimeSuffix === "3gpp" || mimeSuffix === "quicktime") {
                    supported = true;
                }
            }
            return supported;
        };

        var createSWFObject = function(url, params, flashvars){
            if (!url) {
                url = "/devwidgets/video/jwplayer/player-licensed.swf";
            }
            var so = new SWFObject(url, 'ply', '350', '197', '9', '#ffffff');
            so.addParam('allowfullscreen', 'true');
            if (params.allowscriptaccess) {
                so.addParam('allowscriptaccess', params.allowscriptaccess);
            }
            else {
                so.addParam('allowscriptaccess', 'always');
            }
            so.addParam('wmode', 'opaque');
            return so;
        };

        var renderVideoPlayer = function(url){
            var so = createSWFObject(false, {}, {});
            so.addVariable('file', "/p/" + url);
            so.addVariable('stretching', 'uniform');
            so.write("carousel_video");
            return $("#carousel_video_holder").html();
        };

        /////////////////////
        // RENDER CAROUSEL //
        /////////////////////

        var updateViewAfterAnimation = function(carousel, li, index, state){
            if (index > carousel.options.size || index < 1) {
                index = index % carousel.options.size;
                if (!index) {
                    index = carousel.options.size;
                }
                if (index < 1) {
                    index = carousel.options.size + index;
                }
            }
            $("#carousel_container .carousel_view_toggle li").removeClass("carousel_view_toggle_selected");
            $("#carousel_view_toggle_" + carousel.last).removeClass("carousel_view_toggle_selected");
            $("#carousel_view_toggle_" + index).addClass("carousel_view_toggle_selected");
        };

        var stopAutoScrolling = function(carousel){
            carousel.startAuto(0);
        };

        var carouselBinding = function(carousel){
            // Pause autoscrolling if the user moves with the cursor over the clip.
            carousel.clip.hover(function(){
                carousel.stopAuto();
            }, function(){
                carousel.startAuto();
            });

            // Disable autoscrolling if the user clicks the prev or next button.
            carousel.buttonNext.bind('click', function(){
                stopAutoScrolling(carousel);
            });

            carousel.buttonPrev.bind('click', function(){
                stopAutoScrolling(carousel);
            });

            $('.carousel_view_toggle li').bind('click', function(){
                stopAutoScrolling(carousel);
                carousel.scroll($.jcarousel.intval($(this)[0].id.split("carousel_view_toggle_")[1]));
                $("#carousel_container .carousel_view_toggle li").removeClass("carousel_view_toggle_selected");
                $(this).addClass("carousel_view_toggle_selected");
                return false;
            });
        };

        var renderCarousel = function(dataArr){
            $(carouselContainer).html(sakai.api.Util.TemplateRenderer(carouselSingleColumnTemplate, {
                "data": dataArr
            }, false, false));
            $(carouselContainer).jcarousel({
                auto: 5,
                animation: "slow",
                scroll: 1,
                easing: "swing",
                size: dataArr.length,
                initCallback: carouselBinding,
                buttonNextHTML: "

",
                buttonPrevHTML: "

",
                wrap: "circular",
                itemFirstInCallback: {
                    onAfterAnimation: updateViewAfterAnimation
                }
            });
        };

        var parseMessages = function(data, dataArr){
            var messageArr = [];

            for(var item in data.messages){
                if(data.messages[item].hasOwnProperty("sakai:body")){
                    var obj = {};

                    obj.subject = sakai.api.Util.applyThreeDots(data.messages[item]["sakai:subject"], 200,{},"s3d-bold");
                    obj.from = data.messages[item]["sakai:from"];
                    obj.date = sakai.api.l10n.transformDate(sakai.api.Util.parseSakaiDate(data.messages[item]["sakai:created"]));

                    obj.contentType = "message";
                    messageArr.push(obj);
                    if (messageArr.length >= 4) {
                        break;
                    }
                }
            }

            if (messageArr.length) {
                dataArr.push(messageArr);
            }
        }

        var parseContent = function(data, dataArr){
            var noPreviewArr = [];

            for (var item in data.content.results) {
                var obj = {}

                if (data.content.results[item]["_mimeType"] && data.content.results[item]["_mimeType"].substring(0, 6) === "image/") {
                    obj.preview = renderImagePreview(data.content.results[item]["jcr:name"], data.content.results[item]["_lastModified"]);
                }else if (isJwPlayerSupportedVideo(data.content.results[item]["_mimeType"] || "")) {
                    obj.preview = renderVideoPlayer(data.content.results[item]["jcr:name"]);
                } else {
                    obj.preview = false;
                }
                if (data.content.results[item]["sakai:description"]) {
                    obj.description = sakai.api.Util.applyThreeDots(data.content.results[item]["sakai:description"], 700);
                }
                if (data.content.results[item]["sakai:tags"]) {
                    obj.tags = sakai.api.Util.formatTagsExcludeLocation(data.content.results[item]["sakai:tags"]);
                }
                if (data.content.results[item][data.content.results[item]["jcr:name"] + "/comments"]) {
                    obj.comments = [];
                    for (var prop in data.content.results[item][data.content.results[item]["jcr:name"] + "/comments"]) {
                        if (data.content.results[item][data.content.results[item]["jcr:name"] + "/comments"][prop].hasOwnProperty("_id")) {
                            obj.comments.push(data.content.results[item][data.content.results[item]["jcr:name"] + "/comments"][prop]);
                        }
                    }
                }
                if(sakai.config.MimeTypes[data.content.results[item]["_mimeType"]]) {
                    obj.icon = sakai.config.MimeTypes[data.content.results[item]["_mimeType"]].URL;
                }else{
                    obj.icon = sakai.config.MimeTypes.other.URL;
                }

                obj.title = data.content.results[item]["sakai:pooled-content-file-name"];
                obj.mimeType = data.content.results[item]["_mimeType"] || "";
                obj.created = sakai.api.l10n.transformDate(sakai.api.l10n.fromEpoch(data.content.results[item]["_created"]), sakai.data.me)
                obj.createdBy = data.content.results[item]["sakai:pool-content-created-for"];
                obj.lastModified = sakai.api.l10n.transformDate(sakai.api.l10n.fromEpoch(data.content.results[item]["_lastModified"]), sakai.data.me);
                obj.lastModifiedBy = data.content.results[item]["_lastModifiedBy"];
                obj.url = "/content#content_path=/p/" + data.content.results[item]["jcr:name"];
                obj.contentType = "content";

                if (obj.preview) {
                    dataArr.push(obj);
                } else {
                    noPreviewArr.push(obj);
                }
            }

            // Add items with no preview to final array.
            // Objective is to fill one rendered list item with two items (without preview), drop item that's left over if necessary.
            if (noPreviewArr.length) {
                if (noPreviewArr.length % 2) {
                    noPreviewArr.splice(noPreviewArr.length - 1, 1);
                }

                var tempArr = [];
                for (var item in noPreviewArr) {
                    if (tempArr.length != 2) {
                        tempArr.push(noPreviewArr[item]);
                        if (tempArr.length == 2) {
                            dataArr.push(tempArr);
                            tempArr = [];
                        }
                    }
                }
            }
        };

        var parseGroups = function(data, dataArr){
            for(var group in data.groups.results){
                var obj = {};

                if(data.groups.results[group].members || data.groups.results[group].members.length){
                    obj.members = data.groups.results[group].members;
                }
                if(data.groups.results[group]["sakai:group-description"] && data.groups.results[group]["sakai:group-description"].length){
                    obj.description = data.groups.results[group]["sakai:group-description"];
                }
                if(data.groups.results[group]["sakai:tags"] && data.groups.results[group]["sakai:tags"].length){
                    obj.tags = sakai.api.Util.formatTagsExcludeLocation(data.groups.results[group]["sakai:tags"]);
                }

                obj.contentType = "group";
                obj.groupid = data.groups.results[group]["sakai:group-id"];
                obj.title = data.groups.results[group]["sakai:group-title"];

                dataArr.push(obj);
            }
        };

        var parseData = function(data){
            var dataArr = [];

            parseContent(data, dataArr);
            parseGroups(data, dataArr);
            parseMessages(data, dataArr);

            renderCarousel(dataArr);
        };

        var checkDataParsable = function(data){
            if (data.content && data.groups && data.messages) {
                parseData(data);
            }
        };

        var loadFeatured = function(){
            var dataArr = {
                "content": false,
                "groups": false,
                "messages":false
            };
            $.ajax({
                url: "/var/search/pool/me/manager-all.1.json?sortOn=_created&sortOrder=desc&page=0&items=50",
                cache: false,
                success: function(data){
                    dataArr.content = data;
                    checkDataParsable(dataArr);
                }
            });

            $.ajax({
                url: "/var/search/groups-all.json?page=0&items=50&q=*",
                cache: false,
                success: function(data){
                    for (var group in data.results) {
                        $.ajax({
                            url: "/system/userManager/group/" + data.results[group].groupid + ".members.detailed.json?items=1000",
                            cache: false,
                            async: false,
                            success: function(memberData){
                                data.results[group].members = memberData;
                            }
                        });
                    }
                    dataArr.groups = data;
                    checkDataParsable(dataArr);
                }
            });

            sakai.api.Communication.getAllMessages("inbox", "*", 4, 1, "sakai:created", "desc", function(success, data){
                dataArr.messages = data;
                checkDataParsable(dataArr);
            });
        };

        var doInit = function(){
            loadFeatured();
        };

        doInit();
    };

    sakai.api.Widgets.widgetLoader.informOnLoad("carousel");
});<commit_msg>NOJIRA removing a .detailed call<commit_after>/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF licenses this file
 * to you 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.
 */
require(["jquery", "sakai/sakai.api.core"], function($, sakai){

    /**
     * @name sakai_global.carousel
     *
     * @class carousel
     *
     * @description
     *
     * @version 0.0.1
     * @param {String} tuid Unique id of the widget
     * @param {Boolean} showSettings Show the settings of the widget or not
     */
    sakai_global.carousel = function(tuid, showSettings){

        /////////////////////////////
        // Configuration variables //
        /////////////////////////////

        // Containers
        var carouselContainer = "#carousel_container";

        // Templates
        var carouselSingleColumnTemplate = "carousel_single_column_template";

        /////////////////////
        // RENDER PREVIEWS //
        /////////////////////

        var renderImagePreview = function(contentURL, lastModified){
            var json = {
                "contentURL": "/p/" + contentURL + "?_=" + lastModified,
                "sakai": sakai,
                "maxwidth": "350",
                "height": "200px"
            }
            return "";
        };

        var isJwPlayerSupportedVideo = function(mimeType){
            supported = false;
            if (mimeType.substring(0, 6) === "video/") {
                var mimeSuffix = mimeType.substring(6);
                if (mimeSuffix === "x-flv" || mimeSuffix === "mp4" || mimeSuffix === "3gpp" || mimeSuffix === "quicktime") {
                    supported = true;
                }
            }
            return supported;
        };

        var createSWFObject = function(url, params, flashvars){
            if (!url) {
                url = "/devwidgets/video/jwplayer/player-licensed.swf";
            }
            var so = new SWFObject(url, 'ply', '350', '197', '9', '#ffffff');
            so.addParam('allowfullscreen', 'true');
            if (params.allowscriptaccess) {
                so.addParam('allowscriptaccess', params.allowscriptaccess);
            }
            else {
                so.addParam('allowscriptaccess', 'always');
            }
            so.addParam('wmode', 'opaque');
            return so;
        };

        var renderVideoPlayer = function(url){
            var so = createSWFObject(false, {}, {});
            so.addVariable('file', "/p/" + url);
            so.addVariable('stretching', 'uniform');
            so.write("carousel_video");
            return $("#carousel_video_holder").html();
        };

        /////////////////////
        // RENDER CAROUSEL //
        /////////////////////

        var updateViewAfterAnimation = function(carousel, li, index, state){
            if (index > carousel.options.size || index < 1) {
                index = index % carousel.options.size;
                if (!index) {
                    index = carousel.options.size;
                }
                if (index < 1) {
                    index = carousel.options.size + index;
                }
            }
            $("#carousel_container .carousel_view_toggle li").removeClass("carousel_view_toggle_selected");
            $("#carousel_view_toggle_" + carousel.last).removeClass("carousel_view_toggle_selected");
            $("#carousel_view_toggle_" + index).addClass("carousel_view_toggle_selected");
        };

        var stopAutoScrolling = function(carousel){
            carousel.startAuto(0);
        };

        var carouselBinding = function(carousel){
            // Pause autoscrolling if the user moves with the cursor over the clip.
            carousel.clip.hover(function(){
                carousel.stopAuto();
            }, function(){
                carousel.startAuto();
            });

            // Disable autoscrolling if the user clicks the prev or next button.
            carousel.buttonNext.bind('click', function(){
                stopAutoScrolling(carousel);
            });

            carousel.buttonPrev.bind('click', function(){
                stopAutoScrolling(carousel);
            });

            $('.carousel_view_toggle li').bind('click', function(){
                stopAutoScrolling(carousel);
                carousel.scroll($.jcarousel.intval($(this)[0].id.split("carousel_view_toggle_")[1]));
                $("#carousel_container .carousel_view_toggle li").removeClass("carousel_view_toggle_selected");
                $(this).addClass("carousel_view_toggle_selected");
                return false;
            });
        };

        var renderCarousel = function(dataArr){
            $(carouselContainer).html(sakai.api.Util.TemplateRenderer(carouselSingleColumnTemplate, {
                "data": dataArr
            }, false, false));
            $(carouselContainer).jcarousel({
                auto: 5,
                animation: "slow",
                scroll: 1,
                easing: "swing",
                size: dataArr.length,
                initCallback: carouselBinding,
                buttonNextHTML: "

",
                buttonPrevHTML: "

",
                wrap: "circular",
                itemFirstInCallback: {
                    onAfterAnimation: updateViewAfterAnimation
                }
            });
        };

        var parseMessages = function(data, dataArr){
            var messageArr = [];

            for(var item in data.messages){
                if(data.messages[item].hasOwnProperty("sakai:body")){
                    var obj = {};

                    obj.subject = sakai.api.Util.applyThreeDots(data.messages[item]["sakai:subject"], 200,{},"s3d-bold");
                    obj.from = data.messages[item]["sakai:from"];
                    obj.date = sakai.api.l10n.transformDate(sakai.api.Util.parseSakaiDate(data.messages[item]["sakai:created"]));

                    obj.contentType = "message";
                    messageArr.push(obj);
                    if (messageArr.length >= 4) {
                        break;
                    }
                }
            }

            if (messageArr.length) {
                dataArr.push(messageArr);
            }
        }

        var parseContent = function(data, dataArr){
            var noPreviewArr = [];

            for (var item in data.content.results) {
                var obj = {}

                if (data.content.results[item]["_mimeType"] && data.content.results[item]["_mimeType"].substring(0, 6) === "image/") {
                    obj.preview = renderImagePreview(data.content.results[item]["jcr:name"], data.content.results[item]["_lastModified"]);
                }else if (isJwPlayerSupportedVideo(data.content.results[item]["_mimeType"] || "")) {
                    obj.preview = renderVideoPlayer(data.content.results[item]["jcr:name"]);
                } else {
                    obj.preview = false;
                }
                if (data.content.results[item]["sakai:description"]) {
                    obj.description = sakai.api.Util.applyThreeDots(data.content.results[item]["sakai:description"], 700);
                }
                if (data.content.results[item]["sakai:tags"]) {
                    obj.tags = sakai.api.Util.formatTagsExcludeLocation(data.content.results[item]["sakai:tags"]);
                }
                if (data.content.results[item][data.content.results[item]["jcr:name"] + "/comments"]) {
                    obj.comments = [];
                    for (var prop in data.content.results[item][data.content.results[item]["jcr:name"] + "/comments"]) {
                        if (data.content.results[item][data.content.results[item]["jcr:name"] + "/comments"][prop].hasOwnProperty("_id")) {
                            obj.comments.push(data.content.results[item][data.content.results[item]["jcr:name"] + "/comments"][prop]);
                        }
                    }
                }
                if(sakai.config.MimeTypes[data.content.results[item]["_mimeType"]]) {
                    obj.icon = sakai.config.MimeTypes[data.content.results[item]["_mimeType"]].URL;
                }else{
                    obj.icon = sakai.config.MimeTypes.other.URL;
                }

                obj.title = data.content.results[item]["sakai:pooled-content-file-name"];
                obj.mimeType = data.content.results[item]["_mimeType"] || "";
                obj.created = sakai.api.l10n.transformDate(sakai.api.l10n.fromEpoch(data.content.results[item]["_created"]), sakai.data.me)
                obj.createdBy = data.content.results[item]["sakai:pool-content-created-for"];
                obj.lastModified = sakai.api.l10n.transformDate(sakai.api.l10n.fromEpoch(data.content.results[item]["_lastModified"]), sakai.data.me);
                obj.lastModifiedBy = data.content.results[item]["_lastModifiedBy"];
                obj.url = "/content#content_path=/p/" + data.content.results[item]["jcr:name"];
                obj.contentType = "content";

                if (obj.preview) {
                    dataArr.push(obj);
                } else {
                    noPreviewArr.push(obj);
                }
            }

            // Add items with no preview to final array.
            // Objective is to fill one rendered list item with two items (without preview), drop item that's left over if necessary.
            if (noPreviewArr.length) {
                if (noPreviewArr.length % 2) {
                    noPreviewArr.splice(noPreviewArr.length - 1, 1);
                }

                var tempArr = [];
                for (var item in noPreviewArr) {
                    if (tempArr.length != 2) {
                        tempArr.push(noPreviewArr[item]);
                        if (tempArr.length == 2) {
                            dataArr.push(tempArr);
                            tempArr = [];
                        }
                    }
                }
            }
        };

        var parseGroups = function(data, dataArr){
            for(var group in data.groups.results){
                var obj = {};

                if(data.groups.results[group].members || data.groups.results[group].members.length){
                    obj.members = data.groups.results[group].members;
                }
                if(data.groups.results[group]["sakai:group-description"] && data.groups.results[group]["sakai:group-description"].length){
                    obj.description = data.groups.results[group]["sakai:group-description"];
                }
                if(data.groups.results[group]["sakai:tags"] && data.groups.results[group]["sakai:tags"].length){
                    obj.tags = sakai.api.Util.formatTagsExcludeLocation(data.groups.results[group]["sakai:tags"]);
                }

                obj.contentType = "group";
                obj.groupid = data.groups.results[group]["sakai:group-id"];
                obj.title = data.groups.results[group]["sakai:group-title"];

                dataArr.push(obj);
            }
        };

        var parseData = function(data){
            var dataArr = [];

            parseContent(data, dataArr);
            parseGroups(data, dataArr);
            parseMessages(data, dataArr);

            renderCarousel(dataArr);
        };

        var checkDataParsable = function(data){
            if (data.content && data.groups && data.messages) {
                parseData(data);
            }
        };

        var loadFeatured = function(){
            var dataArr = {
                "content": false,
                "groups": false,
                "messages":false
            };
            $.ajax({
                url: "/var/search/pool/me/manager-all.1.json?sortOn=_created&sortOrder=desc&page=0&items=50",
                cache: false,
                success: function(data){
                    dataArr.content = data;
                    checkDataParsable(dataArr);
                }
            });

            $.ajax({
                url: "/var/search/groups-all.json?page=0&items=50&q=*",
                cache: false,
                success: function(data){
                    for (var group in data.results) {
                        $.ajax({
                            url: "/system/userManager/group/" + data.results[group].groupid + ".members.json?items=1000",
                            cache: false,
                            async: false,
                            success: function(memberData){
                                data.results[group].members = memberData;
                            }
                        });
                    }
                    dataArr.groups = data;
                    checkDataParsable(dataArr);
                }
            });

            sakai.api.Communication.getAllMessages("inbox", "*", 4, 1, "sakai:created", "desc", function(success, data){
                dataArr.messages = data;
                checkDataParsable(dataArr);
            });
        };

        var doInit = function(){
            loadFeatured();
        };

        doInit();
    };

    sakai.api.Widgets.widgetLoader.informOnLoad("carousel");
});<|endoftext|>


<commit_before>dojo.provide("dojox.widget.Loader");
dojo.experimental("dojox.widget.Loader");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.declare("dojox.widget.Loader", [dijit._Widget,dijit._Templated], {
	// summary: a configurable global xhr-listener to display
	// a loading message during running xhr's or to simply provide
	// base-level topic to subscribe to for custom loading messages

	// loadIcon: String
	// 	location to the icon used.
	loadIcon: dojo.moduleUrl("dojox.widget.Loader","icons/loading.gif"),

	// loadMessage: String
	//	string to use for progress loading
	loadMessage: 'Loading ...',

	// hasVisuals: Boolean
	// 	true to display a fixed loading message in TR cornder, false to unly provide
	//	"Loader" topic to subscribe to for your own custom loading message.
	hasVisuals: true,

	// attachToPointer
	// 	true to use visual indicator where cursor is
	attachToPointer: true,

	// duration: Integer
	//	time in ms to toggle in/out the visual load indicator
	duration: 125,

	// _offset: Integer
	//	distance in px from the mouse pointer to show attachToPointer avatar
	_offset: 16,

	// holder for mousemove connection
	_pointerConnect: null,
	_xhrStart: null,
	_xhrEnd: null,

	templateString: '
'
		+' '
		+'
',

	postCreate: function(){
		// summary: setup the loader

		if(!this.hasVisuals){
			this.loadNode.style.display = "none"; // _destroy()?
		}else{
			if(this.attachToPointer){
				dojo.removeClass(this.loadNode,"dojoxLoader");
				dojo.addClass(this.loadNode,"dojoxLoaderPointer");
			}
			this._hide();
		}
		this._setMessage(this.loadMessage);

		// FIXME: create our connections.  would be easier, and this might be redundant
		// if Deferred published something
		this._xhrStart = this.connect(dojo,"_ioSetArgs","_show");
		this._xhrEnd = this.connect(dojo.Deferred.prototype,"_fire","_hide");

	},

	_setMessage: function(/* String */ message){
		// summary: set's the message in the loader
		this.loadMessageNode.innerHTML = message;
	},

	_putLoader: function(/* Event */ e){
		// summary: place the floating loading element based on mousemove connection position
		dijit.placeOnScreen(this.loadNode,{ x: e.clientX+this._offset, y:e.clientY+this._offset }, ["TL","BR"]);
	},

	_show: function(){
		// summary: publish and show progress indicator
		dojo.publish("Loader",[{ message: 'started' }]);
		if(this.hasVisuals){
			if(this.attachToPointer){
				this._pointerConnect = this.connect(document,"onmousemove","_putLoader");
			}
			dojo.style(this.loadNode, {
				opacity:0, display:""
			});
			dojo.fadeIn({ node: this.loadNode, duration:this.duration }).play();
		}
	},

	_hide: function(){
		// summary: publish "xhr ended" and hide progress indicator
		dojo.publish("Loader",[{ message: 'ended' }]);
		if(this.hasVisuals){
			if(this.attachToPointer){
				this.disconnect(this._pointerConnect);
			}
			dojo.fadeOut({
				node: this.loadNode,
				duration:this.duration,
				onEnd: dojo.partial(dojo.style, this.loadNode, "display", "none")
			}).play();
		}
	}

});
<commit_msg>Been wanting to drop this from DojoX. Will include in dojoc repo as example, but has little use in the real world so slating for removal in 2.0<commit_after>dojo.provide("dojox.widget.Loader");
dojo.deprecated("dojox.widget.Loader", "", "2.0");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.declare("dojox.widget.Loader", [dijit._Widget,dijit._Templated], {
	// summary: a configurable global xhr-listener to display
	// a loading message during running xhr's or to simply provide
	// base-level topic to subscribe to for custom loading messages
	//
	// loadIcon: String
	// 	location to the icon used.
	loadIcon: dojo.moduleUrl("dojox.widget.Loader","icons/loading.gif"),

	// loadMessage: String
	//	string to use for progress loading
	loadMessage: 'Loading ...',

	// hasVisuals: Boolean
	// 	true to display a fixed loading message in TR cornder, false to unly provide
	//	"Loader" topic to subscribe to for your own custom loading message.
	hasVisuals: true,

	// attachToPointer
	// 	true to use visual indicator where cursor is
	attachToPointer: true,

	// duration: Integer
	//	time in ms to toggle in/out the visual load indicator
	duration: 125,

	// _offset: Integer
	//	distance in px from the mouse pointer to show attachToPointer avatar
	_offset: 16,

	// holder for mousemove connection
	_pointerConnect: null,
	_xhrStart: null,
	_xhrEnd: null,

	templateString: '
'
		+' '
		+'
',

	postCreate: function(){
		// summary: setup the loader

		if(!this.hasVisuals){
			this.loadNode.style.display = "none"; // _destroy()?
		}else{
			if(this.attachToPointer){
				dojo.removeClass(this.loadNode,"dojoxLoader");
				dojo.addClass(this.loadNode,"dojoxLoaderPointer");
			}
			this._hide();
		}
		this._setMessage(this.loadMessage);

		// FIXME: create our connections.  would be easier, and this might be redundant
		// if Deferred published something
		this._xhrStart = this.connect(dojo,"_ioSetArgs","_show");
		this._xhrEnd = this.connect(dojo.Deferred.prototype,"_fire","_hide");

	},

	_setMessage: function(/* String */ message){
		// summary: set's the message in the loader
		this.loadMessageNode.innerHTML = message;
	},

	_putLoader: function(/* Event */ e){
		// summary: place the floating loading element based on mousemove connection position
		dijit.placeOnScreen(this.loadNode,{ x: e.clientX+this._offset, y:e.clientY+this._offset }, ["TL","BR"]);
	},

	_show: function(){
		// summary: publish and show progress indicator
		dojo.publish("Loader",[{ message: 'started' }]);
		if(this.hasVisuals){
			if(this.attachToPointer){
				this._pointerConnect = this.connect(document,"onmousemove","_putLoader");
			}
			dojo.style(this.loadNode, {
				opacity:0, display:""
			});
			dojo.fadeIn({ node: this.loadNode, duration:this.duration }).play();
		}
	},

	_hide: function(){
		// summary: publish "xhr ended" and hide progress indicator
		dojo.publish("Loader",[{ message: 'ended' }]);
		if(this.hasVisuals){
			if(this.attachToPointer){
				this.disconnect(this._pointerConnect);
			}
			dojo.fadeOut({
				node: this.loadNode,
				duration:this.duration,
				onEnd: dojo.partial(dojo.style, this.loadNode, "display", "none")
			}).play();
		}
	}

});
<|endoftext|>


<commit_before>const exec = require('child-process-promise').exec
const version = require('../package.json').version

/**
 * NOTE: Split into two arrays because gsutil acts differently when
 * no files exist at a location. First array includes at least one file for each
 * folder that will be copied in the second.
 */
const first = [
  '_book/index.html',
  '_book/search_index.json',
  '_book/gitbook/gitbook.js',
  '_book/docs/README.md'
]

const second = ['_book/gitbook/**', '_book/docs/**']

const project = 'docs.react-redux-firebase.com'

/**
 * Run shell command with error handling.
 * @param  {string} cmd - Command to run
 * @returns {Promise} Resolves with stdout of running command
 * @private
 */
function runCommand(cmd) {
  return exec(cmd).catch(err =>
    Promise.reject(
      err.message && err.message.indexOf('not found') !== -1
        ? new Error(`${cmd.split(' ')[0]} must be installed to upload`)
        : err
    )
  )
}

/**
 * Upload file or folder to cloud storage. gsutil is used instead of
 * google-cloud/storage module so that folders can be uploaded.
 * @param  {string} entityPath - Local path for entity (file/folder) to upload
 * @returns {Promise} Resolve with an object containing stdout and uploadPath
 * @private
 */
function upload(entityPath) {
  const prefix = `history/v${version.split('-')[0]}`
  const uploadPath = `${project}/${prefix}/${entityPath
    .replace('_book/', '')
    .replace('/**', '')}`
  const command = `gsutil -m cp -r -a public-read ${entityPath} gs://${uploadPath}`
  return runCommand(command).then(
    ({ stdout, stderr }) =>
      stdout ? Promise.reject(stdout) : { output: stderr, uploadPath }
  )
}

/**
 * Upload list of files or folders to Google Cloud Storage
 * @param  {Array} files - List of files/folders to upload
 * @returns {Promise} Resolves with an array of upload results
 * @private
 */
function uploadList(files) {
  return Promise.all(
    files.map(file =>
      upload(file)
        .then(({ uploadPath, output }) => {
          console.log(`Successfully uploaded: ${uploadPath}`) // eslint-disable-line no-console
          return output
        })
        .catch(err => {
          console.log('Error uploading:', err.message || err) // eslint-disable-line no-console
          return Promise.reject(err)
        })
    )
  )
}

;(function() {
  runCommand('gsutil') // check for existence of gsutil
    .then(() => uploadList(first))
    .then(() => uploadList(second))
    .then(() => {
      console.log('Docs uploaded successfully') // eslint-disable-line no-console
      process.exit(0)
    })
    .catch(err => {
      console.log('Error uploading docs:', err.message) // eslint-disable-line no-console
      process.exit(1)
    })
})()
<commit_msg>Fix docs upload path [ci skip]<commit_after>const exec = require('child-process-promise').exec
const version = require('../package.json').version

/**
 * NOTE: Split into two arrays because gsutil acts differently when
 * no files exist at a location. First array includes at least one file for each
 * folder that will be copied in the second.
 */
const first = [
  '_book/index.html',
  '_book/search_index.json',
  '_book/gitbook/gitbook.js',
  '_book/docs/GLOSSARY.md'
]

const second = ['_book/gitbook/**', '_book/docs/**']

const project = 'docs.react-redux-firebase.com'

/**
 * Run shell command with error handling.
 * @param  {string} cmd - Command to run
 * @returns {Promise} Resolves with stdout of running command
 * @private
 */
function runCommand(cmd) {
  return exec(cmd).catch(err =>
    Promise.reject(
      err.message && err.message.indexOf('not found') !== -1
        ? new Error(`${cmd.split(' ')[0]} must be installed to upload`)
        : err
    )
  )
}

/**
 * Upload file or folder to cloud storage. gsutil is used instead of
 * google-cloud/storage module so that folders can be uploaded.
 * @param  {string} entityPath - Local path for entity (file/folder) to upload
 * @returns {Promise} Resolve with an object containing stdout and uploadPath
 * @private
 */
function upload(entityPath) {
  const prefix = `history/v${version.split('-')[0]}`
  const uploadPath = `${project}/${prefix}/${entityPath
    .replace('_book/', '')
    .replace('/**', '')}`
  const command = `gsutil -m cp -r -a public-read ${entityPath} gs://${uploadPath}`
  return runCommand(command).then(
    ({ stdout, stderr }) =>
      stdout ? Promise.reject(stdout) : { output: stderr, uploadPath }
  )
}

/**
 * Upload list of files or folders to Google Cloud Storage
 * @param  {Array} files - List of files/folders to upload
 * @returns {Promise} Resolves with an array of upload results
 * @private
 */
function uploadList(files) {
  return Promise.all(
    files.map(file =>
      upload(file)
        .then(({ uploadPath, output }) => {
          console.log(`Successfully uploaded: ${uploadPath}`) // eslint-disable-line no-console
          return output
        })
        .catch(err => {
          console.log('Error uploading:', err.message || err) // eslint-disable-line no-console
          return Promise.reject(err)
        })
    )
  )
}

;(function() {
  runCommand('gsutil') // check for existence of gsutil
    .then(() => uploadList(first))
    .then(() => uploadList(second))
    .then(() => {
      console.log('Docs uploaded successfully') // eslint-disable-line no-console
      process.exit(0)
    })
    .catch(err => {
      console.log('Error uploading docs:', err.message) // eslint-disable-line no-console
      process.exit(1)
    })
})()
<|endoftext|>


<commit_before>require('colors');
var cli = require('optimist'),
    p = require('path'),
    u = require('util'),
    fs = require('fs'),
    exec = require('child_process').exec,
    Seq = require('seq'),
    read = require('read');

var available = require(p.join(process.mainModule.paths[0],'..','..','package.json')).ngn;

// Basic CLI
var argv = cli
		  .usage('Usage: ngn remove <module or group>')
		  .argv,
		mod = argv._.filter(function(value){return value !== 'remove'})[0];

// Global Package Installer
var uninstall = function(ngnpkg){
  exec('npm uninstall -g '+ngnpkg+' --json --loglevel=silent',function(err,stdout,stderr){
    try {
      // Handle edge case when gyp output screws up npm json format
      if (stdout.substr(0,1) !== '['){
        stdout = stdout.substr(stdout.indexOf('['),stdout.length);
      }
      var out = stdout.replace(/unbuild/gi,'').replace(/\s/).split('@');
      console.log((out[0].toString()+' support removed --> '+' v'+out[1].toString()).red.bold);
    } catch (e) {
      console.log('Module removed, but there were errors:'.yellow.bold);
      console.log(e.message.toString().yellow);
    }
  });
};

// Check first for a module or group and install/warn accordingly
if (available.modules[mod] !== undefined){
  uninstall(mod);
} else if (available.groups[mod] !== undefined){
  available.groups[mod].forEach(function(m){
    uninstall(m);
  });
} else if (['all','*'].indexOf(mod.toString().trim().toLowerCase()) >= 0){
  console.log(('Removing every add-on ('+Object.keys(available.modules).length.toString()+' total). This may take a few moments.').cyan.bold);
  for (var m in available.modules){
    uninstall(m);
  };
} else {
  throw 'No module or group called \"'+mod+'\" is available.';
}
<commit_msg>Fixed removal. Auto-skip non-installed features.<commit_after>require('colors');
var cli = require('optimist'),
    p = require('path'),
    u = require('util'),
    fs = require('fs'),
    exec = require('child_process').exec,
    Seq = require('seq'),
    read = require('read');

var available = require(p.join(process.mainModule.paths[0],'..','..','package.json')).ngn;

// Basic CLI
var argv = cli
		  .usage('Usage: ngn remove <module or group>')
		  .argv,
		mod = argv._.filter(function(value){return value !== 'remove'})[0];

// Global Package Installer
var uninstall = function(ngnpkg){
  exec('npm uninstall -g '+ngnpkg+' --json --loglevel=silent',function(err,stdout,stderr){
    if (stdout.toString().trim().length == 0){
      console.log((ngnpkg+' support not found/installed. Skipped.').yellow);
      return;
    }
    try {
      var out = stdout.toString().trim().replace(/unbuild/gi,'').replace(/\s/,'').split('@');
      console.log(((out[0]||'Unknown').toString()+' support removed --> '+' v'+(out[1]||'?').toString()).red.bold);
    } catch (e) {
      console.log('Module removed, but there were errors:'.yellow.bold);
      console.log(e.message.toString().yellow);
    }
  });
};

// Check first for a module or group and install/warn accordingly
if (available.modules[mod] !== undefined){
  uninstall(mod);
} else if (available.groups[mod] !== undefined){
  available.groups[mod].forEach(function(m){
    uninstall(m);
  });
} else if (['all','*'].indexOf(mod.toString().trim().toLowerCase()) >= 0){
  console.log(('Removing every add-on ('+Object.keys(available.modules).length.toString()+' total). This may take a few moments.').cyan.bold);
  for (var m in available.modules){
    uninstall(m);
  };
} else {
  throw 'No module or group called \"'+mod+'\" is available.';
}
<|endoftext|>


<commit_before>var p = require('path'),
  pkg = require(p.join(__dirname,'..','..','package.json')),
  fs = require('fs'),
  exec = require('child_process').exec,
  events = require('events'),
  evt = new events.EventEmitter(),
  semver = require('semver'),
  installer = require('../lib/installer');
require('colors');

evt.on('updatemods',function(coreupdated){
  if (coreupdated){
    delete require.cache[p.join(__dirname,'..','..','package.json')];
    pkg = require(p.join(__dirname,'..','..','package.json'));
    console.log(('NGN updated to version '+pkg.version).green.bold);

    console.log('Checking for updates...');

    // Loop through modules and update accordingly.
    for (var m in pkg.ngn.modules){
      installer.update(m);
    }
    if (fs.existsSync(p.join(__dirname,'../../../ngn-dev'))){
      installer.update('ngn-dev');
    }
  }
});

// Check for core update
exec('npm show ngn version --silent',function(e,stdout,stderr){
  if (e) throw e;
  if (semver.lt(pkg.version,stdout)){
    console.log('Updating NGN Core...'.yellow.bold);
    exec('npm install -g ngn --silent',function(ee,so,ser){
      evt.emit('updatemods',true);
    });
  } else {
    console.log(('The latest version of NGN, v'+pkg.version+', is already installed.').green.bold);
    evt.emit('updatemods',false);
  }
});<commit_msg>Added support for updating add-ons<commit_after>var p = require('path'),
  pkg = require(p.join(__dirname,'..','..','package.json')),
  fs = require('fs'),
  exec = require('child_process').exec,
  events = require('events'),
  evt = new events.EventEmitter(),
  semver = require('semver'),
  installer = require('../lib/installer');
require('colors');

evt.on('updatemods',function(coreupdated){
  if (coreupdated){
    delete require.cache[p.join(__dirname,'..','..','package.json')];
    pkg = require(p.join(__dirname,'..','..','package.json'));
  }

  console.log(('NGN updated to version '+pkg.version).green.bold);
  console.log('Checking for updates...');

  // Loop through modules and update accordingly.
  for (var m in pkg.ngn.modules){
    installer.update(m);
  }
  if (fs.existsSync(p.join(__dirname,'../../../ngn-dev'))){
    installer.update('ngn-dev');
  }
});

// Check for core update
exec('npm show ngn version --silent',function(e,stdout,stderr){
  if (e) throw e;
  if (semver.lt(pkg.version,stdout)){
    console.log('Updating NGN Core...'.yellow.bold);
    exec('npm install -g ngn --silent',function(ee,so,ser){
      evt.emit('updatemods',true);
    });
  } else {
    console.log(('The latest version of NGN, v'+pkg.version+', is already installed.').green.bold);
    evt.emit('updatemods',false);
  }
});<|endoftext|>