<commit_before>define([
    'model/Player'
], function(Player) {

  'use strict';

  function joinGame(playerName, gameID) {
    var that = this;

    io.socket.get('/game/' + gameID, function (game) {
      io.socket.post('/player', {name: playerName, game: game.id, room: game.startingRoom.id}, function (player) {
        that._player = new Player(player.id, player.name);
        that._player.installViewAdpt(that._viewAdpt.makePlayerViewAdpt(that._player));
        that._currentRoom = player.room;

        fetchRoom.call(that, that._currentRoom, function (room) {
          that._currentRoom = room;
          var doors = {};
          for (var i = 0; i < room.gatewaysOut.length; i++) {
            var gateway = room.gatewaysOut[i];
            doors[gateway.direction] = gateway.roomTo;
          }
          that._viewAdpt.loadRoom({background: room.background, doors: doors});
        });

        /* Populate other players object when join game */
        io.socket.get('/player', function (err, jwr) {
          jwr.body.forEach(function (v, i, a) {
            if (v.id !== that._player.id) {
              _otherPlayers[v.id] = {id: v.id, room: v.room.id, locX: v.locX, locY: v.locY};

              _viewAdpt.addPlayer(v.name);

              if (v.room.id === _currentRoom.id) {
                _viewAdpt.makePlayerHusk(v.id, v.locX, v.locY); // draw other player
              }
            }
          });
        });

      });
    });
  }

  function fetchGames() {
    var that = this;

    io.socket.get('/game', function(games) {
      that._viewAdpt.setGames(games);
    });
  };

  function createGame(name) {
    var that = this;

    io.socket.post('/game', {name: name}, function(game) {
      that.fetchGames();
    });
  }

  function start() {
  }

  function onDoorVisit(doorID) {
    for (var i = 0; i < this._currentRoom.gatewaysOut.length; i++) {
      if (this._currentRoom.gatewaysOut[i].direction === doorID) {
        // get ID of room player is going to
        var id = this._currentRoom.gatewaysOut[i].roomTo;
        break;
      }
    }

    var that = this;

    fetchRoom.call(this, id, function (room) {
      var doors = {};
      for (var i = 0; i < room['gatewaysOut'].length; i++) {
        var gateway = room['gatewaysOut'][i];
        doors[gateway['direction']] = gateway['roomTo'];
      }
      that._currentRoom = room;
      var roomConfig = {background: room.background, doors: doors};

      io.socket.put('/player/changeRoom/' + that._player.id, {room: that._currentRoom.id}, function (player) {
        if (doorID === 'north') {
          that._player.setPosition(that._player.x, that.dimensions.height - 65);
        } else if (doorID === 'east') {
          that._player.setPosition(33, that._player.y);
        } else if (doorID === 'south') {
          that._player.setPosition(that._player.x, 33);
        } else if (doorID === 'west') {
          that._player.setPosition(that.dimensions.width - 65, that._player.y);
        }

        that._viewAdpt.loadRoom(roomConfig);
      });
    });

  }

  function fetchRoom(roomID, cb) {
    var that = this;

    io.socket.get('/room/' + roomID, function (room) {

      that._viewAdpt.removeAllHusks();

      for (var p in that._otherPlayers) {
        if (that._otherPlayers[p].room === room.id) {
          that._viewAdpt.makePlayerHusk(that._otherPlayers[p].id, that._otherPlayers[p].locX, that._otherPlayers[p].locY); // draw other player
        }
      }

      cb(room);
    });
  }

  function initSockets() {
    var that = this;

    io.socket.on('player', function(o) {
      if (o.verb === 'created' && o.id !== that._player.id) {
        console.log('created player event');
        _otherPlayers[o.id] = {id: o.id,
                               name: o.data.name,
                               locX: o.data.locX,
                               locY: o.data.locY,
                               room: o.data.room};

        _viewAdpt.addPlayer(o.data.name);
      } else if (o.verb === 'updated' && o.id !== that._player.id) {
        /*if (o.data.locX !== undefined && o.data.locY !== undefined) {
          _otherPlayers[o.id].locX = o.data.locX;
          _otherPlayers[o.id].locY = o.data.locY;
        }*/
        if (o.data.room !== undefined) {
          _otherPlayers[o.id].room = o.data.room;
        }
        if (_otherPlayers[o.id].room === that._currentRoom.id) {
          _viewAdpt.moveHusk(o.id, o.data.locX, o.data.locY);
        }
      }
    });

    io.socket.on('room', function(o) {
      if (o.verb === 'addedTo' && o.addedId !== that._player.id && o.id === that._currentRoom.id) {
        io.socket.get('/player/' + o.addedId, function (resData) {
          //_otherPlayers[resData.id] = resData;
          _viewAdpt.makePlayerHusk(resData.id, resData.locX, resData.locY); // draw other player
        });
      } else if (o.verb === 'removedFrom' && o.id === that._currentRoom.id) {
        io.socket.get('/player/' + o.removedId, function (resData) {
          //delete _otherPlayers[resData.id];
          _viewAdpt.removeHusk(resData.id); // remove other player image
        });
      } else if (o.verb === 'messaged' && o.data.verb === 'playerUpdated' && o.id === that._currentRoom.id && o.data.id !== that._player.id) {
        _otherPlayers[o.data.id].locX = o.data.data.locX;
        _otherPlayers[o.data.id].locY = o.data.data.locY;
        _viewAdpt.moveHusk(o.data.id, _otherPlayers[o.data.id].locX, _otherPlayers[o.data.id].locY);
      }
    });
  }

  return function GameModel(viewAdpt) {
    console.log('constructing a game model');

    this._player = null;
    this._viewAdpt = viewAdpt;
    this._currentRoom = null;
    this._otherPlayers = {};

    initSockets.call(this);

    Object.defineProperty(this, 'dimensions', {
      value: {width: 768, height: 640},
      writable: false
    });

    this.joinGame = joinGame.bind(this);
    this.fetchGames = fetchGames.bind(this);
    this.createGame = createGame.bind(this);
    this.onDoorVisit = onDoorVisit.bind(this);
    this.start = start.bind(this);
  }
});

<commit_msg>Made DIMENSIONS a static property.<commit_after>define([
    'model/Player'
], function(Player) {

  'use strict';

  var DIMENSIONS = {
    width: 768,
    height: 640
  }

  function joinGame(playerName, gameID) {
    var that = this;

    io.socket.get('/game/' + gameID, function (game) {
      io.socket.post('/player', {name: playerName, game: game.id, room: game.startingRoom.id}, function (player) {
        that._player = new Player(player.id, player.name);
        that._player.installViewAdpt(that._viewAdpt.makePlayerViewAdpt(that._player));
        that._currentRoom = player.room;

        fetchRoom.call(that, that._currentRoom, function (room) {
          that._currentRoom = room;
          var doors = {};
          for (var i = 0; i < room.gatewaysOut.length; i++) {
            var gateway = room.gatewaysOut[i];
            doors[gateway.direction] = gateway.roomTo;
          }
          that._viewAdpt.loadRoom({background: room.background, doors: doors});
        });

        /* Populate other players object when join game */
        io.socket.get('/player', function (err, jwr) {
          jwr.body.forEach(function (v, i, a) {
            if (v.id !== that._player.id) {
              _otherPlayers[v.id] = {id: v.id, room: v.room.id, locX: v.locX, locY: v.locY};

              _viewAdpt.addPlayer(v.name);

              if (v.room.id === _currentRoom.id) {
                _viewAdpt.makePlayerHusk(v.id, v.locX, v.locY); // draw other player
              }
            }
          });
        });

      });
    });
  }

  function fetchGames() {
    var that = this;

    io.socket.get('/game', function(games) {
      that._viewAdpt.setGames(games);
    });
  };

  function createGame(name) {
    var that = this;

    io.socket.post('/game', {name: name}, function(game) {
      that.fetchGames();
    });
  }

  function start() {
  }

  function onDoorVisit(doorID) {
    for (var i = 0; i < this._currentRoom.gatewaysOut.length; i++) {
      if (this._currentRoom.gatewaysOut[i].direction === doorID) {
        // get ID of room player is going to
        var id = this._currentRoom.gatewaysOut[i].roomTo;
        break;
      }
    }

    var that = this;

    fetchRoom.call(this, id, function (room) {
      var doors = {};
      for (var i = 0; i < room['gatewaysOut'].length; i++) {
        var gateway = room['gatewaysOut'][i];
        doors[gateway['direction']] = gateway['roomTo'];
      }
      that._currentRoom = room;
      var roomConfig = {background: room.background, doors: doors};

      io.socket.put('/player/changeRoom/' + that._player.id, {room: that._currentRoom.id}, function (player) {
        if (doorID === 'north') {
          that._player.setPosition(that._player.x, DIMENSIONS.height - 65);
        } else if (doorID === 'east') {
          that._player.setPosition(33, that._player.y);
        } else if (doorID === 'south') {
          that._player.setPosition(that._player.x, 33);
        } else if (doorID === 'west') {
          that._player.setPosition(DIMENSIONS.width - 65, that._player.y);
        }

        that._viewAdpt.loadRoom(roomConfig);
      });
    });

  }

  function fetchRoom(roomID, cb) {
    var that = this;

    io.socket.get('/room/' + roomID, function (room) {

      that._viewAdpt.removeAllHusks();

      for (var p in that._otherPlayers) {
        if (that._otherPlayers[p].room === room.id) {
          that._viewAdpt.makePlayerHusk(that._otherPlayers[p].id, that._otherPlayers[p].locX, that._otherPlayers[p].locY); // draw other player
        }
      }

      cb(room);
    });
  }

  function initSockets() {
    var that = this;

    io.socket.on('player', function(o) {
      if (o.verb === 'created' && o.id !== that._player.id) {
        console.log('created player event');
        _otherPlayers[o.id] = {id: o.id,
                               name: o.data.name,
                               locX: o.data.locX,
                               locY: o.data.locY,
                               room: o.data.room};

        _viewAdpt.addPlayer(o.data.name);
      } else if (o.verb === 'updated' && o.id !== that._player.id) {
        /*if (o.data.locX !== undefined && o.data.locY !== undefined) {
          _otherPlayers[o.id].locX = o.data.locX;
          _otherPlayers[o.id].locY = o.data.locY;
        }*/
        if (o.data.room !== undefined) {
          _otherPlayers[o.id].room = o.data.room;
        }
        if (_otherPlayers[o.id].room === that._currentRoom.id) {
          _viewAdpt.moveHusk(o.id, o.data.locX, o.data.locY);
        }
      }
    });

    io.socket.on('room', function(o) {
      if (o.verb === 'addedTo' && o.addedId !== that._player.id && o.id === that._currentRoom.id) {
        io.socket.get('/player/' + o.addedId, function (resData) {
          //_otherPlayers[resData.id] = resData;
          _viewAdpt.makePlayerHusk(resData.id, resData.locX, resData.locY); // draw other player
        });
      } else if (o.verb === 'removedFrom' && o.id === that._currentRoom.id) {
        io.socket.get('/player/' + o.removedId, function (resData) {
          //delete _otherPlayers[resData.id];
          _viewAdpt.removeHusk(resData.id); // remove other player image
        });
      } else if (o.verb === 'messaged' && o.data.verb === 'playerUpdated' && o.id === that._currentRoom.id && o.data.id !== that._player.id) {
        _otherPlayers[o.data.id].locX = o.data.data.locX;
        _otherPlayers[o.data.id].locY = o.data.data.locY;
        _viewAdpt.moveHusk(o.data.id, _otherPlayers[o.data.id].locX, _otherPlayers[o.data.id].locY);
      }
    });
  }

  return function GameModel(viewAdpt) {
    console.log('constructing a game model');

    this._player = null;
    this._viewAdpt = viewAdpt;
    this._currentRoom = null;
    this._otherPlayers = {};

    initSockets.call(this);

    Object.defineProperty(this, 'dimensions', {
      get: function() {
        return DIMENSIONS;
      }
    });

    this.joinGame = joinGame.bind(this);
    this.fetchGames = fetchGames.bind(this);
    this.createGame = createGame.bind(this);
    this.onDoorVisit = onDoorVisit.bind(this);
    this.start = start.bind(this);
  }
});

