<commit_before>import Ember from 'ember';
import getOwner from 'ember-getowner-polyfill';

export default Ember.Component.extend({
  tagName: 'a',
  attributeBindings: ['href', 'target', 'title', 'rel', 'tabindex'],
  classNameBindings: ['className', 'activeClassName'],

  // You can either pass in the following attributes directly,
  // or you can pass them in nested inside the "params" hash.
  params: {},

  // HTML attributes -- href is defined below.
  rel: Ember.computed.alias('params.rel'),
  title: Ember.computed.alias('params.title'),
  target: Ember.computed.alias('params.target'),
  tabindex: Ember.computed.alias('params.tabindex'),
  className: Ember.computed.alias('params.className'),

  // Ember link-to style attributes
  route: Ember.computed.alias('params.route'),
  model: Ember.computed.alias('params.model'),
  action: Ember.computed.alias('params.action'),
  queryParams: Ember.computed.alias('params.queryParams'),

  // By default, dynamic links on active routes will have class "active", but
  // you can reopen this and set it to blank if you don't like that behavior.
  defaultActiveClass: 'active',

  // You can set an explicit activeClass like in link-to, as well, which can
  // also be passed in via the params hash.
  activeClass: Ember.computed.alias('params.activeClass'),
  activeWhen: Ember.computed.alias('params.activeWhen'),
  activeClassName: Ember.computed('isActive', 'activeClass', 'defaultActiveClass', function() {
    if (this.get('isActive') && this.get('activeClass') !== false) {
      return this.get('activeClass') || this.get('defaultActiveClass');
    }
  }),

  // You can control whether or not the click event bubbles up through the
  // component by setting this property directly or by setting it in the
  // params hash. If no value is set, all clicks will bubble by default.
  bubbles: Ember.computed.alias('params.bubbles'),

  models: Ember.computed('model', function() {
    if (this.get('model') instanceof Array) {
      return this.get('model');
    } else if (this.get('model')) {
      return [this.get('model')];
    } else {
      return [];
    }
  }),

  // These are the arguments to be passed to `transitionToRoute`. They consist
  // of a route name and then an optional model with optional query params.
  routeArguments: Ember.computed('route', 'models', 'queryParams', function() {
    var args = [this.get('route')].concat(this.get('models'));

    if (this.get('queryParams')) {
      args.push({ queryParams: this.get('queryParams') });
    }

    return args;
  }),

  // The href attribute of the link takes one of three forms.
  // If we have a literal href passed in, always defer to it.
  // If we have route parameters, try to construct the route's URL.
  // If we have an action, just '#' should do.
  href: Ember.computed('routeArguments', 'action', 'params.href', function() {
    if (this.get('params.href')) {
      return this.get('params.href');
    } else if (this.get('route')) {
      return this.get('_router').generate(...this.get('routeArguments'));
    } else {
      return '#';
    }
  }),

  // Use prevent default to keep route transitions and actions from
  // refreshing the page. Allows click behavior to bubble up if allowed
  // by the bubbles property
  click: function(event) {
    if ((this.get('action') || this.get('route')) && !(event.metaKey || event.ctrlKey)) {
      event.preventDefault();
      if (this.get('action')) {
        this.performAction();
      } else {
        this.transitionRoute();
      }
      return this.get('bubbles') !== false;
    } else {
      return true;
    }
  },

  // bubble the action to wherever the link was added
  performAction: function() {
    var target = this.get('targetObject') || this.get('_targetObject');
    if (target) {
      target.send(this.get('action'));
    }
  },

  _route: Ember.computed(function() {
    return getOwner(this).lookup('route:application');
  }),

  _router: Ember.computed.alias('_route.router'),

  // have the application route transition to the location
  // specified by the parameters
  transitionRoute: function() {
    this.get('_route').transitionTo(...this.get('routeArguments'));
  },

  isActive: Ember.computed('_router.currentState', 'activeWhen', function() {
    if (this.get('activeWhen') !== undefined) {
      return this.get('activeWhen');
    } else if (this.get('route') && this.get('_router.currentState')) {
      return this.get('_router').isActive(...this.get('routeArguments'));
    } else {
      return false;
    }
  })
});
<commit_msg>Use routing service if available<commit_after>import Ember from 'ember';
import getOwner from 'ember-getowner-polyfill';

export default Ember.Component.extend({
  tagName: 'a',
  attributeBindings: ['href', 'target', 'title', 'rel', 'tabindex'],
  classNameBindings: ['className', 'activeClassName'],

  // You can either pass in the following attributes directly,
  // or you can pass them in nested inside the "params" hash.
  params: {},

  // HTML attributes -- href is defined below.
  rel: Ember.computed.alias('params.rel'),
  title: Ember.computed.alias('params.title'),
  target: Ember.computed.alias('params.target'),
  tabindex: Ember.computed.alias('params.tabindex'),
  className: Ember.computed.alias('params.className'),

  // Ember link-to style attributes
  route: Ember.computed.alias('params.route'),
  model: Ember.computed.alias('params.model'),
  action: Ember.computed.alias('params.action'),
  queryParams: Ember.computed.alias('params.queryParams'),

  // By default, dynamic links on active routes will have class "active", but
  // you can reopen this and set it to blank if you don't like that behavior.
  defaultActiveClass: 'active',

  // You can set an explicit activeClass like in link-to, as well, which can
  // also be passed in via the params hash.
  activeClass: Ember.computed.alias('params.activeClass'),
  activeWhen: Ember.computed.alias('params.activeWhen'),
  activeClassName: Ember.computed('isActive', 'activeClass', 'defaultActiveClass', function() {
    if (this.get('isActive') && this.get('activeClass') !== false) {
      return this.get('activeClass') || this.get('defaultActiveClass');
    }
  }),

  // You can control whether or not the click event bubbles up through the
  // component by setting this property directly or by setting it in the
  // params hash. If no value is set, all clicks will bubble by default.
  bubbles: Ember.computed.alias('params.bubbles'),

  models: Ember.computed('model', function() {
    if (this.get('model') instanceof Array) {
      return this.get('model');
    } else if (this.get('model')) {
      return [this.get('model')];
    } else {
      return [];
    }
  }),

  // These are the arguments to be passed to `transitionToRoute`. They consist
  // of a route name and then an optional model with optional query params.
  routeArguments: Ember.computed('route', 'models', 'queryParams', function() {
    var args = [this.get('route')].concat(this.get('models'));

    if (this.get('queryParams')) {
      args.push({ queryParams: this.get('queryParams') });
    }

    return args;
  }),

  // Arguments suited for routing service
  routingArguments: Ember.computed('route', 'models', 'queryParams', function() {
    return [
      this.get('route'),
      this.get('models'),
      this.get('queryParams') || {}
    ];
  }),

  // The href attribute of the link takes one of three forms.
  // If we have a literal href passed in, always defer to it.
  // If we have route parameters, try to construct the route's URL.
  // If we have an action, just '#' should do.
  href: Ember.computed('routeArguments', 'action', 'params.href', function() {
    if (this.get('params.href')) {
      return this.get('params.href');
    } else if (this.get('route')) {
      if (this.get('_routing')) {
        return this.get('_routing').generateURL(...this.get('routingArguments'));
      } else {
        return this.get('_router').generateURL(...this.get('routeArguments'));
      }
    } else {
      return '#';
    }
  }),

  // Use prevent default to keep route transitions and actions from
  // refreshing the page. Allows click behavior to bubble up if allowed
  // by the bubbles property
  click: function(event) {
    if ((this.get('action') || this.get('route')) && !(event.metaKey || event.ctrlKey)) {
      event.preventDefault();
      if (this.get('action')) {
        this.performAction();
      } else {
        this.transitionRoute();
      }
      return this.get('bubbles') !== false;
    } else {
      return true;
    }
  },

  // bubble the action to wherever the link was added
  performAction: function() {
    var target = this.get('targetObject') || this.get('_targetObject');
    if (target) {
      target.send(this.get('action'));
    }
  },

  _route: Ember.computed(function() {
    return getOwner(this).lookup('route:application');
  }),

  _router: Ember.computed.readOnly('_route.router'),

  _routing: Ember.inject.service(),

  // have the application route transition to the location
  // specified by the parameters
  transitionRoute: function() {
    let routing = this.get('_routing');
    if (routing) {
      routing.transitionTo(...this.get('routingArguments'));
    } else {
      this.get('_router').transitionTo(...this.get('routeArguments'));
    }
  },

  isActive: Ember.computed('_router.currentState', 'activeWhen', function() {
    if (this.get('activeWhen') !== undefined) {
      return this.get('activeWhen');
    } else if (this.get('route') && this.get('_router.currentState')) {
      let routing = this.get('_routing');
      if (routing) {
        let currentState = Ember.get(this, '_routing.currentState');
        if (!currentState) { return false; }
        return routing.isActiveForRoute(this.get('models'), this.get('queryParams') || {}, this.get('route'), currentState, false);
      } else {
        return this.get('_router').isActive(...this.get('routeArguments'));
      }
    } else {
      return false;
    }
  })
});
<|endoftext|>


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

// NOTE:
// This app can only be fully tested when deployed, because
// Pub/Sub requires a live endpoint URL to hit. Nevertheless,
// these tests mock it and partially test it locally.

'use strict';

const test = require(`ava`);
const path = require(`path`);
const utils = require(`@google-cloud/nodejs-repo-tools`);

const cwd = path.join(__dirname, `../`);
const requestObj = utils.getRequest({ cwd: cwd });

