<commit_before>module.exports = function (grunt) {
  'use strict';

  var CONTEXT = process.env.CONTEXT || 'prod';

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-coffee');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-requirejs');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-mocha');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-hull-dox');
  grunt.loadNpmTasks('grunt-hull-widgets');
  grunt.loadNpmTasks('grunt-s3');
  grunt.loadNpmTasks('grunt-git-describe');
  grunt.loadNpmTasks('grunt-coverjs');
  grunt.loadNpmTasks('grunt-plato');

  var pkg = grunt.file.readJSON('component.json');

  var port = 3001;

  // ==========================================================================
  // Project configuration
  // ==========================================================================

  var clientSrc = ['src/hullbase.coffee', 'src/hull.coffee', 'src/client/**/*.coffee'];
  var remoteSrc = ['src/hullbase.coffee', 'src/hull.coffee', 'src/hull-remote.coffee', 'src/remote/**/*.coffee'];

  // Lookup of the available libs and injects them for the build
  // in the requirejs conf
  var clientLibs = grunt.file.glob
    .sync('src/client/**/*.coffee')
    .map(function (clientLib) {
      return clientLib.replace('.coffee', '').replace('src/', 'lib/');
    });

  var remoteLibs = grunt.file.glob
    .sync('src/remote/**/*.coffee')
    .map(function (clientLib) {
      return clientLib.replace('.coffee', '').replace('src/', 'lib/');
    });

  // Lookup of the Aura Extensions and injects them in the requirejs build
  var auraExtensions = grunt.file.glob
    .sync('aura-extensions/**/*.js')
    .map(function (extension) {
      return extension.replace('.js', '');
    });

  var gruntConfig = {
    PKG_VERSION: pkg.version,
    clean: {
      client: {
        src: 'lib/client/**/*'
      },
      remote: {
        src: 'lib/remote/**/*'
      },
      reset: {
        src: ['build', 'lib', 'tmp', 'dist', 'components', 'node_modules']
      }
    },
    dox: {
      files: {
        src: 'widgets/**/main.js',
        dest: 'dist/<%= PKG_VERSION %>/docs'
      }
    },
    coffee: {
      compile: {
        options: {
          header: true
        }
      },
      remote: {
        files: grunt.file.expandMapping(remoteSrc, 'lib/', {
          rename: function (destBase, destPath) {
            return destBase + destPath.replace(/\.coffee$/, '.js').replace(/^src\//, "");
          }
        })
      },
      client: {
        files: grunt.file.expandMapping(clientSrc, 'lib/', {
          rename: function (destBase, destPath) {
            return destBase + destPath.replace(/\.coffee$/, '.js').replace(/^src\//, "");
          }
        })
      }
    },
    connect: {
      server: {
        options: {
          port: port
        }
      }
    },
    requirejs: {
      client: {
        options: {
          baseUrl: '.',
          optimize: CONTEXT!=='prod' ? "none" : "uglify",
          preserveLicenseComments: true,
          paths: {
            aura:           'components/aura/lib',
            underscore:     'components/underscore/underscore',
            eventemitter:   'components/eventemitter2/lib/eventemitter2',
            backbone:       'components/backbone/backbone',
            easyXDM:        'components/easyXDM/easyXDM',
            handlebars:     'components/require-handlebars-plugin/Handlebars',
            requireLib:     'components/requirejs/require',
            moment:         'components/moment/moment',
            cookie:         'components/jquery.cookie/jquery.cookie',
            string:         'components/underscore.string/lib/underscore.string',
            jquery:         'empty:',
            text:           'components/requirejs-text/text',
            base64:         'components/base64/base64'
          },
          shim: {
            backbone:   { exports: 'Backbone', deps: ['underscore', 'jquery'] },
            underscore: { exports: '_' },
            easyXDM:    { exports: 'easyXDM' }
          },
          include: [
            'requireLib',
            'underscore',
            'moment',
            'string',
            'cookie',
            'base64',
            'backbone',
            'handlebars',
            'easyXDM',
            'text',
            'aura/ext/debug',
            'aura/ext/mediator',
            'aura/ext/widgets',
            'lib/hull'
          ].concat(auraExtensions)
           .concat(clientLibs),
          out: 'dist/<%= PKG_VERSION %>/hull.js'
        }
      },
      remote: {
        options: {
          baseUrl: '.',
          optimize: CONTEXT!=='prod' ? "none" : "uglify",
          preserveLicenseComments: true,
          paths: {
            aura:               'components/aura/lib',
            underscore:         'components/underscore/underscore',
            eventemitter:       'components/eventemitter2/lib/eventemitter2',
            easyXDM:            'components/easyXDM/easyXDM',
            requireLib:         'components/requirejs/require',
            jquery:             'components/jquery/jquery',
            text:               'components/requirejs-text/text',
            'route-recognizer': 'components/route-recognizer/dist/route-recognizer.amd',
            analytics:          'components/analytics/analytics',
            base64:             'components/base64/base64'
          },
          shim: {
            underscore: { exports: '_' },
            analytics: { exports: 'analytics' },
            easyXDM:    { exports: 'easyXDM' }
          },
          include: [
            'requireLib',
            'jquery',
            'underscore',
            'eventemitter',
            'easyXDM',
            'text',
            'base64',
            'analytics',
            'aura/ext/debug',
            'aura/ext/mediator',
            'aura/ext/widgets',
            'lib/hull',
            'lib/hull-remote'
          ].concat(remoteLibs),
          out: 'dist/<%= PKG_VERSION %>/hull-remote.js'
        }
      },
      upload: {
        options: {
          paths: {
            jquery: "empty:",
            "jquery.ui.widget" : 'components/jquery-file-upload/js/vendor/jquery.ui.widget',
            "jquery.fileupload" : 'components/jquery-file-upload/js/jquery.fileupload'
          },
          include: [
            'jquery.fileupload'
          ],
          out: 'tmp/widgets/upload/deps/jquery.fileupload.js'
        }
      },
      registration: {
        options: {
          paths: { h5f: 'widgets/registration/h5f' },
          shim: { h5f: { exports: 'H5F' } },
          include: ['h5f'],
          out: 'tmp/widgets/registration/deps.js'
        }
      }
    },
    jshint: {
      files: {
        src: ['lib/**/*.js', 'spec/lib/**/*.js']
      },
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        eqnull: true,
        browser: true,
        nomen: false,
        expr: true,
        globals: {
          console: true,
          require: true,
          define: true,
          _: true,
          $: true
        }
      }
    },
    mocha: {
      hull: {
        src: ["spec/index.html"]
      }
    },
    watch: {
      widgets: {
        files: ['widgets/**/*'],
        tasks: ['hull_widgets']
      },
      remote: {
        files: remoteSrc,
        tasks: ['build_remote', 'mocha']
      },
      client: {
        files: clientSrc,
        tasks: ['build_client', 'mocha']
      },
      spec: {
        files: ['spec/**/*.js'],
        tasks: ['mocha']
      }
    },
    version: {
      template: "define(function () { return '<%= PKG_VERSION %>';});",
      dest: 'lib/version.js'
    },
    hull_widgets: {
      hull: {
        src: 'widgets',
        before: ['requirejs:upload', 'requirejs:registration'],
        dest: 'dist/<%= PKG_VERSION%>/widgets',
        optimize: CONTEXT === 'prod'
      }
    },
    describe: {
      out: 'dist/<%= PKG_VERSION%>/REVISION'
    },
    cover: {
      compile: {
        files: {
          'build/instrumented/*.js' : ['lib/**/*.js']
        },
        options: {
          basePath: 'lib'
        }
      }
    },
    plato: {
      develop: {
        files: {
          'build/report': ['lib/**/*.js']
        }
      }
    }
  };

  var aws = false;
  if (grunt.file.exists('grunt-aws.json')) {
    aws = grunt.file.readJSON('grunt-aws.json');
    if (aws) {
      gruntConfig.aws = aws;
      gruntConfig.s3 = {
        options: {
          key: '<%= aws.key %>',
          secret: '<%= aws.secret %>',
          bucket: '<%= aws.bucket %>',
          access: 'public-read',
          // debug: true,
          encodePaths: true,
          maxOperations: 20
        },
        prod: {
          upload: [
            {
              gzip:  true,
              src: 'dist/<%= PKG_VERSION %>/**/*',
              dest: '/',
              rel: 'dist/'
            },
            {
              gzip:  false,
              src: 'dist/<%= PKG_VERSION %>/**/*',
              dest: '/',
              rel: 'dist/'
            }
          ]
        }
      };
    }
  }
  grunt.initConfig(gruntConfig);

  // default build task
  grunt.registerTask('build_remote', ['clean:remote', 'coffee:remote', 'version', 'requirejs:remote']);
  grunt.registerTask('build_client', ['clean:client', 'coffee:client', 'version', 'requirejs:client']);
  grunt.registerTask('build_libs', ['build_client', 'build_remote']);
  grunt.registerTask('build', ['build_libs', 'hull_widgets']);
  grunt.registerTask('test', ['build', 'cover', 'plato', 'mocha']);
  grunt.registerTask('default', ['connect', 'test', 'watch']);
  grunt.registerTask('dist', ['build', 'dox']);
  grunt.registerTask('deploy', ['dist', 'describe', 's3']);
  grunt.registerTask('reset', ['clean:reset']);

  grunt.registerTask("version", "generate a file from a template", function () {
    var conf = grunt.config("version");
    grunt.file.write(conf.dest, grunt.template.process(conf.template));
    grunt.log.writeln('Generated \'' + conf.dest + '\' successfully.');
  });
};
<commit_msg>Fix grunt-s3 config...<commit_after>module.exports = function (grunt) {
  'use strict';

  var CONTEXT = process.env.CONTEXT || 'prod';

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-coffee');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-requirejs');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-mocha');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-hull-dox');
  grunt.loadNpmTasks('grunt-hull-widgets');
  grunt.loadNpmTasks('grunt-s3');
  grunt.loadNpmTasks('grunt-git-describe');
  grunt.loadNpmTasks('grunt-coverjs');
  grunt.loadNpmTasks('grunt-plato');

  var pkg = grunt.file.readJSON('component.json');

  var port = 3001;

  // ==========================================================================
  // Project configuration
  // ==========================================================================

  var clientSrc = ['src/hullbase.coffee', 'src/hull.coffee', 'src/client/**/*.coffee'];
  var remoteSrc = ['src/hullbase.coffee', 'src/hull.coffee', 'src/hull-remote.coffee', 'src/remote/**/*.coffee'];

  // Lookup of the available libs and injects them for the build
  // in the requirejs conf
  var clientLibs = grunt.file.glob
    .sync('src/client/**/*.coffee')
    .map(function (clientLib) {
      return clientLib.replace('.coffee', '').replace('src/', 'lib/');
    });

  var remoteLibs = grunt.file.glob
    .sync('src/remote/**/*.coffee')
    .map(function (clientLib) {
      return clientLib.replace('.coffee', '').replace('src/', 'lib/');
    });

  // Lookup of the Aura Extensions and injects them in the requirejs build
  var auraExtensions = grunt.file.glob
    .sync('aura-extensions/**/*.js')
    .map(function (extension) {
      return extension.replace('.js', '');
    });

  var gruntConfig = {
    PKG_VERSION: pkg.version,
    clean: {
      client: {
        src: 'lib/client/**/*'
      },
      remote: {
        src: 'lib/remote/**/*'
      },
      reset: {
        src: ['build', 'lib', 'tmp', 'dist', 'components', 'node_modules']
      }
    },
    dox: {
      files: {
        src: 'widgets/**/main.js',
        dest: 'dist/<%= PKG_VERSION %>/docs'
      }
    },
    coffee: {
      compile: {
        options: {
          header: true
        }
      },
      remote: {
        files: grunt.file.expandMapping(remoteSrc, 'lib/', {
          rename: function (destBase, destPath) {
            return destBase + destPath.replace(/\.coffee$/, '.js').replace(/^src\//, "");
          }
        })
      },
      client: {
        files: grunt.file.expandMapping(clientSrc, 'lib/', {
          rename: function (destBase, destPath) {
            return destBase + destPath.replace(/\.coffee$/, '.js').replace(/^src\//, "");
          }
        })
      }
    },
    connect: {
      server: {
        options: {
          port: port
        }
      }
    },
    requirejs: {
      client: {
        options: {
          baseUrl: '.',
          optimize: CONTEXT!=='prod' ? "none" : "uglify",
          preserveLicenseComments: true,
          paths: {
            aura:           'components/aura/lib',
            underscore:     'components/underscore/underscore',
            eventemitter:   'components/eventemitter2/lib/eventemitter2',
            backbone:       'components/backbone/backbone',
            easyXDM:        'components/easyXDM/easyXDM',
            handlebars:     'components/require-handlebars-plugin/Handlebars',
            requireLib:     'components/requirejs/require',
            moment:         'components/moment/moment',
            cookie:         'components/jquery.cookie/jquery.cookie',
            string:         'components/underscore.string/lib/underscore.string',
            jquery:         'empty:',
            text:           'components/requirejs-text/text',
            base64:         'components/base64/base64'
          },
          shim: {
            backbone:   { exports: 'Backbone', deps: ['underscore', 'jquery'] },
            underscore: { exports: '_' },
            easyXDM:    { exports: 'easyXDM' }
          },
          include: [
            'requireLib',
            'underscore',
            'moment',
            'string',
            'cookie',
            'base64',
            'backbone',
            'handlebars',
            'easyXDM',
            'text',
            'aura/ext/debug',
            'aura/ext/mediator',
            'aura/ext/widgets',
            'lib/hull'
          ].concat(auraExtensions)
           .concat(clientLibs),
          out: 'dist/<%= PKG_VERSION %>/hull.js'
        }
      },
      remote: {
        options: {
          baseUrl: '.',
          optimize: CONTEXT!=='prod' ? "none" : "uglify",
          preserveLicenseComments: true,
          paths: {
            aura:               'components/aura/lib',
            underscore:         'components/underscore/underscore',
            eventemitter:       'components/eventemitter2/lib/eventemitter2',
            easyXDM:            'components/easyXDM/easyXDM',
            requireLib:         'components/requirejs/require',
            jquery:             'components/jquery/jquery',
            text:               'components/requirejs-text/text',
            'route-recognizer': 'components/route-recognizer/dist/route-recognizer.amd',
            analytics:          'components/analytics/analytics',
            base64:             'components/base64/base64'
          },
          shim: {
            underscore: { exports: '_' },
            analytics: { exports: 'analytics' },
            easyXDM:    { exports: 'easyXDM' }
          },
          include: [
            'requireLib',
            'jquery',
            'underscore',
            'eventemitter',
            'easyXDM',
            'text',
            'base64',
            'analytics',
            'aura/ext/debug',
            'aura/ext/mediator',
            'aura/ext/widgets',
            'lib/hull',
            'lib/hull-remote'
          ].concat(remoteLibs),
          out: 'dist/<%= PKG_VERSION %>/hull-remote.js'
        }
      },
      upload: {
        options: {
          paths: {
            jquery: "empty:",
            "jquery.ui.widget" : 'components/jquery-file-upload/js/vendor/jquery.ui.widget',
            "jquery.fileupload" : 'components/jquery-file-upload/js/jquery.fileupload'
          },
          include: [
            'jquery.fileupload'
          ],
          out: 'tmp/widgets/upload/deps/jquery.fileupload.js'
        }
      },
      registration: {
        options: {
          paths: { h5f: 'widgets/registration/h5f' },
          shim: { h5f: { exports: 'H5F' } },
          include: ['h5f'],
          out: 'tmp/widgets/registration/deps.js'
        }
      }
    },
    jshint: {
      files: {
        src: ['lib/**/*.js', 'spec/lib/**/*.js']
      },
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        eqnull: true,
        browser: true,
        nomen: false,
        expr: true,
        globals: {
          console: true,
          require: true,
          define: true,
          _: true,
          $: true
        }
      }
    },
    mocha: {
      hull: {
        src: ["spec/index.html"]
      }
    },
    watch: {
      widgets: {
        files: ['widgets/**/*'],
        tasks: ['hull_widgets']
      },
      remote: {
        files: remoteSrc,
        tasks: ['build_remote', 'mocha']
      },
      client: {
        files: clientSrc,
        tasks: ['build_client', 'mocha']
      },
      spec: {
        files: ['spec/**/*.js'],
        tasks: ['mocha']
      }
    },
    version: {
      template: "define(function () { return '<%= PKG_VERSION %>';});",
      dest: 'lib/version.js'
    },
    hull_widgets: {
      hull: {
        src: 'widgets',
        before: ['requirejs:upload', 'requirejs:registration'],
        dest: 'dist/<%= PKG_VERSION%>/widgets',
        optimize: CONTEXT === 'prod'
      }
    },
    describe: {
      out: 'dist/<%= PKG_VERSION%>/REVISION'
    },
    cover: {
      compile: {
        files: {
          'build/instrumented/*.js' : ['lib/**/*.js']
        },
        options: {
          basePath: 'lib'
        }
      }
    },
    plato: {
      develop: {
        files: {
          'build/report': ['lib/**/*.js']
        }
      }
    }
  };

  var aws = false;
  if (grunt.file.exists('grunt-aws.json')) {
    aws = grunt.file.readJSON('grunt-aws.json');
    if (aws) {
      gruntConfig.aws = aws;
      gruntConfig.s3 = {
        options: {
          key: '<%= aws.key %>',
          secret: '<%= aws.secret %>',
          bucket: '<%= aws.bucket %>',
          access: 'public-read',
          // debug: true,
          encodePaths: true,
          maxOperations: 20
        },
        prod: {
          upload: [
            {
              gzip:  true,
              src: 'dist/<%= PKG_VERSION %>/**/*',
              dest: '',
              rel: 'dist/'
            },
            {
              gzip:  false,
              src: 'dist/<%= PKG_VERSION %>/**/*',
              dest: '',
              rel: 'dist/'
            }
          ]
        }
      };
    }
  }
  grunt.initConfig(gruntConfig);

  // default build task
  grunt.registerTask('build_remote', ['clean:remote', 'coffee:remote', 'version', 'requirejs:remote']);
  grunt.registerTask('build_client', ['clean:client', 'coffee:client', 'version', 'requirejs:client']);
  grunt.registerTask('build_libs', ['build_client', 'build_remote']);
  grunt.registerTask('build', ['build_libs', 'hull_widgets']);
  grunt.registerTask('test', ['build', 'cover', 'plato', 'mocha']);
  grunt.registerTask('default', ['connect', 'test', 'watch']);
  grunt.registerTask('dist', ['build', 'dox']);
  grunt.registerTask('deploy', ['dist', 'describe', 's3']);
  grunt.registerTask('reset', ['clean:reset']);

  grunt.registerTask("version", "generate a file from a template", function () {
    var conf = grunt.config("version");
    grunt.file.write(conf.dest, grunt.template.process(conf.template));
    grunt.log.writeln('Generated \'' + conf.dest + '\' successfully.');
  });
};
<|endoftext|>


