<commit_before>Vps.Binding.AbstractPanel = function(config) {
    if (!config.actions) this.actions = {}; //muss hier sein
    Vps.Binding.AbstractPanel.superclass.constructor.apply(this, arguments);
};
Ext.extend(Vps.Binding.AbstractPanel, Ext.Panel,
{
    checkDirty: true,

    initComponent: function() {
        this.activeId = null;

        this.addEvents(
            /**
            * @event datachange
            * Daten wurden geändert, zB um grid neu zu laden
            * @param {Object} result from server
            */
            'datachange',
            'selectionchange',
            'beforeselectionchange',
            'loaded'
        );
        var binds = this.bindings;
        this.bindings = new Ext.util.MixedCollection();
        if (binds) {
            this.addBinding.apply(this, binds);
        }
        this.on('selectionchange', function() {
            var id = this.getSelectedId();
            if (id) {
                this.activeId = id;
                this.bindings.each(function(b) {
                    b.item.enable();
                    if (b.item.ownerCt instanceof Ext.TabPanel) {
                        if (b.item.ownerCt.getActiveTab() != b.item) {
                            //dieses binding überspringen, liegt in einem
                            //tab der nicht aktiv ist
                            return;
                        }
                    }
                    this._loadBinding(b);
                }, this);
            }
        }, this, {buffer: 500});
        this.on('beforeselectionchange', function(id) {
            var ret = true;
            this.bindings.each(function(b) {
                if (!b.item.mabySubmit({
                    callback: function() {
                        b.item.reset();
                        this.selectId(id);
                    },
                    scope: this
                })) {
                    ret = false;
                    return false; //break each
                }
            }, this)
            return ret;
        }, this);

        if (!this.baseParams) {
            this.baseParams = {};
        }
        this.setBaseParams(this.baseParams); //damit baseParams in applyBaseParams modifiziert werden können

        Vps.Binding.AbstractPanel.superclass.initComponent.call(this);
    },

    //private
    _loadBinding: function(b)
    {
        var params = {};
        if (b.componentIdSuffix) {
            params.componentId =
                this.getBaseParams()['componentId'] +
                String.format(b.componentIdSuffix, this.activeId);
        } else if (b.componentId) {
            params.componentId =
                String.format(b.componentId, this.activeId);
        } else {
			//this.getGrid().getSelectionModel().getSelections()[0].data[b.valueParam];
            params[b.queryParam] = this.activeId;
        }
        if (!b.item.hasBaseParams(params)) {
            b.item.applyBaseParams(params);
            b.item.load();
        }
    },
    addBinding: function() {
        for(var i = 0; i < arguments.length; i++){
            var b = arguments[i];
            if (b instanceof Vps.Binding.AbstractPanel) {
                b = {item: b};
            }
            if (!b.queryParam) b.queryParam = 'id';
            b.item.disable();
            b.item.setAutoLoad(false);
            this.bindings.add(b);

            b.item.on('datachange', function(result)
            {
                if (result && result.data && result.data.addedId) {

                    //nachdem ein neuer eintrag hinzugefügt wurde die anderen reloaden
                    this.activeId = result.data.addedId;

                    //neuladen und wenn geladen den neuen auswählen
                    this.reload({
                        callback: function() {
                            this.selectId(this.activeId);
                        },
                        scope: this
                    });

                    //die anderen auch neu laden
                    this.bindings.each(function(b) {
                        b.item.enable();
                        if (b.item.ownerCt instanceof Ext.TabPanel) {
                            if (b.item.ownerCt.getActiveTab() != b.item) {
                                //dieses binding überspringen, liegt in einem
                                //tab der nicht aktiv ist
                                return;
                            }
                        }
                        this._loadBinding(b);
                    }, this);
                } else {
                    this.reload();
                }
            }, this);

            if (b.item instanceof Vps.Auto.FormPanel) {
                b.item.on('addaction', function(form) {
                    this.activeId = 0;
                    this.selectId(0);
                    //bei addaction die anderen disablen
                    this.bindings.each(function(i) {
                        if (i.item != form) {
                            i.item.disable();
                        }
                    }, this);
                }, this);

                b.item.on('deleteaction', function(form) {
                    this.activeId = null;
                    this.selectId(null);
                    //wenn gelöscht alle anderen disablen
                    this.bindings.each(function(i) {
                        i.item.disable();
                    }, this);
                }, this);
            }
            b.item.on('activate', function(item) {
                this.bindings.each(function(i) {
                    if (i.item == item) {
                        if (!item.disabled) {
                            this._loadBinding(i);
                        }
                        return false;
                    }
                }, this);
            }, this);
        }
    },
    removeBinding: function(autoPanel) {
        //todo
    },

    getAction : function(type)
    {
        if (this.actions[type]) return this.actions[type];
    },

    //deprecated
    mabySave : function(callback, callCallbackIfNotDirty)
    {
        var ret = this.mabySubmit(callback.callback, callback.scope || this);
        if(typeof callCallbackIfNotDirty == 'undefined') callCallbackIfNotDirty = true;
        if (ret && callCallbackIfNotDirty) {
            callback.callback.call(callback.scope);
        }
        return ret;
    },

    mabySubmit : function(cb, options)
    {
        if (this.checkDirty && !this.disabled && this.isDirty()) {
            Ext.Msg.show({
            title:trlVps('Save'),
            msg: trlVps('Do you want to save the changes?'),
            buttons: Ext.Msg.YESNOCANCEL,
            scope: this,
            fn: function(button) {
                if (button == 'yes') {
                    if (!options) options = {};
                    options.success = cb.callback;
                    options.scope = cb.scope;
                    this.submit(options);
                } else if (button == 'no') {
                    cb.callback.call(cb.scope || this);
                } else if (button == 'cancel') {
                    //nothing to do, action allread canceled
                }
            }});
            return false;
        }
        return true;
    },

    submit: function(options) {
    },
    reset: function() {
    },
    load: function(params, options) {
    },
    reload : function(options) {
        if (!this.disabled) {
            this.load(null, options);
        }
    },
    getSelectedId: function() {
    },
    selectId: function(id) {
    },
    isDirty: function() {
        return false;
    },
    setBaseParams : function(baseParams) {
        this.baseParams = {};
        this.applyBaseParams(baseParams);
    },
    applyBaseParams : function(baseParams) {
        if (!this.baseParams) { this.baseParams = {}; }
        Ext.apply(this.baseParams, baseParams);
    },
    getBaseParams : function() {
        return this.baseParams || {};
    },

    //um herauszufinden ob params neue baseParams sind
    //wird zB in ComponentPanel überschrieben
    //getBaseParams von aussen holen und mit den neuen vergleichen geht im ComponentPanel
    //nicht, da diese anders gespeichert werden
    hasBaseParams : function(params) {
        var baseParams = this.getBaseParams();
        for (var i in params) {
            if (params[i] != baseParams[i]) return false;
        }
        return true;
    },

    setAutoLoad: function(v) {
        this.autoLoad = v;
    },
    getAutoLoad: function() {
        return this.autoLoad;
    }
});
<commit_msg>wenn keine baseParams in config diese auch nicht setzen. verursachte bug in TabPanel<commit_after>Vps.Binding.AbstractPanel = function(config) {
    if (!config.actions) this.actions = {}; //muss hier sein
    Vps.Binding.AbstractPanel.superclass.constructor.apply(this, arguments);
};
Ext.extend(Vps.Binding.AbstractPanel, Ext.Panel,
{
    checkDirty: true,

    initComponent: function() {
        this.activeId = null;

        this.addEvents(
            /**
            * @event datachange
            * Daten wurden geändert, zB um grid neu zu laden
            * @param {Object} result from server
            */
            'datachange',
            'selectionchange',
            'beforeselectionchange',
            'loaded'
        );
        var binds = this.bindings;
        this.bindings = new Ext.util.MixedCollection();
        if (binds) {
            this.addBinding.apply(this, binds);
        }
        this.on('selectionchange', function() {
            var id = this.getSelectedId();
            if (id) {
                this.activeId = id;
                this.bindings.each(function(b) {
                    b.item.enable();
                    if (b.item.ownerCt instanceof Ext.TabPanel) {
                        if (b.item.ownerCt.getActiveTab() != b.item) {
                            //dieses binding überspringen, liegt in einem
                            //tab der nicht aktiv ist
                            return;
                        }
                    }
                    this._loadBinding(b);
                }, this);
            }
        }, this, {buffer: 500});
        this.on('beforeselectionchange', function(id) {
            var ret = true;
            this.bindings.each(function(b) {
                if (!b.item.mabySubmit({
                    callback: function() {
                        b.item.reset();
                        this.selectId(id);
                    },
                    scope: this
                })) {
                    ret = false;
                    return false; //break each
                }
            }, this)
            return ret;
        }, this);

        if (this.baseParams) {
            this.setBaseParams(this.baseParams); //damit baseParams in applyBaseParams modifiziert werden können
        }
        if (!this.baseParams) {
            this.baseParams = {};
        }

        Vps.Binding.AbstractPanel.superclass.initComponent.call(this);
    },

    //private
    _loadBinding: function(b)
    {
        var params = {};
        if (b.componentIdSuffix) {
            params.componentId =
                this.getBaseParams()['componentId'] +
                String.format(b.componentIdSuffix, this.activeId);
        } else if (b.componentId) {
            params.componentId =
                String.format(b.componentId, this.activeId);
        } else {
			//this.getGrid().getSelectionModel().getSelections()[0].data[b.valueParam];
            params[b.queryParam] = this.activeId;
        }
        if (!b.item.hasBaseParams(params)) {
            b.item.applyBaseParams(params);
            b.item.load();
        }
    },
    addBinding: function() {
        for(var i = 0; i < arguments.length; i++){
            var b = arguments[i];
            if (b instanceof Vps.Binding.AbstractPanel) {
                b = {item: b};
            }
            if (!b.queryParam) b.queryParam = 'id';
            b.item.disable();
            b.item.setAutoLoad(false);
            this.bindings.add(b);

            b.item.on('datachange', function(result)
            {
                if (result && result.data && result.data.addedId) {

                    //nachdem ein neuer eintrag hinzugefügt wurde die anderen reloaden
                    this.activeId = result.data.addedId;

                    //neuladen und wenn geladen den neuen auswählen
                    this.reload({
                        callback: function() {
                            this.selectId(this.activeId);
                        },
                        scope: this
                    });

                    //die anderen auch neu laden
                    this.bindings.each(function(b) {
                        b.item.enable();
                        if (b.item.ownerCt instanceof Ext.TabPanel) {
                            if (b.item.ownerCt.getActiveTab() != b.item) {
                                //dieses binding überspringen, liegt in einem
                                //tab der nicht aktiv ist
                                return;
                            }
                        }
                        this._loadBinding(b);
                    }, this);
                } else {
                    this.reload();
                }
            }, this);

            if (b.item instanceof Vps.Auto.FormPanel) {
                b.item.on('addaction', function(form) {
                    this.activeId = 0;
                    this.selectId(0);
                    //bei addaction die anderen disablen
                    this.bindings.each(function(i) {
                        if (i.item != form) {
                            i.item.disable();
                        }
                    }, this);
                }, this);

                b.item.on('deleteaction', function(form) {
                    this.activeId = null;
                    this.selectId(null);
                    //wenn gelöscht alle anderen disablen
                    this.bindings.each(function(i) {
                        i.item.disable();
                    }, this);
                }, this);
            }
            b.item.on('activate', function(item) {
                this.bindings.each(function(i) {
                    if (i.item == item) {
                        if (!item.disabled) {
                            this._loadBinding(i);
                        }
                        return false;
                    }
                }, this);
            }, this);
        }
    },
    removeBinding: function(autoPanel) {
        //todo
    },

    getAction : function(type)
    {
        if (this.actions[type]) return this.actions[type];
    },

    //deprecated
    mabySave : function(callback, callCallbackIfNotDirty)
    {
        var ret = this.mabySubmit(callback.callback, callback.scope || this);
        if(typeof callCallbackIfNotDirty == 'undefined') callCallbackIfNotDirty = true;
        if (ret && callCallbackIfNotDirty) {
            callback.callback.call(callback.scope);
        }
        return ret;
    },

    mabySubmit : function(cb, options)
    {
        if (this.checkDirty && !this.disabled && this.isDirty()) {
            Ext.Msg.show({
            title:trlVps('Save'),
            msg: trlVps('Do you want to save the changes?'),
            buttons: Ext.Msg.YESNOCANCEL,
            scope: this,
            fn: function(button) {
                if (button == 'yes') {
                    if (!options) options = {};
                    options.success = cb.callback;
                    options.scope = cb.scope;
                    this.submit(options);
                } else if (button == 'no') {
                    cb.callback.call(cb.scope || this);
                } else if (button == 'cancel') {
                    //nothing to do, action allread canceled
                }
            }});
            return false;
        }
        return true;
    },

    submit: function(options) {
    },
    reset: function() {
    },
    load: function(params, options) {
    },
    reload : function(options) {
        if (!this.disabled) {
            this.load(null, options);
        }
    },
    getSelectedId: function() {
    },
    selectId: function(id) {
    },
    isDirty: function() {
        return false;
    },
    setBaseParams : function(baseParams) {
        this.baseParams = {};
        this.applyBaseParams(baseParams);
    },
    applyBaseParams : function(baseParams) {
        if (!this.baseParams) { this.baseParams = {}; }
        Ext.apply(this.baseParams, baseParams);
    },
    getBaseParams : function() {
        return this.baseParams || {};
    },

    //um herauszufinden ob params neue baseParams sind
    //wird zB in ComponentPanel überschrieben
    //getBaseParams von aussen holen und mit den neuen vergleichen geht im ComponentPanel
    //nicht, da diese anders gespeichert werden
    hasBaseParams : function(params) {
        var baseParams = this.getBaseParams();
        for (var i in params) {
            if (params[i] != baseParams[i]) return false;
        }
        return true;
    },

    setAutoLoad: function(v) {
        this.autoLoad = v;
    },
    getAutoLoad: function() {
        return this.autoLoad;
    }
});
<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var autoprefixer = require('gulp-autoprefixer');
var plumber = require('gulp-plumber');
var compass = require('gulp-compass');
var handleErrors = require('../util/handleErrors');