test.serial.cb(`should return a screenshot`, t => {
  requestObj
    .get(`/?url=https://example.com`)
    .send()
    .expect(200)
    .expect(response => {
      t.is(response.type, `image/png`);
      t.true(response.body instanceof Buffer);
      t.true(response.body.length > 0);
    })
    .end(t.end);
});
<commit_msg>remove unappropriated warning (#704)<commit_after>// Copyright 2017, Google, Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

const test = require(`ava`);
const path = require(`path`);
const utils = require(`@google-cloud/nodejs-repo-tools`);

const cwd = path.join(__dirname, `../`);
const requestObj = utils.getRequest({ cwd: cwd });

test.serial.cb(`should return a screenshot`, t => {
  requestObj
    .get(`/?url=https://example.com`)
    .send()
    .expect(200)
    .expect(response => {
      t.is(response.type, `image/png`);
      t.true(response.body instanceof Buffer);
      t.true(response.body.length > 0);
    })
    .end(t.end);
});
<|endoftext|>


<commit_before>const grunt = require("grunt");

function uniq(names) {
    return [...new Set(names)];
}

function sync(patterns) {
    return uniq(grunt.file.expand({ filter: path => !new RegExp(/__test__/g).test(path) }, patterns)).map(name => `./${name}`);
}

const fixJs = "./dist/fix/fix.js";
const fixProxyJs = './dist/fix/fix.proxy.js';
const fixIEJs = "./dist/fix/fix.ie.js";
const fixCompact = "./dist/fix/fix.compact.js";
const fixIECompact = './dist/fix/fix.compact.ie.js';
const workerCompact = './dist/fix/worker.compact.js';
const lodashJs = "src/core/1.lodash.js";

const basicAttachmentMap = {
    polyfill: sync(["src/core/0.foundation.js", "src/polyfill/**/*.js"]).concat(["@babel/polyfill", "es6-promise/auto"]),
    polyfillIE: sync(["src/core/0.foundation.js", "src/polyfill/**/*.js"]).concat([
        "core-js/features/object/define-property",
        "core-js/features/object/create",
        "core-js/features/object/assign",
        "core-js/features/object/get-own-property-symbols",
        "core-js/features/object/get-prototype-of",
        "core-js/features/array/for-each",
        "core-js/features/array/index-of",
        "core-js/features/function/bind",
        "core-js/features/promise",
        "core-js/features/string/replace",
        "core-js/es/map",
        // "core-js",
    ]),
    core: sync([
        "src/less/core/**/*.less",
        "src/less/theme/**/*.less",
        lodashJs,
        "src/core/**/*.js",
        "src/data/**/*.js",
    ]),
    // 最基础的控件
    base: sync([
        "src/less/base/**/*.less",
        "src/third/**/*.js",
        "src/base/**/*.js",
    ]),
    // 实现好的一些基础实例
    case: sync([
        "src/case/**/*.js",
    ]),
    widget: sync([
        "src/less/widget/**/*.less",
        "src/widget/**/*.js",
        "src/component/**/*.js",
    ]),
    router: sync([
        "src/router/**/*.js",
    ]),
    'core_without_normalize': sync(
        ["src/less/core/**/*.less", "src/less/theme/**/*.less", "!src/less/core/normalize.less", "!src/less/core/normalize2.less"],
    ),
    resource: sync(["src/less/resource/**/*.less"]),
    font: sync(["public/less/font.less"]),
    ts: ['./typescript/bundle.ts'],
    ui: sync([
        'ui/less/app.less',
        'ui/less/**/*.less',
        'ui/js/**/*.js',
    ]),
    config: sync(["demo/version.js", "i18n/i18n.cn.js"]),
    utils: sync([
        "src/core/0.foundation.js",
        lodashJs,
        "src/core/constant/**/*.js",
        "src/core/func/**/*.js",
        "src/core/2.base.js",
        "src/core/3.ob.js",
        "src/core/6.inject.js",
        "src/core/utils/*.js",
        "i18n/i18n.cn.js",
        "_mobile/date.i18n.cn.js",
        "src/data/**/*.js",
    ]),
    fix: [fixJs],
    fixProxy: [fixProxyJs],
    fixIE: [fixIEJs],
};

const bundle = [].concat(
    basicAttachmentMap.polyfill,
    basicAttachmentMap.core,
    basicAttachmentMap.fix,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    sync(["public/less/app.less", "public/less/**/*.less"]),
    [fixCompact, workerCompact],
    basicAttachmentMap.router,
    sync(["public/js/**/*.js", "public/js/index.js", "i18n/i18n.cn.js"]),
    basicAttachmentMap.ts,
);

const coreJs = [].concat(
    basicAttachmentMap.polyfill,
    basicAttachmentMap.core,
    basicAttachmentMap.fix,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    ['./dist/fix/fix.compact.js'],
    basicAttachmentMap.router,
    basicAttachmentMap.ts,
);

const resource = sync(["private/less/app.less", "private/less/**/*.less"]);

const config = sync(["public/js/**/*.js", "public/js/index.js", "i18n/i18n.cn.js"]);

const bundleIE = [].concat(
    basicAttachmentMap.polyfillIE,
    basicAttachmentMap.core,
    basicAttachmentMap.fixIE,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    sync(["public/less/app.less", "public/less/**/*.less"]),
    [fixIECompact, workerCompact],
    basicAttachmentMap.router,
    sync(["public/js/**/*.js", "public/js/index.js", "i18n/i18n.cn.js"]),
    basicAttachmentMap.ts,
);

const bundleWithoutNormalize = [].concat(
    basicAttachmentMap.core_without_normalize,
    sync([
        "src/less/base/**/*.less",
        "src/less/widget/**/*.less",
        "public/less/**/*.less",
        "!public/less/app.less",
        // ts的less
    ]),
);

const fineuiWithoutNormalize = [].concat(
    basicAttachmentMap.core_without_normalize,
    sync([
        "src/less/base/**/*.less",
        "src/less/widget/**/*.less",
    ]),
);

const fineui = [].concat(
    basicAttachmentMap.polyfill,
    basicAttachmentMap.core,
    basicAttachmentMap.fix,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    basicAttachmentMap.router,
    [fixCompact, workerCompact],
    basicAttachmentMap.ui,
    basicAttachmentMap.ts,
);

const fineuiProxy = [].concat(
    basicAttachmentMap.core,
    basicAttachmentMap.fixProxy,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    basicAttachmentMap.router,
    [fixCompact, workerCompact],
    basicAttachmentMap.ui,
    basicAttachmentMap.ts,
);

const fineuiIE = [].concat(
    basicAttachmentMap.polyfillIE,
    basicAttachmentMap.core,
    basicAttachmentMap.fixIE,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    basicAttachmentMap.router,
    [fixIECompact, workerCompact],
    basicAttachmentMap.ui,
    basicAttachmentMap.ts,
);

const fineuiWithoutJqueryAndPolyfillJs = [].concat(
    sync([
        "src/core/foundation.js",
        lodashJs,
        "src/core/**/*.js",
        "src/data/**/*.js",
        "dist/fix/fix.js",
        "src/base/**/*.js",
        "src/case/**/*.js",

        "!src/core/platform/web/**/*.js",
        "!src/base/single/input/file.js",
        "!src/case/ztree/**/*.js",
    ]),
    basicAttachmentMap.widget,
    sync([fixCompact, workerCompact, "ui/js/**/*.js"]),
    basicAttachmentMap.ts,
);

const demo = [].concat(
    basicAttachmentMap.polyfill,
    basicAttachmentMap.core,
    basicAttachmentMap.router,
    basicAttachmentMap.fix,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    sync(["public/less/app.less", "public/less/**/*.less"]),
    [fixCompact, workerCompact],
    basicAttachmentMap.config,
    basicAttachmentMap.ts,
    sync(["demo/less/*.less", "demo/less/**/*.less", "demo/app.js", "demo/js/**/*.js", "demo/config.js"]),
);

module.exports = {
    fix: fixJs,
    fixProxy: fixProxyJs,
    fixIE: fixIEJs,
    lodash: lodashJs,
    font: basicAttachmentMap.font,
    bundle: uniq(bundle),
    bundleIE: uniq(bundleIE),
    fineuiWithoutNormalize: uniq(fineuiWithoutNormalize),
    bundleWithoutNormalize: uniq(bundleWithoutNormalize),
    fineui: uniq(fineui),
    fineuiProxy: uniq(fineuiProxy),
    fineuiIE: uniq(fineuiIE),
    fineuiWithoutJqueryAndPolyfillJs: uniq(fineuiWithoutJqueryAndPolyfillJs),
    utils: uniq(basicAttachmentMap.utils),
    demo: uniq(demo),
    coreJs: uniq(coreJs),
    resource: uniq((resource)),
    config: uniq(config),
};
<commit_msg>Pull request #2141: 无JIRA任务 少了点css<commit_after>const grunt = require("grunt");

function uniq(names) {
    return [...new Set(names)];
}

function sync(patterns) {
    return uniq(grunt.file.expand({ filter: path => !new RegExp(/__test__/g).test(path) }, patterns)).map(name => `./${name}`);
}

const fixJs = "./dist/fix/fix.js";
const fixProxyJs = './dist/fix/fix.proxy.js';
const fixIEJs = "./dist/fix/fix.ie.js";
const fixCompact = "./dist/fix/fix.compact.js";
const fixIECompact = './dist/fix/fix.compact.ie.js';
const workerCompact = './dist/fix/worker.compact.js';
const lodashJs = "src/core/1.lodash.js";

const basicAttachmentMap = {
    polyfill: sync(["src/core/0.foundation.js", "src/polyfill/**/*.js"]).concat(["@babel/polyfill", "es6-promise/auto"]),
    polyfillIE: sync(["src/core/0.foundation.js", "src/polyfill/**/*.js"]).concat([
        "core-js/features/object/define-property",
        "core-js/features/object/create",
        "core-js/features/object/assign",
        "core-js/features/object/get-own-property-symbols",
        "core-js/features/object/get-prototype-of",
        "core-js/features/array/for-each",
        "core-js/features/array/index-of",
        "core-js/features/function/bind",
        "core-js/features/promise",
        "core-js/features/string/replace",
        "core-js/es/map",
        // "core-js",
    ]),
    core: sync([
        "src/less/core/**/*.less",
        "src/less/theme/**/*.less",
        lodashJs,
        "src/core/**/*.js",
        "src/data/**/*.js",
    ]),
    // 最基础的控件
    base: sync([
        "src/less/base/**/*.less",
        "src/third/**/*.js",
        "src/base/**/*.js",
    ]),
    // 实现好的一些基础实例
    case: sync([
        "src/case/**/*.js",
    ]),
    widget: sync([
        "src/less/widget/**/*.less",
        "src/widget/**/*.js",
        "src/component/**/*.js",
    ]),
    router: sync([
        "src/router/**/*.js",
    ]),
    'core_without_normalize': sync(
        ["src/less/core/**/*.less", "src/less/theme/**/*.less", "!src/less/core/normalize.less", "!src/less/core/normalize2.less"],
    ),
    resource: sync(["src/less/resource/**/*.less"]),
    font: sync(["public/less/font.less"]),
    ts: ['./typescript/bundle.ts'],
    ui: sync([
        'ui/less/app.less',
        'ui/less/**/*.less',
        'ui/js/**/*.js',
    ]),
    config: sync(["demo/version.js", "i18n/i18n.cn.js"]),
    utils: sync([
        "src/core/0.foundation.js",
        lodashJs,
        "src/core/constant/**/*.js",
        "src/core/func/**/*.js",
        "src/core/2.base.js",
        "src/core/3.ob.js",
        "src/core/6.inject.js",
        "src/core/utils/*.js",
        "i18n/i18n.cn.js",
        "_mobile/date.i18n.cn.js",
        "src/data/**/*.js",
    ]),
    fix: [fixJs],
    fixProxy: [fixProxyJs],
    fixIE: [fixIEJs],
};

const bundle = [].concat(
    basicAttachmentMap.polyfill,
    basicAttachmentMap.core,
    basicAttachmentMap.fix,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    sync(["public/less/app.less", "public/less/**/*.less"]),
    [fixCompact, workerCompact],
    basicAttachmentMap.router,
    sync(["public/js/**/*.js", "public/js/index.js", "i18n/i18n.cn.js"]),
    basicAttachmentMap.ts,
);

const coreJs = [].concat(
    basicAttachmentMap.polyfill,
    basicAttachmentMap.core,
    basicAttachmentMap.fix,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    ['./dist/fix/fix.compact.js'],
    basicAttachmentMap.router,
    basicAttachmentMap.ts,
);

const resource = sync(["private/less/app.less", "private/less/**/*.less"]);

const config = sync(["public/js/**/*.js", "public/js/index.js", "i18n/i18n.cn.js"]);

const bundleIE = [].concat(
    basicAttachmentMap.polyfillIE,
    basicAttachmentMap.core,
    basicAttachmentMap.fixIE,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    sync(["public/less/app.less", "public/less/**/*.less"]),
    [fixIECompact, workerCompact],
    basicAttachmentMap.router,
    sync(["public/js/**/*.js", "public/js/index.js", "i18n/i18n.cn.js"]),
    basicAttachmentMap.ts,
);

const bundleWithoutNormalize = [].concat(
    basicAttachmentMap.core_without_normalize,
    sync([
        "src/less/base/**/*.less",
        "src/less/widget/**/*.less",
        "public/less/**/*.less",
        "!public/less/app.less",
        // ts的less
    ]),
);

const fineuiWithoutNormalize = [].concat(
    basicAttachmentMap.core_without_normalize,
    sync([
        "src/less/base/**/*.less",
        "src/less/widget/**/*.less",
        'ui/less/app.less',
        'ui/less/**/*.less',
    ]),
);

const fineui = [].concat(
    basicAttachmentMap.polyfill,
    basicAttachmentMap.core,
    basicAttachmentMap.fix,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    basicAttachmentMap.router,
    [fixCompact, workerCompact],
    basicAttachmentMap.ui,
    basicAttachmentMap.ts,
);

const fineuiProxy = [].concat(
    basicAttachmentMap.core,
    basicAttachmentMap.fixProxy,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    basicAttachmentMap.router,
    [fixCompact, workerCompact],
    basicAttachmentMap.ui,
    basicAttachmentMap.ts,
);

const fineuiIE = [].concat(
    basicAttachmentMap.polyfillIE,
    basicAttachmentMap.core,
    basicAttachmentMap.fixIE,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    basicAttachmentMap.router,
    [fixIECompact, workerCompact],
    basicAttachmentMap.ui,
    basicAttachmentMap.ts,
);

const fineuiWithoutJqueryAndPolyfillJs = [].concat(
    sync([
        "src/core/foundation.js",
        lodashJs,
        "src/core/**/*.js",
        "src/data/**/*.js",
        "dist/fix/fix.js",
        "src/base/**/*.js",
        "src/case/**/*.js",

        "!src/core/platform/web/**/*.js",
        "!src/base/single/input/file.js",
        "!src/case/ztree/**/*.js",
    ]),
    basicAttachmentMap.widget,
    sync([fixCompact, workerCompact, "ui/js/**/*.js"]),
    basicAttachmentMap.ts,
);

const demo = [].concat(
    basicAttachmentMap.polyfill,
    basicAttachmentMap.core,
    basicAttachmentMap.router,
    basicAttachmentMap.fix,
    basicAttachmentMap.base,
    basicAttachmentMap.case,
    basicAttachmentMap.widget,
    sync(["public/less/app.less", "public/less/**/*.less"]),
    [fixCompact, workerCompact],
    basicAttachmentMap.config,
    basicAttachmentMap.ts,
    sync(["demo/less/*.less", "demo/less/**/*.less", "demo/app.js", "demo/js/**/*.js", "demo/config.js"]),
);

module.exports = {
    fix: fixJs,
    fixProxy: fixProxyJs,
    fixIE: fixIEJs,
    lodash: lodashJs,
    font: basicAttachmentMap.font,
    bundle: uniq(bundle),
    bundleIE: uniq(bundleIE),
    fineuiWithoutNormalize: uniq(fineuiWithoutNormalize),
    bundleWithoutNormalize: uniq(bundleWithoutNormalize),
    fineui: uniq(fineui),
    fineuiProxy: uniq(fineuiProxy),
    fineuiIE: uniq(fineuiIE),
    fineuiWithoutJqueryAndPolyfillJs: uniq(fineuiWithoutJqueryAndPolyfillJs),
    utils: uniq(basicAttachmentMap.utils),
    demo: uniq(demo),
    coreJs: uniq(coreJs),
    resource: uniq((resource)),
    config: uniq(config),
};
<|endoftext|>


<commit_before>controllers.index = function(search, sort, sortDirection) {
  var _this = this;

  function sortFor(type) {
    if(!type) type = "publishedOn";

    if(type == "publishedOn") return function(book) {
      return book.publishedOn;
    };
    if(type == "pages") return function(book) {
      return book.pageUrls.length;
    };
    if(type == "title") return function(book) {
      return book.title;
    };
  }

  var books = store;
  if(search && search != "") {
    regex = RegExp(search, "i");
    books = _.filter(books, function(book) {
      return book.title.match(regex);
    });
  }
  books = _.sortBy(books, sortFor(sort));

  if(!sortDirection) sortDirection = "desc";
  if(sortDirection == "desc") books = books.reverse();

  function perPageFromWindow() {
    var windowWidth = $(window).width();
    if(windowWidth < 1000) return 15;
    else if(windowWidth > 1000 && windowWidth < 1500) return 21;
    else if(windowWidth > 1500) return 25;
  }

  var perPage = perPageFromWindow();
  var pages = utils.pages(books, perPage);

  this.init = function() {
    console.log("starting index");

    $("#search").bind("keydown", function(event) {
      if(event.keyCode == 13) {
        event.preventDefault();
        utils.location({ params: [$("#search").val(), sort, sortDirection], hash: "1" });
      }
    });

    $("#clear-search").bind("click", function() {
      $("#search").val("");
    });

    $("a.sort").bind("click", function(event) {
      event.preventDefault();
      utils.location({ params: [search, $(this).data("sort"), sortDirection], hash: "1" });
    });

    $("a.sort-direction").bind("click", function(event) {
      event.preventDefault();
      utils.location({ params: [search, sort, $(this).data("sort-direction")], hash: "1" });
    });

    $("#view-index").hammer().on("drag swipeleft swiperight", function(event) {
      if(Hammer.utils.isVertical(event.gesture.direction)) return;
      event.gesture.preventDefault();

      if(event.type == 'swipeleft') utils.page(utils.page() + 1, pages);
      else if(event.type == 'swiperight') utils.page(utils.page() - 1, pages);
    });

    $("#view-index").show().addClass("current-view");
  }

  function addBooks(books) {
    $("#items").empty();

    _.each(books, function(book) {
      var item = $("
");
      var link = $("");
      link.attr("href", "#show/" + book.key + "!1");
      var img = $("");
      img.attr("src", book.thumbnailUrl);
      link.append(img);
      item.append(link);

      item.append('

' + book.title + '
' +
        ' ' + book.pageUrls.length + '

');

      $("#items").append(item);
    });
  }

  this.render = function() {
    console.log("rendering");
    var booksPage = utils.paginate(books, perPage);
    addBooks(booksPage);
  }

  this.destroy = function() {
    console.log("destroying index");
    $("#search").unbind("keydown");
    $("#clear-search").unbind("click");
    $("a.sort").unbind("click");
    $("a.sort-direction").unbind("click");
    $("#items").empty();
    $("#view-index").hammer().off("swiperight").off("swipeleft").off("drag");
    $("#view-index").hide().removeClass("current-view");
  }
}
<commit_msg>Show full rows for 800px screen width<commit_after>controllers.index = function(search, sort, sortDirection) {
  var _this = this;

  function sortFor(type) {
    if(!type) type = "publishedOn";

    if(type == "publishedOn") return function(book) {
      return book.publishedOn;
    };
    if(type == "pages") return function(book) {
      return book.pageUrls.length;
    };
    if(type == "title") return function(book) {
      return book.title;
    };
  }

  var books = store;
  if(search && search != "") {
    regex = RegExp(search, "i");
    books = _.filter(books, function(book) {
      return book.title.match(regex);
    });
  }
  books = _.sortBy(books, sortFor(sort));

  if(!sortDirection) sortDirection = "desc";
  if(sortDirection == "desc") books = books.reverse();

  function perPageFromWindow() {
    var windowWidth = $(window).width();
    if(windowWidth < 1000) return 16;
    else if(windowWidth > 1000 && windowWidth < 1500) return 21;
    else if(windowWidth > 1500) return 25;
  }

  var perPage = perPageFromWindow();
  var pages = utils.pages(books, perPage);

  this.init = function() {
    console.log("starting index");

    $("#search").bind("keydown", function(event) {
      if(event.keyCode == 13) {
        event.preventDefault();
        utils.location({ params: [$("#search").val(), sort, sortDirection], hash: "1" });
      }
    });

    $("#clear-search").bind("click", function() {
      $("#search").val("");
    });

    $("a.sort").bind("click", function(event) {
      event.preventDefault();
      utils.location({ params: [search, $(this).data("sort"), sortDirection], hash: "1" });
    });

    $("a.sort-direction").bind("click", function(event) {
      event.preventDefault();
      utils.location({ params: [search, sort, $(this).data("sort-direction")], hash: "1" });
    });

    $("#view-index").hammer().on("drag swipeleft swiperight", function(event) {
      if(Hammer.utils.isVertical(event.gesture.direction)) return;
      event.gesture.preventDefault();

      if(event.type == 'swipeleft') utils.page(utils.page() + 1, pages);
      else if(event.type == 'swiperight') utils.page(utils.page() - 1, pages);
    });

    $("#view-index").show().addClass("current-view");
  }

  function addBooks(books) {
    $("#items").empty();

    _.each(books, function(book) {
      var item = $("
");
      var link = $("");
      link.attr("href", "#show/" + book.key + "!1");
      var img = $("");
      img.attr("src", book.thumbnailUrl);
      link.append(img);
      item.append(link);

      item.append('

' + book.title + '
' +
        ' ' + book.pageUrls.length + '

');

      $("#items").append(item);
    });
  }

  this.render = function() {
    console.log("rendering");
    var booksPage = utils.paginate(books, perPage);
    addBooks(booksPage);
  }

  this.destroy = function() {
    console.log("destroying index");
    $("#search").unbind("keydown");
    $("#clear-search").unbind("click");
    $("a.sort").unbind("click");
    $("a.sort-direction").unbind("click");
    $("#items").empty();
    $("#view-index").hammer().off("swiperight").off("swipeleft").off("drag");
    $("#view-index").hide().removeClass("current-view");
  }
}
<|endoftext|>


<commit_before>
var Bind = require("github/jillix/bind");
var Events = require("github/jillix/events");
var Ui = require("./ui");

module.exports = function(config) {

    // get self (the module)
    var self = this;

    // config
    self.config = config;

    // process config
    processConfig(config);

    // call ui
    Ui.call(self);

    // get the iframe from the module
    var $iframe = $("iframe", self.dom);
    if (!$iframe.get(0)) {
        return console.error("Could not find the upload IFRAME in this module's DOM.");
    }

    // get file inputs
    var $fileInputs = $("input[type='file']", self.dom);

    // create the accept attr value
    var acceptAttrValue = "";

    // for every file type
    for (var i = 0; i < self.config.options.acceptTypes.length; ++i) {

        // get current type
        var cType = self.config.options.acceptTypes[i];

        // append it to the attr value string
        acceptAttrValue += "." + cType + ",";
    }

    // remove last comma
    acceptAttrValue = acceptAttrValue.substring(0, acceptAttrValue.length - 1);

    // set accept attr
    $fileInputs.attr("accept", acceptAttrValue);

    // file input change event
    $fileInputs.on("change", function () {
        // is the file accepted?
        if (acceptAttrValue && !checkFileType.call(self, this)) {
            // empty the value of file input
            // TODO is this supported on IE?
            $(this).val("");
        }
    });

    // forms on submit
    $("form", self.dom).on("submit", function () {

        // get submiited form
        var $form = $(this);

        // set the onload handler (the jQuery "load" event will not fire in IE)
        $iframe.get(0).onload = function() {

            // get text from the page
            var result = $(this.contentWindow.document).text();

            // if no result, return (a 2nd call happens in Webkit browsers with an empty result)
            if (!result) { return; }

            // parse the result
            try {
                result = JSON.parse(result);
            } catch (err) {
                self.emit("uploadFailed");
                console.error(err);
                return;
            }

            if (result.error || !result.success) {
                var error = result.error || "Upload Failed";
                self.emit("uploadFailed", error);
                return console.error(error);
            }

            // emit fileUploaded event and the result
            self.emit("fileUploaded", result.success);

            // get file input jQuery object
            var $inputFile = $form.find("input[type='file']");

            // verify its value
            if (!$inputFile.val()) { return; }

            // set src of iframe
            $iframe.attr("src", "");

            // replace the file input
            $inputFile.replaceWith($inputFile.clone(true));
        };
    });

    // listen to events
    self.on("setData", setData);
    self.on("setTemplate", setTemplate);
    self.on("removeItem", removeItem);

    // handle rendering / wait for external event before rendering to fix render order of uploader containers
    self.waitForEvent = false;
    self.renderingEnabled = false;
    self.on("enableRendering", function () {

        if (self.waitForEvent) {
            self.renderingEnabled = false;

            if (self.template) {
                self.emit("renderUi");
            }
        } else {
            self.renderingEnabled = true;
        }
    });

    // call events
    Events.call(self, config);

    // emit ready event
    self.emit("ready", config);
};

function setTemplate (template) {
    var self = this;

    var template = typeof template === 'string' ? template : (template.id || template._id);
    // check template
    if (!template) {
        // TODO handle error
        return console.error('Invalid upload template');
    }

    self.emit('find', [template], function (err, templates) {

        for (var key in templates) {
            if (!templates.hasOwnProperty(key)) continue;

            if (templates[key]._id === template) {
                self.template = templates[key];
            }
        }

        // TODO handle error
        if (err || !self.template) {
            return console.error(err);
        }

        // clear the hidden input template value
        if ($(".hiddenTemplateValue", $("form", self.dom)).length) {
            $(".hiddenTemplateValue", $("form", self.dom)).val("");
        }

        // do not render uploader controls if no configuration is present
        if (!self.template.options || !self.template.options.uploader) { return; }
        self.uploaderConfig = self.template.options.uploader;

        // clear the renderBuffer
        renderBuffer = [];

        // add template id value to form
        if ($(".hiddenTemplateValue", $("form", self.dom)).length) {
            $(".hiddenTemplateValue", $("form", self.dom)).val(self.template._id);
        } else {
            var $input = $("<input class='hiddenTemplateValue hide' type='hidden' name='templateId'>");
            $("form", self.dom).append($input);
            $input.val(self.template._id);
        }

        // check if template needs to wait for an external event to begin rendering
        if (self.uploaderConfig.waitForEvent) {

            // check if render enabled by event
            if (self.renderingEnabled) {
                self.emit("renderUi");
            } else {
                self.waitForEvent = true;
            }

            self.renderingEnabled = false;
        } else {
            self.renderingEnabled = false;
            self.emit("renderUi");
        }
    });
}

/*
 * This function makes a request to the remove operation to delete a file
 * */
function removeItem (data) {
    var self = this;

    // build data object
    if (typeof data === 'string') {
        data = {
            itemId: data
        };
    }

    self.link('remove', { data: data }, function (err, data) {

        if (err) {
            return;
        }

        self.emit('itemRemoved');
    });
}

/*
 *  This function checks if the selected file has a correct
 *  extension (self.config.options.acceptTypes)
 * */
function checkFileType (fileInput) {
    // get self
    var self = this;

    // get file extension
    var extension = fileInput.value.split(".").reverse()[0];

    // the extension is not supported
    if (self.config.options.acceptTypes.indexOf(extension) === -1) {
        return false;
    }

    // the extension is supported
    return true;
}

/*
 *  This function appends to the upload form hidden inputs with values
 *  from the selected table item
 * */
function setData (data) {
    var self = this;

    // create container for hidden data
    var $form = $("form", self.dom);
    if ($(".hiddenDataContainer", $form).length) {
        var $container = $(".hiddenDataContainer", $form);
    } else {
        var $container = $("

");
        $form.append($container);
    }

    self.formData = data;
    // add hidden inputs to container
    $container.html(buildHiddenData(data, ""));
}

/*
 * This function creates the hidden inputs that will be appended to the form
 * */
function buildHiddenData (data, path) {

    var inputs = "";
    for (var key in data) {
        if (key[0] !== '_' && data.hasOwnProperty(key)) {

            // build the object path
            var objPath = path.length ? (path + "." + key) : key;
            if (typeof data[key] === "object") {
                inputs += buildHiddenData(data[key], objPath);
            } else {
                inputs += '<input type="hidden" class="hide" name="' + objPath + '" value="' + data[key] + '">';
            }
        }
    }

    return inputs;
}

/*
 *  Process config
 *
 * */
function processConfig (config) {
    config.options = config.options || {};
    config.options.acceptTypes = config.options.acceptTypes || [];
}
<commit_msg>Use jxmono for Bind and Events<commit_after>
var Bind = require("github/jxmono/bind");
var Events = require("github/jxmono/events");
var Ui = require("./ui");

module.exports = function(config) {

    // get self (the module)
    var self = this;

    // config
    self.config = config;

    // process config
    processConfig(config);

    // call ui
    Ui.call(self);

    // get the iframe from the module
    var $iframe = $("iframe", self.dom);
    if (!$iframe.get(0)) {
        return console.error("Could not find the upload IFRAME in this module's DOM.");
    }

    // get file inputs
    var $fileInputs = $("input[type='file']", self.dom);

    // create the accept attr value
    var acceptAttrValue = "";

    // for every file type
    for (var i = 0; i < self.config.options.acceptTypes.length; ++i) {

        // get current type
        var cType = self.config.options.acceptTypes[i];

        // append it to the attr value string
        acceptAttrValue += "." + cType + ",";
    }

    // remove last comma
    acceptAttrValue = acceptAttrValue.substring(0, acceptAttrValue.length - 1);

    // set accept attr
    $fileInputs.attr("accept", acceptAttrValue);

    // file input change event
    $fileInputs.on("change", function () {
        // is the file accepted?
        if (acceptAttrValue && !checkFileType.call(self, this)) {
            // empty the value of file input
            // TODO is this supported on IE?
            $(this).val("");
        }
    });

    // forms on submit
    $("form", self.dom).on("submit", function () {

        // get submiited form
        var $form = $(this);

        // set the onload handler (the jQuery "load" event will not fire in IE)
        $iframe.get(0).onload = function() {

            // get text from the page
            var result = $(this.contentWindow.document).text();

            // if no result, return (a 2nd call happens in Webkit browsers with an empty result)
            if (!result) { return; }

            // parse the result
            try {
                result = JSON.parse(result);
            } catch (err) {
                self.emit("uploadFailed");
                console.error(err);
                return;
            }

            if (result.error || !result.success) {
                var error = result.error || "Upload Failed";
                self.emit("uploadFailed", error);
                return console.error(error);
            }

            // emit fileUploaded event and the result
            self.emit("fileUploaded", result.success);

            // get file input jQuery object
            var $inputFile = $form.find("input[type='file']");

            // verify its value
            if (!$inputFile.val()) { return; }

            // set src of iframe
            $iframe.attr("src", "");

            // replace the file input
            $inputFile.replaceWith($inputFile.clone(true));
        };
    });

    // listen to events
    self.on("setData", setData);
    self.on("setTemplate", setTemplate);
    self.on("removeItem", removeItem);

    // handle rendering / wait for external event before rendering to fix render order of uploader containers
    self.waitForEvent = false;
    self.renderingEnabled = false;
    self.on("enableRendering", function () {

        if (self.waitForEvent) {
            self.renderingEnabled = false;

            if (self.template) {
                self.emit("renderUi");
            }
        } else {
            self.renderingEnabled = true;
        }
    });

    // call events
    Events.call(self, config);

    // emit ready event
    self.emit("ready", config);
};

function setTemplate (template) {
    var self = this;

    var template = typeof template === 'string' ? template : (template.id || template._id);
    // check template
    if (!template) {
        // TODO handle error
        return console.error('Invalid upload template');
    }

    self.emit('find', [template], function (err, templates) {

        for (var key in templates) {
            if (!templates.hasOwnProperty(key)) continue;

            if (templates[key]._id === template) {
                self.template = templates[key];
            }
        }

        // TODO handle error
        if (err || !self.template) {
            return console.error(err);
        }

        // clear the hidden input template value
        if ($(".hiddenTemplateValue", $("form", self.dom)).length) {
            $(".hiddenTemplateValue", $("form", self.dom)).val("");
        }

        // do not render uploader controls if no configuration is present
        if (!self.template.options || !self.template.options.uploader) { return; }
        self.uploaderConfig = self.template.options.uploader;

        // clear the renderBuffer
        renderBuffer = [];

        // add template id value to form
        if ($(".hiddenTemplateValue", $("form", self.dom)).length) {
            $(".hiddenTemplateValue", $("form", self.dom)).val(self.template._id);
        } else {
            var $input = $("<input class='hiddenTemplateValue hide' type='hidden' name='templateId'>");
            $("form", self.dom).append($input);
            $input.val(self.template._id);
        }

        // check if template needs to wait for an external event to begin rendering
        if (self.uploaderConfig.waitForEvent) {

            // check if render enabled by event
            if (self.renderingEnabled) {
                self.emit("renderUi");
            } else {
                self.waitForEvent = true;
            }

            self.renderingEnabled = false;
        } else {
            self.renderingEnabled = false;
            self.emit("renderUi");
        }
    });
}

/*
 * This function makes a request to the remove operation to delete a file
 * */
function removeItem (data) {
    var self = this;

    // build data object
    if (typeof data === 'string') {
        data = {
            itemId: data
        };
    }

    self.link('remove', { data: data }, function (err, data) {

        if (err) {
            return;
        }

        self.emit('itemRemoved');
    });
}

/*
 *  This function checks if the selected file has a correct
 *  extension (self.config.options.acceptTypes)
 * */
function checkFileType (fileInput) {
    // get self
    var self = this;

    // get file extension
    var extension = fileInput.value.split(".").reverse()[0];

    // the extension is not supported
    if (self.config.options.acceptTypes.indexOf(extension) === -1) {
        return false;
    }

    // the extension is supported
    return true;
}

/*
 *  This function appends to the upload form hidden inputs with values
 *  from the selected table item
 * */
function setData (data) {
    var self = this;

    // create container for hidden data
    var $form = $("form", self.dom);
    if ($(".hiddenDataContainer", $form).length) {
        var $container = $(".hiddenDataContainer", $form);
    } else {
        var $container = $("

");
        $form.append($container);
    }

    self.formData = data;
    // add hidden inputs to container
    $container.html(buildHiddenData(data, ""));
}

/*
 * This function creates the hidden inputs that will be appended to the form
 * */
function buildHiddenData (data, path) {

    var inputs = "";
    for (var key in data) {
        if (key[0] !== '_' && data.hasOwnProperty(key)) {

            // build the object path
            var objPath = path.length ? (path + "." + key) : key;
            if (typeof data[key] === "object") {
                inputs += buildHiddenData(data[key], objPath);
            } else {
                inputs += '<input type="hidden" class="hide" name="' + objPath + '" value="' + data[key] + '">';
            }
        }
    }

    return inputs;
}

/*
 *  Process config
 *
 * */
function processConfig (config) {
    config.options = config.options || {};
    config.options.acceptTypes = config.options.acceptTypes || [];
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from "react";
import * as Helpers from "./Helpers";
import * as DateUtils from "./DateUtils";
import * as LocaleUtils from "./LocaleUtils";

const keys = {
  LEFT: 37,
  RIGHT: 39,
  ENTER: 13,
  SPACE: 32
};

class Caption extends Component {

  render() {
    const { date, locale, localeUtils, onClick } = this.props;
    return (

        { localeUtils.formatMonthTitle(date, locale) }

    );
  }
}

export default class DayPicker extends Component {

  static propTypes = {

    initialMonth: PropTypes.instanceOf(Date),
    numberOfMonths: PropTypes.number,

    modifiers: PropTypes.object,

    locale: PropTypes.string,
    localeUtils: PropTypes.shape({
      formatMonthTitle: PropTypes.func,
      formatWeekdayShort: PropTypes.func,
      formatWeekdayLong: PropTypes.func,
      getFirstDayOfWeek: PropTypes.func
    }),

    enableOutsideDays: PropTypes.bool,
    canChangeMonth: PropTypes.bool,
    fromMonth: PropTypes.instanceOf(Date),
    toMonth: PropTypes.instanceOf(Date),

    onDayClick: PropTypes.func,
    onDayTouchTap: PropTypes.func,
    onDayMouseEnter: PropTypes.func,
    onDayMouseLeave: PropTypes.func,
    onMonthChange: PropTypes.func,
    onCaptionClick: PropTypes.func,

    renderDay: PropTypes.func,

    captionElement: PropTypes.element

  };

  static defaultProps = {
    tabIndex: 0,
    initialMonth: new Date(),
    numberOfMonths: 1,
    locale: "en",
    localeUtils: LocaleUtils,
    enableOutsideDays: false,
    canChangeMonth: true,
    renderDay: day => day.getDate(),
    captionElement:

  };

  constructor(props) {
    super(props);
    this.state = {
      currentMonth: Helpers.startOfMonth(props.initialMonth)
    };
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.initialMonth !== nextProps.initialMonth) {
      this.setState({
        currentMonth: Helpers.startOfMonth(nextProps.initialMonth)
      });
    }
  }

  allowPreviousMonth() {
    const { fromMonth } = this.props;
    if (!fromMonth) {
      return true;
    }
    const { currentMonth } = this.state;
    return Helpers.getMonthsDiff(currentMonth, fromMonth) < 0;
  }

  allowNextMonth() {
    const { toMonth, numberOfMonths } = this.props;
    if (!toMonth) {
      return true;
    }
    const { currentMonth } = this.state;
    return Helpers.getMonthsDiff(currentMonth, toMonth) >= numberOfMonths;
  }

  allowMonth(d) {
    const { fromMonth, toMonth } = this.props;
    if ((fromMonth && Helpers.getMonthsDiff(fromMonth, d) < 0) ||
      (toMonth && Helpers.getMonthsDiff(toMonth, d) > 0)) {
      return false;
    }
    return true;
  }

  showMonth(d) {
    if (!this.allowMonth(d)) {
      return;
    }
    this.setState({
      currentMonth: Helpers.startOfMonth(d)
    });
  }

  showNextMonth(callback) {
    if (!this.allowNextMonth()) {
      return;
    }
    const { currentMonth } = this.state;
    const nextMonth = DateUtils.addMonths(currentMonth, 1);
    this.setState({
      currentMonth: nextMonth
    }, () => {
      if (callback) {
        callback();
      }
      if (this.props.onMonthChange) {
        this.props.onMonthChange(this.state.currentMonth);
      }
    });
  }

  showPreviousMonth(callback) {
    if (!this.allowPreviousMonth()) {
      return;
    }
    const { currentMonth } = this.state;
    const prevMonth = DateUtils.addMonths(currentMonth, -1);
    this.setState({
      currentMonth: prevMonth
    }, () => {
      if (callback) {
        callback();
      }
      if (this.props.onMonthChange) {
        this.props.onMonthChange(this.state.currentMonth);
      }
    });
  }

  focusPreviousDay(dayNode) {
    const body = dayNode.parentNode.parentNode.parentNode.parentNode;
    let dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
    let nodeIndex;
    for (let i = 0; i < dayNodes.length; i++) {
      if (dayNodes[i] === dayNode) {
        nodeIndex = i;
        break;
      }
    }
    if (nodeIndex === 0) {
      const { currentMonth } = this.state;
      const { numberOfMonths } = this.props;
      const prevMonth = DateUtils.addMonths(currentMonth, -numberOfMonths);
      this.setState({
        currentMonth: prevMonth
      }, () => {
        dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
        dayNodes[dayNodes.length - 1].focus();
      });
    }
    else {
      dayNodes[nodeIndex - 1].focus();
    }
  }

  focusNextDay(dayNode) {
    const body = dayNode.parentNode.parentNode.parentNode.parentNode;
    let dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
    let nodeIndex;
    for (let i = 0; i < dayNodes.length; i++) {
      if (dayNodes[i] === dayNode) {
        nodeIndex = i;
        break;
      }
    }

    if (nodeIndex === dayNodes.length - 1) {
      const { currentMonth } = this.state;
      const { numberOfMonths } = this.props;
      const nextMonth = DateUtils.addMonths(currentMonth, numberOfMonths);
      this.setState({
        currentMonth: nextMonth
      }, () => {
        dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
        dayNodes[0].focus();
      });
    }
    else {
      dayNodes[nodeIndex + 1].focus();
    }
  }

  // Event handlers

  handleKeyDown(e) {
    e.persist();

    if (!this.props.canChangeMonth && this.props.onKeyDown) {
      this.props.onKeyDown(e);
      return;
    }

    if (this.props.canChangeMonth) {
      const callback = this.props.onKeyDown ? () => this.props.onKeyDown(e) : null;

      switch (e.keyCode) {
      case keys.LEFT:
        this.showPreviousMonth(callback);
        break;
      case keys.RIGHT:
        this.showNextMonth(callback);
        break;
      }
    }
  }

  handleDayKeyDown(e, day, modifiers) {
    e.persist();
    switch (e.keyCode) {
    case keys.LEFT:
      e.preventDefault();
      e.stopPropagation();
      this.focusPreviousDay(e.target);
      break;
    case keys.RIGHT:
      e.preventDefault();
      e.stopPropagation();
      this.focusNextDay(e.target);
      break;
    case keys.ENTER:
    case keys.SPACE:
      e.preventDefault();
      e.stopPropagation();
      if (this.props.onDayClick) {
        this.handleDayClick(e, day, modifiers);
      }
      if (this.props.onDayTouchTap) {
        this.handleDayTouchTap(e, day, modifiers);
      }
      break;
    }
  }

  handleNextMonthClick() {
    this.showNextMonth();
  }

  handlePrevMonthClick() {
    this.showPreviousMonth();
  }

  handleCaptionClick(e, currentMonth) {
    e.persist();
    this.props.onCaptionClick(e, currentMonth);
  }

  handleDayTouchTap(e, day, modifiers) {
    e.persist();
    if (modifiers.indexOf("outside") > -1) {
      this.handleOutsideDayPress(day);
    }
    this.props.onDayTouchTap(e, day, modifiers);
  }

  handleDayClick(e, day, modifiers) {
    e.persist();
    if (modifiers.indexOf("outside") > -1) {
      this.handleOutsideDayPress(day);
    }

    this.props.onDayClick(e, day, modifiers);
  }

  handleDayMouseEnter(e, day, modifiers) {
    e.persist();
    this.props.onDayMouseEnter(e, day, modifiers);
  }

  handleDayMouseLeave(e, day, modifiers) {
    e.persist();
    this.props.onDayMouseLeave(e, day, modifiers);
  }

  handleOutsideDayPress(day) {
    const { currentMonth } = this.state;
    const { numberOfMonths } = this.props;
    const diffInMonths = Helpers.getMonthsDiff(currentMonth, day);
    if (diffInMonths > 0 && diffInMonths >= numberOfMonths) {
      this.showNextMonth();
    }
    else if (diffInMonths < 0) {
      this.showPreviousMonth();
    }
  }

  renderNavBar() {
    const baseClass = "DayPicker-NavButton DayPicker-NavButton";
    const isRTL = this.props.dir === "rtl";

    const leftButton = isRTL ? this.allowNextMonth() : this.allowPreviousMonth();
    const rightButton = isRTL ? this.allowPreviousMonth() : this.allowNextMonth();
    return (

        { leftButton &&
          <span
            key="left"
            className={ `${baseClass}--prev` }
            onClick={ isRTL ? ::this.handleNextMonthClick : ::this.handlePrevMonthClick }
          />
        }
        { rightButton &&
          <span
            key="right"
            className={ `${baseClass}--next` }
            onClick={  isRTL ? ::this.handlePrevMonthClick : ::this.handleNextMonthClick }
          />
        }

    );
  }

  renderMonth(date, i) {
    const { locale, localeUtils, onCaptionClick, captionElement } = this.props;

    const caption = React.cloneElement(captionElement, {
      date, localeUtils, locale,
      onClick: onCaptionClick ? e => this.handleCaptionClick(e, date) : null
    });

    return (

        { caption }

            { this.renderWeekDays() }

          { this.renderWeeksInMonth(date) }

    );
  }

  renderWeekDays() {
    const { locale, localeUtils } = this.props;
    const days = [];
    for (let i = 0; i < 7; i++) {
      days.push(

            { localeUtils.formatWeekdayShort(i, locale) }

      );
    }
    return days;
  }

  renderWeeksInMonth(month) {
    const { locale, localeUtils } = this.props;
    const firstDayOfWeek = localeUtils.getFirstDayOfWeek(locale);
    return Helpers.getWeekArray(month, firstDayOfWeek).map((week, i) =>

        { week.map(day => this.renderDay(month, day)) }

    );
  }

  renderDay(month, day) {

    const { enableOutsideDays, modifiers: modifierFunctions } = this.props;

    let className = "DayPicker-Day";
    let modifiers = [];
    const key = `${day.getFullYear()}${day.getMonth()}${day.getDate()}`;

    const isToday = DateUtils.isSameDay(day, new Date());
    if (isToday) {
      modifiers.push("today");
    }

    const isOutside = day.getMonth() !== month.getMonth();
    if (isOutside) {
      modifiers.push("outside");
    }

    if (modifierFunctions) {
      const customModifiers = Helpers.getModifiersForDay(day, modifierFunctions);
      modifiers = [...modifiers, ...customModifiers];
    }

    className += modifiers.map(modifier => ` ${className}--${modifier}`).join("");

    if (isOutside && !enableOutsideDays) {
      return <div key={ `outside-${key}` } className={ className } />;
    }

    const { onDayMouseEnter, onDayMouseLeave, onDayTouchTap, onDayClick }
      = this.props;
    let tabIndex = null;
    if ((onDayTouchTap || onDayClick) && !isOutside) {
      tabIndex = -1;
      // Focus on the first day of the month
      if (day.getDate() === 1) {
        tabIndex = this.props.tabIndex;
      }
    }
    return (

 this.handleDayKeyDown(e, day, modifiers) }
        onMouseEnter= { onDayMouseEnter ?
          (e) => this.handleDayMouseEnter(e, day, modifiers) : null }
        onMouseLeave= { onDayMouseLeave ?
          (e) => this.handleDayMouseLeave(e, day, modifiers) : null }
        onClick= { onDayClick ?
          (e) => this.handleDayClick(e, day, modifiers) : null }
        onTouchTap= { onDayTouchTap ?
          (e) => this.handleDayTouchTap(e, day, modifiers) : null }
        >
        { this.props.renderDay(day) }

    );
  }

  render() {
    const { numberOfMonths, locale, canChangeMonth, ...attributes } = this.props;
    const { currentMonth } = this.state;
    let className = `DayPicker DayPicker--${locale}`;

    if (!this.props.onDayClick && !this.props.onDayTouchTap) {
      className = `${className} DayPicker--interactionDisabled`;
    }
    if (attributes.className) {
      className = `${className} ${attributes.className}`;
    }

    const months = [];
    let month;
    for (let i = 0; i < numberOfMonths; i++) {
      month = DateUtils.addMonths(currentMonth, i);
      months.push(this.renderMonth(month, i));
    }

    return (

 this.handleKeyDown(e) }
        {...attributes}>
        { canChangeMonth && this.renderNavBar() }
        { months }

    );
  }

}
<commit_msg>Spread attributes before applying props<commit_after>import React, { Component, PropTypes } from "react";
import * as Helpers from "./Helpers";
import * as DateUtils from "./DateUtils";
import * as LocaleUtils from "./LocaleUtils";

const keys = {
  LEFT: 37,
  RIGHT: 39,
  ENTER: 13,
  SPACE: 32
};

class Caption extends Component {

  render() {
    const { date, locale, localeUtils, onClick } = this.props;
    return (

        { localeUtils.formatMonthTitle(date, locale) }

    );
  }
}

export default class DayPicker extends Component {

  static propTypes = {

    initialMonth: PropTypes.instanceOf(Date),
    numberOfMonths: PropTypes.number,

    modifiers: PropTypes.object,

    locale: PropTypes.string,
    localeUtils: PropTypes.shape({
      formatMonthTitle: PropTypes.func,
      formatWeekdayShort: PropTypes.func,
      formatWeekdayLong: PropTypes.func,
      getFirstDayOfWeek: PropTypes.func
    }),

    enableOutsideDays: PropTypes.bool,
    canChangeMonth: PropTypes.bool,
    fromMonth: PropTypes.instanceOf(Date),
    toMonth: PropTypes.instanceOf(Date),

    onDayClick: PropTypes.func,
    onDayTouchTap: PropTypes.func,
    onDayMouseEnter: PropTypes.func,
    onDayMouseLeave: PropTypes.func,
    onMonthChange: PropTypes.func,
    onCaptionClick: PropTypes.func,

    renderDay: PropTypes.func,

    captionElement: PropTypes.element

  };

  static defaultProps = {
    tabIndex: 0,
    initialMonth: new Date(),
    numberOfMonths: 1,
    locale: "en",
    localeUtils: LocaleUtils,
    enableOutsideDays: false,
    canChangeMonth: true,
    renderDay: day => day.getDate(),
    captionElement:

  };

  constructor(props) {
    super(props);
    this.state = {
      currentMonth: Helpers.startOfMonth(props.initialMonth)
    };
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.initialMonth !== nextProps.initialMonth) {
      this.setState({
        currentMonth: Helpers.startOfMonth(nextProps.initialMonth)
      });
    }
  }

  allowPreviousMonth() {
    const { fromMonth } = this.props;
    if (!fromMonth) {
      return true;
    }
    const { currentMonth } = this.state;
    return Helpers.getMonthsDiff(currentMonth, fromMonth) < 0;
  }

  allowNextMonth() {
    const { toMonth, numberOfMonths } = this.props;
    if (!toMonth) {
      return true;
    }
    const { currentMonth } = this.state;
    return Helpers.getMonthsDiff(currentMonth, toMonth) >= numberOfMonths;
  }

  allowMonth(d) {
    const { fromMonth, toMonth } = this.props;
    if ((fromMonth && Helpers.getMonthsDiff(fromMonth, d) < 0) ||
      (toMonth && Helpers.getMonthsDiff(toMonth, d) > 0)) {
      return false;
    }
    return true;
  }

  showMonth(d) {
    if (!this.allowMonth(d)) {
      return;
    }
    this.setState({
      currentMonth: Helpers.startOfMonth(d)
    });
  }

  showNextMonth(callback) {
    if (!this.allowNextMonth()) {
      return;
    }
    const { currentMonth } = this.state;
    const nextMonth = DateUtils.addMonths(currentMonth, 1);
    this.setState({
      currentMonth: nextMonth
    }, () => {
      if (callback) {
        callback();
      }
      if (this.props.onMonthChange) {
        this.props.onMonthChange(this.state.currentMonth);
      }
    });
  }

  showPreviousMonth(callback) {
    if (!this.allowPreviousMonth()) {
      return;
    }
    const { currentMonth } = this.state;
    const prevMonth = DateUtils.addMonths(currentMonth, -1);
    this.setState({
      currentMonth: prevMonth
    }, () => {
      if (callback) {
        callback();
      }
      if (this.props.onMonthChange) {
        this.props.onMonthChange(this.state.currentMonth);
      }
    });
  }

  focusPreviousDay(dayNode) {
    const body = dayNode.parentNode.parentNode.parentNode.parentNode;
    let dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
    let nodeIndex;
    for (let i = 0; i < dayNodes.length; i++) {
      if (dayNodes[i] === dayNode) {
        nodeIndex = i;
        break;
      }
    }
    if (nodeIndex === 0) {
      const { currentMonth } = this.state;
      const { numberOfMonths } = this.props;
      const prevMonth = DateUtils.addMonths(currentMonth, -numberOfMonths);
      this.setState({
        currentMonth: prevMonth
      }, () => {
        dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
        dayNodes[dayNodes.length - 1].focus();
      });
    }
    else {
      dayNodes[nodeIndex - 1].focus();
    }
  }

  focusNextDay(dayNode) {
    const body = dayNode.parentNode.parentNode.parentNode.parentNode;
    let dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
    let nodeIndex;
    for (let i = 0; i < dayNodes.length; i++) {
      if (dayNodes[i] === dayNode) {
        nodeIndex = i;
        break;
      }
    }

    if (nodeIndex === dayNodes.length - 1) {
      const { currentMonth } = this.state;
      const { numberOfMonths } = this.props;
      const nextMonth = DateUtils.addMonths(currentMonth, numberOfMonths);
      this.setState({
        currentMonth: nextMonth
      }, () => {
        dayNodes = body.querySelectorAll(".DayPicker-Day:not(.DayPicker-Day--outside)");
        dayNodes[0].focus();
      });
    }
    else {
      dayNodes[nodeIndex + 1].focus();
    }
  }

  // Event handlers

  handleKeyDown(e) {
    e.persist();
    const { canChangeMonth, onKeyDown } = this.props;

    if (!canChangeMonth && onKeyDown) {
      onKeyDown(e);
      return;
    }

    if (canChangeMonth) {
      switch (e.keyCode) {
      case keys.LEFT:
        this.showPreviousMonth(onKeyDown);
        break;
      case keys.RIGHT:
        this.showNextMonth(onKeyDown);
        break;
      default:
        if (onKeyDown) {
          onKeyDown(e);
        }
      }
    }
  }

  handleDayKeyDown(e, day, modifiers) {
    e.persist();
    switch (e.keyCode) {
    case keys.LEFT:
      e.preventDefault();
      e.stopPropagation();
      this.focusPreviousDay(e.target);
      break;
    case keys.RIGHT:
      e.preventDefault();
      e.stopPropagation();
      this.focusNextDay(e.target);
      break;
    case keys.ENTER:
    case keys.SPACE:
      e.preventDefault();
      e.stopPropagation();
      if (this.props.onDayClick) {
        this.handleDayClick(e, day, modifiers);
      }
      if (this.props.onDayTouchTap) {
        this.handleDayTouchTap(e, day, modifiers);
      }
      break;
    }
  }

  handleNextMonthClick() {
    this.showNextMonth();
  }

  handlePrevMonthClick() {
    this.showPreviousMonth();
  }

  handleCaptionClick(e, currentMonth) {
    e.persist();
    this.props.onCaptionClick(e, currentMonth);
  }

  handleDayTouchTap(e, day, modifiers) {
    e.persist();
    if (modifiers.indexOf("outside") > -1) {
      this.handleOutsideDayPress(day);
    }
    this.props.onDayTouchTap(e, day, modifiers);
  }

  handleDayClick(e, day, modifiers) {
    e.persist();
    if (modifiers.indexOf("outside") > -1) {
      this.handleOutsideDayPress(day);
    }

    this.props.onDayClick(e, day, modifiers);
  }

  handleDayMouseEnter(e, day, modifiers) {
    e.persist();
    this.props.onDayMouseEnter(e, day, modifiers);
  }

  handleDayMouseLeave(e, day, modifiers) {
    e.persist();
    this.props.onDayMouseLeave(e, day, modifiers);
  }

  handleOutsideDayPress(day) {
    const { currentMonth } = this.state;
    const { numberOfMonths } = this.props;
    const diffInMonths = Helpers.getMonthsDiff(currentMonth, day);
    if (diffInMonths > 0 && diffInMonths >= numberOfMonths) {
      this.showNextMonth();
    }
    else if (diffInMonths < 0) {
      this.showPreviousMonth();
    }
  }

  renderNavBar() {
    const baseClass = "DayPicker-NavButton DayPicker-NavButton";
    const isRTL = this.props.dir === "rtl";

    const leftButton = isRTL ? this.allowNextMonth() : this.allowPreviousMonth();
    const rightButton = isRTL ? this.allowPreviousMonth() : this.allowNextMonth();
    return (

        { leftButton &&
          <span
            key="left"
            className={ `${baseClass}--prev` }
            onClick={ isRTL ? ::this.handleNextMonthClick : ::this.handlePrevMonthClick }
          />
        }
        { rightButton &&
          <span
            key="right"
            className={ `${baseClass}--next` }
            onClick={  isRTL ? ::this.handlePrevMonthClick : ::this.handleNextMonthClick }
          />
        }

    );
  }

  renderMonth(date, i) {
    const { locale, localeUtils, onCaptionClick, captionElement } = this.props;

    const caption = React.cloneElement(captionElement, {
      date, localeUtils, locale,
      onClick: onCaptionClick ? e => this.handleCaptionClick(e, date) : null
    });

    return (

        { caption }

            { this.renderWeekDays() }

          { this.renderWeeksInMonth(date) }

    );
  }

  renderWeekDays() {
    const { locale, localeUtils } = this.props;
    const days = [];
    for (let i = 0; i < 7; i++) {
      days.push(

            { localeUtils.formatWeekdayShort(i, locale) }

      );
    }
    return days;
  }

  renderWeeksInMonth(month) {
    const { locale, localeUtils } = this.props;
    const firstDayOfWeek = localeUtils.getFirstDayOfWeek(locale);
    return Helpers.getWeekArray(month, firstDayOfWeek).map((week, i) =>

        { week.map(day => this.renderDay(month, day)) }

    );
  }

  renderDay(month, day) {

    const { enableOutsideDays, modifiers: modifierFunctions } = this.props;

    let className = "DayPicker-Day";
    let modifiers = [];
    const key = `${day.getFullYear()}${day.getMonth()}${day.getDate()}`;

    const isToday = DateUtils.isSameDay(day, new Date());
    if (isToday) {
      modifiers.push("today");
    }

    const isOutside = day.getMonth() !== month.getMonth();
    if (isOutside) {
      modifiers.push("outside");
    }

    if (modifierFunctions) {
      const customModifiers = Helpers.getModifiersForDay(day, modifierFunctions);
      modifiers = [...modifiers, ...customModifiers];
    }

    className += modifiers.map(modifier => ` ${className}--${modifier}`).join("");

    if (isOutside && !enableOutsideDays) {
      return <div key={ `outside-${key}` } className={ className } />;
    }

    const { onDayMouseEnter, onDayMouseLeave, onDayTouchTap, onDayClick }
      = this.props;
    let tabIndex = null;
    if ((onDayTouchTap || onDayClick) && !isOutside) {
      tabIndex = -1;
      // Focus on the first day of the month
      if (day.getDate() === 1) {
        tabIndex = this.props.tabIndex;
      }
    }
    return (

 this.handleDayKeyDown(e, day, modifiers) }
        onMouseEnter= { onDayMouseEnter ?
          (e) => this.handleDayMouseEnter(e, day, modifiers) : null }
        onMouseLeave= { onDayMouseLeave ?
          (e) => this.handleDayMouseLeave(e, day, modifiers) : null }
        onClick= { onDayClick ?
          (e) => this.handleDayClick(e, day, modifiers) : null }
        onTouchTap= { onDayTouchTap ?
          (e) => this.handleDayTouchTap(e, day, modifiers) : null }
        >
        { this.props.renderDay(day) }

    );
  }

  render() {
    const { numberOfMonths, locale, canChangeMonth, ...attributes } = this.props;
    const { currentMonth } = this.state;
    let className = `DayPicker DayPicker--${locale}`;

    if (!this.props.onDayClick && !this.props.onDayTouchTap) {
      className = `${className} DayPicker--interactionDisabled`;
    }
    if (attributes.className) {
      className = `${className} ${attributes.className}`;
    }

    const months = [];
    let month;
    for (let i = 0; i < numberOfMonths; i++) {
      month = DateUtils.addMonths(currentMonth, i);
      months.push(this.renderMonth(month, i));
    }

    return (

 this.handleKeyDown(e) }>
        { canChangeMonth && this.renderNavBar() }
        { months }

    );
  }

}
<|endoftext|>


<commit_before>/* global window, localStorage, navigator */

import Ember from 'ember';
const {
  computed,
} = Ember;

import getOwner from 'ember-getowner-polyfill';

export default Ember.Component.extend({
  // http://discuss.emberjs.com/t/best-practices-accessing-app-config-from-addon-code/7006/16
  config: computed(function() {
    return getOwner(this).resolveRegistration('config:environment').emberSmartBanner;
  }),

  title: computed.or('titleIOS', 'titleAndroid', 'config.title'),
  description: computed.or('descriptionIOS', 'descriptionAndroid', 'config.description'),
  linkText: computed.or('linkTextIOS', 'linkTextAndroid', 'config.linkText'),
  iconUrl: computed.reads('config.iconUrl'),
  showBannerReminder: computed.or('config.alwayShowBanner', 'afterCloseBool', 'afterVisitBool', 'showBannerDefault'),
  showBanner: computed.and('showBannerReminder', 'openBanner'),
  alwayShowBanner: '',  // Set showBanner to true to always show
  showBannerDefault: true,
  link: computed.or('appStoreLink', 'marketLink', 'config.link'),

  mobileOperatingSystem: computed(function() {
    const userAgent = navigator.userAgent || navigator.vendor || window.opera;
    if (userAgent.match(/iPad/i) || userAgent.match(/iPhone/i) || userAgent.match(/iPod/i)) {
      return 'iOS';
    } else if (userAgent.match(/Android/i)) {
      return 'Android';
    } else {
      return 'unknown';
    }
  }),

  iOS: computed.equal('mobileOperatingSystem', 'iOS'),
  android: computed.equal('mobileOperatingSystem', 'Android'),

  titleIOS: computed.and('iOS', 'config.titleIOS'),
  descriptionIOS: computed.and('iOS', 'config.descriptionIOS'),
  linkTextIOS: computed.and('iOS', 'config.linkTextIOS'),
  appStoreLanguage: computed.reads('config.appStoreLanguage'),
  appIdIOS: computed.reads('reads.appIdIOS'),
  appStoreLink: computed(function() {
    return (this.get('iOS') && (this.get('config.appStoreLink') || 'https://itunes.apple.com/' + this.get('appStoreLanguage') + '/app/' + this.get('appIdIOS')));
  }),

  titleAndroid: computed.and('android', 'config.titleAndroid'),
  descriptionAndroid: computed.and('android', 'config.descriptionAndroid'),
  linkTextAndroid: computed.and('android', 'config.linkTextAndroid'),
  appIdAndroid: computed.reads('reads.appIdAndroid'),
  marketLink: computed(function() {
    return (this.get('android') && (this.get('config.marketLink') || 'market://details?id=' + this.get('appIdAndroid')));
  }),

  closeBanner: 'false',
  openBanner: computed.none('closeBanner'),

  actions: {
    openLink: function() {
      this.setTimeStamp('lastDayVisited');
    },

    closeBanner: function() {
      this.set('closeBanner', true);
      this.setTimeStamp('lastDayClosed');
    }
  },

  setTimeStamp(key) {
    const now = new Date();
    this.setItem(key, now);
  },

  setItem(key, value) {
    localStorage.setItem(this._namespacedKey(key), JSON.stringify(value));
  },

  getItem(key) {
    const result = localStorage.getItem(this._namespacedKey(key));
    if (result) {
      return JSON.parse(result);
    }
  },

  namespace: 'ember-smart-banner',

  _namespacedKey(keyName) {
    return this.get('namespace') + `.${keyName}`;
  },

  reminderAfterClose: computed.reads('config.reminderAfterClose'), // Number of days after user closes banner to wait to show banner again, 0 for always show
  reminderAfterVisit: computed.reads('config.reminderAfterVisit'), // Number of days after visit to wait to show banner again, 0 for always show

  afterCloseBool: computed.gte('daysSinceClose', 'reminderAfterClose'),
  afterVisitBool: computed.gte('daysSinceVisit', 'reminderAfterVisit'),

  daysSinceClose: computed(function() {
    const timeSinceClosed = new Date() - Date.parse(this.getItem('lastDayClosed'));
    return Math.floor(timeSinceClosed / (24 * 60 * 60 * 1000)); // Convert ms to days
  }),

  daysSinceVisit: computed(function() {
    const timeSinceVisited = new Date() - Date.parse(this.getItem('lastDayVisited'));
    return Math.floor(timeSinceVisited / (24 * 60 * 60 * 1000)); // Convert ms to days
  }),

  //https://github.com/jasny/jquery.smartbanner/blob/master/jquery.smartbanner.js
});
<commit_msg>fix close banner logic<commit_after>/* global window, localStorage, navigator */

import Ember from 'ember';
const {
  computed,
} = Ember;

import getOwner from 'ember-getowner-polyfill';

export default Ember.Component.extend({
  // http://discuss.emberjs.com/t/best-practices-accessing-app-config-from-addon-code/7006/16
  config: computed(function() {
    return getOwner(this).resolveRegistration('config:environment').emberSmartBanner;
  }),

  title: computed.or('titleIOS', 'titleAndroid', 'config.title'),
  description: computed.or('descriptionIOS', 'descriptionAndroid', 'config.description'),
  linkText: computed.or('linkTextIOS', 'linkTextAndroid', 'config.linkText'),
  iconUrl: computed.reads('config.iconUrl'),
  showBannerReminder: computed.or('config.alwayShowBanner', 'afterCloseBool', 'afterVisitBool', 'showBannerDefault'),
  showBanner: computed.and('showBannerReminder', 'openBanner'),
  alwayShowBanner: '',  // Set showBanner to true to always show
  showBannerDefault: true,
  link: computed.or('appStoreLink', 'marketLink', 'config.link'),

  mobileOperatingSystem: computed(function() {
    const userAgent = navigator.userAgent || navigator.vendor || window.opera;
    if (userAgent.match(/iPad/i) || userAgent.match(/iPhone/i) || userAgent.match(/iPod/i)) {
      return 'iOS';
    } else if (userAgent.match(/Android/i)) {
      return 'Android';
    } else {
      return 'unknown';
    }
  }),

  iOS: computed.equal('mobileOperatingSystem', 'iOS'),
  android: computed.equal('mobileOperatingSystem', 'Android'),

  titleIOS: computed.and('iOS', 'config.titleIOS'),
  descriptionIOS: computed.and('iOS', 'config.descriptionIOS'),
  linkTextIOS: computed.and('iOS', 'config.linkTextIOS'),
  appStoreLanguage: computed.reads('config.appStoreLanguage'),
  appIdIOS: computed.reads('reads.appIdIOS'),
  appStoreLink: computed(function() {
    return (this.get('iOS') && (this.get('config.appStoreLink') || 'https://itunes.apple.com/' + this.get('appStoreLanguage') + '/app/' + this.get('appIdIOS')));
  }),

  titleAndroid: computed.and('android', 'config.titleAndroid'),
  descriptionAndroid: computed.and('android', 'config.descriptionAndroid'),
  linkTextAndroid: computed.and('android', 'config.linkTextAndroid'),
  appIdAndroid: computed.reads('reads.appIdAndroid'),
  marketLink: computed(function() {
    return (this.get('android') && (this.get('config.marketLink') || 'market://details?id=' + this.get('appIdAndroid')));
  }),

  closeBanner: false,
  openBanner: computed.not('closeBanner'),

  actions: {
    openLink: function() {
      this.setTimeStamp('lastDayVisited');
    },

    closeBanner: function() {
      this.set('closeBanner', true);
      this.setTimeStamp('lastDayClosed');
    }
  },

  setTimeStamp(key) {
    const now = new Date();
    this.setItem(key, now);
  },

  setItem(key, value) {
    localStorage.setItem(this._namespacedKey(key), JSON.stringify(value));
  },

  getItem(key) {
    const result = localStorage.getItem(this._namespacedKey(key));
    if (result) {
      return JSON.parse(result);
    }
  },

  namespace: 'ember-smart-banner',

  _namespacedKey(keyName) {
    return this.get('namespace') + `.${keyName}`;
  },

  reminderAfterClose: computed.reads('config.reminderAfterClose'), // Number of days after user closes banner to wait to show banner again, 0 for always show
  reminderAfterVisit: computed.reads('config.reminderAfterVisit'), // Number of days after visit to wait to show banner again, 0 for always show

  afterCloseBool: computed.gte('daysSinceClose', 'reminderAfterClose'),
  afterVisitBool: computed.gte('daysSinceVisit', 'reminderAfterVisit'),

  daysSinceClose: computed(function() {
    const timeSinceClosed = new Date() - Date.parse(this.getItem('lastDayClosed'));
    return Math.floor(timeSinceClosed / (24 * 60 * 60 * 1000)); // Convert ms to days
  }),

  daysSinceVisit: computed(function() {
    const timeSinceVisited = new Date() - Date.parse(this.getItem('lastDayVisited'));
    return Math.floor(timeSinceVisited / (24 * 60 * 60 * 1000)); // Convert ms to days
  }),

  //https://github.com/jasny/jquery.smartbanner/blob/master/jquery.smartbanner.js
});
<|endoftext|>


<commit_before>const webpack = require('webpack');
const lodash = require('lodash');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const autoprefixer = require('autoprefixer');
const baseConfig = require('./config.base');
const commons = require('./common.js');

module.exports = lodash.merge(baseConfig, {
    devtool: 'source-map',
    debug: false,

    output: {
        path: commons.root('dist'),
        filename: '[name].bundle.[hash].js',
        sourceMapFilename: '[file].map',
        chunkFilename: '[id].chunk.js',
        publicPath: '/'
    },

    module: {
        loaders: baseConfig.module.loaders.concat([
            {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract('style', 'css?minimize', 'postcss')
            }, {
                test: /\.less$/,
                exclude: /node_modules/,
                loader: ExtractTextPlugin.extract('style', 'css?minimize!less', 'postcss')
            }, {
                test: /\.json$/,
                loader: ExtractTextPlugin.extract('json'),
            }
        ])
    },

    plugins: baseConfig.plugins.concat([
        new CopyWebpackPlugin([{ from: 'public', to: 'public' }]),
        new ExtractTextPlugin('[name].bundle.[hash].css', {}),
        new webpack.optimize.OccurenceOrderPlugin(),
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': '"production"'
        }),
        new webpack.optimize.UglifyJsPlugin({
            compressor: {
                warnings: false
            }
        }),
        new webpack.optimize.DedupePlugin(),
    ]),

    postcss: [
        autoprefixer({ browsers: ['last 2 versions'] })
    ],
});
<commit_msg>Fix typo<commit_after>const webpack = require('webpack');
const lodash = require('lodash');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const autoprefixer = require('autoprefixer');
const baseConfig = require('./config.base');
const commons = require('./common.js');