<commit_before>/*global describe, it*/
require('../initialize-globals').load();
var validator = require('../../app/lib/validators');
describe('Validator', function() {
  var validate = validator.validate;
  describe('#validate', function() {
    describe('##required', function() {
      var property = {
        name: "papa",
        value: undefined
      },
        validator = {
          type: "required",
          value: undefined,
          options: {}
        };
      it("property undefined required false", function() {
        property.value = undefined;
        validator.value = false;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.not.have.property('value');
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it("property undefined required true", function() {
        property.value = undefined;
        validator.value = true;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.not.have.property('value');
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors').be.an('Array');
      });
      it("property defined required false", function() {
        property.value = "singe";
        validator.value = false;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it("property defined required false", function() {
        property.value = "singe";
        validator.value = true;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });

    });
    describe('##string', function() {
      var property = {
        name: "firstName",
        value: "pierre"
      },
        validator = {
          type: "string",
          options: {}
        };
      it('The minLength shoul be ok with a minLength 1', function() {
        validator.options.minLength = 1;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it('The minLength shoul be ko with a stringLength of 7', function() {
        validator.options.minLength = 7;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors');
      });
      it('The maxLength should be ok with a stringLength of 7', function() {
        validator.options.minLength = 0;
        validator.options.maxLength = 7;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
        //console.log(validationResult);
      });
      it('The maxLength  be ko with a stringLength of 1', function() {
        validator.options.maxLength = 1;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors');

      });
    });
    describe('##regex', function() {
      var property = {
        name: "email",
        value: "pierre@pierr.com"
      },
        validator = {
          type: "regex",
          options: {}
        };
      it("should validate with a regex", function() {
        validator.value = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it("should invalidate with a regex", function() {
        property.value = "sjhbcbdjbvjhds";
        validator.value = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        var validationResult = validate(property, [validator]);
        //console.log(validationResult);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors').to.be.an('Array');
      });
    });
    describe('##function', function() {
      var property = {
        name: "bool"
      },
        validator = {
          type: "function",
          options: {}
        };
      it("Simple function should test its a bool true.", function() {
        property.value = true;
        validator.value = function(prop, opt) {
          return prop === true;
        };
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it("Simple function should test its a bool false.", function() {
        property.value = false;
        validator.value = function(prop, opt) {
          return prop === true;
        };
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors').be.an("Array");
      });
    });
    describe('##two validator', function() {
      var property = {
        name: "bool"
      },
        validator = {
          type: "function",
          options: {}
        }, validator2 = {
          type: "function",
          options: {}
        };
      it("Two validators, two ok.", function() {
        property.value = true;
        validator.value = function(prop, opt) {
          return prop === true;
        };
        var validationResult = validate(property, [validator, validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined).empty;
      });
      it("Two validators, one ok, one wrong", function() {
        property.value = false;
        validator.value = function(prop, opt) {
          return prop === true;
        };
        validator2.value = function(prop, opt) {
          return prop === false;
        };
        var validationResult = validate(property, [validator, validator2]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors').be.an("Array").and.have.length(1);
      });
      it("Two validators, two wrong", function() {
        property.value = true;
        validator.value = function(prop, opt) {
          return prop === false;
        };
        validator2.value = function(prop, opt) {
          return prop === false;
        };
        var validationResult = validate(property, [validator, validator2]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors').be.an("Array").and.have.length(2);
      });
    });
describe('##No validator', function() {
      var property = {
        name: "bool"
      },
        validator = {
          type: "function",
          options: {}
        }, validator2 = {
          type: "function",
          options: {}
        };
      it("No validators should be ok.", function() {
        property.value = true;
        var validationResult = validate(property);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it("An empty array of validators should be ok.", function() {
        property.value = true;
        var validationResult = validate(property, []);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
    });
  });
});<commit_msg>Add tessts on the uinternationalization of errors<commit_after>/*global describe, it*/
require('../initialize-globals').load();
var validator = require('../../app/lib/validators');
describe('Validator', function() {
  var validate = validator.validate;
  describe('#validate', function() {
    describe('##required', function() {
      var property = {
        name: "papa",
        value: undefined
      },
        validator = {
          type: "required",
          value: undefined,
          options: {}
        };
      it("property undefined required false", function() {
        property.value = undefined;
        validator.value = false;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.not.have.property('value');
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it("property undefined required true", function() {
        property.value = undefined;
        validator.value = true;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.not.have.property('value');
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors').be.an('Array');
        //console.log('Validation results: %j', validationResult);
      });
      it("property defined required false", function() {
        property.value = "singe";
        validator.value = false;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it("property defined required false", function() {
        property.value = "singe";
        validator.value = true;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });

    });
    describe('##string', function() {
      var property = {
        name: "firstName",
        value: "pierre"
      },
        validator = {
          type: "string",
          options: {}
        };
      it('The minLength shoul be ok with a minLength 1', function() {
        validator.options.minLength = 1;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it('The minLength shoul be ko with a stringLength of 7', function() {
        validator.options.minLength = 7;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors');
        //console.log('Validation results: %j', validationResult);
      });
      it('The maxLength should be ok with a stringLength of 7', function() {
        validator.options.minLength = 0;
        validator.options.maxLength = 7;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
        //console.log(validationResult);
      });
      it('The maxLength  be ko with a stringLength of 1', function() {
        validator.options.maxLength = 1;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors');

      });
    });
    describe('##regex', function() {
      var property = {
        name: "email",
        value: "pierre@pierr.com"
      },
        validator = {
          type: "regex",
          options: {}
        };
      it("should validate with a regex", function() {
        validator.value = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it("should invalidate with a regex", function() {
        property.value = "sjhbcbdjbvjhds";
        validator.value = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        var validationResult = validate(property, [validator]);
        //console.log(validationResult);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value', property.value);
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors').to.be.an('Array');
        //console.log('Validation results: %j', validationResult);
      });
    });
    describe('##function', function() {
      var property = {
        name: "bool"
      },
        validator = {
          type: "function",
          options: {}
        };
      it("Simple function should test its a bool true.", function() {
        property.value = true;
        validator.value = function(prop, opt) {
          opt = opt || {};
          return prop === true;
        };
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it("Simple function should test its a bool false.", function() {
        property.value = false;
        validator.value = function(prop, opt) {
          opt = opt || {};
          return prop === true;
        };
        var validationResult = validate(property, [validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors').be.an("Array");
        //console.log('Validation results: %j', validationResult);
      });
    });
    describe('##two validator', function() {
      var property = {
        name: "bool"
      },
        validator = {
          type: "function",
          options: {}
        }, validator2 = {
          type: "function",
          options: {}
        };
      it("Two validators, two ok.", function() {
        property.value = true;
        validator.value = function(prop, opt) {
          opt = opt || {};
          return prop === true;
        };
        var validationResult = validate(property, [validator, validator]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined).empty;
      });
      it("Two validators, one ok, one wrong", function() {
        property.value = false;
        validator.value = function(prop, opt) {
          return prop === true;
        };
        validator2.value = function(prop, opt) {
          return prop === false;
        };
        var validationResult = validate(property, [validator, validator2]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors').be.an("Array").and.have.length(1);
      });
      it("Two validators, two wrong", function() {
        property.value = true;
        validator.value = function(prop, opt) {
          return prop === false;
        };
        validator2.value = function(prop, opt) {
          return prop === false;
        };
        var validationResult = validate(property, [validator, validator2]);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', false);
        validationResult.should.have.property('errors').be.an("Array").and.have.length(2);
      });
    });
describe('##No validator', function() {
      var property = {
        name: "bool"
      },
        validator = {
          type: "function",
          options: {}
        }, validator2 = {
          type: "function",
          options: {}
        };
      it("No validators should be ok.", function() {
        property.value = true;
        var validationResult = validate(property);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
      it("An empty array of validators should be ok.", function() {
        property.value = true;
        var validationResult = validate(property, []);
        validationResult.should.be.an('object');
        validationResult.should.have.property('name', property.name);
        validationResult.should.have.property('value');
        validationResult.should.have.property('isValid', true);
        validationResult.should.have.property('errors', undefined);
      });
    });
  });
});<|endoftext|>


<commit_before>var global      = require('./global');
var speakingurl = require('speakingurl');
var moment      = require('moment');
var pikaday     = require('pikaday');

module.exports = {};

var app_data = {};

var current_ajax_requests = {};

function initSlugs() {
	$('[data-type="slug"]').each(function(idx, item) {
		var generate_from = $('[data-name="' + item.dataset.slugGenerateFrom + '"]', $(item).closest('.tab'));
		generate_from = (generate_from.length == 0 ? null : $(generate_from.get(0)));
		if (generate_from.length == 0) return;

		$(item).change(function() {
			this.dataset.slugIsEmpty = (this.value.length == 0 ? 'true' : 'false');

			if (generate_from == null) return;

			if (this.dataset.slugIsEmpty == 'true')
			{
				updateSlug($(item), $(generate_from));
			}
			checkSlug($(item));
		});

		if (generate_from != null)
		{
			generate_from.keyup(function() {
				updateSlug($(item), generate_from);

				//TODO maybe delay calling checkSlug?
				checkSlug($(item));
			});
			updateSlug($(item), generate_from);
		}
	});
}

function updateSlug(slug_field, generate_from_field) {
	if (slug_field.get(0).dataset.slugIsEmpty == 'false') return;
	slug_field.val(speakingurl(generate_from_field.val()));
}

function checkSlug(slug_field) {
	var value = slug_field.val();
	var name = slug_field.attr('name');

	if (current_ajax_requests[name] != undefined)
	{
		current_ajax_requests[name].abort();
		current_ajax_requests[name] = undefined;
	}

	var field = $('.field[data-name="' + slug_field.attr('name') + '"]');
	var error_label = $('.error-label', field);

	if (value.length == 0)
	{
		error_label.html(app_data.trans.errors.slug_empty);
		markSlugField(slug_field, true);
	}
	else
	{
		var icon_div = $('.field[data-name="' + name + '"] .ui.icon.input');
		icon_div.addClass('loading');
		field.addClass('loading');

		var post_data = {
			value: value,
			id_language: slug_field.data('id-language'),
			id_item: app_data.config.id_item
		};

		current_ajax_requests[name] = $.post(app_data.config.check_slug_route, post_data,
			function(data) {
			current_ajax_requests[name] = undefined;

			//TODO check for generic errors, like TokenMismatch (should catch it in Error handler of ajax response); do sth smart in that case .. like .. reload?

			error_label.html(app_data.trans.errors.slug_already_exists);
			markSlugField(slug_field, !data.valid);
		}, 'json');
	}
}

function markSlugField(slug_field, is_error) {
	var field = $('.field[data-name="' + slug_field.attr('name') + '"]');
	var icon_div = $('.field[data-name="' + slug_field.attr('name') + '"] .ui.icon.input');
	var icon = $('.field[data-name="' + slug_field.attr('name') + '"] .ui.icon.input .icon');

	icon_div.removeClass('loading');
	field.removeClass('loading');
	if (is_error)
	{
		field.addClass('error');
		icon.removeClass('checkmark').addClass('remove');
	}
	else
	{
		field.removeClass('error');
		icon.removeClass('remove').addClass('checkmark');
	}
}

function initValidation() {
	$('.validation-required, .validation-int').change(function() {
		validateItem($(this));
	}).keyup(function() {
		validateItem($(this));
	});
}

function validateItem(item) {
	var name        = item.attr('name');
	var field       = $('.field[data-name="' + name + '"]');
	var error_label = $('.error-label', field);

	var error = '';
	if (item.hasClass('validation-required'))
	{
		var value = item.val();
		if (value.length == 0)
		{
			error = app_data.trans.errors.validation_required;
		}
	}

	if (item.hasClass('validation-int') || item.hasClass('validation-float'))
	{
		var value = item.val();
		if (value.length > 0 && isNaN(value))
		{
			error = app_data.trans.errors.validation_number;
		}
	}

	if (error == '')
	{
		field.removeClass('error');
	}
	else
	{
		field.addClass('error');
		error_label.html(error);
	}
}

function initSaveButton() {
	$('form.add').submit(function(e) {
		//if we're still loading stuff, don't continue
		if ($('.field.loading').length > 0)
		{
			e.preventDefault();
			//TODO inform user why nothing is happening
			return;
		}

		//if there are errors on the form, tell that to the user, and don't continue
		if ($('.field.error').length > 0)
		{
			e.preventDefault();

			$('.errors-modal').modal({
				blurring: true
			}).modal('show');

			return;
		}

		if ($('.preview-button').hasClass('loading'))
		{
			$('.preview-button').removeClass('loading');
		}
		else
		{
			$('.save-button').addClass('loading').attr('disabled', 'disabled');
		}
	});

	$('.preview-button').click(function() {
		$('.preview-button').addClass('loading');
	});
}

function initMessageClose() {
	$('.message .close').on('click', function() {
		$(this).parent().transition('fade down');
	});
}

function initRichEditors() {
	var is_mobile = ($(window).width() < 768);
	var remove_buttons = is_mobile ?
		'Print,Preview,Save,Templates,NewPage,Find,Replace,SelectAll,Scayt,Form,Checkbox,Radio,TextField,Textarea,Select,Button,ImageButton,HiddenField,Language,BidiRtl,BidiLtr,About,Source,Cut,Copy,Paste,PasteText,PasteFromWord,Outdent,Indent,Blockquote,CreateDiv,Flash,SpecialChar,Smiley,PageBreak,Iframe,ShowBlocks'
		:
		'Print,Preview,Save,Templates,Find,Replace,SelectAll,Scayt,Form,Checkbox,Radio,TextField,Textarea,Select,Button,ImageButton,HiddenField,Language,BidiRtl,BidiLtr,About,Flash,NewPage';

	var file_browser_base_href = app_data.config.base_url + '/vendor/common/admin_assets/js/ckeditor/plugins/kcfinder/';

	$('textarea[data-type="rich_text"]').each(function(idx, el) {
		CKEDITOR.replace(el, {
			entities: false,
			baseHref: app_data.config.base_url,
			toolbarGroups: [
				{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
				{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
				{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker', 'editing' ] },
				{ name: 'forms', groups: [ 'forms' ] },
				{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
				{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi', 'paragraph' ] },
				'/',
				{ name: 'links', groups: [ 'links' ] },
				{ name: 'insert', groups: [ 'insert' ] },
				{ name: 'styles', groups: [ 'styles' ] },
				{ name: 'colors', groups: [ 'colors' ] },
				{ name: 'tools', groups: [ 'tools' ] },
				{ name: 'others', groups: [ 'others' ] },
				{ name: 'about', groups: [ 'about' ] }
			],
			removeButtons: remove_buttons,
			filebrowserBrowseUrl: file_browser_base_href + 'browse.php?opener=ckeditor&type=files',
			filebrowserImageBrowseUrl: file_browser_base_href + 'browse.php?opener=ckeditor&type=images',
			filebrowserFlashBrowseUrl: file_browser_base_href + 'browse.php?opener=ckeditor&type=flash',
			filebrowserUploadUrl: file_browser_base_href + 'upload.php?opener=ckeditor&type=files',
			filebrowserImageUploadUrl: file_browser_base_href + 'upload.php?opener=ckeditor&type=images',
			filebrowserFlashUploadUrl: file_browser_base_href + 'upload.php?opener=ckeditor&type=flash'
		});
	});
}

function initCheckboxes() {
	$('.ui.checkbox').checkbox({
		onChange: function() {
			$('[name="' + this.dataset.name + '"]').val(this.checked ? 'true' : 'false');
		}
	});
}

function initTabs() {
	$('.menu .item').tab();
}

function initDatePicker() {
	moment.locale(window.navigator.language);

	$('[data-type="date"]').each(function(index, item) {
		var picker = new pikaday({
			field: item,
			firstDay: 1,
			format: app_data.config.formatter_date_pattern,
			onSelect: function(date) {
				$('[name="' + item.dataset.dateRel + '"]').val(moment(date).format('YYYY-MM-DD'));
			}
		});
	});
}

function initMessages() {
	app_data.config.messages.forEach(function(message) {
		global.showToast('success', message);
	});
}

function initErrorMessages() {
	app_data.config.errors.forEach(function(message) {
		global.showToast('error', message);
	});
}

function initDropdowns() {
	$('.ui.dropdown').dropdown({
		placeholder: false
	});
}

module.exports.init = function(trans, config) {
	app_data.trans = trans;
	app_data.config = config;

	$(document).ready(function() {
		initSlugs();
		initValidation();
		initSaveButton();
		initMessageClose();
		initRichEditors();
		initCheckboxes();
		initTabs();
		initDatePicker();
		initMessages();
		initErrorMessages();
		initDropdowns();
	});
};
<commit_msg>Validation fix - validation now runs before save<commit_after>var global      = require('./global');
var speakingurl = require('speakingurl');
var moment      = require('moment');
var pikaday     = require('pikaday');

module.exports = {};

var app_data = {};

var current_ajax_requests = {};

function initSlugs() {
	$('[data-type="slug"]').each(function(idx, item) {
		var generate_from = $('[data-name="' + item.dataset.slugGenerateFrom + '"]', $(item).closest('.tab'));
		generate_from = (generate_from.length == 0 ? null : $(generate_from.get(0)));
		if (generate_from.length == 0) return;

		$(item).change(function() {
			this.dataset.slugIsEmpty = (this.value.length == 0 ? 'true' : 'false');

			if (generate_from == null) return;

			if (this.dataset.slugIsEmpty == 'true')
			{
				updateSlug($(item), $(generate_from));
			}
			checkSlug($(item));
		});

		if (generate_from != null)
		{
			generate_from.keyup(function() {
				updateSlug($(item), generate_from);

				//TODO maybe delay calling checkSlug?
				checkSlug($(item));
			});
			updateSlug($(item), generate_from);
		}
	});
}

function updateSlug(slug_field, generate_from_field) {
	if (slug_field.get(0).dataset.slugIsEmpty == 'false') return;
	slug_field.val(speakingurl(generate_from_field.val()));
}

function checkSlug(slug_field) {
	var value = slug_field.val();
	var name = slug_field.attr('name');

	if (current_ajax_requests[name] != undefined)
	{
		current_ajax_requests[name].abort();
		current_ajax_requests[name] = undefined;
	}

	var field = $('.field[data-name="' + slug_field.attr('name') + '"]');
	var error_label = $('.error-label', field);

	if (value.length == 0)
	{
		error_label.html(app_data.trans.errors.slug_empty);
		markSlugField(slug_field, true);
	}
	else
	{
		var icon_div = $('.field[data-name="' + name + '"] .ui.icon.input');
		icon_div.addClass('loading');
		field.addClass('loading');

		var post_data = {
			value: value,
			id_language: slug_field.data('id-language'),
			id_item: app_data.config.id_item
		};

		current_ajax_requests[name] = $.post(app_data.config.check_slug_route, post_data,
			function(data) {
			current_ajax_requests[name] = undefined;

			//TODO check for generic errors, like TokenMismatch (should catch it in Error handler of ajax response); do sth smart in that case .. like .. reload?

			error_label.html(app_data.trans.errors.slug_already_exists);
			markSlugField(slug_field, !data.valid);
		}, 'json');
	}
}

function markSlugField(slug_field, is_error) {
	var field = $('.field[data-name="' + slug_field.attr('name') + '"]');
	var icon_div = $('.field[data-name="' + slug_field.attr('name') + '"] .ui.icon.input');
	var icon = $('.field[data-name="' + slug_field.attr('name') + '"] .ui.icon.input .icon');

	icon_div.removeClass('loading');
	field.removeClass('loading');
	if (is_error)
	{
		field.addClass('error');
		icon.removeClass('checkmark').addClass('remove');
	}
	else
	{
		field.removeClass('error');
		icon.removeClass('remove').addClass('checkmark');
	}
}

var validation_selector = '.validation-required, .validation-int';
function initValidation() {
	$(validation_selector).change(function() {
		validateItem($(this));
	}).keyup(function() {
		validateItem($(this));
	});
}

function validateItems() {
	$(validation_selector).each(function(idx, item) {
		validateItem($(item));
	});
}

function validateItem(item) {
	var name        = item.attr('name');
	var field       = $('.field[data-name="' + name + '"]');
	var error_label = $('.error-label', field);

	var error = '';
	if (item.hasClass('validation-required'))
	{
		var value = item.val();
		if (value.length == 0)
		{
			error = app_data.trans.errors.validation_required;
		}
	}

	if (item.hasClass('validation-int') || item.hasClass('validation-float'))
	{
		var value = item.val();
		if (value.length > 0 && isNaN(value))
		{
			error = app_data.trans.errors.validation_number;
		}
	}

	if (error == '')
	{
		field.removeClass('error');
	}
	else
	{
		field.addClass('error');
		error_label.html(error);
	}
}

function initSaveButton() {
	$('form.add').submit(function(e) {
		//if we're still loading stuff, don't continue
		if ($('.field.loading').length > 0)
		{
			e.preventDefault();
			//TODO inform user why nothing is happening
			return;
		}

		validateItems();

		//if there are errors on the form, tell that to the user, and don't continue
		if ($('.field.error').length > 0)
		{
			e.preventDefault();

			$('.errors-modal').modal({
				blurring: true
			}).modal('show');

			return;
		}

		if ($('.preview-button').hasClass('loading'))
		{
			$('.preview-button').removeClass('loading');
		}
		else
		{
			$('.save-button').addClass('loading').attr('disabled', 'disabled');
		}
	});

	$('.preview-button').click(function() {
		$('.preview-button').addClass('loading');
	});
}

function initMessageClose() {
	$('.message .close').on('click', function() {
		$(this).parent().transition('fade down');
	});
}

function initRichEditors() {
	var is_mobile = ($(window).width() < 768);
	var remove_buttons = is_mobile ?
		'Print,Preview,Save,Templates,NewPage,Find,Replace,SelectAll,Scayt,Form,Checkbox,Radio,TextField,Textarea,Select,Button,ImageButton,HiddenField,Language,BidiRtl,BidiLtr,About,Source,Cut,Copy,Paste,PasteText,PasteFromWord,Outdent,Indent,Blockquote,CreateDiv,Flash,SpecialChar,Smiley,PageBreak,Iframe,ShowBlocks'
		:
		'Print,Preview,Save,Templates,Find,Replace,SelectAll,Scayt,Form,Checkbox,Radio,TextField,Textarea,Select,Button,ImageButton,HiddenField,Language,BidiRtl,BidiLtr,About,Flash,NewPage';

	var file_browser_base_href = app_data.config.base_url + '/vendor/common/admin_assets/js/ckeditor/plugins/kcfinder/';

	$('textarea[data-type="rich_text"]').each(function(idx, el) {
		CKEDITOR.replace(el, {
			entities: false,
			baseHref: app_data.config.base_url,
			toolbarGroups: [
				{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
				{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
				{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker', 'editing' ] },
				{ name: 'forms', groups: [ 'forms' ] },
				{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
				{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi', 'paragraph' ] },
				'/',
				{ name: 'links', groups: [ 'links' ] },
				{ name: 'insert', groups: [ 'insert' ] },
				{ name: 'styles', groups: [ 'styles' ] },
				{ name: 'colors', groups: [ 'colors' ] },
				{ name: 'tools', groups: [ 'tools' ] },
				{ name: 'others', groups: [ 'others' ] },
				{ name: 'about', groups: [ 'about' ] }
			],
			removeButtons: remove_buttons,
			filebrowserBrowseUrl: file_browser_base_href + 'browse.php?opener=ckeditor&type=files',
			filebrowserImageBrowseUrl: file_browser_base_href + 'browse.php?opener=ckeditor&type=images',
			filebrowserFlashBrowseUrl: file_browser_base_href + 'browse.php?opener=ckeditor&type=flash',
			filebrowserUploadUrl: file_browser_base_href + 'upload.php?opener=ckeditor&type=files',
			filebrowserImageUploadUrl: file_browser_base_href + 'upload.php?opener=ckeditor&type=images',
			filebrowserFlashUploadUrl: file_browser_base_href + 'upload.php?opener=ckeditor&type=flash'
		});
	});
}

function initCheckboxes() {
	$('.ui.checkbox').checkbox({
		onChange: function() {
			$('[name="' + this.dataset.name + '"]').val(this.checked ? 'true' : 'false');
		}
	});
}

function initTabs() {
	$('.menu .item').tab();
}

function initDatePicker() {
	moment.locale(window.navigator.language);

	$('[data-type="date"]').each(function(index, item) {
		var picker = new pikaday({
			field: item,
			firstDay: 1,
			format: app_data.config.formatter_date_pattern,
			onSelect: function(date) {
				$('[name="' + item.dataset.dateRel + '"]').val(moment(date).format('YYYY-MM-DD'));
			}
		});
	});
}

function initMessages() {
	app_data.config.messages.forEach(function(message) {
		global.showToast('success', message);
	});
}

function initErrorMessages() {
	app_data.config.errors.forEach(function(message) {
		global.showToast('error', message);
	});
}

function initDropdowns() {
	$('.ui.dropdown').dropdown({
		placeholder: false
	});
}

module.exports.init = function(trans, config) {
	app_data.trans = trans;
	app_data.config = config;

	$(document).ready(function() {
		initSlugs();
		initValidation();
		initSaveButton();
		initMessageClose();
		initRichEditors();
		initCheckboxes();
		initTabs();
		initDatePicker();
		initMessages();
		initErrorMessages();
		initDropdowns();
	});
};
<|endoftext|>


<commit_before>// Generate a single webpack bundle for all tests for faster testing
// See https://github.com/webpack/karma-webpack#alternative-usage

// Include all files that end with .test.js (core tests)
var context = require.context('.', true, /.*test\.js$/); //make sure you have your directory and regex test set correctly!
context.keys().forEach(context);

// Include all files in the addons directory that end with .test.js
var addonContext = require.context('../../../addons/', true, /.*test\.js$/); //make sure you have your directory and regex test set correctly!
addonContext.keys().forEach(addonContext);
<commit_msg>Configure Raven with a fake DSN to prevent errors in output<commit_after>// Generate a single webpack bundle for all tests for faster testing
// See https://github.com/webpack/karma-webpack#alternative-usage

// Configure raven with a fake DSN to avoid errors in test output
var Raven = require('raven-js');
Raven.config('http://abc@example.com:80/2');

// Include all files that end with .test.js (core tests)
var context = require.context('.', true, /.*test\.js$/); //make sure you have your directory and regex test set correctly!
context.keys().forEach(context);

// Include all files in the addons directory that end with .test.js
var addonContext = require.context('../../../addons/', true, /.*test\.js$/); //make sure you have your directory and regex test set correctly!
addonContext.keys().forEach(addonContext);
<|endoftext|>


<commit_before>// Module is used for Iframework.Library and has info about ins and outs
// Node is used by Graph, and has info about x, y, w, h

$(function(){

  var library = {
    image: [
      {"src":"meemoo:image/cam","info":{"title":"cam","author":"meemoo","description":"HTML5 webcam with getUserMedia."}},
      {"src":"meemoo:image/transform","info":{"title":"transform","author":"meemoo","description":"scale, translate, and/or rotate image (centered)"}},
      {"src":"meemoo:image/fit","info":{"title":"fit","author":"meemoo","description":"scale and crop an image to fit the given size. easy way to make thumbnails."}},
      {"src":"meemoo:image/crop","info":{"title":"crop","author":"meemoo","description":"crop an image to a rectangle"}},
      {"src":"meemoo:image/rectangle","info":{"title":"rectangle","author":"meemoo","description":"draw a rectangle"}},
      {"src":"meemoo:image/circle","info":{"title":"circle","author":"meemoo","description":"draw a circle"}},
      {"src":"meemoo:image/text","info":{"title":"text","author":"meemoo","description":"draw text to a canvas"}},
      {"src":"meemoo:video/player","info":{"title":"video","author":"meemoo","description":"HTML5 video player"}},
      {"src":"meemoo:view/layers","info":{"title":"layers","author":"meemoo","description":"can get any of the canvases in the graph and make a stack of them"}}
    ],
    effects: [
      {"src":"meemoo:image/chromakey","info":{"title":"chromakey","author":"forresto, timtaubert","description":"greenscreen chromakey"}},
      {"src":"meemoo:image/lumakey","info":{"title":"lumakey","author":"forresto","description":"remove white or black, lumakey"}},
      {"src":"meemoo:image/grid","info":{"title":"grid","author":"forresto","description":"images stack up in a grid"}},
      {"src":"meemoo:image/interlace","info":{"title":"interlace","author":"forresto","description":"interlace images together"}},
      {"src":"meemoo:image/slitscan","info":{"title":"slitscan","author":"forresto","description":"slitscan effect"}},
      {"src":"meemoo:image/tile","info":{"title":"tile","author":"forresto","description":"tile to fill canvas, reflect mirror tile for seamless"}},
      {"src":"meemoo:image/particles","info":{"title":"particles","author":"forresto","description":"make a stream of particles from an image or spritesheet"}},
      {"src":"meemoo:image/trails","info":{"title":"trails","author":"forresto","description":"draws image without clearing, leaving motion trails"}},
      {"src":"meemoo:image/monochrome","info":{"title":"monochrome","author":"ticky+flickr+forresto","description":"monochrome by atkinson, bayer, floydsteinberg, or no dither"}}
    ],
    util: [
      {"src":"meemoo:util/stats","info":{"title":"stats.js","author":"mr.doob","description":"fps stats graph"}},
      {"src":"meemoo:image/palette","info":{"title":"palette","author":"nrabinowitz","description":"get color palette from image color quantize"}},
      {"src":"meemoo:util/color-hsla","info":{"title":"color-hsla","author":"meemoo","description":"make hsla() css color (hue, saturation, lightness, alpha)"}},
      {"src":"meemoo:util/math","info":{"title":"math","author":"silentmatt","description":"math equation evaluator"}}
    ],
    flow: [
      {"src":"meemoo:util/gate","info":{"title":"gate","author":"meemoo","description":"stop the data flow and let one through"}},
      {"src":"meemoo:time/throttle","info":{"title":"throttle","author":"meemoo","description":"too many fps? use throttle to limit data rate passing through flow."}},
      {"src":"meemoo:time/delay","info":{"title":"delay","author":"meemoo","description":"holds x values until the next one comes"}},
      {"src":"meemoo:util/count","info":{"title":"count","author":"meemoo","description":"count the times that the data input is hit"}}
    ],
    time: [
      {"src":"meemoo:time/tween","info":{"title":"tween","author":"sole","description":"Interpolate between two values."}},
      {"src":"meemoo:time/countdown","info":{"title":"countdown","author":"forresto","description":"Countdown to a bang."}},
      {"src":"meemoo:time/metronome","info":{"title":"metronome","author":"forresto","description":"Metronome beats per minute"}}
    ],
    file: [
      {"src":"meemoo:image/in","info":{"title":"image","author":"forresto","description":"hold a canvas or get image from url"}},
      {"src":"meemoo:file/webm","info":{"title":"webm","author":"antimatter15","description":"(Chrome only) Canvas to WebM video encoder thanks to antimatter15/whammy."}}
    ],
    ui: [
      {"src":"meemoo:ui/button","info":{"title":"button","author":"meemoo","description":"a button sends a bang, and you can attach a keyboard key"}},
      {"src":"meemoo:ui/hslider","info":{"title":"hslider","author":"meemoo","description":"horizontal slider"}},
      {"src":"meemoo:ui/vslider","info":{"title":"vslider","author":"meemoo","description":"vertical slider"}},
      {"src":"meemoo:ui/number","info":{"title":"number","author":"meemoo","description":"simple number box"}},
      {"src":"meemoo:ui/text","info":{"title":"text","author":"meemoo","description":"a text box to save and send text"}},
      {"src":"meemoo:ui/textarea","info":{"title":"textarea","author":"meemoo","description":"a multiline text box to edit and send text"}},
      {"src":"meemoo:ui/checkbox","info":{"title":"checkbox","author":"meemoo","description":"a checkbox to send boolean on/off"}},
      {"src":"meemoo:ui/xy","info":{"title":"xy pad","author":"meemoo","description":"sends coordinates as percentage"}},
      {"src":"meemoo:ui/mouse","info":{"title":"mouse","author":"meemoo","description":"sends mouse coordinates as percentage"}},
      {"src":"meemoo:ui/motion","info":{"title":"motion","author":"meemoo","description":"sends device motion (accelerometer) data as percentage (Chrome and iOS only)"}},
      {"src":"meemoo:ui/leap","info":{"title":"leap","author":"meemoo","description":"leap motion hand tracker"}},
      {"src":"meemoo:ui/facetracker","info":{"title":"facetracker","author":"meemoo","description":"checks image for face, sends coordinates"}}
    ],
    animation: [
      {"src":"meemoo:variable/animation","info":{"title":"animation","author":"meemoo","description":"holds a stack of canvases to use as an animation"}},
      {"src":"http://forresto.github.com/meemoo-canvas2gif/canvas2gif.html","info":{"title":"gif","author":"forresto","description":"canvas image data to animated gif"}}
    ],
    "iframe---fading": [
      {"src":"http://forresto.github.com/meemoo-camcanvas/onionskin.html","info":{"title":"cam+onionskin","author":"taboca + forresto + ginger","description":"flash webcam image to canvas with onionskin of last frame"}},
      // {"src":"http://forresto.github.com/meemoo-camcanvas/webcam2canvas.html","info":{"title":"cam","author":"taboca + Forrest Oliphant","description":"flash webcam image to canvas"}},
      // {"src":"http://forresto.github.com/meemoo-image/transform.html","info":{"title":"transform","author":"forresto","description":"scale, translate, and/or rotate image (centered)"}},
      // {"src":"http://forresto.github.com/meemoo-image/combine.html","info":{"title":"combine","author":"forresto","description":"combine image layers"}},
      // {"src":"http://forresto.github.com/meemoo-image/crop.html","info":{"title":"crop","author":"meemoo","description":"crop image"}},
      {"src":"http://forresto.github.com/meemoo-blend/blend.html","info":{"title":"blend","author":"forresto","description":"blend imageData under and over with given mode"}},
      // {"src":"http://forresto.github.com/meemoo-image/mask.html","info":{"title":"alpha mask","author":"forresto","description":"use a grayscale image as the alpha for another image"}},
      // {"src":"http://forresto.github.com/meemoo-image/threshold.html","info":{"title":"threshold","author":"forresto","description":"image to monochrome via luminosity threshold"}},
      // {"src":"http://forresto.github.com/meemoo-image/alpha.html","info":{"title":"alpha","author":"forresto","description":"use a greyscale image as the alpha for a color image"}},
      {"src":"http://forresto.github.com/meemoo-image/aviary.html","info":{"title":"aviary","author":"aviary","description":"aviary.com image editor with enhance, brightness, contrast, crop, paint, stickers, text..."}},
      {"src":"http://forresto.github.com/meemoo-paint/paint.html","info":{"title":"paint","author":"forresto","description":"canvas pixel paint"}},
      {"src":"http://automata.github.com/meemoo-harmony/","info":{"title":"harmony","author":"ze frank + mr.doob + automata","description":"sketchy procedural drawing tool"}},
      {"src":"http://forresto.github.com/meemoo-image/text.html","info":{"title":"text","author":"forresto","description":"text to image"}},
      // {"src":"http://forresto.github.com/meemoo-image/rectangle.html","info":{"title":"rectangle","author":"forresto","description":"draw a rectangle"}},
      // {"src":"http://forresto.github.com/meemoo-image/circle.html","info":{"title":"circle","author":"forresto","description":"draw a circle or an arc"}},
      {"src":"http://forresto.github.com/meemoo-modules/processing.html","info":{"title":"processing.js","description":"processing code loader"}},
      {"src":"http://forresto.github.com/meemoo-modules/canvasarray.html","info":{"title":"canvas array","author":"forresto","description":"hold a stack of canvases for reuse, click sends it, arrows navigate to prev/next"}},
      // {"src":"http://forresto.github.com/meemoo-image/spritesheet.html","info":{"title":"spritesheet","author":"forresto","description":"makes a single-image filmstrip sprite sheet"}},
      // {"src":"http://forresto.github.com/meemoo-image/spritesplit.html","info":{"title":"spritesplit","author":"forresto","description":"separates images from filmstrip sprite sheet"}}
      // {"src":"http://forresto.github.com/meemoo-math/math.html","info":{"title":"math","author":"silentmatt + forresto","description":"math equation evaluator"}},
      // {"src":"http://forresto.github.com/meemoo-modules/color-hsla.html","info":{"title":"color-hsla","author":"forresto","description":"make hsla() css color (hue, saturation, lightness, alpha)"}},
      // {"src":"http://forresto.github.com/meemoo-modules/color-rgba.html","info":{"title":"color-rgba","author":"forresto","description":"make rgba() css color (red, green, blue, alpha)"}},
      {"src":"http://forresto.github.com/meemoo-modules/string-join.html","info":{"title":"string-join","author":"forresto","description":"join text strings into one string"}},
      {"src":"http://forresto.github.com/meemoo-modules/log.html","info":{"title":"log","author":"meemoo","description":"log all messages"}},
      // {"src":"http://meemoo-image-in.phpfogapp.com/image-in.html","info":{"title":"image-in","author":"forresto","description":"Public image url to get the canvas pixel data."}},
      {"src":"http://forresto.github.com/meemoo-modules/file-reader-image.html","info":{"title":"image file","author":"forresto","description":"Select or drag local images to get the canvas pixel data. Requires a browser with the FileReader API, like Firefox or Chrome."}},
      {"src":"http://forresto.github.com/meemoo-modules/imgur.html","info":{"title":"imgur","author":"forresto","description":"image data url to Imgur image sharing service"}},
      // {"src":"http://forresto.github.com/meemoo-modules/img2canvas.html","info":{"title":"img2canvas","author":"forresto","description":"image data url to canvas image data"}},
      {"src":"http://forresto.github.com/meemoo-modules/canvas2img.html","info":{"title":"canvas2img","author":"forresto","description":"canvas image data to image data url"}},
      {"src":"http://forresto.github.com/meemoo-modules/delay.html","info":{"title":"delay","author":"forresto","description":"hold a stack of stack of data until buffer is full"}},
      // {"src":"http://forresto.github.com/meemoo-modules/timer.html","info":{"title":"timer","author":"forresto","description":"countdown to bang"}},
      {"src":"http://forresto.github.com/meemoo-modules/clock.html","info":{"title":"clock","author":"forresto","description":"time: hours minutes seconds with percentages"}},
      {"src":"http://forresto.github.com/meemoo-modules/metronome.html","info":{"title":"metronome","author":"forresto","description":"meemoo.js module for rhythm in bpm or ms"}},
      {"src":"http://forresto.github.com/meemoo-modules/taptempo.html","info":{"title":"taptempo","author":"forresto","description":"tap out your rhythm, averages last 4 taps"}},
      {"src":"http://forresto.github.com/meemoo-modules/audioarray.html","info":{"title":"audioarray","author":"forresto","description":"hold and address a stack of audio objects"}},
      {"src":"http://forresto.github.com/meemoo-modules/speech2text.html","info":{"title":"speech2text","author":"forresto","description":"speech to text with x-webkit-speech"}},
      {"src":"http://forresto.github.com/meemoo-speak.js/text2speech.html","info":{"title":"text2speech","author":"forresto","description":"text to speech with speak.js"}}
    ]
  };

  Iframework.loadLibrary(library);

});
<commit_msg>no file category<commit_after>// Module is used for Iframework.Library and has info about ins and outs
// Node is used by Graph, and has info about x, y, w, h

$(function(){

  var library = {
    image: [
      {"src":"meemoo:image/in","info":{"title":"image","author":"forresto","description":"hold a canvas or get image from url or service"}},
      {"src":"meemoo:image/cam","info":{"title":"cam","author":"meemoo","description":"HTML5 webcam with getUserMedia."}},
      {"src":"meemoo:image/transform","info":{"title":"transform","author":"meemoo","description":"scale, translate, and/or rotate image (centered)"}},
      {"src":"meemoo:image/fit","info":{"title":"fit","author":"meemoo","description":"scale and crop an image to fit the given size. easy way to make thumbnails."}},
      {"src":"meemoo:image/crop","info":{"title":"crop","author":"meemoo","description":"crop an image to a rectangle"}},
      {"src":"meemoo:image/rectangle","info":{"title":"rectangle","author":"meemoo","description":"draw a rectangle"}},
      {"src":"meemoo:image/circle","info":{"title":"circle","author":"meemoo","description":"draw a circle"}},
      {"src":"meemoo:image/text","info":{"title":"text","author":"meemoo","description":"draw text to a canvas"}},
      {"src":"meemoo:video/player","info":{"title":"video","author":"meemoo","description":"HTML5 video player"}},
      {"src":"meemoo:view/layers","info":{"title":"layers","author":"meemoo","description":"can get any of the canvases in the graph and make a stack of them"}}
    ],
    effects: [
      {"src":"meemoo:image/chromakey","info":{"title":"chromakey","author":"forresto, timtaubert","description":"greenscreen chromakey"}},
      {"src":"meemoo:image/lumakey","info":{"title":"lumakey","author":"forresto","description":"remove white or black, lumakey"}},
      {"src":"meemoo:image/grid","info":{"title":"grid","author":"forresto","description":"images stack up in a grid"}},
      {"src":"meemoo:image/interlace","info":{"title":"interlace","author":"forresto","description":"interlace images together"}},
      {"src":"meemoo:image/slitscan","info":{"title":"slitscan","author":"forresto","description":"slitscan effect"}},
      {"src":"meemoo:image/tile","info":{"title":"tile","author":"forresto","description":"tile to fill canvas, reflect mirror tile for seamless"}},
      {"src":"meemoo:image/particles","info":{"title":"particles","author":"forresto","description":"make a stream of particles from an image or spritesheet"}},
      {"src":"meemoo:image/trails","info":{"title":"trails","author":"forresto","description":"draws image without clearing, leaving motion trails"}},
      {"src":"meemoo:image/monochrome","info":{"title":"monochrome","author":"ticky+flickr+forresto","description":"monochrome by atkinson, bayer, floydsteinberg, or no dither"}}
    ],
    util: [
      {"src":"meemoo:util/stats","info":{"title":"stats.js","author":"mr.doob","description":"fps stats graph"}},
      {"src":"meemoo:image/palette","info":{"title":"palette","author":"nrabinowitz","description":"get color palette from image color quantize"}},
      {"src":"meemoo:util/color-hsla","info":{"title":"color-hsla","author":"meemoo","description":"make hsla() css color (hue, saturation, lightness, alpha)"}},
      {"src":"meemoo:util/math","info":{"title":"math","author":"silentmatt","description":"math equation evaluator"}}
    ],
    flow: [
      {"src":"meemoo:util/gate","info":{"title":"gate","author":"meemoo","description":"stop the data flow and let one through"}},
      {"src":"meemoo:time/throttle","info":{"title":"throttle","author":"meemoo","description":"too many fps? use throttle to limit data rate passing through flow."}},
      {"src":"meemoo:time/delay","info":{"title":"delay","author":"meemoo","description":"holds x values until the next one comes"}},
      {"src":"meemoo:util/count","info":{"title":"count","author":"meemoo","description":"count the times that the data input is hit"}}
    ],
    time: [
      {"src":"meemoo:time/tween","info":{"title":"tween","author":"sole","description":"Interpolate between two values."}},
      {"src":"meemoo:time/countdown","info":{"title":"countdown","author":"forresto","description":"Countdown to a bang."}},
      {"src":"meemoo:time/metronome","info":{"title":"metronome","author":"forresto","description":"Metronome beats per minute"}}
    ],
    ui: [
      {"src":"meemoo:ui/button","info":{"title":"button","author":"meemoo","description":"a button sends a bang, and you can attach a keyboard key"}},
      {"src":"meemoo:ui/hslider","info":{"title":"hslider","author":"meemoo","description":"horizontal slider"}},
      {"src":"meemoo:ui/vslider","info":{"title":"vslider","author":"meemoo","description":"vertical slider"}},
      {"src":"meemoo:ui/number","info":{"title":"number","author":"meemoo","description":"simple number box"}},
      {"src":"meemoo:ui/text","info":{"title":"text","author":"meemoo","description":"a text box to save and send text"}},
      {"src":"meemoo:ui/textarea","info":{"title":"textarea","author":"meemoo","description":"a multiline text box to edit and send text"}},
      {"src":"meemoo:ui/checkbox","info":{"title":"checkbox","author":"meemoo","description":"a checkbox to send boolean on/off"}},
      {"src":"meemoo:ui/xy","info":{"title":"xy pad","author":"meemoo","description":"sends coordinates as percentage"}},
      {"src":"meemoo:ui/mouse","info":{"title":"mouse","author":"meemoo","description":"sends mouse coordinates as percentage"}},
      {"src":"meemoo:ui/motion","info":{"title":"motion","author":"meemoo","description":"sends device motion (accelerometer) data as percentage (Chrome and iOS only)"}},
      {"src":"meemoo:ui/leap","info":{"title":"leap","author":"meemoo","description":"leap motion hand tracker"}},
      {"src":"meemoo:ui/facetracker","info":{"title":"facetracker","author":"meemoo","description":"checks image for face, sends coordinates"}}
    ],
    animation: [
      {"src":"meemoo:variable/animation","info":{"title":"animation","author":"meemoo","description":"holds a stack of canvases to use as an animation"}},
      {"src":"http://forresto.github.com/meemoo-canvas2gif/canvas2gif.html","info":{"title":"gif","author":"forresto","description":"canvas image data to animated gif"}},
      {"src":"meemoo:file/webm","info":{"title":"webm","author":"antimatter15","description":"(Chrome only) Canvas to WebM video encoder thanks to antimatter15/whammy."}}
    ],
    "iframe---fading": [
      {"src":"http://forresto.github.com/meemoo-camcanvas/onionskin.html","info":{"title":"cam+onionskin","author":"taboca + forresto + ginger","description":"flash webcam image to canvas with onionskin of last frame"}},
      // {"src":"http://forresto.github.com/meemoo-camcanvas/webcam2canvas.html","info":{"title":"cam","author":"taboca + Forrest Oliphant","description":"flash webcam image to canvas"}},
      // {"src":"http://forresto.github.com/meemoo-image/transform.html","info":{"title":"transform","author":"forresto","description":"scale, translate, and/or rotate image (centered)"}},
      // {"src":"http://forresto.github.com/meemoo-image/combine.html","info":{"title":"combine","author":"forresto","description":"combine image layers"}},
      // {"src":"http://forresto.github.com/meemoo-image/crop.html","info":{"title":"crop","author":"meemoo","description":"crop image"}},
      {"src":"http://forresto.github.com/meemoo-blend/blend.html","info":{"title":"blend","author":"forresto","description":"blend imageData under and over with given mode"}},
      // {"src":"http://forresto.github.com/meemoo-image/mask.html","info":{"title":"alpha mask","author":"forresto","description":"use a grayscale image as the alpha for another image"}},
      // {"src":"http://forresto.github.com/meemoo-image/threshold.html","info":{"title":"threshold","author":"forresto","description":"image to monochrome via luminosity threshold"}},
      // {"src":"http://forresto.github.com/meemoo-image/alpha.html","info":{"title":"alpha","author":"forresto","description":"use a greyscale image as the alpha for a color image"}},
      {"src":"http://forresto.github.com/meemoo-image/aviary.html","info":{"title":"aviary","author":"aviary","description":"aviary.com image editor with enhance, brightness, contrast, crop, paint, stickers, text..."}},
      {"src":"http://forresto.github.com/meemoo-paint/paint.html","info":{"title":"paint","author":"forresto","description":"canvas pixel paint"}},
      {"src":"http://automata.github.com/meemoo-harmony/","info":{"title":"harmony","author":"ze frank + mr.doob + automata","description":"sketchy procedural drawing tool"}},
      {"src":"http://forresto.github.com/meemoo-image/text.html","info":{"title":"text","author":"forresto","description":"text to image"}},
      // {"src":"http://forresto.github.com/meemoo-image/rectangle.html","info":{"title":"rectangle","author":"forresto","description":"draw a rectangle"}},
      // {"src":"http://forresto.github.com/meemoo-image/circle.html","info":{"title":"circle","author":"forresto","description":"draw a circle or an arc"}},
      {"src":"http://forresto.github.com/meemoo-modules/processing.html","info":{"title":"processing.js","description":"processing code loader"}},
      {"src":"http://forresto.github.com/meemoo-modules/canvasarray.html","info":{"title":"canvas array","author":"forresto","description":"hold a stack of canvases for reuse, click sends it, arrows navigate to prev/next"}},
      // {"src":"http://forresto.github.com/meemoo-image/spritesheet.html","info":{"title":"spritesheet","author":"forresto","description":"makes a single-image filmstrip sprite sheet"}},
      // {"src":"http://forresto.github.com/meemoo-image/spritesplit.html","info":{"title":"spritesplit","author":"forresto","description":"separates images from filmstrip sprite sheet"}}
      // {"src":"http://forresto.github.com/meemoo-math/math.html","info":{"title":"math","author":"silentmatt + forresto","description":"math equation evaluator"}},
      // {"src":"http://forresto.github.com/meemoo-modules/color-hsla.html","info":{"title":"color-hsla","author":"forresto","description":"make hsla() css color (hue, saturation, lightness, alpha)"}},
      // {"src":"http://forresto.github.com/meemoo-modules/color-rgba.html","info":{"title":"color-rgba","author":"forresto","description":"make rgba() css color (red, green, blue, alpha)"}},
      {"src":"http://forresto.github.com/meemoo-modules/string-join.html","info":{"title":"string-join","author":"forresto","description":"join text strings into one string"}},
      {"src":"http://forresto.github.com/meemoo-modules/log.html","info":{"title":"log","author":"meemoo","description":"log all messages"}},
      // {"src":"http://meemoo-image-in.phpfogapp.com/image-in.html","info":{"title":"image-in","author":"forresto","description":"Public image url to get the canvas pixel data."}},
      {"src":"http://forresto.github.com/meemoo-modules/file-reader-image.html","info":{"title":"image file","author":"forresto","description":"Select or drag local images to get the canvas pixel data. Requires a browser with the FileReader API, like Firefox or Chrome."}},
      {"src":"http://forresto.github.com/meemoo-modules/imgur.html","info":{"title":"imgur","author":"forresto","description":"image data url to Imgur image sharing service"}},
      // {"src":"http://forresto.github.com/meemoo-modules/img2canvas.html","info":{"title":"img2canvas","author":"forresto","description":"image data url to canvas image data"}},
      {"src":"http://forresto.github.com/meemoo-modules/canvas2img.html","info":{"title":"canvas2img","author":"forresto","description":"canvas image data to image data url"}},
      {"src":"http://forresto.github.com/meemoo-modules/delay.html","info":{"title":"delay","author":"forresto","description":"hold a stack of stack of data until buffer is full"}},
      // {"src":"http://forresto.github.com/meemoo-modules/timer.html","info":{"title":"timer","author":"forresto","description":"countdown to bang"}},
      {"src":"http://forresto.github.com/meemoo-modules/clock.html","info":{"title":"clock","author":"forresto","description":"time: hours minutes seconds with percentages"}},
      {"src":"http://forresto.github.com/meemoo-modules/metronome.html","info":{"title":"metronome","author":"forresto","description":"meemoo.js module for rhythm in bpm or ms"}},
      {"src":"http://forresto.github.com/meemoo-modules/taptempo.html","info":{"title":"taptempo","author":"forresto","description":"tap out your rhythm, averages last 4 taps"}},
      {"src":"http://forresto.github.com/meemoo-modules/audioarray.html","info":{"title":"audioarray","author":"forresto","description":"hold and address a stack of audio objects"}},
      {"src":"http://forresto.github.com/meemoo-modules/speech2text.html","info":{"title":"speech2text","author":"forresto","description":"speech to text with x-webkit-speech"}},
      {"src":"http://forresto.github.com/meemoo-speak.js/text2speech.html","info":{"title":"text2speech","author":"forresto","description":"text to speech with speak.js"}}
    ]
  };

  Iframework.loadLibrary(library);

});
<|endoftext|>


<commit_before>(function() {
  'use strict';

  angular.module('Core')
    .service('smoothScrollService', smoothScrollService);

  smoothScrollService.$inject = ['commonService'];

  function smoothScrollService(commonService) {
    var service = this;
    service.scrollToElementId = scrollToElementId;

    /* ======================================== Var ==================================================== */
    service.userData = {

    };

    /* ======================================== Services =============================================== */

    /* ======================================== Public Methods ========================================= */
    function scrollToElementId(elementId, isRelativeToWindow) {
      var startYPos = currentYPosition();
      var targetYPos;
      if(isRelativeToWindow === true) {
        targetYPos = targetYPositionToWindow(elementId);
      } else {
        targetYPos = targetYPositionToElement(elementId);
      }
      var distance = targetYPos > startYPos ? (targetYPos - startYPos) : (startYPos - targetYPos);
      if (distance < 100) {
        scrollTo(0, targetYPos);
        return;
      }

      var speed = Math.round(distance / 100);
      if (speed >= 20) {
        speed = 20;
      }
      var step = Math.round(distance / 25);
      var leapY = targetYPos > startYPos ? (startYPos + step) : startYPos - step;
      var timer = 0;
      if (targetYPos > startYPos) {
        for (var i = startYPos; i < targetYPos; i += step) {
          if(isRelativeToWindow === true) {
            setTimeout("window.scrollTo(0, " + leapY + ")", timer * speed);
          } else {
            setTimeout(function() {
              document.getElementById(elementId).scrollTop = leapY;
            }, timer * speed);
          }
          leapY += step;
          if (leapY > targetYPos) leapY = targetYPos;
          timer++;
        }
        return;
      }
      for (var i = startYPos; i > targetYPos; i -= step) {
        if(isRelativeToWindow === true) {
          setTimeout("window.scrollTo(0, " + leapY + ")", timer * speed);
        } else {
          setTimeout(function() {
            document.getElementById(elementId).scrollTop = leapY;
          }, timer * speed);
        }
        leapY -= step;
        if (leapY < targetYPos) {
          leapY = targetYPos;
        }
        timer++;
      }
    }

    /* ======================================== Private Methods ======================================== */
    function targetYPositionToElement(elementId) {
      return document.getElementById(elementId).scrollHeight;
    }

    function targetYPositionToWindow(elementId) {
      var element = document.getElementById(elementId);
      var y = element.offsetTop;
      var node = element;
      while (node.offsetParent && (node.offsetParent != document.body)) {
        node = node.offsetParent;
        y += node.offsetTop;
      }
      return y;
    }

    function currentYPosition() {
      // Firefox, Chrome, Opera, Safari
      if (self.pageYOffset) {
        return self.pageYOffset;
      }

      // Internet Explorer 6 - standards mode
      if (document.documentElement && document.documentElement.scrollTop) {
        return document.documentElement.scrollTop;
      }

      // Internet Explorer 6, 7 and 8
      if (document.body.scrollTop) {
        return document.body.scrollTop;
      }

      return 0;
    }

    function init() {

    }

    init();
  }
})();
<commit_msg>smoothScroll: Update to scroll within a div<commit_after>(function() {
  'use strict';

  angular.module('Core')
      .service('smoothScrollService', smoothScrollService);

  smoothScrollService.$inject = ['commonService'];

  function smoothScrollService(commonService) {
    var service = this;
    service.scrollToElementId = scrollToElementId;

    /* ======================================== Var ==================================================== */
    service.userData = {

    };

    var docEle;

    /* ======================================== Services =============================================== */

    /* ======================================== Public Methods ========================================= */
    function scrollToElementId(elementId, isRelativeToWindow) {
      docEle = document.getElementById(elementId);
      if(docEle === null || docEle === undefined) {
        return;
      }
      var startYPos = currentYPosition();
      var targetYPos;
      if(isRelativeToWindow === true) {
        targetYPos = targetYPositionToWindow();
      } else {
        targetYPos = targetYPositionToElement();
      }

      var distance = targetYPos > startYPos ? (targetYPos - startYPos) : (startYPos - targetYPos);
      if (distance < 100) {
        scrollTo(0, targetYPos);
        return;
      }

      var speed = Math.round(distance / 100);
      if (speed >= 20) {
        speed = 20;
      }
      var step = Math.round(distance / 25);
      var leapY = targetYPos > startYPos ? (startYPos + step) : startYPos - step;
      var timer = 0;
      if (targetYPos > startYPos) {
        for (var i = startYPos; i < targetYPos; i += step) {
          if(isRelativeToWindow === true) {
            setTimeout("window.scrollTo(0, " + leapY + ")", timer * speed);
          } else {
            setTimeout(function() {
              docEle.scrollTop = leapY;
            }, timer * speed);
          }

          leapY += step;
          if (leapY > targetYPos) leapY = targetYPos;
          timer++;
        }
        return;
      }
      for (var i = startYPos; i > targetYPos; i -= step) {
        if(isRelativeToWindow === true) {
          setTimeout("window.scrollTo(0, " + leapY + ")", timer * speed);
        } else {
          setTimeout(function() {
            docEle.scrollTop = leapY;
          }, timer * speed);
        }
        leapY -= step;
        if (leapY < targetYPos) {
          leapY = targetYPos;
        }
        timer++;
      }
    }

    /* ======================================== Private Methods ======================================== */
    function targetYPositionToElement() {
      return docEle.scrollHeight;
    }

    function targetYPositionToWindow() {
      var y = docEle.offsetTop;
      var node = docEle;
      while (node.offsetParent && (node.offsetParent != document.body)) {
        node = node.offsetParent;
        y += node.offsetTop;
      }
      return y;
    }

    function currentYPosition() {
      // Firefox, Chrome, Opera, Safari
      if (self.pageYOffset) {
        return self.pageYOffset;
      }

      // Internet Explorer 6 - standards mode
      if (document.documentElement && document.documentElement.scrollTop) {
        return document.documentElement.scrollTop;
      }

      // Internet Explorer 6, 7 and 8
      if (document.body.scrollTop) {
        return document.body.scrollTop;
      }

      return 0;
    }

    function init() {

    }

    init();
  }
})();<|endoftext|>