var browserSync = require('browser-sync');

var config = require('../config');
var paths = config.paths;

gulp.task('compass', function() {
  return gulp.src(paths.src + '/' + paths.scss + '/' + config.scss.main)
    .pipe(plumber())
    .pipe(compass({
      css: paths.tmp + '/' + paths.css,
      sass: paths.src + '/' + paths.scss,
      image: paths.src + '/' + paths.images,
      javascripts: paths.src + '/' + paths.js,
      fonts: paths.src + '/' + paths.fonts,
      import_path: paths.components
        //, require: ['susy', 'modular-scale']
    }))
    .on('error', handleErrors)
    .pipe(autoprefixer(config.autoprefixer.def))
    .pipe(gulp.dest(paths.tmp + '/css'))
    .pipe(browserSync.reload({
      stream: true
    }));
});
<commit_msg>rm browsersync from compass<commit_after>'use strict';

var gulp = require('gulp');
var autoprefixer = require('gulp-autoprefixer');
var plumber = require('gulp-plumber');
var compass = require('gulp-compass');
var handleErrors = require('../util/handleErrors');

var config = require('../config');
var paths = config.paths;

gulp.task('compass', function() {
  return gulp.src(paths.src + '/' + paths.scss + '/' + config.scss.main)
    .pipe(plumber())
    .pipe(compass({
      css: paths.tmp + '/' + paths.css,
      sass: paths.src + '/' + paths.scss,
      image: paths.src + '/' + paths.images,
      javascripts: paths.src + '/' + paths.js,
      fonts: paths.src + '/' + paths.fonts,
      import_path: paths.components
        //, require: ['susy', 'modular-scale']
    }))
    .on('error', handleErrors)
    .pipe(autoprefixer(config.autoprefixer.def))
    .pipe(gulp.dest(paths.tmp + '/css'));
});
<|endoftext|>


<commit_before>import * as main from '../../src/main';
const {
  isTrue,
  isFalse,
  OPTION_KEYS,
  printException,
  collectUrlParams,
  formatUrl,
  openImages,
  getOptions,
  setStyle,
  onOriginalButtonClick,
} = main;

const makeResultParams = ({ format, name }) => {
  return {
    protocol: 'https:',
    host: 'pbs.twimg.com',
    pathname: '/media/hogefuga123',
    format,
    name: name || null,
  };
};

describe('Utils', () => {
  describe('printException', () => {
    it('エラーメッセージの表示(予期せぬ状況の確認)', () => {
      console.log = jest.fn();
      printException('exception message');
      expect(console.log.mock.calls[0][0]).toBe(
        'tooi: exception message at: http://localhost/'
      );
    });
  });

  describe('URLのツール', () => {
    // URLの変換のテストの場合たち
    const cases = [
      {
        title: '何もなし',
        url: 'https://pbs.twimg.com/media/hogefuga123',
        params: { format: 'jpg' },
      },
      {
        title: '.jpg',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg',
        params: { format: 'jpg' },
      },
      {
        title: '.png',
        url: 'https://pbs.twimg.com/media/hogefuga123.png',
        params: { format: 'png' },
      },
      {
        title: '.jpg:orig',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg:orig',
        params: { format: 'jpg', name: 'orig' },
      },
      {
        title: '.jpg:large',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg:large',
        params: { format: 'jpg', name: 'large' },
      },
      {
        title: '?format=jpg',
        url: 'https://pbs.twimg.com/media/hogefuga123?format=jpg',
        params: { format: 'jpg' },
      },
      {
        title: '?format=png',
        url: 'https://pbs.twimg.com/media/hogefuga123?format=png',
        params: { format: 'png' },
      },
      {
        title: '.jpg?format=jpg',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg?format=jpg',
        params: { format: 'jpg' },
      },
      {
        title: '.jpg?format=png',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg?format=png',
        params: { format: 'jpg' },
      },
      {
        title: '.png?format=jpg',
        url: 'https://pbs.twimg.com/media/hogefuga123.png?format=jpg',
        params: { format: 'png' },
      },
      {
        title: '.jpg?name=large',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg?name=large',
        params: { format: 'jpg', name: 'large' },
      },
      {
        title: '?format=jpg&name=large',
        url: 'https://pbs.twimg.com/media/hogefuga123?format=jpg&name=large',
        params: { format: 'jpg', name: 'large' },
      },
      {
        title: '.png?format=jpg&name=orig',
        url: 'https://pbs.twimg.com/media/hogefuga123.png?format=jpg&name=orig',
        params: { format: 'png', name: 'orig' },
      },
    ];

    describe('collectUrlParams 画像urlの要素を集める', () => {
      cases.forEach(singleCase => {
        const { title, url, params } = singleCase;
        it(title, () => {
          expect(collectUrlParams(url)).toStrictEqual(makeResultParams(params));
        });
      });

      it('twitterの画像URLでないときnull', () => {
        expect(collectUrlParams('https://twitter.com/tos')).toBe(null);
      });
    });

    describe('formatUrl 画像URLを https～?format=〜&name=orig に揃える', () => {
      cases.forEach(singleCase => {
        const { title, url, params } = singleCase;
        it(title, () => {
          expect(formatUrl(url)).toBe(
            `https://pbs.twimg.com/media/hogefuga123?format=${params.format}&name=orig`
          );
        });
      });

      it('twitterの画像URLでないときそのまま', () => {
        expect(formatUrl('https://twitter.com/tos')).toBe(
          'https://twitter.com/tos'
        );
      });
    });
  });

  describe('openImages 画像を開く', () => {
    it('画像URLを1つ渡したとき開く', () => {
      window.open = jest.fn();
      openImages(['https://pbs.twimg.com/media/1st?format=jpg&name=orig']);
      expect(window.open.mock.calls.length).toBe(1);
      expect(window.open.mock.calls[0][0]).toBe(
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig'
      );
    });

    it('画像URLを2つ渡したとき逆順に開く', () => {
      window.open = jest.fn();
      openImages([
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig',
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig',
      ]);
      expect(window.open.mock.calls.length).toBe(2);
      expect(window.open.mock.calls[0][0]).toBe(
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig'
      );
      expect(window.open.mock.calls[1][0]).toBe(
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig'
      );
    });

    it('画像URLを4つ渡したとき逆順に開く', () => {
      window.open = jest.fn();
      openImages([
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig',
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig',
        'https://pbs.twimg.com/media/3rd?format=jpg&name=orig',
        'https://pbs.twimg.com/media/4th?format=jpg&name=orig',
      ]);
      expect(window.open.mock.calls.length).toBe(4);
      expect(window.open.mock.calls[0][0]).toBe(
        'https://pbs.twimg.com/media/4th?format=jpg&name=orig'
      );
      expect(window.open.mock.calls[1][0]).toBe(
        'https://pbs.twimg.com/media/3rd?format=jpg&name=orig'
      );
      expect(window.open.mock.calls[2][0]).toBe(
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig'
      );
      expect(window.open.mock.calls[3][0]).toBe(
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig'
      );
    });

    it('画像URLでないURLを1つ渡したときもそのまま開く', () => {
      window.open = jest.fn();
      openImages(['https://twitter.com/tos']);
      expect(window.open.mock.calls.length).toBe(1);
      expect(window.open.mock.calls[0][0]).toBe('https://twitter.com/tos');
    });

    it('undefinedを1つ渡したとき開かない', () => {
      window.open = jest.fn();
      openImages([undefined]);
      expect(window.open.mock.calls.length).toBe(0);
    });

    it('URLとundefinedを混ぜたときURLだけ開いてundefinedは開かない', () => {
      window.open = jest.fn();
      openImages([
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig',
        undefined,
        'https://twitter.com/tos',
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig',
      ]);
      expect(window.open.mock.calls.length).toBe(3);
      expect(window.open.mock.calls[0][0]).toBe(
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig'
      );
      expect(window.open.mock.calls[1][0]).toBe('https://twitter.com/tos');
      expect(window.open.mock.calls[2][0]).toBe(
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig'
      );
    });

    it('要素0個の配列を渡したとき開かない', () => {
      window.open = jest.fn();
      openImages([]);
      expect(window.open.mock.calls.length).toBe(0);
    });
  });

  describe('getOptions', () => {
    describe('Chrome拡張機能のとき', () => {
      const originalChrome = window.chrome;
      beforeAll(() => {
        delete window.chrome;
        window.chrome = { runtime: { id: 'id' } };
      });
      afterAll(() => {
        window.chrome = originalChrome;
      });

      it('初期設定を取得できる', () => {
        const expected = {};
        OPTION_KEYS.forEach(key => {
          expected[key] = isTrue;
        });
        window.chrome.runtime.sendMessage = jest.fn((_, callback) =>
          callback({ data: {} })
        );
        expect(getOptions()).resolves.toStrictEqual(expected);
      });

      it('設定した値を取得できる', () => {
        const expected = {};
        OPTION_KEYS.forEach((key, i) => {
          expected[key] = i % 2 === 0 ? isTrue : isFalse;
        });
        window.chrome.runtime.sendMessage = jest.fn((_, callback) =>
          callback({ data: { ...expected } })
        );
        return getOptions().then(options => {
          return expect(options).toStrictEqual(expected);
        });
      });

      it('設定が取得できなかったらreject', () => {
        const expected = {};
        OPTION_KEYS.forEach(key => {
          expected[key] = isTrue;
        });
        window.chrome.runtime.sendMessage = jest.fn((_, callback) =>
          callback({})
        );
        expect(getOptions()).rejects.toBeUndefined();
      });
    });

    describe('Chrome拡張機能でないとき', () => {
      const originalChrome = window.chrome;
      beforeAll(() => {
        delete window.chrome;
        window.chrome = undefined;
      });
      afterAll(() => {
        window.chrome = originalChrome;
      });

      it('初期設定を取得できる', () => {
        const expected = {};
        OPTION_KEYS.forEach(key => {
          expected[key] = isFalse;
        });
        expect(getOptions()).resolves.toStrictEqual(expected);
      });
    });
  });

  describe('setStyle DOM要素にスタイルを当てる', () => {
    it('スタイル当たる', () => {
      const div = document.createElement('div');
      expect(div).toMatchSnapshot();
      setStyle(div, {
        display: 'none',
        color: '#123',
        'background-color': 'rgba(12, 34, 56, 0.7)',
      });
      expect(div).toMatchSnapshot();
    });
    it('空のスタイル渡すと何もしない', () => {
      const div = document.createElement('div');
      expect(div).toMatchSnapshot();
      setStyle(div, {});
      expect(div).toMatchSnapshot();
    });
    it('すでにあるスタイルは上書きされるが消えることはない', () => {
      const div = document.createElement('div');
      div.style.color = '#456';
      div.style.backgroundColor = '#789abc';
      div.style.fontSize = '150px';
      expect(div).toMatchSnapshot();
      setStyle(div, {
        display: 'none',
        color: '#123',
        'background-color': 'rgba(12, 34, 56, 0.7)',
      });
      expect(div).toMatchSnapshot();
    });
  });

  describe('onOriginalButtonClick ボタンがクリックされたときのコールバック', () => {
    it('イベントを止める', () => {
      /* SKIP: dont know why openImages wont be called */
      // jest.spyOn(main, 'openImages');

      const event = {
        preventDefault: jest.fn(),
        stopPropagation: jest.fn(),
      };
      const imgSrcs = ['src1', 'src2'];
      onOriginalButtonClick(event, imgSrcs);

      expect(event.preventDefault).toHaveBeenCalledTimes(1);
      expect(event.stopPropagation).toHaveBeenCalledTimes(1);

      // expect(openImages).toHaveBeenCalledTimes(1);
      // expect(openImages.mock.calls[0][0]).toStrictEqual(imgSrcs);
    });
  });
});
<commit_msg>fix comment<commit_after>import * as main from '../../src/main';
const {
  isTrue,
  isFalse,
  OPTION_KEYS,
  printException,
  collectUrlParams,
  formatUrl,
  openImages,
  getOptions,
  setStyle,
  onOriginalButtonClick,
} = main;