module.exports = lodash.merge(baseConfig, {
    devtool: 'source-map',
    debug: false,

    output: {
        path: commons.root('dist'),
        filename: '[name].bundle.[hash].js',
        sourceMapFilename: '[file].map',
        chunkFilename: '[id].chunk.js',
        publicPath: '/'
    },

    module: {
        loaders: baseConfig.module.loaders.concat([
            {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract('style', 'css?minimize', 'postcss')
            }, {
                test: /\.less$/,
                exclude: /node_modules/,
                loader: ExtractTextPlugin.extract('style', 'css?minimize!less', 'postcss')
            }, {
                test: /\.json$/,
                loader: ExtractTextPlugin.extract('json'),
            }
        ])
    },

    plugins: baseConfig.plugins.concat([
        new CopyWebpackPlugin([{ from: 'public', to: 'public' }]),
        new ExtractTextPlugin('[name].bundle.[hash].css', {}),
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': '"production"'
        }),
        new webpack.optimize.UglifyJsPlugin({
            compressor: {
                warnings: false
            }
        }),
        new webpack.optimize.DedupePlugin(),
    ]),

    postcss: [
        autoprefixer({ browsers: ['last 2 versions'] })
    ],
});
<|endoftext|>


<commit_before>/**
 * Put tasks defined in ~extend.js appended files within the more general tasks listed below.
 */