<|endoftext|>


<commit_before>$.fn.romoDatepicker = function() {
  return $.map(this, function(element) {
    return new RomoDatepicker(element);
  });
}

var RomoDatepicker = function(element) {
  this.elem = $(element);
  this.defaultFormat = 'yyyy-mm-dd'
  this.monthNames = [
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
  ]
  this.defaultLeftArrowClass  = '';
  this.defaultRightArrowClass = '';
  this.defaultIndicatorClass  = '';
  this.itemSelector = 'TD.romo-datepicker-day:not(.disabled)';
  this.calTable = $();
  this.date = undefined;
  this.today = new Date;

  this.doInit();
  this.doSetFormat();
  this.doSetDate(this.elem.val());
  this.doBindDropdown();
  this.doBuildUI();

  this.elem.trigger('datepicker:ready', [this]);
}

RomoDatepicker.prototype.doInit = function() {
  // override as needed
}

RomoDatepicker.prototype.doSetFormat = function() {
  var format = this.elem.data('romo-datepicker-format') || this.defaultFormat;
  this.formatValues = this._parseFormatValues(format);
}

RomoDatepicker.prototype.doSetDate = function(value) {
  this.date = this._parseDate(value);
  if (this.date !== undefined) {
    this.elem.val(this._formatDate(this.date));
  } else {
    this.elem.val(value);
  }
}

RomoDatepicker.prototype.doBindDropdown = function() {
  this.elem.addClass('romo');
  this.elem.attr('data-romo-dropdown-disable-toggle', 'true');
  if (this.elem.data('romo-dropdown-width') === undefined) {
    this.elem.attr('data-romo-dropdown-width', 'elem');
  }
  this.romoDropdown = this.elem.romoDropdown()[0];

  this.romoDropdown.doSetPopupZIndex(this.elem);
  this.romoDropdown.bodyElem.addClass('romo-datepicker-calendar');
  this.romoDropdown.elem.on('dropdown:popupOpen', $.proxy(this.onPopupOpen, this));
  this.romoDropdown.elem.on('dropdown:popupClose', $.proxy(this.onPopupClose, this));

  this.romoDropdown.elem.on('dropdown:toggle', $.proxy(function(e, dropdown) {
    this.elem.trigger('datepicker:dropdown:toggle', [dropdown, this]);
  }, this));
  this.romoDropdown.elem.on('dropdown:popupOpen', $.proxy(function(e, dropdown) {
    this.elem.trigger('datepicker:dropdown:popupOpen', [dropdown, this]);
  }, this));
  this.romoDropdown.elem.on('dropdown:popupClose', $.proxy(function(e, dropdown) {
    this.elem.trigger('datepicker:dropdown:popupClose', [dropdown, this]);
  }, this));

  this.elem.on('datepicker:triggerToggle', $.proxy(function(e) {
    this.romoDropdown.elem.trigger('dropdown:triggerToggle', []);
  }, this));
  this.elem.on('datepicker:triggerPopupOpen', $.proxy(function(e) {
    this.romoDropdown.elem.trigger('dropdown:triggerPopupOpen', []);
  }, this));
  this.elem.on('datepicker:triggerPopupClose', $.proxy(function(e) {
    this.romoDropdown.elem.trigger('dropdown:triggerPopupClose', []);
  }, this));
}

RomoDatepicker.prototype.doBuildUI = function() {
  this.calTable = this._buildCalendar();
  this.romoDropdown.bodyElem.html('');
  this.romoDropdown.bodyElem.append(this.calTable);
}

RomoDatepicker.prototype.doRefreshUI = function(date) {
  this._refreshCalendar(date || this.date || (new Date));
  this.calTable.find(this.itemSelector).on('hover', $.proxy(this.onItemHover, this));
  this.calTable.find(this.itemSelector).on('click', $.proxy(this.onItemClick, this));
}

RomoDatepicker.prototype.doSelectHighlightedItem = function() {
  var prevValue = this.elem.val();
  var newValue = this.calTable.find('TD.romo-datepicker-highlight').data('romo-datepicker-value');

  this.romoDropdown.doPopupClose();
  this.elem.trigger('datepicker:itemSelected', [newValue, prevValue, this]);

  if (newValue !== prevValue) {
    this.doSetDate(newValue);

    this.elem.trigger('change');
    this.elem.trigger('datepicker:change', [newValue, prevValue, this]);
  }
}

RomoDatepicker.prototype.onPopupOpen = function(e) {
  if (this.elem.hasClass('disabled') === false) {
    this.doSetDate(this.elem.val());
    this.doRefreshUI();
  }
}

RomoDatepicker.prototype.onPopupClose = function(e) {
  this._highlightItem($());
}

RomoDatepicker.prototype.onItemHover = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }
  this._highlightItem($(e.target));
}

RomoDatepicker.prototype.onItemClick = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }
  this.doSelectHighlightedItem();
}

RomoDatepicker.prototype.onPrevClick = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }
  this.doRefreshToPrevMonth();
}

RomoDatepicker.prototype.onNextClick = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }
  this.doRefreshToNextMonth();
}

RomoDatepicker.prototype._refreshCalendar = function(date) {
  this.calTable.find('.romo-datepicker-title').html(this._buildCalendarTitle(date));
  this.calTable.find('tbody').empty().append(this._buildCalendarBody(date));
  this.refreshDate = date;
}