const makeResultParams = ({ format, name }) => {
  return {
    protocol: 'https:',
    host: 'pbs.twimg.com',
    pathname: '/media/hogefuga123',
    format,
    name: name || null,
  };
};

describe('Utils', () => {
  describe('printException', () => {
    it('エラーメッセージの表示(予期せぬ状況の確認)', () => {
      console.log = jest.fn();
      printException('exception message');
      expect(console.log.mock.calls[0][0]).toBe(
        'tooi: exception message at: http://localhost/'
      );
    });
  });

  describe('URLのツール', () => {
    // URLの変換のテストの場合たち
    const cases = [
      {
        title: '何もなし',
        url: 'https://pbs.twimg.com/media/hogefuga123',
        params: { format: 'jpg' },
      },
      {
        title: '.jpg',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg',
        params: { format: 'jpg' },
      },
      {
        title: '.png',
        url: 'https://pbs.twimg.com/media/hogefuga123.png',
        params: { format: 'png' },
      },
      {
        title: '.jpg:orig',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg:orig',
        params: { format: 'jpg', name: 'orig' },
      },
      {
        title: '.jpg:large',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg:large',
        params: { format: 'jpg', name: 'large' },
      },
      {
        title: '?format=jpg',
        url: 'https://pbs.twimg.com/media/hogefuga123?format=jpg',
        params: { format: 'jpg' },
      },
      {
        title: '?format=png',
        url: 'https://pbs.twimg.com/media/hogefuga123?format=png',
        params: { format: 'png' },
      },
      {
        title: '.jpg?format=jpg',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg?format=jpg',
        params: { format: 'jpg' },
      },
      {
        title: '.jpg?format=png',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg?format=png',
        params: { format: 'jpg' },
      },
      {
        title: '.png?format=jpg',
        url: 'https://pbs.twimg.com/media/hogefuga123.png?format=jpg',
        params: { format: 'png' },
      },
      {
        title: '.jpg?name=large',
        url: 'https://pbs.twimg.com/media/hogefuga123.jpg?name=large',
        params: { format: 'jpg', name: 'large' },
      },
      {
        title: '?format=jpg&name=large',
        url: 'https://pbs.twimg.com/media/hogefuga123?format=jpg&name=large',
        params: { format: 'jpg', name: 'large' },
      },
      {
        title: '.png?format=jpg&name=orig',
        url: 'https://pbs.twimg.com/media/hogefuga123.png?format=jpg&name=orig',
        params: { format: 'png', name: 'orig' },
      },
    ];

    describe('collectUrlParams 画像urlの要素を集める', () => {
      cases.forEach(singleCase => {
        const { title, url, params } = singleCase;
        it(title, () => {
          expect(collectUrlParams(url)).toStrictEqual(makeResultParams(params));
        });
      });

      it('twitterの画像URLでないときnull', () => {
        expect(collectUrlParams('https://twitter.com/tos')).toBe(null);
      });
    });

    describe('formatUrl 画像URLを https～?format=〜&name=orig に揃える', () => {
      cases.forEach(singleCase => {
        const { title, url, params } = singleCase;
        it(title, () => {
          expect(formatUrl(url)).toBe(
            `https://pbs.twimg.com/media/hogefuga123?format=${params.format}&name=orig`
          );
        });
      });

      it('twitterの画像URLでないときそのまま', () => {
        expect(formatUrl('https://twitter.com/tos')).toBe(
          'https://twitter.com/tos'
        );
      });
    });
  });

  describe('openImages 画像を開く', () => {
    it('画像URLを1つ渡したとき開く', () => {
      window.open = jest.fn();
      openImages(['https://pbs.twimg.com/media/1st?format=jpg&name=orig']);
      expect(window.open.mock.calls.length).toBe(1);
      expect(window.open.mock.calls[0][0]).toBe(
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig'
      );
    });

    it('画像URLを2つ渡したとき逆順に開く', () => {
      window.open = jest.fn();
      openImages([
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig',
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig',
      ]);
      expect(window.open.mock.calls.length).toBe(2);
      expect(window.open.mock.calls[0][0]).toBe(
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig'
      );
      expect(window.open.mock.calls[1][0]).toBe(
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig'
      );
    });

    it('画像URLを4つ渡したとき逆順に開く', () => {
      window.open = jest.fn();
      openImages([
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig',
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig',
        'https://pbs.twimg.com/media/3rd?format=jpg&name=orig',
        'https://pbs.twimg.com/media/4th?format=jpg&name=orig',
      ]);
      expect(window.open.mock.calls.length).toBe(4);
      expect(window.open.mock.calls[0][0]).toBe(
        'https://pbs.twimg.com/media/4th?format=jpg&name=orig'
      );
      expect(window.open.mock.calls[1][0]).toBe(
        'https://pbs.twimg.com/media/3rd?format=jpg&name=orig'
      );
      expect(window.open.mock.calls[2][0]).toBe(
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig'
      );
      expect(window.open.mock.calls[3][0]).toBe(
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig'
      );
    });

    it('画像URLでないURLを1つ渡したときもそのまま開く', () => {
      window.open = jest.fn();
      openImages(['https://twitter.com/tos']);
      expect(window.open.mock.calls.length).toBe(1);
      expect(window.open.mock.calls[0][0]).toBe('https://twitter.com/tos');
    });

    it('undefinedを1つ渡したとき開かない', () => {
      window.open = jest.fn();
      openImages([undefined]);
      expect(window.open.mock.calls.length).toBe(0);
    });

    it('URLとundefinedを混ぜたときURLだけ開いてundefinedは開かない', () => {
      window.open = jest.fn();
      openImages([
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig',
        undefined,
        'https://twitter.com/tos',
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig',
      ]);
      expect(window.open.mock.calls.length).toBe(3);
      expect(window.open.mock.calls[0][0]).toBe(
        'https://pbs.twimg.com/media/2nd?format=jpg&name=orig'
      );
      expect(window.open.mock.calls[1][0]).toBe('https://twitter.com/tos');
      expect(window.open.mock.calls[2][0]).toBe(
        'https://pbs.twimg.com/media/1st?format=jpg&name=orig'
      );
    });

    it('要素0個の配列を渡したとき開かない', () => {
      window.open = jest.fn();
      openImages([]);
      expect(window.open.mock.calls.length).toBe(0);
    });
  });

  describe('getOptions', () => {
    describe('Chrome拡張機能のとき', () => {
      const originalChrome = window.chrome;
      beforeAll(() => {
        delete window.chrome;
        window.chrome = { runtime: { id: 'id' } };
      });
      afterAll(() => {
        window.chrome = originalChrome;
      });

      it('初期設定を取得できる', () => {
        const expected = {};
        OPTION_KEYS.forEach(key => {
          expected[key] = isTrue;
        });
        window.chrome.runtime.sendMessage = jest.fn((_, callback) =>
          callback({ data: {} })
        );
        expect(getOptions()).resolves.toStrictEqual(expected);
      });

      it('設定した値を取得できる', () => {
        const expected = {};
        OPTION_KEYS.forEach((key, i) => {
          expected[key] = i % 2 === 0 ? isTrue : isFalse;
        });
        window.chrome.runtime.sendMessage = jest.fn((_, callback) =>
          callback({ data: { ...expected } })
        );
        return getOptions().then(options => {
          return expect(options).toStrictEqual(expected);
        });
      });

      it('設定が取得できなかったらreject', () => {
        const expected = {};
        OPTION_KEYS.forEach(key => {
          expected[key] = isTrue;
        });
        window.chrome.runtime.sendMessage = jest.fn((_, callback) =>
          callback({})
        );
        expect(getOptions()).rejects.toBeUndefined();
      });
    });

    describe('Chrome拡張機能でないとき', () => {
      const originalChrome = window.chrome;
      beforeAll(() => {
        delete window.chrome;
        window.chrome = undefined;
      });
      afterAll(() => {
        window.chrome = originalChrome;
      });

      it('初期設定を取得できる', () => {
        const expected = {};
        OPTION_KEYS.forEach(key => {
          expected[key] = isFalse;
        });
        expect(getOptions()).resolves.toStrictEqual(expected);
      });
    });
  });

  describe('setStyle DOM要素にスタイルを当てる', () => {
    it('スタイル当たる', () => {
      const div = document.createElement('div');
      expect(div).toMatchSnapshot();
      setStyle(div, {
        display: 'none',
        color: '#123',
        'background-color': 'rgba(12, 34, 56, 0.7)',
      });
      expect(div).toMatchSnapshot();
    });
    it('空のスタイル渡すと何もしない', () => {
      const div = document.createElement('div');
      expect(div).toMatchSnapshot();
      setStyle(div, {});
      expect(div).toMatchSnapshot();
    });
    it('すでにあるスタイルは上書きされるが消えることはない', () => {
      const div = document.createElement('div');
      div.style.color = '#456';
      div.style.backgroundColor = '#789abc';
      div.style.fontSize = '150px';
      expect(div).toMatchSnapshot();
      setStyle(div, {
        display: 'none',
        color: '#123',
        'background-color': 'rgba(12, 34, 56, 0.7)',
      });
      expect(div).toMatchSnapshot();
    });
  });

  describe('onOriginalButtonClick ボタンがクリックされたときのコールバック', () => {
    it('イベントを止める', () => {
      /* SKIP: なぜかうまくmockできないので飛ばす */
      // jest.spyOn(main, 'openImages');

      const event = {
        preventDefault: jest.fn(),
        stopPropagation: jest.fn(),
      };
      const imgSrcs = ['src1', 'src2'];
      onOriginalButtonClick(event, imgSrcs);

      expect(event.preventDefault).toHaveBeenCalledTimes(1);
      expect(event.stopPropagation).toHaveBeenCalledTimes(1);

      // expect(openImages).toHaveBeenCalledTimes(1);
      // expect(openImages.mock.calls[0][0]).toStrictEqual(imgSrcs);
    });
  });
});
<|endoftext|>