'use strict';

const gulp = require('gulp');

gulp.task('contrib:data', [
]);

gulp.task('contrib:frontend-copy', [
  // Comment or delete if you wish to disable this.
  'stylus:frontend-copy'
]);

gulp.task('contrib:once', [
  // Comment or delete if you wish to disable this.
  'stylus:once'
]);

gulp.task('contrib:static', [
]);

gulp.task('contrib:syncback', [
]);

gulp.task('contrib:tcp-ip', [
]);

gulp.task('contrib:template', [
]);

gulp.task('contrib:watch', [
  // Comment or delete if you wish to disable this.
  'stylus:watch'
]);
<commit_msg>replaceing stylus:once in main profile extend/contrib.js<commit_after>/**
 * Put tasks defined in ~extend.js appended files within the more general tasks listed below.
 */
'use strict';

const gulp = require('gulp');

gulp.task('contrib:data', [
]);

gulp.task('contrib:frontend-copy', [
  // Comment or delete if you wish to disable this.
  'stylus:frontend-copy'
]);

gulp.task('contrib:once', [
  // Comment or delete if you wish to disable this.
  'stylus:diff-then-comment'
  // If you are a power-user, delete 'stylus:diff-then-comment'. If you still want Stylus, uncomment 'stylus:once' for
  // better performance, or replace with 'stylus:no-comment' (also more performant) if you do not want line comments in
  // your CSS.
  //'stylus:once'
]);