RomoDatepicker.prototype._buildCalendar = function() {
  var table = $('

');
  table.append(this._buildCalendarHeader());
  table.append($('

'));
  return table;
}

RomoDatepicker.prototype._buildCalendarHeader = function() {
  var header = $('
</thead');

  var row = $('

');
  row.append($(''));
  row.append($('	'));
  row.append($(''));
  header.append(row);

  row = $('

');
  row.append($('Su	'));
  row.append($('M	'));
  row.append($('T	'));
  row.append($('W	'));
  row.append($('Th	'));
  row.append($('F	'));
  row.append($('S	'));
  header.append(row);

  return header;
}

RomoDatepicker.prototype._buildCalendarTitle = function(date) {
  return this.monthNames[date.getUTCMonth()] + ' ' + date.getUTCFullYear().toString();
}

RomoDatepicker.prototype._buildCalendarBody = function(date) {
  var ty = this.today.getUTCFullYear();
  var tm = this.today.getUTCMonth();
  var td = this.today.getUTCDate();
  var year = date.getUTCFullYear();
  var month = date.getUTCMonth();
  var day = date.getUTCDate();
  var fomdow = this._UTCDate(year, month, 1).getUTCDay(); // first-of-the-month day-of-the-week
  if (fomdow == 0) {
    fomdow = 7;  // don't start calendar on the first-of-the-month, show last week of prev month
  }
  var iDate = this._UTCDate(year, month, 1 - fomdow);
  var iWeek = 0;
  var html = [];

  while (iWeek < 6) { // render 6 weeks in the calendar
    var y = iDate.getUTCFullYear();
    var m = iDate.getUTCMonth();
    var d = iDate.getUTCDate();
    var dow = iDate.getUTCDay();
    var cls = [];

    if (dow === 0) {
      html.push('
');
    }

    cls.push('romo-datepicker-day');
    if (dow === 0 || dow === 6) {
      cls.push('romo-datepicker-day-weekend');
    }
    if (y !== year || m !== month) {
      cls.push('romo-datepicker-day-other');
    }
    if (y === ty && m === tm && d === td) {
      cls.push('romo-datepicker-day-today');
    }
    if (y === year && m === month && d === day) {
      cls.push('selected');
    }

    html.push('');
    html.push(d.toString());
    html.push('	');

    if (dow === 6) {
      html.push('
');
      iWeek += 1;
    }
    iDate.setUTCDate(iDate.getUTCDate()+1);
  }

  return $(html.join(''));
}

RomoDatepicker.prototype._addIndicatorToElem = function() {
  // TODO, if opt and indicator icon class
  // create icon
  // append to elem
}

RomoDatepicker.prototype._highlightItem = function(item) {
  this.calTable.find('TD.romo-datepicker-highlight').removeClass('romo-datepicker-highlight');
  item.addClass('romo-datepicker-highlight');
}

RomoDatepicker.prototype._formatDate = function(date) {
  var year = date.getUTCFullYear();
  var month = date.getUTCMonth() + 1;
  var day = date.getUTCDate();

  return this.formatValues.reduce(function(prev, curr) {
    switch (curr) {
      case "yyyy":
      case "yyy":
        prev += year.toString();
        break;
      case "yy":
      case "y":
        prev += year.toString().slice(-2);
        break;
      case "mm":
        prev += ("00"+ month.toString()).slice(-2); // pad 2 with "0"s
        break;
      case "m":
        prev += month.toString();
        break;
      case "dd":
        prev += ("00"+ day.toString()).slice(-2); // pad 2 with "0"s
        break;
      case "d":
        prev += day.toString();
        break;
      default:
        prev += curr; // delimeter, pass-thru
    }
    return prev;
  }, '');
}

RomoDatepicker.prototype._parseFormatValues = function(value) {
  var regex, matches;

  regex = /^([m]{1,2})([^md]+)([d]{1,2})([^dy]+)([y]{2,4})$/; // mm dd yyyy or mm dd yy
  matches = this._regexMatches(value, regex);
  if (matches.length === 5) {
    return matches;
  }

  regex = /^([y]{3,4})([^ym]+)([m]{1,2})([^md]+)([d]{1,2})$/; // yyyy mm dd
  matches = this._regexMatches(value, regex);
  if (matches.length === 5) {
    return matches;
  }

  return ['yyyy', '-', 'mm', '-', 'dd'];
}

RomoDatepicker.prototype._parseDate = function(value) {
  if (value.trim() === '') {
    return undefined;
  }

  var dateValues = this._parseDateValues(value.trim());
  if (dateValues.length === 0) {
    return undefined;
  }

  var year = parseInt(dateValues[0]);
  if (year < 0) {
    return undefined;
  }
  if (dateValues[0].length > 2 && year < 100) {
    return undefined;
  }
  if (dateValues[0].length === 2 && year < 100) {
    year = this._currentYear() - (this._currentYear() % 1000) + year;
  }

  var month = parseInt(dateValues[1]) - 1;
  if (month < 0 || month > 11) {
    return undefined;
  }

  var day = parseInt(dateValues[2]);
  var date = this._UTCDate(year, month, day);
  if (date.getUTCMonth() !== month) {
    return undefined;
  }

  return date;
}

RomoDatepicker.prototype._parseDateValues = function(value) {
  var regex, matches;

  regex = /^([0-9]{1,2})[\/\-\.]+([0-9]{1,2})[\/\-\.]+([0-9]{2,4})$/; // mm dd yyyy or mm dd yy
  matches = this._regexMatches(value, regex);
  if (matches.length === 3) {
    return [matches[2], matches[0], matches[1]];
  }

  regex = /^([0-9]{3,4})[\/\-\.]+([0-9]{1,2})[\/\-\.]+([0-9]{1,2})$/; // yyyy mm dd
  matches = this._regexMatches(value, regex);
  if (matches.length === 3) {
    return matches;
  }

  regex = /^([0-9]{1,2})[\/\-\.]+([0-9]{1,2})$/; // mm dd
  matches = this._regexMatches(value, regex);
  if (matches.length === 2) {
    return [this._currentYear(), matches[0], matches[1]];
  }

  return [];
}

RomoDatepicker.prototype._regexMatches = function(value, regex) {
  if (regex.test(value) === true) {
    return regex.exec(value).slice(1);
  }
  return [];
}

RomoDatepicker.prototype._currentYear = function() {
  return (new Date).getUTCFullYear();
}

RomoDatepicker.prototype._UTCDate = function(year, month, day) {
  return new Date(Date.UTC.apply(Date, [year, month, day]));
}

Romo.onInitUI(function(e) {
  $(e.target).find('[data-romo-datepicker-auto="true"]').romoDatepicker();
});
<commit_msg>datepicker: more proper selected style behavior<commit_after>$.fn.romoDatepicker = function() {
  return $.map(this, function(element) {
    return new RomoDatepicker(element);
  });
}

var RomoDatepicker = function(element) {
  this.elem = $(element);
  this.defaultFormat = 'yyyy-mm-dd'
  this.monthNames = [
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
  ]
  this.defaultLeftArrowClass  = '';
  this.defaultRightArrowClass = '';
  this.defaultIndicatorClass  = '';
  this.itemSelector = 'TD.romo-datepicker-day:not(.disabled)';
  this.calTable = $();
  this.date = undefined;
  this.today = new Date;

  this.doInit();
  this.doSetFormat();
  this.doSetDate(this.elem.val());
  this.doBindDropdown();
  this.doBuildUI();

  this.elem.trigger('datepicker:ready', [this]);
}

RomoDatepicker.prototype.doInit = function() {
  // override as needed
}

RomoDatepicker.prototype.doSetFormat = function() {
  var format = this.elem.data('romo-datepicker-format') || this.defaultFormat;
  this.formatValues = this._parseFormatValues(format);
}

RomoDatepicker.prototype.doSetDate = function(value) {
  this.date = this._parseDate(value);
  if (this.date !== undefined) {
    this.elem.val(this._formatDate(this.date));
  } else {
    this.elem.val(value);
  }
}

RomoDatepicker.prototype.doBindDropdown = function() {
  this.elem.addClass('romo');
  this.elem.attr('data-romo-dropdown-disable-toggle', 'true');
  if (this.elem.data('romo-dropdown-width') === undefined) {
    this.elem.attr('data-romo-dropdown-width', 'elem');
  }
  this.romoDropdown = this.elem.romoDropdown()[0];

  this.romoDropdown.doSetPopupZIndex(this.elem);
  this.romoDropdown.bodyElem.addClass('romo-datepicker-calendar');
  this.romoDropdown.elem.on('dropdown:popupOpen', $.proxy(this.onPopupOpen, this));
  this.romoDropdown.elem.on('dropdown:popupClose', $.proxy(this.onPopupClose, this));

  this.romoDropdown.elem.on('dropdown:toggle', $.proxy(function(e, dropdown) {
    this.elem.trigger('datepicker:dropdown:toggle', [dropdown, this]);
  }, this));
  this.romoDropdown.elem.on('dropdown:popupOpen', $.proxy(function(e, dropdown) {
    this.elem.trigger('datepicker:dropdown:popupOpen', [dropdown, this]);
  }, this));
  this.romoDropdown.elem.on('dropdown:popupClose', $.proxy(function(e, dropdown) {
    this.elem.trigger('datepicker:dropdown:popupClose', [dropdown, this]);
  }, this));

  this.elem.on('datepicker:triggerToggle', $.proxy(function(e) {
    this.romoDropdown.elem.trigger('dropdown:triggerToggle', []);
  }, this));
  this.elem.on('datepicker:triggerPopupOpen', $.proxy(function(e) {
    this.romoDropdown.elem.trigger('dropdown:triggerPopupOpen', []);
  }, this));
  this.elem.on('datepicker:triggerPopupClose', $.proxy(function(e) {
    this.romoDropdown.elem.trigger('dropdown:triggerPopupClose', []);
  }, this));
}

RomoDatepicker.prototype.doBuildUI = function() {
  this.calTable = this._buildCalendar();
  this.romoDropdown.bodyElem.html('');
  this.romoDropdown.bodyElem.append(this.calTable);
}

RomoDatepicker.prototype.doRefreshUI = function(date) {
  this._refreshCalendar(date || this.date || (new Date));
  this.calTable.find(this.itemSelector).on('hover', $.proxy(this.onItemHover, this));
  this.calTable.find(this.itemSelector).on('click', $.proxy(this.onItemClick, this));
}

RomoDatepicker.prototype.doSelectHighlightedItem = function() {
  var prevValue = this.elem.val();
  var newValue = this.calTable.find('TD.romo-datepicker-highlight').data('romo-datepicker-value');

  this.romoDropdown.doPopupClose();
  this.elem.trigger('datepicker:itemSelected', [newValue, prevValue, this]);

  if (newValue !== prevValue) {
    this.doSetDate(newValue);

    this.elem.trigger('change');
    this.elem.trigger('datepicker:change', [newValue, prevValue, this]);
  }
}

RomoDatepicker.prototype.onPopupOpen = function(e) {
  if (this.elem.hasClass('disabled') === false) {
    this.doSetDate(this.elem.val());
    this.doRefreshUI();
  }
}

RomoDatepicker.prototype.onPopupClose = function(e) {
  this._highlightItem($());
}

RomoDatepicker.prototype.onItemHover = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }
  this._highlightItem($(e.target));
}

RomoDatepicker.prototype.onItemClick = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }
  this.doSelectHighlightedItem();
}

RomoDatepicker.prototype.onPrevClick = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }
  this.doRefreshToPrevMonth();
}

RomoDatepicker.prototype.onNextClick = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }
  this.doRefreshToNextMonth();
}

RomoDatepicker.prototype._refreshCalendar = function(date) {
  this.calTable.find('.romo-datepicker-title').html(this._buildCalendarTitle(date));
  this.calTable.find('tbody').empty().append(this._buildCalendarBody(date));
  this.refreshDate = date;
}