<commit_before>
function InfoPanel(id, title, header, headerComments, toolbar) {

  var currentObj = this;
  this.id = id;
  this.header = header;
  this.headerComments = headerComments;
  this.isVisible = true;
  this.showAll = false;
  this.defaultTags = [ "TSTART", "TSTOP", "TIMEUNIT", "TIMESYS", "DURATION", "FRMTIME",
                       "DATE-OBS", "DATE-END", "OBJECT", "OBSERVER", "TELESCOP", "INSTRUME",
                       "OBS_ID", "OBS_MODE", "EXP_ID", "MJDREF", "MJDREFF", "MJDREFI"];

  this.$html = $('
' +
                   '<button class="btn btn-default btnShowAll"></button>' +
                   '<button class="btn btn-default btnHide"></button>' +
                   '
' + title + ':
' +
                   '

' +
                 '
');

  this.container = this.$html.find(".properties");

  if (!isNull(toolbar)){
    this.btnShow = $('<button class="btn  btn-default btnShow ' + this.id + '"> ' + title + '</button>');
    this.btnShow.click(function(event){
      if (currentObj.btnShow.hasClass("plotHidden")) {
        currentObj.show();
      } else {
        currentObj.hide();
      }
    });
    toolbar.find(".container").append(this.btnShow);

    this.btnHide = this.$html.find(".btnHide");
    this.btnHide.click(function(event){
       currentObj.hide();
    });

    this.btnShowAll = this.$html.find(".btnShowAll");
    this.btnShowAll.click(function(event){
      currentObj.showAll = !currentObj.showAll;
      currentObj.redraw();
    });

  } else {
    this.$html.find(".btnHide").hide();
    this.$html.find(".btnShowAll").hide();
  }

  this.show = function (){
    currentObj.isVisible = true;
    currentObj.$html.show();
    currentObj.btnShow.removeClass("plotHidden");
    currentObj.btnShow.find("i").switchClass( "fa-eye-slash", "fa-eye");
    currentObj.redraw();
  }

  this.hide = function (){
    currentObj.isVisible = false;
    currentObj.$html.hide();
    currentObj.btnShow.addClass("plotHidden");
    currentObj.btnShow.find("i").switchClass( "fa-eye", "fa-eye-slash");
  }

  this.getPropertyHtml = function(tag, value, comment) {
    return $('
' +
              '' + tag + '	' +
              '' + value + '	' +
              '' + comment + '	' +
            '
');
  }

  this.redraw = function() {
    this.container.html("");

    var keys = [];
    for (key in this.header) {
      if (this.defaultTags.includes(key) || this.showAll) {
        keys.push(key);
      }
    }

    if (keys.length > 0) {
      keys.sort ();

      for (i in keys){
        var tag = keys[i];
        this.container.append(this.getPropertyHtml(tag, this.header[tag], this.headerComments[tag]));
      }
    } else {
      this.container.append('
No default header tags found!
');
    }

  }

  this.redraw();

  log ("new infoPanel id: " + this.id);

  return this;
}
<commit_msg>DAVE-190: Icon change: show all fields in header<commit_after>
function InfoPanel(id, title, header, headerComments, toolbar) {

  var currentObj = this;
  this.id = id;
  this.header = header;
  this.headerComments = headerComments;
  this.isVisible = true;
  this.showAll = false;
  this.defaultTags = [ "TSTART", "TSTOP", "TIMEUNIT", "TIMESYS", "DURATION", "FRMTIME",
                       "DATE-OBS", "DATE-END", "OBJECT", "OBSERVER", "TELESCOP", "INSTRUME",
                       "OBS_ID", "OBS_MODE", "EXP_ID", "MJDREF", "MJDREFF", "MJDREFI"];

  this.$html = $('
' +
                   '<button class="btn btn-default btnShowAll"></button>' +
                   '<button class="btn btn-default btnHide"></button>' +
                   '
' + title + ':
' +
                   '

' +
                 '
');

  this.container = this.$html.find(".properties");

  if (!isNull(toolbar)){
    this.btnShow = $('<button class="btn  btn-default btnShow ' + this.id + '"> ' + title + '</button>');
    this.btnShow.click(function(event){
      if (currentObj.btnShow.hasClass("plotHidden")) {
        currentObj.show();
      } else {
        currentObj.hide();
      }
    });
    toolbar.find(".container").append(this.btnShow);

    this.btnHide = this.$html.find(".btnHide");
    this.btnHide.click(function(event){
       currentObj.hide();
    });

    this.btnShowAll = this.$html.find(".btnShowAll");
    this.btnShowAll.click(function(event){
      currentObj.showAll = !currentObj.showAll;
      if (currentObj.showAll) {
        currentObj.btnShowAll.find("i").switchClass("fa-plus-square-o", "fa-minus-square-o");
      } else {
        currentObj.btnShowAll.find("i").switchClass("fa-minus-square-o", "fa-plus-square-o");
      }
      currentObj.redraw();
    });

  } else {
    this.$html.find(".btnHide").hide();
    this.$html.find(".btnShowAll").hide();
  }

  this.show = function (){
    currentObj.isVisible = true;
    currentObj.$html.show();
    currentObj.btnShow.removeClass("plotHidden");
    currentObj.btnShow.find("i").switchClass("fa-eye-slash", "fa-eye");
    currentObj.redraw();
  }

  this.hide = function (){
    currentObj.isVisible = false;
    currentObj.$html.hide();
    currentObj.btnShow.addClass("plotHidden");
    currentObj.btnShow.find("i").switchClass("fa-eye", "fa-eye-slash");
  }

  this.getPropertyHtml = function(tag, value, comment) {
    return $('
' +
              '' + tag + '	' +
              '' + value + '	' +
              '' + comment + '	' +
            '
');
  }

  this.redraw = function() {
    this.container.html("");

    var keys = [];
    for (key in this.header) {
      if (this.defaultTags.includes(key) || this.showAll) {
        keys.push(key);
      }
    }

    if (keys.length > 0) {
      keys.sort ();

      for (i in keys){
        var tag = keys[i];
        this.container.append(this.getPropertyHtml(tag, this.header[tag], this.headerComments[tag]));
      }
    } else {
      this.container.append('
No default header tags found!
');
    }

  }

  this.redraw();

  log ("new infoPanel id: " + this.id);

  return this;
}
<|endoftext|>


<commit_before><commit_msg>add missing semicolon<commit_after><|endoftext|>


<commit_before><commit_msg>Removed interface validation for reimage<commit_after><|endoftext|>


<commit_before><commit_msg>Refactored a block of code into a function.<commit_after><|endoftext|>


<commit_before>;
(function() {

  /* Sparkline AddIn, based on jquery.sparkline.js sparklines.
   *
   */
  var sparkline = {
    name: "sparkline",
    label: "Sparkline",
    defaults: {
      type: 'line'
    },
    implementation: function (tgt, st, opt) {
      var t = $(tgt);
      t.sparkline(st.value.split(/,/),opt);
      t.removeClass("sparkline");
    }
  };
  Dashboards.registerAddIn("Table", "colType", new AddIn(sparkline));

  var pvSparkline = {
    name: "pvSparkline",
    label: "Protovis Sparkline",
    defaults: {
      height: 10,
      strokeStyle: "#000",
      lineWidth: 1,
      width: undefined,
      canvasMargin: 2
    },
    implementation: function(tgt, st, opt) {
      var ph = $(tgt),
      sparklineData = st.value,
      data = sparklineData.split(",");
      n = data.length,
      w = opt.width || ph.width(),
      h = opt.height,
      min = pv.min.index(data),
      max = pv.max.index(data);
      ph.empty();

      var container = $("

").appendTo(ph);

      //console.log("count "+count);

      var vis = new pv.Panel()
      .canvas(container.get(0))
      .width(w)
      .height(h)
      .margin(opt.canvasMargin);

      vis.add(pv.Line)
      .data(data)
      .left(pv.Scale.linear(0, n - 1).range(0, w).by(pv.index))
      .bottom(pv.Scale.linear(data).range(0, h))
      .strokeStyle(opt.strokeStyle)
      .lineWidth(opt.lineWidth);

      vis.render();

    }
  };
  Dashboards.registerAddIn("Table", "colType", new AddIn(pvSparkline));

  var dataBar = {
    name: "dataBar",
    label: "Data Bar",
    defaults: {
      widthRatio:1,
      height: 10,
      startColor: "#55A4D6",
      endColor: "#448FC8",
      stroke: null,
      max: undefined,
      includeValue: false,
      valueFormat: function(v, format, st) {
        return "" + sprintf(format,v) + "";
      }
    },
    implementation: function(tgt, st, opt) {
      var max = opt.max || Math.max.apply(Math,st.tableData.map(function(e){return Math.abs(e[st.colIdx]);}));
      var cell = $(tgt);
      cell.empty();

      var ph =$("

").addClass('dataBarContainer').appendTo(cell);
      var wtmp = opt.widthRatio * ph.width();
      var htmp = opt.height;

      var value = st.value;
      var leftVal=0, rightVal=parseFloat(value);
      if(leftVal>rightVal){
      	leftVal = value;
      	rightVal = 0;
      }
      var delta = rightVal - leftVal;
      var xx = pv.Scale.linear(0,max).range(0,wtmp);

      var paper = Raphael(ph.get(0), xx(delta), htmp);
      var c = paper.rect(xx(leftVal), 0, xx(delta), htmp);

      c.attr({
      	fill: "90-"+opt.startColor + "-" + opt.endColor,
      	stroke: opt.stroke,
      	title: "Value: "+ value
      });

      if(opt.includeValue) {
        ph.append(opt.valueFormat(st.value, st.colFormat, st));
      }
    }
  };
  Dashboards.registerAddIn("Table", "colType", new AddIn(dataBar));

  var trendArrow = {
    name: "trendArrow",
    label: "Trend Arrows",
    defaults: {
      includeValue: false,
      valueFormat: function(v,format,st) {
        return sprintf(format,v);
      }
    },
    implementation: function(tgt, st, opt) {
      var ph = $(tgt),
      trendClass =  st.value < 0 ? "down" : "up";
      var trend = $("

");
      trend.addClass('trend');
      trend.addClass(trendClass);
      ph.empty();
      if(opt.includeValue) {
        ph.append(opt.valueFormat(st.value, st.colFormat, st));
      }
      ph.append(trend);
    }
  };
  Dashboards.registerAddIn("Table", "colType", new AddIn(trendArrow));

  var link = {
    name: "hyperlink",
    label: "Hyperlink",
    defaults:{
      openInNewTab: true,
      prependHttpIfNeeded: true,
      regexp: null
    },

    implementation: function(tgt, st, opt){

      var ph = $(tgt);
      var link = st.value;
      if (opt.prependHttpIfNeeded && !/^https?:\/\//.test(link)){
        link = "http://" + link;
      }
      // is this text an hyperlink?
      if(opt.regexp == null || (new RegExp(opt.regexp).test(st.value))){
        var a = $("").attr("href",link).addClass("hyperlinkAddIn");
        a.text(st.value);
        if(opt.openInNewTab){
          a.attr("target","_blank");
        }
        ph.empty().append(a);
      }
    }

  };
  Dashboards.registerAddIn("Table", "colType", new AddIn(link));

})();

<commit_msg>- Fixed defaults in addins (dataBar and trendArrow) so that they work with a specified colFormat<commit_after>;
(function() {

  /* Sparkline AddIn, based on jquery.sparkline.js sparklines.
   *
   */
  var sparkline = {
    name: "sparkline",
    label: "Sparkline",
    defaults: {
      type: 'line'
    },
    implementation: function (tgt, st, opt) {
      var t = $(tgt);
      t.sparkline(st.value.split(/,/),opt);
      t.removeClass("sparkline");
    }
  };
  Dashboards.registerAddIn("Table", "colType", new AddIn(sparkline));

  var pvSparkline = {
    name: "pvSparkline",
    label: "Protovis Sparkline",
    defaults: {
      height: 10,
      strokeStyle: "#000",
      lineWidth: 1,
      width: undefined,
      canvasMargin: 2
    },
    implementation: function(tgt, st, opt) {
      var ph = $(tgt),
      sparklineData = st.value,
      data = sparklineData.split(",");
      n = data.length,
      w = opt.width || ph.width(),
      h = opt.height,
      min = pv.min.index(data),
      max = pv.max.index(data);
      ph.empty();

      var container = $("

").appendTo(ph);

      //console.log("count "+count);

      var vis = new pv.Panel()
      .canvas(container.get(0))
      .width(w)
      .height(h)
      .margin(opt.canvasMargin);

      vis.add(pv.Line)
      .data(data)
      .left(pv.Scale.linear(0, n - 1).range(0, w).by(pv.index))
      .bottom(pv.Scale.linear(data).range(0, h))
      .strokeStyle(opt.strokeStyle)
      .lineWidth(opt.lineWidth);

      vis.render();

    }
  };
  Dashboards.registerAddIn("Table", "colType", new AddIn(pvSparkline));

  var dataBar = {
    name: "dataBar",
    label: "Data Bar",
    defaults: {
      widthRatio:1,
      height: 10,
      startColor: "#55A4D6",
      endColor: "#448FC8",
      stroke: null,
      max: undefined,
      includeValue: false,
      valueFormat: function(v, format, st) {
        return "" + sprintf(format || "%.1f",v) + "";
      }
    },
    implementation: function(tgt, st, opt) {
      var max = opt.max || Math.max.apply(Math,st.tableData.map(function(e){return Math.abs(e[st.colIdx]);}));
      var cell = $(tgt);
      cell.empty();

      var ph =$("

").addClass('dataBarContainer').appendTo(cell);
      var wtmp = opt.widthRatio * ph.width();
      var htmp = opt.height;

      var value = st.value;
      var leftVal=0, rightVal=parseFloat(value);
      if(leftVal>rightVal){
      	leftVal = value;
      	rightVal = 0;
      }
      var delta = rightVal - leftVal;
      var xx = pv.Scale.linear(0,max).range(0,wtmp);

      var paper = Raphael(ph.get(0), xx(delta), htmp);
      var c = paper.rect(xx(leftVal), 0, xx(delta), htmp);

      c.attr({
      	fill: "90-"+opt.startColor + "-" + opt.endColor,
      	stroke: opt.stroke,
      	title: "Value: "+ value
      });

      if(opt.includeValue) {
        ph.append(opt.valueFormat(st.value, st.colFormat, st));
      }
    }
  };
  Dashboards.registerAddIn("Table", "colType", new AddIn(dataBar));

  var trendArrow = {
    name: "trendArrow",
    label: "Trend Arrows",
    defaults: {
      includeValue: false,
      valueFormat: function(v,format,st) {
        return sprintf(format || "%.1f",v);
      }
    },
    implementation: function(tgt, st, opt) {
      var ph = $(tgt),
      trendClass =  st.value < 0 ? "down" : "up";
      var trend = $("

");
      trend.addClass('trend');
      trend.addClass(trendClass);
      ph.empty();
      if(opt.includeValue) {
        ph.append(opt.valueFormat(st.value, st.colFormat, st));
      }
      ph.append(trend);
    }
  };
  Dashboards.registerAddIn("Table", "colType", new AddIn(trendArrow));

  var link = {
    name: "hyperlink",
    label: "Hyperlink",
    defaults:{
      openInNewTab: true,
      prependHttpIfNeeded: true,
      regexp: null
    },

    implementation: function(tgt, st, opt){

      var ph = $(tgt);
      var link = st.value;
      if (opt.prependHttpIfNeeded && !/^https?:\/\//.test(link)){
        link = "http://" + link;
      }
      // is this text an hyperlink?
      if(opt.regexp == null || (new RegExp(opt.regexp).test(st.value))){
        var a = $("").attr("href",link).addClass("hyperlinkAddIn");
        a.text(st.value);
        if(opt.openInNewTab){
          a.attr("target","_blank");
        }
        ph.empty().append(a);
      }
    }

  };
  Dashboards.registerAddIn("Table", "colType", new AddIn(link));

})();

<|endoftext|>


<commit_before>function ddg_spice_video(api_result) {
    if(!api_result || api_result.length === 0) {
        return;
    }

    $.ajaxSetup({
        cache: true
    });

    var encodedQuery = DDG.get_query_encoded().replace(/(?:vimeo|youtube|videos?)/i, '');
    console.log('Video encoded query: '+encodedQuery);

    // Change the "More at ..." link.
    var change_more = function(obj) {
	var more_at_link = $(".zero_click_more_at_link");
	more_at_link.attr("href", obj.search_link);
        more_at_link.find("img").attr("src", obj.image);
        more_at_link.find("span").html(obj.text);
    };

    Spice.render({
        data: api_result,
        source_name : 'YouTube',
        source_url : 'https://www.youtube.com/results?search_query=' + encodedQuery,
        header1 : "Video Search",
        template_frame: "carousel",
        template_normal: "video",
        carousel_css_id: "video",
        carousel_items: api_result,
        force_no_fold : 1,
        carousel_template_detail: "video_detail",
	template_options: {
	    li_width: 120
	},
	item_callback: function(i, item) {
	    var more_at_link = $(".zero_click_more_at_link").get(0);
	    if(item.provider in ddg_spice_video.providers) {
		var providers = ddg_spice_video.providers;
		change_more({
		    "search_link": providers[item.provider].search_link + encodedQuery,
		    "image": providers[item.provider].image,
		    "text": providers[item.provider].text
		});
	    }
	    resizeDetail();
	}
    });

    function resizeDetail() {
	var $video = $("#spice_video");
	var width = $video.width() - 18;
	var height = Math.floor(width * 0.5625) + 30;
	$("#video #embed").width(width);
	$("#video #embed").height(height);

	var video_title = $("#video #video-title").width();
	var video_links = $("#video .links").width();

	if(width - (video_title + video_links) < 20) {
	    $("#video .links").css("position", "static");
	} else {
	    $("#video .links").css("position", "absolute");
	}
    }

    $(document).ready(function() {
	resizeDetail();
	$(window).resize(resizeDetail);
    });
}

ddg_spice_video.providers = {
    "YouTube": {
	"search_link": "https://www.youtube.com/results?search_query=",
	"image": "https://icons.duckduckgo.com/i/www.youtube.com.ico",
	"text": "More at YouTube",
	"embed": "https://www.youtube-nocookie.com/embed/",
	"play_url": "https://www.youtube.com/watch?v=",
	"user_url": "https://www.youtube.com/user/",
	"embed_options": {
	    "iv_load_policy": 3,
	    "autoplay": 1,
	    "wmode": "opaque"
	}
    },
    "Vimeo": {
	"search_link": "https://www.vimeo.com/search?q=",
	"image": "https://icons.duckduckgo.com/i/www.vimeo.com.ico",
	"text": "More at Vimeo",
	"embed": "https://player.vimeo.com/video/",
	"play_url": "https://vimeo.com/",
	"user_url": "https://vimeo.com/",
	"embed_options": {
	    "api": 0,
	    "autoplay": 1
	}
    }
};

// This is the callback function of /itt.
ddg_spice_video.itunes = function(api_result) {
    if(!api_result || !api_result.results || api_result.results.length === 0) {
        return;
    }

    var itunes = $("#itunes");
    var artist = itunes.data("artist").toLowerCase();
    var song = itunes.data("song").toLowerCase();

    // Find the song that matches.
    for(var i = 0; i < api_result.results.length; i++) {
	if(artist === api_result.results[i].artistName.toLowerCase() ||
	   artist === api_result.results[i].trackName.toLowerCase() ||
	   song === api_result.results[i].artistName.toLowerCase() ||
	   song === api_result.results[i].trackName.toLowerCase()) {
	    itunes.attr("href", api_result.results[i].trackViewUrl);
	    itunes.toggle();
	    break;
	}
    }

};

Handlebars.registerHelper("userURL", function(provider, uploader) {
    if(provider in ddg_spice_video.providers) {
	return ddg_spice_video.providers[provider].user_url + uploader;
    }
    return "";
});

Handlebars.registerHelper("checkMusic", function(category, title, options) {
    // Remove things from the title that we don't really need.
    var stripTitle = function(s) {
	// Remove things like "(Explicit)".
	s = s.replace(/\(.*\)|\[.*\]/g, "");
	// Remove things like "feat. Alicia Keys".
	s = s.replace(/\s+f(?:ea|)t\..*$/g, "");
	// Trim the ends of the string.
	return s.replace(/^\s+|\s+$/g, "");
    };

    title = stripTitle(title);
    var songData = title.split(" - ");
    var artist = songData[0];
    var song = songData[1] || artist;

    // Call iTunes.
    $.getScript("/iit/" + encodeURIComponent(title));

    // Only add links to the music if, well, we have links to the music section.
    if(category === "Music") {
	// There's no need to escape the values--Handlebars.js does this for us.
	return options.fn({
	    title: title,
	    artist: artist,
	    song: song
	});
    }
});

// We'll use this for showing the view counts.
Handlebars.registerHelper("formatViews", function(views) {
    "use strict";
    if(views) {
	return String(views).replace(/(\d)(?=(\d{3})+(\.\d+|)\b)/g, "$1,");
    }
});

Handlebars.registerHelper("embedURL", function(provider, id) {
    function parameters(embed_options) {
	var result = [];
	for(o in embed_options) {
	    result.push(o + "=" + embed_options[o]);
	}
	return result.join("&");
    }

    if(provider in ddg_spice_video.providers) {
	return ddg_spice_video.providers[provider].embed + id + "?" +
	    parameters(ddg_spice_video.providers[provider].embed_options);
    }
    return "";
});

Handlebars.registerHelper("playURL", function(provider, id) {
    if(provider in ddg_spice_video.providers) {
	return ddg_spice_video.providers[provider].play_url + id;
    }
    return "";
});

Handlebars.registerHelper("checkStatistics", function(viewCount, options) {
    if(viewCount === null) {
	return "";
    }
    return options.fn({viewCount: viewCount});
});
<commit_msg>Video: squelch console.log on encodedQuery.<commit_after>function ddg_spice_video(api_result) {
    if(!api_result || api_result.length === 0) {
        return;
    }

    $.ajaxSetup({
        cache: true
    });

    var encodedQuery = DDG.get_query_encoded().replace(/(?:vimeo|youtube|videos?)/i, '');

    // Change the "More at ..." link.
    var change_more = function(obj) {
	var more_at_link = $(".zero_click_more_at_link");
	more_at_link.attr("href", obj.search_link);
        more_at_link.find("img").attr("src", obj.image);
        more_at_link.find("span").html(obj.text);
    };

    Spice.render({
        data: api_result,
        source_name : 'YouTube',
        source_url : 'https://www.youtube.com/results?search_query=' + encodedQuery,
        header1 : "Video Search",
        template_frame: "carousel",
        template_normal: "video",
        carousel_css_id: "video",
        carousel_items: api_result,
        force_no_fold : 1,
        carousel_template_detail: "video_detail",
	template_options: {
	    li_width: 120
	},
	item_callback: function(i, item) {
	    var more_at_link = $(".zero_click_more_at_link").get(0);
	    if(item.provider in ddg_spice_video.providers) {
		var providers = ddg_spice_video.providers;
		change_more({
		    "search_link": providers[item.provider].search_link + encodedQuery,
		    "image": providers[item.provider].image,
		    "text": providers[item.provider].text
		});
	    }
	    resizeDetail();
	}
    });

    function resizeDetail() {
	var $video = $("#spice_video");
	var width = $video.width() - 18;
	var height = Math.floor(width * 0.5625) + 30;
	$("#video #embed").width(width);
	$("#video #embed").height(height);

	var video_title = $("#video #video-title").width();
	var video_links = $("#video .links").width();

	if(width - (video_title + video_links) < 20) {
	    $("#video .links").css("position", "static");
	} else {
	    $("#video .links").css("position", "absolute");
	}
    }

    $(document).ready(function() {
	resizeDetail();
	$(window).resize(resizeDetail);
    });
}

ddg_spice_video.providers = {
    "YouTube": {
	"search_link": "https://www.youtube.com/results?search_query=",
	"image": "https://icons.duckduckgo.com/i/www.youtube.com.ico",
	"text": "More at YouTube",
	"embed": "https://www.youtube-nocookie.com/embed/",
	"play_url": "https://www.youtube.com/watch?v=",
	"user_url": "https://www.youtube.com/user/",
	"embed_options": {
	    "iv_load_policy": 3,
	    "autoplay": 1,
	    "wmode": "opaque"
	}
    },
    "Vimeo": {
	"search_link": "https://www.vimeo.com/search?q=",
	"image": "https://icons.duckduckgo.com/i/www.vimeo.com.ico",
	"text": "More at Vimeo",
	"embed": "https://player.vimeo.com/video/",
	"play_url": "https://vimeo.com/",
	"user_url": "https://vimeo.com/",
	"embed_options": {
	    "api": 0,
	    "autoplay": 1
	}
    }
};

// This is the callback function of /itt.
ddg_spice_video.itunes = function(api_result) {
    if(!api_result || !api_result.results || api_result.results.length === 0) {
        return;
    }

    var itunes = $("#itunes");
    var artist = itunes.data("artist").toLowerCase();
    var song = itunes.data("song").toLowerCase();

    // Find the song that matches.
    for(var i = 0; i < api_result.results.length; i++) {
	if(artist === api_result.results[i].artistName.toLowerCase() ||
	   artist === api_result.results[i].trackName.toLowerCase() ||
	   song === api_result.results[i].artistName.toLowerCase() ||
	   song === api_result.results[i].trackName.toLowerCase()) {
	    itunes.attr("href", api_result.results[i].trackViewUrl);
	    itunes.toggle();
	    break;
	}
    }

};

Handlebars.registerHelper("userURL", function(provider, uploader) {
    if(provider in ddg_spice_video.providers) {
	return ddg_spice_video.providers[provider].user_url + uploader;
    }
    return "";
});

Handlebars.registerHelper("checkMusic", function(category, title, options) {
    // Remove things from the title that we don't really need.
    var stripTitle = function(s) {
	// Remove things like "(Explicit)".
	s = s.replace(/\(.*\)|\[.*\]/g, "");
	// Remove things like "feat. Alicia Keys".
	s = s.replace(/\s+f(?:ea|)t\..*$/g, "");
	// Trim the ends of the string.
	return s.replace(/^\s+|\s+$/g, "");
    };

    title = stripTitle(title);
    var songData = title.split(" - ");
    var artist = songData[0];
    var song = songData[1] || artist;

    // Call iTunes.
    $.getScript("/iit/" + encodeURIComponent(title));

    // Only add links to the music if, well, we have links to the music section.
    if(category === "Music") {
	// There's no need to escape the values--Handlebars.js does this for us.
	return options.fn({
	    title: title,
	    artist: artist,
	    song: song
	});
    }
});

// We'll use this for showing the view counts.
Handlebars.registerHelper("formatViews", function(views) {
    "use strict";
    if(views) {
	return String(views).replace(/(\d)(?=(\d{3})+(\.\d+|)\b)/g, "$1,");
    }
});

Handlebars.registerHelper("embedURL", function(provider, id) {
    function parameters(embed_options) {
	var result = [];
	for(o in embed_options) {
	    result.push(o + "=" + embed_options[o]);
	}
	return result.join("&");
    }

    if(provider in ddg_spice_video.providers) {
	return ddg_spice_video.providers[provider].embed + id + "?" +
	    parameters(ddg_spice_video.providers[provider].embed_options);
    }
    return "";
});

Handlebars.registerHelper("playURL", function(provider, id) {
    if(provider in ddg_spice_video.providers) {
	return ddg_spice_video.providers[provider].play_url + id;
    }
    return "";
});

Handlebars.registerHelper("checkStatistics", function(viewCount, options) {
    if(viewCount === null) {
	return "";
    }
    return options.fn({viewCount: viewCount});
});
<|endoftext|>


<commit_before>YUI.add('pnm-photos', function (Y) {

var PNM_ENV = YUI.namespace('Env.PNM'),

    Lang = Y.Lang,
    Photos, cache;

// Create model cache. Server uses a strict maximum number of entries which is
// not a supported attribute by `CacheOffline`.
if ('max' in PNM_ENV.CACHE.photos) {
    cache = new Y.Cache(PNM_ENV.CACHE.photos);
} else {
    cache = new Y.CacheOffline(PNM_ENV.CACHE.photos);
}

Photos = Y.Base.create('photos', Y.LazyModelList, [], {

    model: Y.PNM.Photo,
    cache: cache,
    url  : 'http://api.flickr.com/services/rest/?method=flickr.photos.search' +
                '&api_key={api_key}' +
                '&woe_id={woeid}' +
                '&per_page={num}' +
                '&page={page}' +
                '&safe_search=1' +
                '&sort=interestingness-desc' +
                '&format=json',

    buildQuery: function (options) {
        options || (options = {});

        return Lang.sub(this.query, {
            api_key: PNM_ENV.FLICKR.api_key || '',
            start  : options.start || 0,
            num    : options.num || 60,
            woeid  : options.place.get('id'),
            attrs  : this.model.YQL_ATTRS
        });
    },

    sync: function (action, options, callback) {
        if (action !== 'read') { return callback('Only "read" is supported.'); }

        var cache = this.cache,
            num   = options.num || 60,
            url, hit;

        url = Lang.sub(this.url, {
            api_key: PNM_ENV.FLICKR.api_key || '',
            woeid  : options.place.get('id'),
            num    : num,
            page   : Math.ceil((options.start || 0) / num) + 1
        });

        hit = cache && cache.retrieve(url);

        if  (hit) {
            return callback(null, hit.response);
        }

        Y.jsonp(url, {
            format: function (url, proxy) {
                return url + '&jsoncallback=' + proxy;
            },

            on: {
                failure: function () {
                    callback.apply(null, arguments);
                },

                success: function (response) {
                    if (response.stat !== 'ok') {
                        return callback(response.message, response);
                    }

                    if (cache && response) {
                        cache.add(url, response);
                    }

                    callback(null, response);
                }
            }
        });
    },

    parse: function (results) {
        var photos     = results && results.photos && results.photos.photo,
            modelProto = this.model.prototype;

        if (!Lang.isArray(photos)) {
            photos = photos ? [photos] : [];
        }

        return Y.Array.map(photos, modelProto.parse, modelProto);
    },

    getPrev: function (photo) {
        // Check that the photo is in the list first.
        if (photo && this.getById(photo.get('id'))) {
            return this.revive(this.indexOf(photo) - 1);
        }
    },

    getNext: function (photo) {
        // Check that the photo is in the list first.
        if (photo && this.getById(photo.get('id'))) {
            return this.revive(this.indexOf(photo) + 1);
        }
    }

});

Y.namespace('PNM').Photos = Photos;

}, '0.7.2', {
    requires: [
        'cache-offline',
        'jsonp',
        'lazy-model-list',
        'pnm-photo'
    ]
});
<commit_msg>Remove unused method from Photos ModelList<commit_after>YUI.add('pnm-photos', function (Y) {

var PNM_ENV = YUI.namespace('Env.PNM'),

    Lang = Y.Lang,
    Photos, cache;

// Create model cache. Server uses a strict maximum number of entries which is
// not a supported attribute by `CacheOffline`.
if ('max' in PNM_ENV.CACHE.photos) {
    cache = new Y.Cache(PNM_ENV.CACHE.photos);
} else {
    cache = new Y.CacheOffline(PNM_ENV.CACHE.photos);
}

Photos = Y.Base.create('photos', Y.LazyModelList, [], {

    model: Y.PNM.Photo,
    cache: cache,
    url  : 'http://api.flickr.com/services/rest/?method=flickr.photos.search' +
                '&api_key={api_key}' +
                '&woe_id={woeid}' +
                '&per_page={num}' +
                '&page={page}' +
                '&safe_search=1' +
                '&sort=interestingness-desc' +
                '&format=json',

    sync: function (action, options, callback) {
        if (action !== 'read') { return callback('Only "read" is supported.'); }

        var cache = this.cache,
            num   = options.num || 60,
            url, hit;

        url = Lang.sub(this.url, {
            api_key: PNM_ENV.FLICKR.api_key || '',
            woeid  : options.place.get('id'),
            num    : num,
            page   : Math.ceil((options.start || 0) / num) + 1
        });

        hit = cache && cache.retrieve(url);

        if  (hit) {
            return callback(null, hit.response);
        }

        Y.jsonp(url, {
            format: function (url, proxy) {
                return url + '&jsoncallback=' + proxy;
            },

            on: {
                failure: function () {
                    callback.apply(null, arguments);
                },

                success: function (response) {
                    if (response.stat !== 'ok') {
                        return callback(response.message, response);
                    }

                    if (cache && response) {
                        cache.add(url, response);
                    }

                    callback(null, response);
                }
            }
        });
    },

    parse: function (results) {
        var photos     = results && results.photos && results.photos.photo,
            modelProto = this.model.prototype;

        if (!Lang.isArray(photos)) {
            photos = photos ? [photos] : [];
        }

        return Y.Array.map(photos, modelProto.parse, modelProto);
    },

    getPrev: function (photo) {
        // Check that the photo is in the list first.
        if (photo && this.getById(photo.get('id'))) {
            return this.revive(this.indexOf(photo) - 1);
        }
    },

    getNext: function (photo) {
        // Check that the photo is in the list first.
        if (photo && this.getById(photo.get('id'))) {
            return this.revive(this.indexOf(photo) + 1);
        }
    }

});

Y.namespace('PNM').Photos = Photos;

}, '0.7.2', {
    requires: [
        'cache-offline',
        'jsonp',
        'lazy-model-list',
        'pnm-photo'
    ]
});
<|endoftext|>


<commit_before>/**
 * @classDestription - Placeholder for Projects application variables and functions.
 * @class - Projects
 */
var Projects = (function($) {
	var constructor = function(infoboxoptions){
		this.AddressMarker = null;

		this.Events = [];

		// Can we geolocate?
		this.geolocate = navigator.geolocation;

		this.getEvents = function( rows, Map, Default )
		{
			// Copy the Project data to the Event object
			for (var i in rows)
			{
				this.Events[i] = new Event();
				for(var colname in rows[ i ])
				{
					    this.Events[ i ].data[ colname ] = rows[ i ][ colname ];
				}

                var ll = this.Events[i].data['Location'];
                var lla = ll.split(',');

                if ( lla.length == 2 ) {

                    var Lat = null;
                    var Lng = null;

                    // Create the Google LatLng object

                    Lat = lla[0];
                    Lng = lla[1];

                    this.Events[i].latlng = new google.maps.LatLng(Lat,Lng);

                    var project_type = $.trim(this.Events[i].data[ 'Project type' ]);

                    // Create the markers for each event

                    var icon = '';
                    var panel_class = '';

                    if ( !(project_type in project_type_info) ) {
                        project_type = 'Other';
                    }

                    icon = project_type_info[ project_type ].pin_url;

                    project_type_info[ project_type ].count++;
                    project_type_info[ 'All' ].count++;

                    panel_class = project_type_info[ project_type ].id + '-panel';

                    this.Events[i].marker = new google.maps.Marker({
                        position:   this.Events[i].latlng,
                        map:        Map.Map,
                        icon:       icon,
                        shadow:     'img/shadow.png',
                        clickable:  true
                    });

                    this.Events[i].panel = {
                        Lat: Lat,
                        Lng: Lng,
                        map: Map.Map
                    };

                    // Make the info box
                    this.Events[i].infobox = new InfoBox(infoboxoptions);

                    var p_description = this.Events[i].data[ 'Organization name' ];

                    var accordion = '';
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '                  ' + "\n";
                    accordion += '                    ' + p_description + "\n";
                    accordion += '                  ' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
Organization:

' + this.Events[i].data[ 'Organization name' ] + '(' + this.Events[i].data[ 'Which best describes your type of organization?' ] + ')</style>
' + "\n";
                    accordion += '
Location:

' + this.Events[i].data[ 'Address of the project' ] + '
' + "\n";
                    accordion += '
Project Type:

' + this.Events[i].data[ 'Project type' ] + '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
<button id="show-on-map-' + i + '" type="button" class="btn btn-default">Show on map</button>
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";

                    $('#accordion').append(accordion);
                }
			}
			for(var i in this.Events)
			{
				// Listen for marker clicks
				google.maps.event.addListener(this.Events[i].marker, 'click', this.Events[i].toggleInfoBox(Map.Map,this.Events[i]));
                $('#show-on-map-' + i).on( "click", null, {  map: Map.Map, default: Default, panel: this.Events[i].panel }, this.centerPin );

			}

		};

        /**
         * PROJECT FILTER functions
         */
        this.displayProjectTypeFilters = function( ) {
            for ( var project_type in project_type_info ) {
                var project = project_type_info [ project_type ];
                var li = '
' + project_type + '' + project.count + '
';
                $("#project-type-filter-buttons").append( li );
            }
        }

        this.displayProjectTypeCounts = function ( ) {
            for ( var project_type in project_type_info ) {
                var project = project_type_info [ project_type ];
                $('#cnt-' + project.id).html( project.count );
            }
        }

        /**
         * MAP functions
         */
        this.centerPin = function ( e ) {
            var Latlng = new google.maps.LatLng(
                e.data.panel.Lat,
                e.data.panel.Lng
            );
            e.data.map.setCenter(Latlng);
            e.data.map.setZoom(e.data.default.zoomaddress);
        }

		/**
		 * Set the address for a latlng
		 */
		this.codeLatLng = function(Latlng)
		{
			var Geocoder = new google.maps.Geocoder();
			Geocoder.geocode(
				{'latLng': Latlng},
				function(Results,Status)
				{
					if (Status == google.maps.GeocoderStatus.OK)
					{
						if (Results[0])
						{
							var formattedAddress = Results[0].formatted_address.split(',');
							$('#nav-address').val(formattedAddress[0]);

							// Mask the exact address before recording
							// Example: '1456 W Greenleaf Ave' becomes '1400 W Greenleaf Ave'
							var addarray = $.trim($('#nav-address').val()).split(' ');
							// Chicago addresses start with numbers. So look for them and mask them.
							if(addarray[0].match(/^[0-9]+$/) !== null)
							{
								var replacement = addarray[0].substr(0,addarray[0].length-2)+'00';
								if(replacement !== '00')
								{
									addarray[0] = replacement;
								}
								else
								{
									addarray[0] = '0';
								}
							}
							var maskedAddress = addarray.join(' ');
							//_gaq.push(['_trackEvent', 'Find Me', 'Address', maskedAddress]);
						}
						else
						{
							alert('We\'re sorry. We could not find an address for this location.');
						}
					}
					else
					{
						alert('We\'re sorry. We could not find an address for this location.');
					}
				}
			);
		};

		// Put a Pan/Zoom control on the map
		this.setFindMeControl = function(controlDiv,Map,Project,Default)
		{
			// Set CSS styles for the DIV containing the control
			// Setting padding to 5 px will offset the control
			// from the edge of the map.
			controlDiv.style.padding = '1em';
			// Set CSS for the control border.
			var controlUI = document.createElement('div');
			controlUI.style.backgroundColor = '#333';
			//controlUI.style.color = 'white';
			controlUI.style.borderStyle = 'solid';
			controlUI.style.borderWidth = '0px';
			controlUI.style.cursor = 'pointer';
			controlUI.style.textAlign = 'center';
			controlUI.style.borderRadius = '6px';
			controlUI.title = 'Click to find your location.';
			controlDiv.appendChild(controlUI);
			// Set CSS for the control interior.
			var controlText = document.createElement('div');
			controlText.style.fontFamily = '"Helvetica Neue",Helvetica,Arial,sans-serif';
			controlText.style.fontSize = '12px';
			controlText.style.color = '#fff';
			controlText.style.paddingLeft = '.5em';
			controlText.style.paddingRight = '.5em';
			controlText.style.paddingTop = '.3em';
			controlText.style.paddingBottom = '.3em';
			controlText.innerHTML = 'Find Me';
			controlUI.appendChild(controlText);
			// Setup the click event listeners.
			google.maps.event.addDomListener(controlUI, 'click', function() {
				if(navigator.geolocation)
				{
					navigator.geolocation.getCurrentPosition(
						// Success
						function(position)
						{
							//_gaq.push(['_trackEvent', 'GPS', 'Success']);
							var Latlng = new google.maps.LatLng(
								position.coords.latitude,
								position.coords.longitude
							);
							Map.Map.setCenter(Latlng);
							Map.Map.setZoom(Default.zoomaddress);
							// Make a map marker if none exists yet
							if(Project.AddressMarker === null)
							{
								Project.AddressMarker = new google.maps.Marker({
									position:Latlng,
									map: Map.Map,
									icon:Default.iconlocation,
									clickable:false
								});
							}
							else
							{
								// Move the marker to the new location
								Project.AddressMarker.setPosition(Latlng);
								// If the marker is hidden, unhide it
								if(Project.AddressMarker.getMap() === null)
								{
									Project.AddressMarker.setMap(Map.Map);
								}
							}
							Project.codeLatLng(Latlng);
						},
						// Failure
						function()
						{
							alert('We\'re sorry. We could not find you. Please type in an address.');
						},
						{
							timeout:5000,
							enableHighAccuracy:true
						}
					);
				}
			});
		};

		this.setMapLegend = function(controlDiv,Map,Project,Default)
		{
			// Set CSS styles for the DIV containing the control
			// Setting padding to 5 px will offset the control
			// from the edge of the map.
			controlDiv.style.padding = '1em';
			// Set CSS for the control border.
			var controlUI = document.createElement('div');
			controlUI.style.backgroundColor = 'rgba(255,255,255,0.7)';
			//controlUI.style.color = 'white';
			controlUI.style.borderStyle = 'solid';
			controlUI.style.borderWidth = '0px';
			controlUI.style.cursor = 'pointer';
			controlUI.style.textAlign = 'center';
			controlUI.style.borderRadius = '6px';
			controlUI.title = 'Click to hide.';
			controlDiv.appendChild(controlUI);
			// Set CSS for the control interior.
			var controlText = document.createElement('div');
			controlText.style.fontFamily = '"Helvetica Neue",Helvetica,Arial,sans-serif';
			controlText.style.fontSize = '12px';
			controlText.style.color = '#333';
			controlText.style.paddingLeft = '.5em';
			controlText.style.paddingRight = '.5em';
			controlText.style.paddingTop = '.3em';
			controlText.style.paddingBottom = '.3em';
			controlText.innerHTML = '
Free
';
			controlUI.appendChild(controlText);
		// Setup the click event listeners.
			google.maps.event.addDomListener(controlUI, 'click', function() {
				Map.Map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].clear();
			});
		};

		this.setMarkersByProjectType = function( project_type_to_display )
		{
            if ( project_type_to_display == 'all' ) {
                $('.panel-default').css("display", "block");
            } else {
                $('.panel-default').css("display", "none");
                $('.' + project_type_to_display + '-panel').css("display", "block");
            }

			for(var i in this.Events)
			{

                var ptype = this.Events[i].data[ 'Project type' ];

                if ( project_type_to_display == 'all'
                || ( typeof project_type_info[ (ptype) ] !== 'undefined' && project_type_info[ (ptype) ].id == project_type_to_display )) {
                    this.Events[i].marker.setIcon( project_type_info[ (ptype) ].pin_url );
                } else {
					this.Events[i].marker.setIcon('img/grey-transparent.png');
				}

			}
		};
	};
	return constructor;
})(jQuery);
<commit_msg>Added fields to left panel<commit_after>/**
 * @classDestription - Placeholder for Projects application variables and functions.
 * @class - Projects
 */
var Projects = (function($) {
	var constructor = function(infoboxoptions){
		this.AddressMarker = null;

		this.Events = [];

		// Can we geolocate?
		this.geolocate = navigator.geolocation;

		this.getEvents = function( rows, Map, Default )
		{
			// Copy the Project data to the Event object
			for (var i in rows)
			{
				this.Events[i] = new Event();
				for(var colname in rows[ i ])
				{
					    this.Events[ i ].data[ colname ] = rows[ i ][ colname ];
				}

                var ll = this.Events[i].data['Location'];
                var lla = ll.split(',');

                if (lla.length != 2) {
                } else {

                    var Lat = null;
                    var Lng = null;

                    // Create the Google LatLng object

                    Lat = lla[0];
                    Lng = lla[1];

                    this.Events[i].latlng = new google.maps.LatLng(Lat, Lng);

                    var project_type = $.trim(this.Events[i].data[ 'Project type' ]);

                    // Create the markers for each event

                    var icon = '';
                    var panel_class = '';

                    if (!(project_type in project_type_info)) {
                        project_type = 'Other';
                    }

                    icon = project_type_info[ project_type ].pin_url;

                    project_type_info[ project_type ].count++;
                    project_type_info[ 'All' ].count++;

                    panel_class = project_type_info[ project_type ].id + '-panel';

                    this.Events[i].marker = new google.maps.Marker({
                        position: this.Events[i].latlng,
                        map: Map.Map,
                        icon: icon,
                        shadow: 'img/shadow.png',
                        clickable: true
                    });

                    this.Events[i].panel = {
                        Lat: Lat,
                        Lng: Lng,
                        map: Map.Map
                    };

                    // Make the info box
                    this.Events[i].infobox = new InfoBox(infoboxoptions);

                    var data = this.Events[i].data;
                    var organization_name = data[ 'Organization name' ];

                    var accordion = '';
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '                  ' + "\n";
                    accordion += '                    ' + organization_name + "\n";
                    accordion += '                  ' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion +=  this.displayIt( 'Organization Type:', data[ 'Which best describes your type of organization?' ] );
                    accordion +=  this.displayIt( 'Organization website or Facebook page:', data[ 'Organization website or Facebook page' ] );
                    accordion +=  this.displayIt( 'Contact:', data[ 'Name of contact person' ] );
                    accordion +=  this.displayIt( 'Phone:', data[ 'Phone number' ] );
                    accordion +=  this.displayIt( 'Email:', data[ 'Email address' ] );

                    accordion += '
Project Type: ' + data[ 'Project type' ] + '
' + "\n";
                    accordion += '
' + data[ 'Project description' ] + "\n";
                    accordion += '
' + data[ 'How often does this project occur?' ] + "\n";
                    accordion += '
' + data[ 'What is the start date of your project?' ] + ' through ' + data[ 'What is the finish date (or anticipated finish date)?' ] + "\n";
                    accordion +=  this.displayIt( 'Website:', data[ 'Project website' ] );
                    accordion +=  this.displayIt( 'Partners:', data[ 'Who are the partners you are working with?' ] );
                    accordion +=  this.displayIt( 'Focus:', data[ 'Is the project area-wide or located at one site?' ] );
                    accordion +=  this.displayIt( 'Neighborhoods/Cities:', data[ 'For area-wide projects, list the neighborhoods/cities this project occurs.' ] );
                    accordion +=  this.displayIt( 'Project Boundaries:', data[ 'Does this project have more specific boundaries?' ] );
                    accordion +=  this.displayIt( 'Neighborhood Assoc. Support:', data[ 'Does the project have the support of the neighborhood association?' ] );
                    accordion +=  this.displayIt( 'Needs:', data[ 'The project is in need of' ] );
                    accordion +=  this.displayIt( 'Will Help:', data[ 'We are happy to talk to others about our project and experience' ] );

                    accordion +=  this.displayIt( 'Website:', data[ 'Project' ] );

                    accordion += '' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
Show on map
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";
                    accordion += '
' + "\n";

                    $('#accordion').append(accordion);
                }
			}
			for(var i in this.Events)
			{
				// Listen for marker clicks
				google.maps.event.addListener(this.Events[i].marker, 'click', this.Events[i].toggleInfoBox(Map.Map,this.Events[i]));
                $('#show-on-map-' + i).on( "click", null, {  map: Map.Map, default: Default, panel: this.Events[i].panel }, this.centerPin );

			}

		};

        this.displayIt = function( label, value ) {
            if ( value ) {
                return '
' + label  +' ' + value + '
' + "\n";
            } else {
                return '';
            }
        }

        /**
         * PROJECT FILTER functions
         */
        this.displayProjectTypeFilters = function( ) {
            for ( var project_type in project_type_info ) {
                var project = project_type_info [ project_type ];
                var li = '
' + project_type + '' + project.count + '
';
                $("#project-type-filter-buttons").append( li );
            }
        }

        this.displayProjectTypeCounts = function ( ) {
            for ( var project_type in project_type_info ) {
                var project = project_type_info [ project_type ];
                $('#cnt-' + project.id).html( project.count );
            }
        }

        /**
         * MAP functions
         */
        this.centerPin = function ( e ) {
            var Latlng = new google.maps.LatLng(
                e.data.panel.Lat,
                e.data.panel.Lng
            );
            e.data.map.setCenter(Latlng);
            e.data.map.setZoom(e.data.default.zoomaddress);
        }

		/**
		 * Set the address for a latlng
		 */
		this.codeLatLng = function(Latlng)
		{
			var Geocoder = new google.maps.Geocoder();
			Geocoder.geocode(
				{'latLng': Latlng},
				function(Results,Status)
				{
					if (Status == google.maps.GeocoderStatus.OK)
					{
						if (Results[0])
						{
							var formattedAddress = Results[0].formatted_address.split(',');
							$('#nav-address').val(formattedAddress[0]);

							// Mask the exact address before recording
							// Example: '1456 W Greenleaf Ave' becomes '1400 W Greenleaf Ave'
							var addarray = $.trim($('#nav-address').val()).split(' ');
							// Chicago addresses start with numbers. So look for them and mask them.
							if(addarray[0].match(/^[0-9]+$/) !== null)
							{
								var replacement = addarray[0].substr(0,addarray[0].length-2)+'00';
								if(replacement !== '00')
								{
									addarray[0] = replacement;
								}
								else
								{
									addarray[0] = '0';
								}
							}
							var maskedAddress = addarray.join(' ');
							//_gaq.push(['_trackEvent', 'Find Me', 'Address', maskedAddress]);
						}
						else
						{
							alert('We\'re sorry. We could not find an address for this location.');
						}
					}
					else
					{
						alert('We\'re sorry. We could not find an address for this location.');
					}
				}
			);
		};

		// Put a Pan/Zoom control on the map
		this.setFindMeControl = function(controlDiv,Map,Project,Default)
		{
			// Set CSS styles for the DIV containing the control
			// Setting padding to 5 px will offset the control
			// from the edge of the map.
			controlDiv.style.padding = '1em';
			// Set CSS for the control border.
			var controlUI = document.createElement('div');
			controlUI.style.backgroundColor = '#333';
			//controlUI.style.color = 'white';
			controlUI.style.borderStyle = 'solid';
			controlUI.style.borderWidth = '0px';
			controlUI.style.cursor = 'pointer';
			controlUI.style.textAlign = 'center';
			controlUI.style.borderRadius = '6px';
			controlUI.title = 'Click to find your location.';
			controlDiv.appendChild(controlUI);
			// Set CSS for the control interior.
			var controlText = document.createElement('div');
			controlText.style.fontFamily = '"Helvetica Neue",Helvetica,Arial,sans-serif';
			controlText.style.fontSize = '12px';
			controlText.style.color = '#fff';
			controlText.style.paddingLeft = '.5em';
			controlText.style.paddingRight = '.5em';
			controlText.style.paddingTop = '.3em';
			controlText.style.paddingBottom = '.3em';
			controlText.innerHTML = 'Find Me';
			controlUI.appendChild(controlText);
			// Setup the click event listeners.
			google.maps.event.addDomListener(controlUI, 'click', function() {
				if(navigator.geolocation)
				{
					navigator.geolocation.getCurrentPosition(
						// Success
						function(position)
						{
							//_gaq.push(['_trackEvent', 'GPS', 'Success']);
							var Latlng = new google.maps.LatLng(
								position.coords.latitude,
								position.coords.longitude
							);
							Map.Map.setCenter(Latlng);
							Map.Map.setZoom(Default.zoomaddress);
							// Make a map marker if none exists yet
							if(Project.AddressMarker === null)
							{
								Project.AddressMarker = new google.maps.Marker({
									position:Latlng,
									map: Map.Map,
									icon:Default.iconlocation,
									clickable:false
								});
							}
							else
							{
								// Move the marker to the new location
								Project.AddressMarker.setPosition(Latlng);
								// If the marker is hidden, unhide it
								if(Project.AddressMarker.getMap() === null)
								{
									Project.AddressMarker.setMap(Map.Map);
								}
							}
							Project.codeLatLng(Latlng);
						},
						// Failure
						function()
						{
							alert('We\'re sorry. We could not find you. Please type in an address.');
						},
						{
							timeout:5000,
							enableHighAccuracy:true
						}
					);
				}
			});
		};

		this.setMapLegend = function(controlDiv,Map,Project,Default)
		{
			// Set CSS styles for the DIV containing the control
			// Setting padding to 5 px will offset the control
			// from the edge of the map.
			controlDiv.style.padding = '1em';
			// Set CSS for the control border.
			var controlUI = document.createElement('div');
			controlUI.style.backgroundColor = 'rgba(255,255,255,0.7)';
			//controlUI.style.color = 'white';
			controlUI.style.borderStyle = 'solid';
			controlUI.style.borderWidth = '0px';
			controlUI.style.cursor = 'pointer';
			controlUI.style.textAlign = 'center';
			controlUI.style.borderRadius = '6px';
			controlUI.title = 'Click to hide.';
			controlDiv.appendChild(controlUI);
			// Set CSS for the control interior.
			var controlText = document.createElement('div');
			controlText.style.fontFamily = '"Helvetica Neue",Helvetica,Arial,sans-serif';
			controlText.style.fontSize = '12px';
			controlText.style.color = '#333';
			controlText.style.paddingLeft = '.5em';
			controlText.style.paddingRight = '.5em';
			controlText.style.paddingTop = '.3em';
			controlText.style.paddingBottom = '.3em';
			controlText.innerHTML = '
Free
';
			controlUI.appendChild(controlText);
		// Setup the click event listeners.
			google.maps.event.addDomListener(controlUI, 'click', function() {
				Map.Map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].clear();
			});
		};

		this.setMarkersByProjectType = function( project_type_to_display )
		{
            if ( project_type_to_display == 'all' ) {
                $('.panel-default').css("display", "block");
            } else {
                $('.panel-default').css("display", "none");
                $('.' + project_type_to_display + '-panel').css("display", "block");
            }

			for(var i in this.Events)
			{

                var ptype = this.Events[i].data[ 'Project type' ];

                if ( project_type_to_display == 'all'
                || ( typeof project_type_info[ (ptype) ] !== 'undefined' && project_type_info[ (ptype) ].id == project_type_to_display )) {
                    this.Events[i].marker.setIcon( project_type_info[ (ptype) ].pin_url );
                } else {
					this.Events[i].marker.setIcon('img/grey-transparent.png');
				}

			}
		};
	};
	return constructor;
})(jQuery);
<|endoftext|>