gulp.task('contrib:static', [
]);

gulp.task('contrib:syncback', [
]);

gulp.task('contrib:tcp-ip', [
]);

gulp.task('contrib:template', [
]);

gulp.task('contrib:watch', [
  // Comment or delete if you wish to disable this.
  'stylus:watch'
]);
<|endoftext|>


<commit_before>define(['app', 'authentication', '/app/js/services/filters.js', 'URI', 'editFormUtility', '/app/js/services/filters/linkify.js', '/app/js/directives/projecttable.js',], function(app) {
  app.controller('DonorCtrl', function ($scope, $http, editFormUtility) {
    var sID = new URI().query(true).id;

    $scope.DonorID = sID;
    $scope.countries = [];

    editFormUtility.load(sID).then(function(data) {
        console.log('donor data: ', data);
        $scope.donor = data;
    });

    $http.get('/api/v2013/index/select?cb=1418322176016&q=((realm_ss:chm)%20AND%20(schema_s:lwProject)%20AND%20(donor_ss:'+sID+'))&rows=25&sort=createdDate_dt+desc,+title_t+asc&start=0&wt=json').then(function(data) {
       $http.get('/api/v2013/thesaurus/domains/countries/terms', { cache: true }).then(function(data2) {
          $scope.countries = data2.data;
        $scope.matches = data.data.response.docs;
            _.each($scope.matches,function(match){
                  match.countryLong=[];
                  _.each(match.country_ss, function (countryCode){
                        _.each($scope.countries,function(country){
                            if(country.identifier === countryCode)
                              match.countryLong.push(country.name);
                        });
                  });
            });

 console.log('$scope.matches ', $scope.matches);
      });
    });

    $scope.count = function(o) { var c=0;for(var k in o)++c;return c;};

  });
});
<commit_msg>fixed api call and country issue<commit_after>define(['app', 'authentication', '/app/js/services/filters.js', 'URI', 'editFormUtility', '/app/js/services/filters/linkify.js', '/app/js/directives/projecttable.js',], function(app) {
  app.controller('DonorCtrl', function ($scope, $http, editFormUtility) {
    var sID = new URI().query(true).id;

    $scope.DonorID = sID;
    $scope.countries = [];

    editFormUtility.load(sID).then(function(data) {
        console.log('donor data: ', data);
        $scope.donor = data;
    });

    $http.get('/api/v2013/index/select?cb=1418322176016&q=((realm_ss:chm)%20AND%20(schema_s:lwProject)%20AND%20(donor_ss:'+sID+'))&rows=25&sort=createdDate_dt+desc,+title_t+asc&start=0&wt=json').then(function(data) {
       $http.get('/api/v2013/thesaurus/domains/countries/terms', { cache: true }).then(function(data2) {
          $scope.countries = data2.data;
          $scope.matches = data.data.response.docs;
            _.each($scope.matches,function(match){
                  match.countryLong=[];
                  _.each(match.country_ss, function (countryCode){
                        _.each($scope.countries,function(country){
                            if(country.identifier === countryCode)
                              match.countryLong.push(country.name);
                        });
                  });
            });

 console.log('$scope.matches ', $scope.matches);
      });
    });

        $scope.count = function(o) { var c=0;for(var k in o)++c;return c;};

  });
});
<|endoftext|>