RomoDatepicker.prototype._buildCalendar = function() {
  var table = $('

');
  table.append(this._buildCalendarHeader());
  table.append($('

'));
  return table;
}

RomoDatepicker.prototype._buildCalendarHeader = function() {
  var header = $('
</thead');

  var row = $('

');
  row.append($(''));
  row.append($('	'));
  row.append($(''));
  header.append(row);

  row = $('

');
  row.append($('Su	'));
  row.append($('M	'));
  row.append($('T	'));
  row.append($('W	'));
  row.append($('Th	'));
  row.append($('F	'));
  row.append($('S	'));
  header.append(row);

  return header;
}

RomoDatepicker.prototype._buildCalendarTitle = function(date) {
  return this.monthNames[date.getUTCMonth()] + ' ' + date.getUTCFullYear().toString();
}

RomoDatepicker.prototype._buildCalendarBody = function(date) {
  var ty = this.today.getUTCFullYear();
  var tm = this.today.getUTCMonth();
  var td = this.today.getUTCDate();
  var year = date.getUTCFullYear();
  var month = date.getUTCMonth();
  var day = date.getUTCDate();
  var fomdow = this._UTCDate(year, month, 1).getUTCDay(); // first-of-the-month day-of-the-week
  if (fomdow == 0) {
    fomdow = 7;  // don't start calendar on the first-of-the-month, show last week of prev month
  }
  var iDate = this._UTCDate(year, month, 1 - fomdow);
  var iWeek = 0;
  var html = [];

  while (iWeek < 6) { // render 6 weeks in the calendar
    var y = iDate.getUTCFullYear();
    var m = iDate.getUTCMonth();
    var d = iDate.getUTCDate();
    var dow = iDate.getUTCDay();
    var cls = [];

    if (dow === 0) {
      html.push('
');
    }

    cls.push('romo-datepicker-day');
    if (dow === 0 || dow === 6) {
      cls.push('romo-datepicker-day-weekend');
    }
    if (y !== year || m !== month) {
      cls.push('romo-datepicker-day-other');
    }
    if (y === ty && m === tm && d === td) {
      cls.push('romo-datepicker-day-today');
    }
    if (this.date &&
        y === this.date.getUTCFullYear() &&
        m === this.date.getUTCMonth() &&
        d === this.date.getUTCDate()) {
      cls.push('selected');
    }

    html.push('');
    html.push(d.toString());
    html.push('	');

    if (dow === 6) {
      html.push('
');
      iWeek += 1;
    }
    iDate.setUTCDate(iDate.getUTCDate()+1);
  }

  return $(html.join(''));
}

RomoDatepicker.prototype._addIndicatorToElem = function() {
  // TODO, if opt and indicator icon class
  // create icon
  // append to elem
}

RomoDatepicker.prototype._highlightItem = function(item) {
  this.calTable.find('TD.romo-datepicker-highlight').removeClass('romo-datepicker-highlight');
  item.addClass('romo-datepicker-highlight');
}

RomoDatepicker.prototype._formatDate = function(date) {
  var year = date.getUTCFullYear();
  var month = date.getUTCMonth() + 1;
  var day = date.getUTCDate();

  return this.formatValues.reduce(function(prev, curr) {
    switch (curr) {
      case "yyyy":
      case "yyy":
        prev += year.toString();
        break;
      case "yy":
      case "y":
        prev += year.toString().slice(-2);
        break;
      case "mm":
        prev += ("00"+ month.toString()).slice(-2); // pad 2 with "0"s
        break;
      case "m":
        prev += month.toString();
        break;
      case "dd":
        prev += ("00"+ day.toString()).slice(-2); // pad 2 with "0"s
        break;
      case "d":
        prev += day.toString();
        break;
      default:
        prev += curr; // delimeter, pass-thru
    }
    return prev;
  }, '');
}

RomoDatepicker.prototype._parseFormatValues = function(value) {
  var regex, matches;

  regex = /^([m]{1,2})([^md]+)([d]{1,2})([^dy]+)([y]{2,4})$/; // mm dd yyyy or mm dd yy
  matches = this._regexMatches(value, regex);
  if (matches.length === 5) {
    return matches;
  }

  regex = /^([y]{3,4})([^ym]+)([m]{1,2})([^md]+)([d]{1,2})$/; // yyyy mm dd
  matches = this._regexMatches(value, regex);
  if (matches.length === 5) {
    return matches;
  }

  return ['yyyy', '-', 'mm', '-', 'dd'];
}

RomoDatepicker.prototype._parseDate = function(value) {
  if (value.trim() === '') {
    return undefined;
  }

  var dateValues = this._parseDateValues(value.trim());
  if (dateValues.length === 0) {
    return undefined;
  }

  var year = parseInt(dateValues[0]);
  if (year < 0) {
    return undefined;
  }
  if (dateValues[0].length > 2 && year < 100) {
    return undefined;
  }
  if (dateValues[0].length === 2 && year < 100) {
    year = this._currentYear() - (this._currentYear() % 1000) + year;
  }

  var month = parseInt(dateValues[1]) - 1;
  if (month < 0 || month > 11) {
    return undefined;
  }

  var day = parseInt(dateValues[2]);
  var date = this._UTCDate(year, month, day);
  if (date.getUTCMonth() !== month) {
    return undefined;
  }

  return date;
}

RomoDatepicker.prototype._parseDateValues = function(value) {
  var regex, matches;

  regex = /^([0-9]{1,2})[\/\-\.]+([0-9]{1,2})[\/\-\.]+([0-9]{2,4})$/; // mm dd yyyy or mm dd yy
  matches = this._regexMatches(value, regex);
  if (matches.length === 3) {
    return [matches[2], matches[0], matches[1]];
  }

  regex = /^([0-9]{3,4})[\/\-\.]+([0-9]{1,2})[\/\-\.]+([0-9]{1,2})$/; // yyyy mm dd
  matches = this._regexMatches(value, regex);
  if (matches.length === 3) {
    return matches;
  }

  regex = /^([0-9]{1,2})[\/\-\.]+([0-9]{1,2})$/; // mm dd
  matches = this._regexMatches(value, regex);
  if (matches.length === 2) {
    return [this._currentYear(), matches[0], matches[1]];
  }

  return [];
}

RomoDatepicker.prototype._regexMatches = function(value, regex) {
  if (regex.test(value) === true) {
    return regex.exec(value).slice(1);
  }
  return [];
}

RomoDatepicker.prototype._currentYear = function() {
  return (new Date).getUTCFullYear();
}

RomoDatepicker.prototype._UTCDate = function(year, month, day) {
  return new Date(Date.UTC.apply(Date, [year, month, day]));
}

Romo.onInitUI(function(e) {
  $(e.target).find('[data-romo-datepicker-auto="true"]').romoDatepicker();
});
<|endoftext|>


<commit_before>function createRequest(route) {
  $.post(route, function(data) {
    Materialize.toast(data.message, 4000, '', function() {
      if (data.refresh) {
        window.location.reload();
      }
    });
  }).fail(function(data) {
    Materialize.toast(data.responseJSON.message, 4000, '', function() {
      if (data.responseJSON.refresh) {
        window.location.reload();
      }
    });
  });
}

function createRequestFromForm(route, formSelector) {
  $.post(route, $(formSelector).serialize(),
    function(data) {
      Materialize.toast(data.message, 4000, '', function() {
        if (data.refresh) {
          window.location.reload();
        }
      });
    })
  .fail(function(data) {
    Materialize.toast(data.responseJSON.message, 4000, '', function() {
      if (data.responseJSON.refresh) {
        window.location.reload();
      }
    });
  });
}

function deleteModal() {
  $('#deleteConfirm').attr('onclick', 'deleteAccount(); return false;');
  $('#deleteModal').openModal();
}

function deleteAccount() {
  createRequest('/settings/account/delete');
}

function resetAvatar() {
  createRequest('/settings/profile/avatar/reset');
}

/**
 * Handle submissions
 */
$('#displayNameForm').submit(function(e) {
  createRequestFromForm('/settings/profile/display_name', '#displayNameForm');
  e.preventDefault();
});

$('#avatarForm').submit(function(e) {
  createRequestFromForm('/settings/profile/avatar', '#avatarForm');
  e.preventDefault();
});

$('#emailForm').submit(function(e) {
  createRequestFromForm('/settings/account/email', '#emailForm');
  e.preventDefault();
});

$('#passwordForm').submit(function(e) {
  createRequestFromForm('/settings/account/password', '#passwordForm');
  e.preventDefault();
});
<commit_msg>Refactor settingsActions.js<commit_after>function notify(data) {
  Materialize.toast(data.message, 4000, '', function() {
    if (data.refresh) {
      window.location.reload();
    }
  });
}

function createRequest(route) {
  $.post(route, function(data) {
    notify(data);
  }).fail(function(data) {
    notify(data.responseJSON);
  });
}

function createRequestFromForm(route, formSelector) {
  $.post(route, $(formSelector).serialize(), function(data) {
    notify(data);
  }).fail(function(data) {
    notify(data.responseJSON);
  });
}

function deleteModal() {
  $('#deleteConfirm').attr('onclick', 'deleteAccount(); return false;');
  $('#deleteModal').openModal();
}

function deleteAccount() {
  createRequest('/settings/account/delete');
}

function resetAvatar() {
  createRequest('/settings/profile/avatar/reset');
}

/**
 * Handle submissions
 */
$('#displayNameForm').submit(function(e) {
  createRequestFromForm('/settings/profile/display_name', '#displayNameForm');
  e.preventDefault();
});

$('#avatarForm').submit(function(e) {
  createRequestFromForm('/settings/profile/avatar', '#avatarForm');
  e.preventDefault();
});

$('#emailForm').submit(function(e) {
  createRequestFromForm('/settings/account/email', '#emailForm');
  e.preventDefault();
});

$('#passwordForm').submit(function(e) {
  createRequestFromForm('/settings/account/password', '#passwordForm');
  e.preventDefault();
});
<|endoftext|>


<commit_before>$(function() {
	$(document).on('click', '[data-microshare]', function(e){
		e.preventDefault();

		var shareScheme,
			shareService = $(this).attr('data-microshare').toLowerCase(),
			shareTitle = $(this).attr('data-microshare-title') || document.title,
			shareUrl = $(this).attr('data-microshare-url') || document.URL,
			shareMap = [{
					name: ['facebook', 'fb'],
					link: 'https://www.facebook.com/sharer/sharer.php?u='
				}, {
					name: ['twitter', 'tw'],
					link: 'https://twitter.com/home?status='
				}, {
					name: ['googleplus', 'gplus'],
					link: 'https://plus.google.com/share?url='
				}, {
					name: ['linkedin', 'in'],
					link: 'https://www.linkedin.com/shareArticle?mini=true&url='+shareUrl+'&title='+shareTitle+'&summary=&source='
				}];

			for(var x in shareMap) {
				if(shareMap[x].name.indexOf(shareService) > -1) {
					shareScheme = shareMap[x].link + shareUrl;
					break;
				}
			}

		window.open(shareScheme,'_blank','height=400, width=800');

	});
});
<commit_msg>Ajusta variáveis e separa função que abre pop-up<commit_after>$(function() {
  'use strict';

  var openPopup;

  openPopup = function(e) {
    e.preventDefault();

    var shareService,
      shareTitle,
      shareUrl,
      shareMap,
      shareScheme;

    shareService = $(this).attr('data-microshare').toLowerCase(),
    shareTitle = $(this).attr('data-microshare-title') || document.title,
    shareUrl = $(this).attr('data-microshare-url') || document.URL,

		shareMap = [{
      name: ['facebook', 'fb'],
      link: 'https://www.facebook.com/sharer/sharer.php?u='
    }, {
      name: ['twitter', 'tw'],
      link: 'https://twitter.com/home?status='
    }, {
      name: ['googleplus', 'gplus'],
      link: 'https://plus.google.com/share?url='
    }, {
      name: ['linkedin', 'in'],
      link: 'https://www.linkedin.com/shareArticle?mini=true&url=' + shareUrl + '&title=' + shareTitle + '&summary=&source='
    }];

    for (var x in shareMap) {
      if (shareMap[x].name.indexOf(shareService) > -1) {
        shareScheme = shareMap[x].link + shareUrl;
        break;
      }
    }

    window.open(shareScheme, '_blank', 'height=400, width=800');
  };

  $(document).on('click', '[data-microshare]', openPopup);
});
<|endoftext|>


<commit_before>
jQuery(document).ready(function() {
  // Add the 'less than IE9' class to appropriate version of IE by checking for their support of cssFloat (true in v9)
  if (!jQuery.support.cssFloat) { jQuery('html').addClass('lt-ie9').addClass('no-js'); }

  jQuery(document).foundation(function (response) {
    // console.log(response.errors); < this line will produce error in ie9!
    if (window.console) console.log(response.errors);
  });

  // The Echo extension puts an item in personal tools that Foreground really should have in the top menu
  // to make this easier, we move it here and loaded earlier to speed up transform
  jQuery("#pt-notifications").prependTo("#echo-notifications");

  // Append font-awesome icons
  jQuery('[id^=ca-nstab] a').prepend('  ')
  jQuery('li#ca-talk a').prepend('  ')
  jQuery('li#ca-edit a').prepend('  ')
  jQuery('li#ca-viewsource a').prepend('  ')
  jQuery('li#ca-form_edit a').prepend('  ')
  jQuery('li#ca-history a').prepend('  ')
  jQuery('li#ca-delete a').prepend('  ')
  jQuery('li#ca-move a').prepend('  ')
  jQuery('li#ca-protect a').prepend('  ')
  jQuery('li#ca-unprotect a').prepend('  ')
  jQuery('li#ca-watch a').prepend('  ')
  jQuery('li#ca-unwatch a').prepend('  ')
  jQuery('li#ca-purge a').prepend('  ')
  jQuery('li#ca-undelete a').prepend('  ')
  jQuery('li#ca-ask_delete_permanently a').prepend('  ')

if ( jQuery( '#ca-addsection' ).length ) {
  jQuery('li#ca-addsection a').html('  ' + jQuery('li#ca-addsection a').attr('title').replace(/\[.+/g,""))
}

  jQuery('li#pt-userpage a').prepend('  ')
  jQuery('li#pt-mytalk a').prepend('  ')
  jQuery('li#pt-adminlinks a').prepend('  ')
  jQuery('li#pt-preferences a').prepend('  ')
  jQuery('li#pt-watchlist a').prepend('  ')
  jQuery('li#pt-mycontris a').prepend('  ')
  jQuery('li#pt-logout a').prepend('  ')

  jQuery('li#t-smwbrowselink a').prepend('  ')
  jQuery('li#t-whatlinkshere a').prepend('  ')
  jQuery('li#t-blockip a').prepend('  ')
  jQuery('li#t-recentchangeslinked a').prepend('  ')
  jQuery('li#t-contributions a').prepend('  ')
  jQuery('li#t-log a').prepend('  ')
  jQuery('li#t-emailuser a').prepend('  ')
  jQuery('li#t-userrights a').prepend('  ')
  jQuery('li#t-upload a').prepend('  ')
  jQuery('li#t-specialpages a').prepend('  ')
  jQuery('li#t-print a').prepend('  ')
  jQuery('li#t-permalink a').prepend('  ')
  jQuery('li#t-info a').prepend('  ')

  jQuery('ul#toolbox-dropdown.dropdown>li#n-recentchanges a').prepend('  ')
  jQuery('ul#toolbox-dropdown.dropdown>li#n-help a').prepend('  ')

  // Turn categories into labels
  jQuery('#mw-normal-catlinks ul li a').addClass('label');

  // Make the Page Action button respond to hover
  jQuery('a.button.dropdown').mouseenter(function(){
    jQuery('ul#drop1').addClass('open').addClass('right').css('top', '32px').css('left', '785px');
  });
  jQuery('ul#drop1').mouseleave(function(){
    jQuery('ul#drop1').removeClass('open').css('top', '-9999px').css('left', '785px');
  });

});
<commit_msg>Close #98. Not sure why not aligned with everything else.<commit_after>
jQuery(document).ready(function() {
  // Add the 'less than IE9' class to appropriate version of IE by checking for their support of cssFloat (true in v9)
  if (!jQuery.support.cssFloat) { jQuery('html').addClass('lt-ie9').addClass('no-js'); }

  jQuery(document).foundation(function (response) {
    // console.log(response.errors); < this line will produce error in ie9!
    if (window.console) console.log(response.errors);
  });

  // The Echo extension puts an item in personal tools that Foreground really should have in the top menu
  // to make this easier, we move it here and loaded earlier to speed up transform
  jQuery("#pt-notifications").prependTo("#echo-notifications");

  // Append font-awesome icons
  jQuery('[id^=ca-nstab] a').prepend(' ')
  jQuery('li#ca-talk a').prepend(' ')
  jQuery('li#ca-edit a').prepend(' ')
  jQuery('li#ca-viewsource a').prepend(' ')
  jQuery('li#ca-form_edit a').prepend(' ')
  jQuery('li#ca-history a').prepend(' ')
  jQuery('li#ca-delete a').prepend(' ')
  jQuery('li#ca-move a').prepend(' ')
  jQuery('li#ca-protect a').prepend(' ')
  jQuery('li#ca-unprotect a').prepend(' ')
  jQuery('li#ca-watch a').prepend(' ')
  jQuery('li#ca-unwatch a').prepend(' ')
  jQuery('li#ca-purge a').prepend(' ')
  jQuery('li#ca-undelete a').prepend(' ')
  jQuery('li#ca-ask_delete_permanently a').prepend(' ')

if ( jQuery( '#ca-addsection' ).length ) {
  jQuery('li#ca-addsection a').html(' ' + jQuery('li#ca-addsection a').attr('title').replace(/\[.+/g,""))
}

  jQuery('li#pt-uls a').prepend(' ')
  jQuery('li#pt-userpage a').prepend(' ')
  jQuery('li#pt-mytalk a').prepend(' ')
  jQuery('li#pt-adminlinks a').prepend(' ')
  jQuery('li#pt-preferences a').prepend(' ')
  jQuery('li#pt-watchlist a').prepend(' ')
  jQuery('li#pt-mycontris a').prepend(' ')
  jQuery('li#pt-logout a').prepend(' ')

  jQuery('li#t-smwbrowselink a').prepend(' ')
  jQuery('li#t-whatlinkshere a').prepend(' ')
  jQuery('li#t-blockip a').prepend(' ')
  jQuery('li#t-recentchangeslinked a').prepend(' ')
  jQuery('li#t-contributions a').prepend(' ')
  jQuery('li#t-log a').prepend(' ')
  jQuery('li#t-emailuser a').prepend(' ')
  jQuery('li#t-userrights a').prepend(' ')
  jQuery('li#t-upload a').prepend(' ')
  jQuery('li#t-specialpages a').prepend(' ')
  jQuery('li#t-print a').prepend(' ')
  jQuery('li#t-permalink a').prepend(' ')
  jQuery('li#t-info a').prepend(' ')

  jQuery('ul#toolbox-dropdown.dropdown>li#n-recentchanges a').prepend(' ')
  jQuery('ul#toolbox-dropdown.dropdown>li#n-help a').prepend(' ')

  // Turn categories into labels
  jQuery('#mw-normal-catlinks ul li a').addClass('label');

  // Make the Page Action button respond to hover
  jQuery('a.button.dropdown').mouseenter(function(){
    jQuery('ul#drop1').addClass('open').addClass('right').css('top', '32px').css('left', '785px');
  });
  jQuery('ul#drop1').mouseleave(function(){
    jQuery('ul#drop1').removeClass('open').css('top', '-9999px').css('left', '785px');
  });

});
<|endoftext|>


<commit_before>import React from 'react';
import { Link } from '@patternfly/documentation-framework/components';
import { Card, CardBody, Grid, GridItem, PageSection, Split, SplitItem, Title } from '@patternfly/react-core';
import './community.css';
import { getTitle } from '@patternfly/documentation-framework/helpers/getTitle';
import communityPageHeader from './community-page-header.svg';
import community1 from './community-1.svg';
import community2 from './community-2.svg';
import community3 from './community-3.svg';
import ChatIcon from '@patternfly/react-icons/dist/esm/icons/chat-icon';
import QuestionIcon from '@patternfly/react-icons/dist/esm/icons/question-icon';
import CatalogIcon from '@patternfly/react-icons/dist/esm/icons/catalog-icon';
import MailBulkIcon from '@patternfly/react-icons/dist/esm/icons/mail-bulk-icon';
import TwitterIcon from '@patternfly/react-icons/dist/esm/icons/twitter-icon';
import CalendarIcon from '@patternfly/react-icons/dist/esm/icons/calendar-alt-icon';

const CommunityPage = () => {
  if (typeof document !== 'undefined') {
    document.title = getTitle('Community');
  }

  return (
    <PageSection className="ws-community-page pf-m-light-100">
      <Title size="4xl" className="pf-u-mb-lg ws-page-title" headingLevel="h1">Community</Title>

At the core of PatternFly is our community of people—in other words, our Flyers. Together, we celebrate creativity and foster a sense of teamwork and unity.

      <Grid sm={12} md={6} hasGutter className="pf-u-mt-3xl">
        <GridItem className="pf-u-pr-xl">

        </GridItem>
        <GridItem>
          <Title size="3xl" className="ws-title" headingLevel="h2">Who we are</Title>

We’re made of designers, developers, and other UX professionals with a passion for open source. We each have different ways of working with others and supporting the community—there’s no one way to be a Flyer. Whether we’re contributing to PatternFly or just staying up to date on new releases, we work together to make PatternFly a vibrant community of passionate people.

        </GridItem>
      </Grid>

      <Title size="3xl" className="pf-u-mb-sm ws-page-title pf-u-mt-3xl" headingLevel="h2">What we're building</Title>

Our work extends beyond products and apps. We’re always exploring new ways we can welcome ideas and build better experiences for the very people who make PatternFly what it is today.

      <Grid sm={12} md={4} hasGutter className="pf-u-my-lg pf-u-text-align-center ws-building-grid">
        <Card>
          <CardBody>

            <Title size="xl" className="ws-title" headingLevel="h3">Building global connections</Title>

              Flyers may be spread all over the globe, but we make sure to come together once a month to share updates and collect feedback. All meetings are recorded and published on PatternFly’s YouTube channel, and you can join PatternFly’s mailing list for the invites.

            <Title size="xl" className="ws-title" headingLevel="h3">
              Join our mailing list
            </Title>
          </CardBody>
        </Card>
        <Card>
          <CardBody>

            <Title size="xl" className="ws-title" headingLevel="h3">Building PatternFly roadmaps</Title>

              To stay on top of all changes and keep everyone informed, we regularly update PatternFly roadmaps. This gives us an opportunity to share what Flyers are working on and what updates we’re planning.

            <Title size="xl" className="ws-title" headingLevel="h3">
              Explore PatternFly roadmaps
            </Title>
          </CardBody>
        </Card>
        <Card>
          <CardBody>

            <Title size="xl" className="ws-title" headingLevel="h3">Building accessible experiences</Title>

              A community isn’t really a community unless everyone is included, so accessible UX is important to us. We regularly test and audit PatternFly’s accessibility and share guidance whenever we can.

            <Title size="xl" className="ws-title" headingLevel="h3">
              <Link to="/accessibility/accessibility-fundamentals">
                Read our accessibility guide
              </Link>
            </Title>
          </CardBody>
        </Card>
      </Grid>

      <Title size="3xl" className="pf-u-mb-sm ws-page-title pf-u-mt-3xl" headingLevel="h2">Creating new communities</Title>

Sometimes Flyers branch out and build groups of their own, which is how new communities are born. While PatternFly communities are separate from PatternFly and not supported as part of the design system, we still love seeing our Flyers forming new groups and developing their visions into actions.

      <Title size="xl" className="pf-u-mb-sm ws-page-title pf-u-mt-xl" headingLevel="h3">PatternFly Elements</Title>

 PatternFly Elements is a community created by Red Hat's web-based developers. It focuses on creating web components for use across Red Hat's sites and SaaS products and features theming options available for your own brand library.

      <Title size="xl" className="pf-u-mb-sm ws-page-title pf-u-mt-xl" headingLevel="h3">PatternFly Kotlin</Title>

PatternFly Kotlin is a Kotlin implementation of PatternFly based on fritz2, targeting Kotlin/JS. The goal of this project is to provide all PatternFly components in Kotlin, matching the reactive nature of fritz2. The components use stores, handlers, and other elements from the fritz2 API. For a quick overview, check out the PatternFly Kotlin showcase.

      <Title size="4xl" className="pf-u-mb-lg ws-page-title ws-keep-growing pf-u-mt-3xl" headingLevel="h2">Let's keep growing</Title>

The PatternFly community is never finished growing, and we want to keep it that way. Feel free to reach out whenever — we’re always open.

      <Grid sm={12} md={6} gutter="sm" className="pf-u-my-lg pf-l-grid pf-m-all-12-col-on-sm pf-m-all-6-col-on-md pf-m-gutter" style={{ maxWidth: '450px' }}>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><ChatIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Chat with us</Title>
              Slack
            </SplitItem>
          </Split>
        </GridItem>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><MailBulkIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Stay in the loop</Title>
              PatternFly mailing list
            </SplitItem>
          </Split>
        </GridItem>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><QuestionIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Ask a question</Title>
              PatternFly forum
            </SplitItem>
          </Split>
        </GridItem>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><CatalogIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Read the latest</Title>
              PatternFly Medium
            </SplitItem>
          </Split>
        </GridItem>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><TwitterIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Send us a Tweet</Title>
              PatternFly Twitter
            </SplitItem>
          </Split>
        </GridItem>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><CalendarIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Attend office hours</Title>
              PatternFly calendar
            </SplitItem>
          </Split>
        </GridItem>
      </Grid>
    </PageSection>
  )
};

export default CommunityPage;
<commit_msg>Add Ansible design library as a community project (#3168)<commit_after>import React from 'react';
import { Link } from '@patternfly/documentation-framework/components';
import { Card, CardBody, Grid, GridItem, PageSection, Split, SplitItem, Title } from '@patternfly/react-core';
import './community.css';
import { getTitle } from '@patternfly/documentation-framework/helpers/getTitle';
import communityPageHeader from './community-page-header.svg';
import community1 from './community-1.svg';
import community2 from './community-2.svg';
import community3 from './community-3.svg';
import ChatIcon from '@patternfly/react-icons/dist/esm/icons/chat-icon';
import QuestionIcon from '@patternfly/react-icons/dist/esm/icons/question-icon';
import CatalogIcon from '@patternfly/react-icons/dist/esm/icons/catalog-icon';
import MailBulkIcon from '@patternfly/react-icons/dist/esm/icons/mail-bulk-icon';
import TwitterIcon from '@patternfly/react-icons/dist/esm/icons/twitter-icon';
import CalendarIcon from '@patternfly/react-icons/dist/esm/icons/calendar-alt-icon';

const CommunityPage = () => {
  if (typeof document !== 'undefined') {
    document.title = getTitle('Community');
  }

  return (
    <PageSection className="ws-community-page pf-m-light-100">
      <Title size="4xl" className="pf-u-mb-lg ws-page-title" headingLevel="h1">Community</Title>

At the core of PatternFly is our community of people—in other words, our Flyers. Together, we celebrate creativity and foster a sense of teamwork and unity.

      <Grid sm={12} md={6} hasGutter className="pf-u-mt-3xl">
        <GridItem className="pf-u-pr-xl">

        </GridItem>
        <GridItem>
          <Title size="3xl" className="ws-title" headingLevel="h2">Who we are</Title>

We’re made of designers, developers, and other UX professionals with a passion for open source. We each have different ways of working with others and supporting the community—there’s no one way to be a Flyer. Whether we’re contributing to PatternFly or just staying up to date on new releases, we work together to make PatternFly a vibrant community of passionate people.

        </GridItem>
      </Grid>

      <Title size="3xl" className="pf-u-mb-sm ws-page-title pf-u-mt-3xl" headingLevel="h2">What we're building</Title>

Our work extends beyond products and apps. We’re always exploring new ways we can welcome ideas and build better experiences for the very people who make PatternFly what it is today.

      <Grid sm={12} md={4} hasGutter className="pf-u-my-lg pf-u-text-align-center ws-building-grid">
        <Card>
          <CardBody>

            <Title size="xl" className="ws-title" headingLevel="h3">Building global connections</Title>

              Flyers may be spread all over the globe, but we make sure to come together once a month to share updates and collect feedback. All meetings are recorded and published on PatternFly’s YouTube channel, and you can join PatternFly’s mailing list for the invites.

            <Title size="xl" className="ws-title" headingLevel="h3">
              Join our mailing list
            </Title>
          </CardBody>
        </Card>
        <Card>
          <CardBody>

            <Title size="xl" className="ws-title" headingLevel="h3">Building PatternFly roadmaps</Title>

              To stay on top of all changes and keep everyone informed, we regularly update PatternFly roadmaps. This gives us an opportunity to share what Flyers are working on and what updates we’re planning.

            <Title size="xl" className="ws-title" headingLevel="h3">
              Explore PatternFly roadmaps
            </Title>
          </CardBody>
        </Card>
        <Card>
          <CardBody>

            <Title size="xl" className="ws-title" headingLevel="h3">Building accessible experiences</Title>

              A community isn’t really a community unless everyone is included, so accessible UX is important to us. We regularly test and audit PatternFly’s accessibility and share guidance whenever we can.

            <Title size="xl" className="ws-title" headingLevel="h3">
              <Link to="/accessibility/accessibility-fundamentals">
                Read our accessibility guide
              </Link>
            </Title>
          </CardBody>
        </Card>
      </Grid>

      <Title size="3xl" className="pf-u-mb-sm ws-page-title pf-u-mt-3xl" headingLevel="h2">Creating new communities</Title>

Sometimes Flyers branch out and build groups of their own, which is how new communities are born. While PatternFly communities are separate from PatternFly and not supported as part of the design system, we still love seeing our Flyers forming new groups and developing their visions into actions.

      <Title size="xl" className="pf-u-mb-sm ws-page-title pf-u-mt-xl" headingLevel="h3">PatternFly Elements</Title>

 PatternFly Elements is a community created by Red Hat's web-based developers. It focuses on creating web components for use across Red Hat's sites and SaaS products and features theming options available for your own brand library.

      <Title size="xl" className="pf-u-mb-sm ws-page-title pf-u-mt-xl" headingLevel="h3">PatternFly Kotlin</Title>

PatternFly Kotlin is a Kotlin implementation of PatternFly based on fritz2, targeting Kotlin/JS. The goal of this project is to provide all PatternFly components in Kotlin, matching the reactive nature of fritz2. The components use stores, handlers, and other elements from the fritz2 API. For a quick overview, check out the PatternFly Kotlin showcase.

      <Title size="xl" className="pf-u-mb-sm ws-page-title pf-u-mt-xl" headingLevel="h3">Ansible Component Guide and Sketch Library</Title>

The Ansible Component Guide and Sketch Library is an additional resource that designers can use that is built on top of existing PatternFly components. It is a rapid mockup prototyping tool that can be used to quickly put together repeatable design patterns and layouts across projects. Although this is specific to Ansible, many of the components are generalized and can fit many product use cases and are easily detachable to update as needed.

      <Title size="4xl" className="pf-u-mb-lg ws-page-title ws-keep-growing pf-u-mt-3xl" headingLevel="h2">Let's keep growing</Title>

The PatternFly community is never finished growing, and we want to keep it that way. Feel free to reach out whenever — we’re always open.

      <Grid sm={12} md={6} gutter="sm" className="pf-u-my-lg pf-l-grid pf-m-all-12-col-on-sm pf-m-all-6-col-on-md pf-m-gutter" style={{ maxWidth: '450px' }}>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><ChatIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Chat with us</Title>
              Slack
            </SplitItem>
          </Split>
        </GridItem>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><MailBulkIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Stay in the loop</Title>
              PatternFly mailing list
            </SplitItem>
          </Split>
        </GridItem>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><QuestionIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Ask a question</Title>
              PatternFly forum
            </SplitItem>
          </Split>
        </GridItem>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><CatalogIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Read the latest</Title>
              PatternFly Medium
            </SplitItem>
          </Split>
        </GridItem>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><TwitterIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Send us a Tweet</Title>
              PatternFly Twitter
            </SplitItem>
          </Split>
        </GridItem>
        <GridItem>
          <Split>
            <SplitItem style={{ marginRight: '12px' }}><CalendarIcon /></SplitItem>
            <SplitItem isFilled>
              <Title size="lg" className="ws-title" headingLevel="h3">Attend office hours</Title>
              PatternFly calendar
            </SplitItem>
          </Split>
        </GridItem>
      </Grid>
    </PageSection>
  )
};

export default CommunityPage;
<|endoftext|>


<commit_before>(function(oCanvas, window, document, undefined){

	// Define the class
	var background = function () {

		// Return an object when instantiated
		return {

			// Set properties
			bg: "",
			type: "transparent",
			loaded: false,

			init: function () {
				this.set(this.core.settings.background);
			},

			// Method for setting the background
			set: function (value) {
				var _this = this;

				// Get background type (gradient, image, color or transparent)
				if (~value.indexOf("gradient")) {
					this.type = "gradient";
				} else if (~value.indexOf("image")) {
					this.type = "image";
				} else if (this.core.style && this.core.style.isColor(value)) {
					this.type = "color";
				} else {
					this.type = "transparent";
				}

				// Handle the different background types
				if (this.type === "color") {

					// Set color as background
					this.bg = value;
					if (this.core.timeline && !this.core.timeline.running) {
						this.core.draw.redraw();
					}
					this.loaded = true;
				}
				else if (this.type === "gradient") {

					// Get gradient object and set it as background
					this.bg = this.core.style ? this.core.style.getGradient(value, 0, 0, this.core.width, this.core.height) : "";
					if (this.core.timeline && !this.core.timeline.running) {
						this.core.draw.redraw();
					}
					this.loaded = true;
				}
				else if (this.type === "image") {

					// Parse image string
					var matches = /image\((.*?)(,(\s|)(repeat|repeat-x|repeat-y|no-repeat)|)\)/.exec(value),
						path = matches[1],
						repeat = matches[4] || "repeat",
						image = new Image();

					// Set image as background
					image.src = path;
					image.onload = function () {
						_this.bg = _this.core.canvas.createPattern(this, repeat);
						_this.loaded = true;
						if (_this.core.timeline && !_this.core.timeline.running) {
							_this.core.redraw();
						}
					};
				}

				else {
					// Background type is transparent, redraw the background (clears the canvas)
					this.redraw();
					this.loaded = true;
				}
			},

			// Method for getting the background data
			get: function () {
				return {
					type: this.type,
					value: this.bg
				};
			},

			// Method for redrawing the background (replaces everything thas has been drawn)
			redraw: function (trigger) {
				var core = this.core;

				// Fill canvas with the background color if it's not transparent
				if (this.type !== "transparent") {
					core.canvas.fillStyle = this.bg;
					core.canvas.fillRect(0, 0, core.width, core.height);
				}

				// Only clear the canvas if no background is specified
				else {
					core.canvas.clearRect(0, 0, core.width, core.height);
				}
			}
		};
	};

	// Register the module
	oCanvas.registerModule("background", background, "init");

})(oCanvas, window, document);<commit_msg>Defined a return value for the set() method in the background module.<commit_after>(function(oCanvas, window, document, undefined){

	// Define the class
	var background = function () {

		// Return an object when instantiated
		return {

			// Set properties
			bg: "",
			type: "transparent",
			loaded: false,

			init: function () {
				this.set(this.core.settings.background);
			},

			// Method for setting the background
			set: function (value) {
				var _this = this;

				// Get background type (gradient, image, color or transparent)
				if (~value.indexOf("gradient")) {
					this.type = "gradient";
				} else if (~value.indexOf("image")) {
					this.type = "image";
				} else if (this.core.style && this.core.style.isColor(value)) {
					this.type = "color";
				} else {
					this.type = "transparent";
				}

				// Handle the different background types
				if (this.type === "color") {

					// Set color as background
					this.bg = value;
					if (this.core.timeline && !this.core.timeline.running) {
						this.core.draw.redraw();
					}
					this.loaded = true;
				}
				else if (this.type === "gradient") {

					// Get gradient object and set it as background
					this.bg = this.core.style ? this.core.style.getGradient(value, 0, 0, this.core.width, this.core.height) : "";
					if (this.core.timeline && !this.core.timeline.running) {
						this.core.draw.redraw();
					}
					this.loaded = true;
				}
				else if (this.type === "image") {

					// Parse image string
					var matches = /image\((.*?)(,(\s|)(repeat|repeat-x|repeat-y|no-repeat)|)\)/.exec(value),
						path = matches[1],
						repeat = matches[4] || "repeat",
						image = new Image();

					// Set image as background
					image.src = path;
					image.onload = function () {
						_this.bg = _this.core.canvas.createPattern(this, repeat);
						_this.loaded = true;
						if (_this.core.timeline && !_this.core.timeline.running) {
							_this.core.redraw();
						}
					};
				}

				else {
					// Background type is transparent, redraw the background (clears the canvas)
					this.redraw();
					this.loaded = true;
				}

				return this;
			},

			// Method for getting the background data
			get: function () {
				return {
					type: this.type,
					value: this.bg
				};
			},

			// Method for redrawing the background (replaces everything thas has been drawn)
			redraw: function (trigger) {
				var core = this.core;

				// Fill canvas with the background color if it's not transparent
				if (this.type !== "transparent") {
					core.canvas.fillStyle = this.bg;
					core.canvas.fillRect(0, 0, core.width, core.height);
				}

				// Only clear the canvas if no background is specified
				else {
					core.canvas.clearRect(0, 0, core.width, core.height);
				}
			}
		};
	};

	// Register the module
	oCanvas.registerModule("background", background, "init");

})(oCanvas, window, document);<|endoftext|>


<commit_before>const faker = require('faker')
const { assign } = require('lodash')

const {
  getSelectorForElementWithText,
  getKeyValueTableRowValueCell,
  getMetaListItemValueSelector,
} = require('../../helpers/selectors')
const { appendUid, getUid } = require('../../helpers/uuid')
const { getAddress } = require('../../helpers/address')

const getCheckBoxLabel = (text) => getSelectorForElementWithText(
  text,
  {
    el: '//span',
    className: 'c-multiple-choice__label-text',
  }
)

module.exports = {
  url: process.env.QA_HOST,
  props: {},
  elements: {
    firstCompanyFromList: '.c-entity-list li:first-child h3 a',
    firstName: '#field-first_name',
    firstNameError: 'label[for=field-first_name] span:nth-child(2)',
    lastName: '#field-last_name',
    lastNameError: 'label[for=field-last_name] span:nth-child(2)',
    jobTitle: '#field-job_title',
    primaryContactYes: '[for="field-primary-1"]',
    primaryContactNo: '[for="field-primary-2"]',
    primaryContactError: '#group-field-primary > .c-form-group__error-message',
    telephoneCountryCode: '#field-telephone_countrycode',
    telephoneCountryCodeError: 'label[for=field-telephone_countrycode] span:nth-child(2)',
    telephoneNumber: '#field-telephone_number',
    emailAddress: '#field-email',
    emailAddressError: 'label[for=field-email] span:nth-child(2)',
    acceptsEmailMarketingFromDit: getCheckBoxLabel('Accepts email marketing from DIT'),
    sameAddressAsCompanyYes: '[for="field-address_same_as_company-1"]',
    sameAddressAsCompanyNo: '[for="field-address_same_as_company-2"]',
    alternativePhoneNumber: '#field-telephone_alternative',
    alternativeEmail: '#field-email_alternative',
    notes: '#field-notes',
  },

  commands: [
    {
      clickOnFirstCompanyFromList () {
        return this
          .click('@firstCompanyFromList')
      },

      createNewContact (details = {}, isPrimary, callback) {
        const firstName = faker.name.firstName()
        const lastName = appendUid(faker.name.lastName())

        const contact = assign({}, {
          firstName,
          lastName,
          jobTitle: faker.name.jobTitle(),
          telephoneCountryCode: faker.random.number(),
          telephoneNumber: faker.phone.phoneNumberFormat(),
          emailAddress: faker.internet.email(firstName, lastName),
          alternativePhoneNumber: '666555444',
          alternativeEmail: faker.internet.email(lastName, firstName),
          notes: `${faker.name.jobDescriptor() + firstName}`,
        }, details)

        return this
          .waitForElementPresent('@primaryContactYes')
          .api.perform((done) => {
            this.click(`@primaryContact${isPrimary ? 'Yes' : 'No'}`)

            for (const key in contact) {
              if (contact[key]) {
                this.setValue(`@${key}`, contact[key])
              }
            }

            contact.heading = `${contact.firstName} ${contact.lastName}`

            done()
          })
          .perform(() => {
            this
              .click('@acceptsEmailMarketingFromDit')
              .click('@sameAddressAsCompanyYes')

            callback(assign({}, contact, {
              acceptsEmailMarketingFromDit: 'Yes',
              primaryPhoneNumber: `(${contact.telephoneCountryCode}) ${contact.telephoneNumber}`,
              uniqueSearchTerm: getUid(contact.lastName),
            }))
          })
      },

      createNewPrimaryContactWithNewCompanyAddress (details = {}, callback) {
        const firstName = faker.name.firstName()
        const lastName = appendUid(faker.name.lastName())
        const contact = assign({}, {
          firstName,
          lastName,
          jobTitle: faker.name.jobTitle(),
          telephoneCountryCode: faker.random.number(),
          telephoneNumber: faker.phone.phoneNumberFormat(),
          emailAddress: faker.internet.email(firstName, lastName),
          alternativePhoneNumber: '666555444',
          alternativeEmail: faker.internet.email(lastName, firstName),
          notes: `${faker.name.jobDescriptor() + firstName}`,
        }, details)
        const postcodeLookup = {
          address1: 'postCodeLookupAddress1',
          address2: 'postCodeLookupAddress2',
          town: 'postCodeLookupTown',
          county: 'postCodeLookupCounty',
          country: 'postCodeLookupCountry',
          postcode: 'postCode',
        }

        this.api.page.location().section.localHeader
          .waitForElementPresent('@header')

        // setup form to use the postCode lookup functionality
        this
          .click('@primaryContactYes')
          .click('@sameAddressAsCompanyNo')
          .api.perform((done) => {
            for (const key in contact) {
              if (contact[key]) {
                this.setValue(`@${key}`, contact[key])
              }
            }
            done()
          })

        return this.api
          .perform((done) => {
            this.api
              .page.address()
              .getAddressInputValues('EC2Y 9AE', postcodeLookup, '@postCodeLookupSuggestions', (addressInputValues) => {
                callback(assign({}, {
                  acceptsEmailMarketingFromDit: 'No',
                  type: 'Primary',
                  primaryPhoneNumber: `(${contact.telephoneCountryCode}) ${contact.telephoneNumber}`,
                  address: getAddress(addressInputValues),
                  uniqueSearchTerm: getUid(contact.lastName),
                }, addressInputValues, contact))
                done()
              })
          })
      },
    },
  ],
  sections: {
    firstContactSearchResult: {
      selector: '.c-entity-list li:first-child',
      elements: {
        header: {
          selector: 'a',
        },
        company: getMetaListItemValueSelector('Company'),
        sector: getMetaListItemValueSelector('Sector'),
      },
    },
    contactDetails: {
      selector: '.table--key-value',
      elements: {
        jobTitle: getKeyValueTableRowValueCell('Job title'),
        phoneNumber: getKeyValueTableRowValueCell('Phone number'),
        email: getKeyValueTableRowValueCell('Email'),
        emailMarketing: getKeyValueTableRowValueCell('Email marketing'),
        address: getKeyValueTableRowValueCell('Address'),
        alternativeTelephone: getKeyValueTableRowValueCell('Alternative telephone'),
        alternativeEmail: getKeyValueTableRowValueCell('Alternative email'),
        notes: getKeyValueTableRowValueCell('Notes'),
      },
    },
  },
}
<commit_msg>Change acceptance tests to match new email prefs<commit_after>const faker = require('faker')
const { assign } = require('lodash')

const {
  getSelectorForElementWithText,
  getKeyValueTableRowValueCell,
  getMetaListItemValueSelector,
} = require('../../helpers/selectors')
const { appendUid, getUid } = require('../../helpers/uuid')
const { getAddress } = require('../../helpers/address')

const getCheckBoxLabel = (text) => getSelectorForElementWithText(
  text,
  {
    el: '//span',
    className: 'c-multiple-choice__label-text',
  }
)

module.exports = {
  url: process.env.QA_HOST,
  props: {},
  elements: {
    firstCompanyFromList: '.c-entity-list li:first-child h3 a',
    firstName: '#field-first_name',
    firstNameError: 'label[for=field-first_name] span:nth-child(2)',
    lastName: '#field-last_name',
    lastNameError: 'label[for=field-last_name] span:nth-child(2)',
    jobTitle: '#field-job_title',
    primaryContactYes: '[for="field-primary-1"]',
    primaryContactNo: '[for="field-primary-2"]',
    primaryContactError: '#group-field-primary > .c-form-group__error-message',
    telephoneCountryCode: '#field-telephone_countrycode',
    telephoneCountryCodeError: 'label[for=field-telephone_countrycode] span:nth-child(2)',
    telephoneNumber: '#field-telephone_number',
    emailAddress: '#field-email',
    emailAddressError: 'label[for=field-email] span:nth-child(2)',
    acceptsEmailMarketingFromDit: getCheckBoxLabel('Does not accept email marketing'),
    sameAddressAsCompanyYes: '[for="field-address_same_as_company-1"]',
    sameAddressAsCompanyNo: '[for="field-address_same_as_company-2"]',
    alternativePhoneNumber: '#field-telephone_alternative',
    alternativeEmail: '#field-email_alternative',
    notes: '#field-notes',
  },

  commands: [
    {
      clickOnFirstCompanyFromList () {
        return this
          .click('@firstCompanyFromList')
      },

      createNewContact (details = {}, isPrimary, callback) {
        const firstName = faker.name.firstName()
        const lastName = appendUid(faker.name.lastName())

        const contact = assign({}, {
          firstName,
          lastName,
          jobTitle: faker.name.jobTitle(),
          telephoneCountryCode: faker.random.number(),
          telephoneNumber: faker.phone.phoneNumberFormat(),
          emailAddress: faker.internet.email(firstName, lastName),
          alternativePhoneNumber: '666555444',
          alternativeEmail: faker.internet.email(lastName, firstName),
          notes: `${faker.name.jobDescriptor() + firstName}`,
        }, details)

        return this
          .waitForElementPresent('@primaryContactYes')
          .api.perform((done) => {
            this.click(`@primaryContact${isPrimary ? 'Yes' : 'No'}`)

            for (const key in contact) {
              if (contact[key]) {
                this.setValue(`@${key}`, contact[key])
              }
            }

            contact.heading = `${contact.firstName} ${contact.lastName}`

            done()
          })
          .perform(() => {
            this
              .click('@sameAddressAsCompanyYes')

            callback(assign({}, contact, {
              acceptsEmailMarketingFromDit: 'Can be marketed to',
              primaryPhoneNumber: `(${contact.telephoneCountryCode}) ${contact.telephoneNumber}`,
              uniqueSearchTerm: getUid(contact.lastName),
            }))
          })
      },

      createNewPrimaryContactWithNewCompanyAddress (details = {}, callback) {
        const firstName = faker.name.firstName()
        const lastName = appendUid(faker.name.lastName())
        const contact = assign({}, {
          firstName,
          lastName,
          jobTitle: faker.name.jobTitle(),
          telephoneCountryCode: faker.random.number(),
          telephoneNumber: faker.phone.phoneNumberFormat(),
          emailAddress: faker.internet.email(firstName, lastName),
          alternativePhoneNumber: '666555444',
          alternativeEmail: faker.internet.email(lastName, firstName),
          notes: `${faker.name.jobDescriptor() + firstName}`,
        }, details)
        const postcodeLookup = {
          address1: 'postCodeLookupAddress1',
          address2: 'postCodeLookupAddress2',
          town: 'postCodeLookupTown',
          county: 'postCodeLookupCounty',
          country: 'postCodeLookupCountry',
          postcode: 'postCode',
        }

        this.api.page.location().section.localHeader
          .waitForElementPresent('@header')

        // setup form to use the postCode lookup functionality
        this
          .click('@primaryContactYes')
          .click('@sameAddressAsCompanyNo')
          .api.perform((done) => {
            for (const key in contact) {
              if (contact[key]) {
                this.setValue(`@${key}`, contact[key])
              }
            }
            done()
          })

        return this.api
          .perform((done) => {
            this.api
              .page.address()
              .getAddressInputValues('EC2Y 9AE', postcodeLookup, '@postCodeLookupSuggestions', (addressInputValues) => {
                callback(assign({}, {
                  acceptsEmailMarketingFromDit: 'Can be marketed to',
                  type: 'Primary',
                  primaryPhoneNumber: `(${contact.telephoneCountryCode}) ${contact.telephoneNumber}`,
                  address: getAddress(addressInputValues),
                  uniqueSearchTerm: getUid(contact.lastName),
                }, addressInputValues, contact))
                done()
              })
          })
      },
    },
  ],
  sections: {
    firstContactSearchResult: {
      selector: '.c-entity-list li:first-child',
      elements: {
        header: {
          selector: 'a',
        },
        company: getMetaListItemValueSelector('Company'),
        sector: getMetaListItemValueSelector('Sector'),
      },
    },
    contactDetails: {
      selector: '.table--key-value',
      elements: {
        jobTitle: getKeyValueTableRowValueCell('Job title'),
        phoneNumber: getKeyValueTableRowValueCell('Phone number'),
        email: getKeyValueTableRowValueCell('Email'),
        emailMarketing: getKeyValueTableRowValueCell('Email marketing'),
        address: getKeyValueTableRowValueCell('Address'),
        alternativeTelephone: getKeyValueTableRowValueCell('Alternative telephone'),
        alternativeEmail: getKeyValueTableRowValueCell('Alternative email'),
        notes: getKeyValueTableRowValueCell('Notes'),
      },
    },
  },
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Jonas Devlieghere

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

var is = new Installer();
var dm = new DownloadManager();
var nf = new Notifier();
var rd = new RealDebrid();

$(document).ready(function() {
    // Run Installer
    is.run();

    // Add to Context Menu
    chrome.contextMenus.create({
        "title": "Download with Real-Debrid",
        "contexts": ["page", "link", "selection"],
        "onclick": function(info) {
            console.log(info);
            if (typeof info.selectionText !== "undefined") {
                rd.selectionHandler(info.selectionText);
            } else if (typeof info.linkUrl !== "undefined") {
                rd.urlHandler(info.linkUrl);
            }else{
                rd.urlHandler(info.pageUrl);
            }
        }
    });

    // Register Handlers
    chrome.downloads.onChanged.addListener(dm.changeHandler);
    chrome.notifications.onClicked.addListener(nf.clickHandler);
});

/* RealDebrid */
function RealDebrid() {

    var that = this;

    this.selectionHandler = function(selection) {
        var urls = selection.split(" ");
        var regex = new RegExp(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/);
        $.each(urls, function(index, url) {
            if (url.match(regex)) {
                that.urlHandler(url);
            }
        });
    };

    this.urlHandler = function(url) {
        that.unrestrict(url, function(result) {
            if (!result.error) {
                that.download(result);
            } else if (result.error == 1) {
                nf.error("Please make sure you are logged in. Click here to go to real-debrid.com", function() {
                    chrome.tabs.create({
                        url: 'https://real-debrid.com'
                    }, function() {});
                });
            } else {
                nf.basic(result.message, url);
            }
        });
    };

    this.download = function(data) {
        var downloadUrl = data.generated_links[0][2];
        dm.download(downloadUrl);
    };

    this.api = function(url, callback) {
        $.ajax({
            type: "GET",
            url: url,
            dataType: 'json',
            data: {},
            crossDomain: true,
            xhrFields: {
                withCredentials: true
            },
            success: callback,
            error: function() {
                nf.error("Could not reach real-debrid.com");
            }
        });
    };

    this.unrestrict = function(url, callback) {
        var apiUrl = 'https://real-debrid.com/ajax/unrestrict.php?link=' + url;
        that.api(apiUrl, callback);
    };

    this.account = function(callback) {
        var apiUrl = 'https://real-debrid.com/api/account.php?out=json';
        that.api(apiUrl, callback);
    };
}

/* Notifier */
function Notifier() {

    var notificationId = 0;
    var callbacks = {};
    var that = this;

    this.basic = function(title, text, onClicked) {
        var id = ++notificationId;
        var options = {
            iconUrl: "/icons/icon-128.png",
            type: "basic",
            title: title,
            message: text,
            priority: 1
        };
        chrome.notifications.create("id_" + id, options, function(notificationId) {
            if (onClicked) {
                callbacks[notificationId] = onClicked;
            }
        });
    };

    this.error = function(text, callback) {
        that.basic("Error", text, callback);
    };

    this.info = function(text, callback) {
        that.basic("Real-Debrid", text, callback);
    };

    this.clickHandler = function(notificationId) {
        if (callbacks[notificationId]) {
            callbacks[notificationId]();
            delete callbacks[notificationId];
        }
    };
}

/* Installer */
function Installer() {

    var that = this;

    this.onInstall = function() {
        nf.info("Extension installed");
    };

    this.onUpdate = function() {
        var message = "Extension updated to version " + that.getVersion() + ". Click here to see all changes.";
        nf.info(message, function() {
            chrome.tabs.create({
                url: 'https://github.com/JDevlieghere/Real-Debrid/blob/master/CHANGELOG.md'
            }, function() {});
        });
    };

    this.getVersion = function() {
        var details = chrome.app.getDetails();
        return details.version;
    };

    this.run = function() {
        var currVersion = that.getVersion();
        var prevVersion = localStorage['version'];
        if (currVersion != prevVersion) {
            if (typeof prevVersion == 'undefined') {
                that.onInstall();
            } else {
                that.onUpdate();
            }
            localStorage['version'] = currVersion;
        }
    };
}

/* Download Manager */
function DownloadManager() {

    var active = [];
    var that = this;

    this.download = function(url) {
        chrome.downloads.download({
            url: url
        }, function(downloadId) {
            that.addActive(downloadId);
        });
    };

    this.checkComplete = function() {
        if (active.length === 0) {
            nf.info("All download complete");
        }
    };

    this.addActive = function(id) {
        active.push(downloadId);
    };

    this.removeActive = function(id) {
        var index = active.indexOf(id);
        active.splice(index, 1);
    };

    this.changeHandler = function(downloadItemDelta) {
        if (active.indexOf(downloadItemDelta.id) > -1 && downloadItemDelta.state) {
            if (downloadItemDelta.state.current == "complete") {
                that.checkComplete();
                that.removeActive(downloadItemDelta.id);
            } else if (downloadItemDelta.state.current == "interrupted") {
                that.removeActive(downloadItemDelta.id);
            }
        }
    };
}
<commit_msg>Added messaging<commit_after>/*
Copyright 2014 Jonas Devlieghere

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

var is = new Installer();
var dm = new DownloadManager();
var nf = new Notifier();
var rd = new RealDebrid();

$(document).ready(function() {
    // Run Installer
    is.run();

    // Add to Context Menu
    chrome.contextMenus.create({
        "title": "Download with Real-Debrid",
        "contexts": ["page", "link", "selection"],
        "onclick": function(info) {
            console.log(info);
            if (typeof info.selectionText !== "undefined") {
                rd.selectionHandler(info.selectionText);
            } else if (typeof info.linkUrl !== "undefined") {
                rd.urlHandler(info.linkUrl);
            } else {
                rd.urlHandler(info.pageUrl);
            }
        }
    });

    // Register Handlers
    chrome.downloads.onChanged.addListener(dm.changeHandler);
    chrome.notifications.onClicked.addListener(nf.clickHandler);
});

/* RealDebrid */
function RealDebrid() {

    var that = this;

    this.selectionHandler = function(selection) {
        var urls = selection.split(" ");
        var regex = new RegExp(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/);
        $.each(urls, function(index, url) {
            if (url.match(regex)) {
                that.urlHandler(url);
            }
        });
    };

    this.urlHandler = function(url) {
        that.unrestrict(url, function(result) {
            if (!result.error) {
                that.download(result);
            } else if (result.error == 1) {
                nf.error("Please make sure you are logged in. Click here to go to real-debrid.com", function() {
                    chrome.tabs.create({
                        url: 'https://real-debrid.com'
                    }, function() {});
                });
            } else {
                nf.basic(result.message, url);
            }
        });
    };

    this.download = function(data) {
        var downloadUrl = data.generated_links[0][2];
        dm.download(downloadUrl);
    };

    this.api = function(url, callback) {
        $.ajax({
            type: "GET",
            url: url,
            dataType: 'json',
            data: {},
            crossDomain: true,
            xhrFields: {
                withCredentials: true
            },
            success: callback,
            error: function() {
                nf.error("Could not reach real-debrid.com");
            }
        });
    };

    this.unrestrict = function(url, callback) {
        var apiUrl = 'https://real-debrid.com/ajax/unrestrict.php?link=' + url;
        that.api(apiUrl, callback);
    };

    this.account = function(callback) {
        var apiUrl = 'https://real-debrid.com/api/account.php?out=json';
        that.api(apiUrl, callback);
    };
}

/* Notifier */
function Notifier() {

    var notificationId = 0;
    var callbacks = {};
    var that = this;

    this.basic = function(title, text, onClicked) {
        var id = ++notificationId;
        var options = {
            iconUrl: "/icons/icon-128.png",
            type: "basic",
            title: title,
            message: text,
            priority: 1
        };
        chrome.notifications.create("id_" + id, options, function(notificationId) {
            if (onClicked) {
                callbacks[notificationId] = onClicked;
            }
        });
    };

    this.error = function(text, callback) {
        that.basic("Error", text, callback);
    };

    this.info = function(text, callback) {
        that.basic("Real-Debrid", text, callback);
    };

    this.clickHandler = function(notificationId) {
        if (callbacks[notificationId]) {
            callbacks[notificationId]();
            delete callbacks[notificationId];
        }
    };
}

/* Installer */
function Installer() {

    var that = this;

    this.onInstall = function() {
        nf.info("Extension installed");
    };

    this.onUpdate = function() {
        var message = "Extension updated to version " + that.getVersion() + ". Click here to see all changes.";
        nf.info(message, function() {
            chrome.tabs.create({
                url: 'https://github.com/JDevlieghere/Real-Debrid/blob/master/CHANGELOG.md'
            }, function() {});
        });
    };

    this.getVersion = function() {
        var details = chrome.app.getDetails();
        return details.version;
    };

    this.run = function() {
        var currVersion = that.getVersion();
        var prevVersion = localStorage['version'];
        if (currVersion != prevVersion) {
            if (typeof prevVersion == 'undefined') {
                that.onInstall();
            } else {
                that.onUpdate();
            }
            localStorage['version'] = currVersion;
        }
    };
}

/* Download Manager */
function DownloadManager() {

    var queue = [];
    var active = [];
    var that = this;
    var port = chrome.runtime.connect({
        name: "realdebrid"
    });

    this.download = function(url) {
        chrome.downloads.download({
            url: url
        }, function(downloadId) {
            that.addToActive(downloadId);
        });
    };

    this.checkComplete = function() {
        if (active.length === 0) {
            nf.info("All download complete");
        }
    };

    this.addToQueue = function(id) {
        queue.push(id)
    };

    this.addToActive = function(id) {
        active.push(id);
        port.postMessage({
            status: "started",
            downloadId: id
        });
    };

    this.removeFromActive = function(id) {
        var index = active.indexOf(id);
        active.splice(index, 1);
        port.postMessage({
            status: "finished",
            downloadId: id
        });
    };

    this.changeHandler = function(downloadItemDelta) {
        if (active.indexOf(downloadItemDelta.id) > -1 && downloadItemDelta.state) {
            if (downloadItemDelta.state.current == "complete") {
                that.checkComplete();
                that.removeFromActive(downloadItemDelta.id);
            } else if (downloadItemDelta.state.current == "interrupted") {
                that.removeFromActive(downloadItemDelta.id);
            }
        }
    };
}
<|endoftext|>