<commit_before>'use strict';

var React = require('react'),
    Router = require('react-router'),
    ReactBootstrap = require('react-bootstrap'),
    Reflux = require('reflux');

var SignIn = require('./membership/components/signin'),
    SignUp = require('./membership/components/signup'),
    Posts = require('./posts/components/posts'),
    Post = require('./posts/components/post'),
    Moderation = require('./posts/components/moderation'),
    Header = require('./shared/components/header'),
    Footer = require('./shared/components/footer'),
    actions = require('./actions'),
    userStore = require('./membership/stores/user');

var Grid = ReactBootstrap.Grid,
    Route = Router.Route;

var App = React.createClass({
    mixins: [Reflux.connect(userStore)],

    getInitialState: function() {
        return {user: null};
    },

    render: function() {
        return (
            <Grid>

                <Router.RouteHandler user={this.state.user} />

            </Grid>
        );
    }
});

// <Redirect from="/" to="posts" />
var routes = (
    <Route handler={App}>
        <Route path="/" handler={Posts} />
        <Route name="posts" path="posts" handler={Posts} />
        <Route name="post" path="post/:slug" handler={Post} />
        <Route name="moderation" path="post/:slug/moderation"
               handler={Moderation} />
        <Route name="signin" path="signin" handler={SignIn} />
        <Route name="signup" path="signup" handler={SignUp} />
    </Route>
);

actions.searchPosts();
actions.loadDailyQuote();

Router.run(routes, Router.HistoryLocation, function(Root) {
    React.render(<Root/>, document.body);
});
<commit_msg>Set initial user state as undefined; call user action.<commit_after>'use strict';

var React = require('react'),
    Router = require('react-router'),
    ReactBootstrap = require('react-bootstrap'),
    Reflux = require('reflux');

var SignIn = require('./membership/components/signin'),
    SignUp = require('./membership/components/signup'),
    Posts = require('./posts/components/posts'),
    Post = require('./posts/components/post'),
    Moderation = require('./posts/components/moderation'),
    Header = require('./shared/components/header'),
    Footer = require('./shared/components/footer'),
    actions = require('./actions'),
    userStore = require('./membership/stores/user');

var Grid = ReactBootstrap.Grid,
    Route = Router.Route;

var App = React.createClass({
    mixins: [Reflux.connect(userStore)],

    getInitialState: function() {
        return {user: undefined};
    },

    render: function() {
        return (
            <Grid>

                <Router.RouteHandler user={this.state.user} />

            </Grid>
        );
    }
});

// <Redirect from="/" to="posts" />
var routes = (
    <Route handler={App}>
        <Route path="/" handler={Posts} />
        <Route name="posts" path="posts" handler={Posts} />
        <Route name="post" path="post/:slug" handler={Post} />
        <Route name="moderation" path="post/:slug/moderation"
               handler={Moderation} />
        <Route name="signin" path="signin" handler={SignIn} />
        <Route name="signup" path="signup" handler={SignUp} />
    </Route>
);

actions.loadDailyQuote();
actions.searchPosts();
actions.user();

Router.run(routes, Router.HistoryLocation, function(Root) {
    React.render(<Root/>, document.body);
});
<|endoftext|>


<commit_before>function debug(str, escape) {
  str = String(str);
  if ('undefined' === typeof escape) {
    escape = true;
  }
  if (escape) {
    str = escapeHtml(str);
  }
  $('debug_output').innerHTML += '»' + str + '«
';
}

module.exports = debug;

var escapeHtml = require('escape-html');
<commit_msg>avoid using PrototypeJS in debug<commit_after>function debug(str, escape) {
  str = String(str);
  if ('undefined' === typeof escape) {
    escape = true;
  }
  if (escape) {
    str = escapeHtml(str);
  }
  document.getElementById('debug_output').innerHTML += '»' + str + '«
';
}

module.exports = debug;

var escapeHtml = require('escape-html');
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012-2016 InSeven Limited.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

Promise.prototype.always = function(onAlways) {
  return this.then(onAlways, onAlways);
};

(function($) {
  jQuery.fn.selectText = function() {
    var element = this[0],
      range,
      selection;
    if (document.body.createTextRange) {
      range = document.body.createTextRange();
      range.moveToElementText(element);
      range.select();
    } else if (window.getSelection) {
      selection = window.getSelection();
      range = document.createRange();
      range.selectNodeContents(element);
      selection.removeAllRanges();
      selection.addRange(range);
    }
  };

  App = {};

  App.Controller = function(device) {
    this.init(device);
  };

  App.Controller.SAVE = false;
  App.Controller.DEBUG = true;

  App.Controller.Domain = {
    SETTINGS: "settings",
    THUMBNAILS: "thumbnails",
    GAMES: "games"
  };

  jQuery.extend(App.Controller.prototype, {
    init: function(device) {
      var self = this;
      self.device = device;

      self.store = new App.Store("save-state", 50);
      var initCallback = self.initCallback.bind(self);
      self.store.open(initCallback);
    },

    initCallback: function(opened, error) {
      var self = this;
      if (opened) {
        self.logging = new App.Logging(window.config.logging_level, "app");
        self.logging.info("Version: " + window.config.version);
        self.logging.info(
          "Screen size: " + $(window).width() + " x " + $(window).height()
        );
        self.logging.info("User Agent: " + navigator.userAgent);

        self.library = new App.Library(
          self.store,
          function(identifier) {
            self.console.clear();
            self.console.show();
            setTimeout(function() {
              self.load(identifier);
            }, 400);
          },
          function() {
            self.gameBoy = new App.GameBoy(self.store, self.library);
            self.games = new App.Games(self.device, self.gameBoy, self.library);

            self.console = new App.Console(
              self.device,
              self.gameBoy,
              {
                didHide: function() {
                  self.games.update();
                }
              },
              self.store
            );
            var callback = function() {
              self.settings = new App.Settings(
                self.drive,
                self.store,
                self.gameBoy,
                self.console
              );

              self.settingsButton = new App.Controls.Button(
                $("#button-account"),
                {
                  touchUpInside: function() {
                    self.settings.show();
                  }
                }
              );

              self.consoleButton = new App.Controls.Button($("#button-done"), {
                touchUp: function() {
                  self.logging.info("Show console");
                  self.console.show();
                }
              });

              self.redeem = new App.Controls.Button($("#button-redeem"), {
                touchUpInside: function() {
                  $("#redeem-code").blur();
                  var code = $("#redeem-code").val();
                  drive
                    .redeemToken(code)
                    .then(function() {
                      self.drive.authorize();
                    })
                    .fail(function() {
                      alert("Unable to sign in.");
                    });
                }
              });

              self.drive.onStateChange(function(state) {
                if (state == App.Drive.State.UNKNOWN) {
                  self.logging.info("Google Drive state unknown.");
                } else if (state == App.Drive.State.UNAUTHORIZED) {
                  self.logging.info("Google Drive state unauthorized.");
                  self.settingsButton.hide();
                  self.consoleButton.hide();
                  self.clear();
                  self.console.hide();

                  if (window.navigator.onLine === true) {
                    self.drive
                      .authURL()
                      .then(function(url) {
                        $("#google-drive-auth").attr("href", url);
                        $("#redeem-code").val("");
                        $("#screen-account").show();
                      })
                      .fail(function() {
                        alert("Unable to generate Google authentication URL.");
                      });
                  }
                } else if (state == App.Drive.State.AUTHORIZED) {
                  self.logging.info("Google Drive state authorized.");
                  $("#screen-account").hide();
                  self.settingsButton.show();
                  self.drive.user().then(function(user) {
                    $("#account-details").html(user.email);
                  });
                  self.games.update();
                }
              });
              self.drive.authorize();

              self.checkForUpdate();

              // Ensure sound is enabled on a user interaction.

              self.soundMenu = new App.SoundMenu(
                function() {
                  self.gameBoy.pause();
                },
                function() {
                  self.gameBoy.run();
                }
              );

              self.gameBoy.setSoundEnabled(false);
              self.soundMenu.onEnable = function() {
                self.gameBoy.setSoundEnabled(true);
              };

              // Restore settings.
              self.restorePrevious().always(function() {
                self.console.setAnimationEnabled(true);
                $("#screen-splash").css("display", "none");
                self.soundMenu.show();
              });

              setInterval(function() {
                autoSave();
              }, 1000);
            };
            var instance = App.Drive.Instance(callback);
            self.drive = instance.drive;
            if (!instance.newInstance) {
              callback();
            }
          }
        );
      } else {
        alert(
          "Unable to create database.\nPlease accept increased storage size when asked.",
          error
        );
        return;
      }
    },

    /**
     * Restores the previous ROM and game state if one was present.
     *
     * If the ROM was successfully loaded, the returned Promise will resolved; otherwise it will rejected.
     *
     * @return Returns a Promise indicating.
     */
    restorePrevious: function() {
      var self = this;
      return new Promise(function(resolve, reject) {
        self.store.property(
          App.Controller.Domain.SETTINGS,
          App.Store.Property.GAME,
          function(identifier) {
            if (identifier !== undefined) {
              self.load(identifier).then(
                function() {
                  resolve();
                },
                function(error) {
                  reject(error);
                }
              );
            } else {
              reject();
            }
          }
        );
      });
    },

    load: function(identifier) {
      var self = this;
      return new Promise(function(resolve, reject) {
        var title = self.library.titleForIdentifier(identifier);
        self.gameBoy
          .load(identifier)
          .then(function() {
            self.store.setProperty(
              App.Controller.Domain.SETTINGS,
              App.Store.Property.GAME,
              identifier
            );
            self.consoleButton.setTitle(title);
            self.consoleButton.show();
            self.console.show().then(
              function() {
                resolve();
              },
              function(error) {
                reject(error);
              }
            );
          })
          .fail(function(e) {
            alert("Unable to load ROM\n" + e);
            self.store.deleteProperty(
              App.Controller.Domain.SETTINGS,
              App.Store.Property.GAME
            );
            self.consoleButton.hide();
            reject(e);
          });
      });
    },

    clear: function() {
      var self = this;
      self.console.clear();
      self.store.deleteProperty(
        App.Controller.Domain.SETTINGS,
        App.Store.Property.GAME
      );
    },

    checkForUpdate: function() {
      var self = this;

      if (self.updateCheck !== undefined) {
        return self.updateCheck.promise();
      }

      var deferred = jQuery.Deferred();
      self.updateCheck = deferred;

      deferred.promise().then(function(details) {
        alert(
          "Update available.\nRelaunch the application to update.\n\nVersion " +
            details.version +
            "\n\n" +
            details.details
        );
      });

      if (
        window.applicationCache !== undefined &&
        window.applicationCache !== null
      ) {
        self.logging.info(
          "Checking for application update (status " +
            window.applicationCache.status +
            ")"
        );
        window.applicationCache.addEventListener("updateready", function(
          event
        ) {
          self.logging.info(
            "Application update received (status " +
              window.applicationCache.status +
              ")"
          );
          if (
            window.applicationCache.status ==
            window.applicationCache.UPDATEREADY
          ) {
            jQuery
              .get("version.txt", function(version) {
                jQuery
                  .get("release.txt", function(data) {
                    deferred.resolve({
                      version: $.trim(version),
                      details: data
                    });
                  })
                  .fail(function() {
                    deferred.reject();
                  });
              })
              .fail(function() {
                deferred.reject();
              });
          } else {
            deferred.reject();
          }
        });
      }

      return deferred.promise();
    },

    setValue: function(domain, key, value) {
      var self = this;
      self.store.setProperty(domain, key, value);
    },

    getValue: function(domain, key, callback) {
      var self = this;
      return self.store.property(domain, key, callback);
    },

    deleteValue: function(domain, key) {
      var self = this;
      self.store.deleteProperty(key);
    }
  });

  $(document).ready(function() {
    var iPhone = navigator.userAgent.indexOf("iPhone OS") !== -1;
    var iPad = navigator.userAgent.indexOf("iPad") !== -1;
    if (window.navigator.standalone === true && (iPhone || iPad)) {
      bootstrap();
    } else {
      var callback = function() {
        var self = this;
        var drive = self.drive;
        var code = drive.getParameters().code;
        if (code !== undefined) {
          self.logging.info("Received authentication token: " + code);
          $("#screen-authorizing").show();
          $("#authorization-code").val(code);
        } else {
          $("#screen-instructions").show();
        }
      };

      var instance = App.Drive.Instance(callback);
      self.drive = instance.drive;
      if (!instance.newInstance) {
        callback();
      }
    }
  });
})(jQuery);

function bootstrap() {
  var device = new App.Device();
  window.tracker = new App.Tracker();
  window.app = new App.Controller(device);
  window.applicationRunning = true;
}

function sendLogs() {
  window.location.href =
    "mailto:support@inseven.co.uk?subject=Game Play Color Logs&body=Description:%0A%0APlease describe the issue you are seeing.%0A%0ALogs:%0A%0A" +
    encodeURIComponent(App.Logging.logs());
}

window.onerror = function(message, url, linenumber) {
  var logging = new App.Logging(window.config.logging_level, "error");
  logging.error(message + " " + message + " " + linenumber);

  var handleError = function() {
    if (confirm("Game Play encountered an error.\nSend crash report?")) {
      window.location.href =
        "mailto:crashes@inseven.co.uk?subject=Crash Report: Game Play Color&body=Description:%0A%0APlease describe what you were doing at the time.%0A%0AError:%0A%0A" +
        encodeURIComponent(message) +
        "%0A" +
        encodeURIComponent(url) +
        "%0A" +
        encodeURIComponent(linenumber) +
        "%0A%0ALogs:%0A%0A" +
        encodeURIComponent(App.Logging.logs());
    }
  };

  if (
    window.applicationCache.status == window.applicationCache.IDLE &&
    (window.navigator.standalone === true || window.applicationRunning === true)
  ) {
    handleError();
  }

  return false;
};

window.onmessage = function(message) {
  if (message.data === "debug") {
    $("#screen-instructions").hide();
    bootstrap();
  } else if (message.data == "crash") {
    boom();
  }
};
<commit_msg>Moved a line of code to reduce chance of issue<commit_after>/*
 * Copyright (C) 2012-2016 InSeven Limited.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

Promise.prototype.always = function(onAlways) {
  return this.then(onAlways, onAlways);
};

(function($) {
  jQuery.fn.selectText = function() {
    var element = this[0],
      range,
      selection;
    if (document.body.createTextRange) {
      range = document.body.createTextRange();
      range.moveToElementText(element);
      range.select();
    } else if (window.getSelection) {
      selection = window.getSelection();
      range = document.createRange();
      range.selectNodeContents(element);
      selection.removeAllRanges();
      selection.addRange(range);
    }
  };

  App = {};

  App.Controller = function(device) {
    this.init(device);
  };

  App.Controller.SAVE = false;
  App.Controller.DEBUG = true;

  App.Controller.Domain = {
    SETTINGS: "settings",
    THUMBNAILS: "thumbnails",
    GAMES: "games"
  };

  jQuery.extend(App.Controller.prototype, {
    init: function(device) {
      var self = this;
      self.device = device;

      self.store = new App.Store("save-state", 50);
      var initCallback = self.initCallback.bind(self);
      self.store.open(initCallback);
    },

    initCallback: function(opened, error) {
      var self = this;
      if (opened) {
        self.logging = new App.Logging(window.config.logging_level, "app");
        self.logging.info("Version: " + window.config.version);
        self.logging.info(
          "Screen size: " + $(window).width() + " x " + $(window).height()
        );
        self.logging.info("User Agent: " + navigator.userAgent);

        self.library = new App.Library(
          self.store,
          function(identifier) {
            self.console.clear();
            self.console.show();
            setTimeout(function() {
              self.load(identifier);
            }, 400);
          },
          function() {
            self.gameBoy = new App.GameBoy(self.store, self.library);
            self.games = new App.Games(self.device, self.gameBoy, self.library);

            self.console = new App.Console(
              self.device,
              self.gameBoy,
              {
                didHide: function() {
                  self.games.update();
                }
              },
              self.store
            );
            var callback = function() {
              self.settings = new App.Settings(
                self.drive,
                self.store,
                self.gameBoy,
                self.console
              );

              self.settingsButton = new App.Controls.Button(
                $("#button-account"),
                {
                  touchUpInside: function() {
                    self.settings.show();
                  }
                }
              );

              self.consoleButton = new App.Controls.Button($("#button-done"), {
                touchUp: function() {
                  self.logging.info("Show console");
                  self.console.show();
                }
              });

              self.redeem = new App.Controls.Button($("#button-redeem"), {
                touchUpInside: function() {
                  $("#redeem-code").blur();
                  var code = $("#redeem-code").val();
                  drive
                    .redeemToken(code)
                    .then(function() {
                      self.drive.authorize();
                    })
                    .fail(function() {
                      alert("Unable to sign in.");
                    });
                }
              });

              self.drive.onStateChange(function(state) {
                if (state == App.Drive.State.UNKNOWN) {
                  self.logging.info("Google Drive state unknown.");
                } else if (state == App.Drive.State.UNAUTHORIZED) {
                  self.logging.info("Google Drive state unauthorized.");
                  self.settingsButton.hide();
                  self.consoleButton.hide();
                  self.clear();
                  self.console.hide();

                  if (window.navigator.onLine === true) {
                    self.drive
                      .authURL()
                      .then(function(url) {
                        $("#google-drive-auth").attr("href", url);
                        $("#redeem-code").val("");
                        $("#screen-account").show();
                      })
                      .fail(function() {
                        alert("Unable to generate Google authentication URL.");
                      });
                  }
                } else if (state == App.Drive.State.AUTHORIZED) {
                  self.logging.info("Google Drive state authorized.");
                  $("#screen-account").hide();
                  self.settingsButton.show();
                  self.drive.user().then(function(user) {
                    $("#account-details").html(user.email);
                  });
                  self.games.update();
                }
              });
              self.drive.authorize();

              self.checkForUpdate();

              // Ensure sound is enabled on a user interaction.

              self.soundMenu = new App.SoundMenu(
                function() {
                  self.gameBoy.pause();
                },
                function() {
                  self.gameBoy.run();
                }
              );

              self.gameBoy.setSoundEnabled(false);
              self.soundMenu.onEnable = function() {
                self.gameBoy.setSoundEnabled(true);
              };

              // Restore settings.
              self.restorePrevious().always(function() {
                self.console.setAnimationEnabled(true);
                $("#screen-splash").css("display", "none");
                self.soundMenu.show();
              });

              setInterval(function() {
                autoSave();
              }, 1000);
            };
            var instance = App.Drive.Instance(callback);
            self.drive = instance.drive;
            if (!instance.newInstance) {
              callback();
            }
          }
        );
      } else {
        alert(
          "Unable to create database.\nPlease accept increased storage size when asked.",
          error
        );
        return;
      }
    },

    /**
     * Restores the previous ROM and game state if one was present.
     *
     * If the ROM was successfully loaded, the returned Promise will resolved; otherwise it will rejected.
     *
     * @return Returns a Promise indicating.
     */
    restorePrevious: function() {
      var self = this;
      return new Promise(function(resolve, reject) {
        self.store.property(
          App.Controller.Domain.SETTINGS,
          App.Store.Property.GAME,
          function(identifier) {
            if (identifier !== undefined) {
              self.load(identifier).then(
                function() {
                  resolve();
                },
                function(error) {
                  reject(error);
                }
              );
            } else {
              reject();
            }
          }
        );
      });
    },

    load: function(identifier) {
      var self = this;
      return new Promise(function(resolve, reject) {
        var title = self.library.titleForIdentifier(identifier);
        self.gameBoy
          .load(identifier)
          .then(function() {
            self.store.setProperty(
              App.Controller.Domain.SETTINGS,
              App.Store.Property.GAME,
              identifier
            );
            self.consoleButton.setTitle(title);
            self.consoleButton.show();
            self.console.show().then(
              function() {
                resolve();
              },
              function(error) {
                reject(error);
              }
            );
          })
          .fail(function(e) {
            alert("Unable to load ROM\n" + e);
            self.store.deleteProperty(
              App.Controller.Domain.SETTINGS,
              App.Store.Property.GAME
            );
            self.consoleButton.hide();
            reject(e);
          });
      });
    },

    clear: function() {
      var self = this;
      self.console.clear();
      self.store.deleteProperty(
        App.Controller.Domain.SETTINGS,
        App.Store.Property.GAME
      );
    },

    checkForUpdate: function() {
      var self = this;

      if (self.updateCheck !== undefined) {
        return self.updateCheck.promise();
      }

      var deferred = jQuery.Deferred();
      self.updateCheck = deferred;

      deferred.promise().then(function(details) {
        alert(
          "Update available.\nRelaunch the application to update.\n\nVersion " +
            details.version +
            "\n\n" +
            details.details
        );
      });

      if (
        window.applicationCache !== undefined &&
        window.applicationCache !== null
      ) {
        self.logging.info(
          "Checking for application update (status " +
            window.applicationCache.status +
            ")"
        );
        window.applicationCache.addEventListener("updateready", function(
          event
        ) {
          self.logging.info(
            "Application update received (status " +
              window.applicationCache.status +
              ")"
          );
          if (
            window.applicationCache.status ==
            window.applicationCache.UPDATEREADY
          ) {
            jQuery
              .get("version.txt", function(version) {
                jQuery
                  .get("release.txt", function(data) {
                    deferred.resolve({
                      version: $.trim(version),
                      details: data
                    });
                  })
                  .fail(function() {
                    deferred.reject();
                  });
              })
              .fail(function() {
                deferred.reject();
              });
          } else {
            deferred.reject();
          }
        });
      }

      return deferred.promise();
    },

    setValue: function(domain, key, value) {
      var self = this;
      self.store.setProperty(domain, key, value);
    },

    getValue: function(domain, key, callback) {
      var self = this;
      return self.store.property(domain, key, callback);
    },

    deleteValue: function(domain, key) {
      var self = this;
      self.store.deleteProperty(key);
    }
  });

  $(document).ready(function() {
    var iPhone = navigator.userAgent.indexOf("iPhone OS") !== -1;
    var iPad = navigator.userAgent.indexOf("iPad") !== -1;
    if (window.navigator.standalone === true && (iPhone || iPad)) {
      bootstrap();
    } else {

      var self = this;
      var callback = function() {
        var drive = self.drive;
        var code = drive.getParameters().code;
        if (code !== undefined) {
          self.logging.info("Received authentication token: " + code);
          $("#screen-authorizing").show();
          $("#authorization-code").val(code);
        } else {
          $("#screen-instructions").show();
        }
      };

      var instance = App.Drive.Instance(callback);
      self.drive = instance.drive;
      if (!instance.newInstance) {
        callback();
      }
    }
  });
})(jQuery);

function bootstrap() {
  var device = new App.Device();
  window.tracker = new App.Tracker();
  window.app = new App.Controller(device);
  window.applicationRunning = true;
}

function sendLogs() {
  window.location.href =
    "mailto:support@inseven.co.uk?subject=Game Play Color Logs&body=Description:%0A%0APlease describe the issue you are seeing.%0A%0ALogs:%0A%0A" +
    encodeURIComponent(App.Logging.logs());
}

window.onerror = function(message, url, linenumber) {
  var logging = new App.Logging(window.config.logging_level, "error");
  logging.error(message + " " + message + " " + linenumber);

  var handleError = function() {
    if (confirm("Game Play encountered an error.\nSend crash report?")) {
      window.location.href =
        "mailto:crashes@inseven.co.uk?subject=Crash Report: Game Play Color&body=Description:%0A%0APlease describe what you were doing at the time.%0A%0AError:%0A%0A" +
        encodeURIComponent(message) +
        "%0A" +
        encodeURIComponent(url) +
        "%0A" +
        encodeURIComponent(linenumber) +
        "%0A%0ALogs:%0A%0A" +
        encodeURIComponent(App.Logging.logs());
    }
  };

  if (
    window.applicationCache.status == window.applicationCache.IDLE &&
    (window.navigator.standalone === true || window.applicationRunning === true)
  ) {
    handleError();
  }

  return false;
};

window.onmessage = function(message) {
  if (message.data === "debug") {
    $("#screen-instructions").hide();
    bootstrap();
  } else if (message.data == "crash") {
    boom();
  }
};
<|endoftext|>


<commit_before>(function ($, list) {
    $('body').prepend('
It runs!
');

    $.ajax({
        method: 'GET',
        url: 'data/data.json'
    }).done(function (todos) {
        console.log(todos);
        // Got data of all existing todo's, produce the DOM and append to container
        $('#todo-list').append(
            list.makeList(todos));
    });

    // handler for add item to the to do list
    $('#add-todo-form').on('submit', function (e) {
        e.preventDefault();
        console.log('submitting to do item', e);

        var newItem = $('#add-todo-form > input').val();

        if (!newItem) {
            alert('Please put something in the input');
            return;
        }

        $.ajax({
            method: 'GET',
            url: 'data/add-item.json'
        }).done(function (data) {
            console.log('add item data', data);
            alert('Item added!');
            // Server responds OK, item added. Now we sync the UI.
            var todo = newItem;
            var index  = $('#todo-list > li').length;
            $('#todo-list').append(list.makeItem(todo, index));
        }).fail(function (xhr) {
            console.warn('add item fail', xhr);
        });

    });

}(jQuery, this.todo.list));
<commit_msg>keep the jquery selectors together<commit_after>(function ($, list) {
    $('body').prepend('
It runs!
');
    var $todoListContainer = $('#todo-list');
    var $addTodoForm = $('#add-todo-form');
    var $addTodoInput = $('#add-todo-form > input');

    $.ajax({
        method: 'GET',
        url: 'data/data.json'
    }).done(function (todos) {
        console.log(todos);
        // Got data of all existing todo's, produce the DOM and append to container
        $todoListContainer.append(
            list.makeList(todos));
    });

    // handler for add item to the to do list
    $addTodoForm.on('submit', function (e) {
        e.preventDefault();
        console.log('submitting to do item', e);

        var newItem = $addTodoInput.val();

        if (!newItem) {
            alert('Please put something in the input');
            return;
        }

        $.ajax({
            method: 'GET',
            url: 'data/add-item.json'
        }).done(function (data) {
            console.log('add item data', data);
            alert('Item added!');
            // Server responds OK, item added. Now we sync the UI.
            var todo = newItem;
            var index  = $todoListContainer.children('li').length;
            $todoListContainer.append(list.makeItem(todo, index));
        }).fail(function (xhr) {
            console.warn('add item fail', xhr);
        });

    });

}(jQuery, this.todo.list));
<|endoftext|>


<commit_before>var openElement = '.js-nav-open'
var closeElement = '.js-nav-close'
var overlayElement = '.js-nav-overlay'
var activeClass = 'is-active'
var el = document.querySelectorAll('.js-nav-container, .js-nav-push, .js-nav-overlay, html, body')
const stickyNavShrinker = require('./sticky-nav-shrink')
const LocationSelector = require('./locationSelector')
const location = new LocationSelector()
const SupportedCities = require('./supportedCities')
const supportedCities = new SupportedCities()

const hideForCity = (cityId) => {
  var citySpecificElements = document.querySelectorAll('[data-city]')
  for (let i = 0; i < citySpecificElements.length; i++) {
    let citiesRequired = citySpecificElements[i].getAttribute('data-city')
    if (citiesRequired.indexOf(cityId) > -1) {
      citySpecificElements[i].classList.add('is-active') // desktop
    }
  }
  var currentCity = document.querySelector('.js-current-city')
  currentCity.innerHTML = supportedCities.get(cityId).name
}

var init = function () {
  document.querySelector(openElement).addEventListener('click', function (e) {
    open()
  })

  document.querySelector(closeElement).addEventListener('click', function (e) {
    close()
  })

  document.querySelector(overlayElement).addEventListener('click', function (e) {
    close()
  })

  location
    .getCurrent()
    .then((result) => {
      hideForCity(result.id)
    })

  stickyNavShrinker.init()
}

var open = function () {
  var i

  for (i = 0; i < el.length; ++i) {
    el[i].classList.add(activeClass)
  }
}

var close = function () {
  var i

  for (i = 0; i < el.length; ++i) {
    el[i].classList.remove(activeClass)
  }
}

module.exports = {
  init: init,
  open: open,
  close: close
}
<commit_msg>tidy up<commit_after>const stickyNavShrinker = require('./sticky-nav-shrink')
const LocationSelector = require('./locationSelector')
const SupportedCities = require('./supportedCities')

const openElement = '.js-nav-open'
const closeElement = '.js-nav-close'
const overlayElement = '.js-nav-overlay'
const activeClass = 'is-active'
const el = document.querySelectorAll('.js-nav-container, .js-nav-push, .js-nav-overlay, html, body')
const supportedCities = new SupportedCities()
const location = new LocationSelector()

const hideForCity = (cityId) => {
  var citySpecificElements = document.querySelectorAll('[data-city]')
  for (let i = 0; i < citySpecificElements.length; i++) {
    let citiesRequired = citySpecificElements[i].getAttribute('data-city')
    if (citiesRequired.indexOf(cityId) > -1) {
      citySpecificElements[i].classList.add('is-active') // desktop
    }
  }
  var currentCity = document.querySelector('.js-current-city')
  currentCity.innerHTML = supportedCities.get(cityId).name
}

const mobileCityChangeInit = () => {

}

var init = function () {
  document.querySelector(openElement).addEventListener('click', function (e) {
    open()
  })

  document.querySelector(closeElement).addEventListener('click', function (e) {
    close()
  })

  document.querySelector(overlayElement).addEventListener('click', function (e) {
    close()
  })

  location
    .getCurrent()
    .then((result) => {
      hideForCity(result.id)
    })

  stickyNavShrinker.init()
}

var open = function () {
  var i

  for (i = 0; i < el.length; ++i) {
    el[i].classList.add(activeClass)
  }
}

var close = function () {
  var i

  for (i = 0; i < el.length; ++i) {
    el[i].classList.remove(activeClass)
  }
}

module.exports = {
  init: init,
  open: open,
  close: close
}
<|endoftext|>


<commit_before>import React     from 'react';
import ReactDOM  from 'react-dom';
import SearchBar from './components/SearchBar';

class App extends React.Component
{
    handleTermChange (term)
    {
        console.log(term);
    }

    render ()
    {
        return (

                <SearchBar onTermChange={this.handleTermChange} />

        );
    }
}

ReactDOM.render(<App />, document.getElementById('app'));
<commit_msg>Implementing new GifList and GifItem components. Adding basic hardcoded state for gifs.<commit_after>import React     from 'react';
import ReactDOM  from 'react-dom';
import SearchBar from './components/SearchBar';
import GifList   from './components/GifList';

class App extends React.Component
{
    constructor (props)
    {
        super(props);

        this.state = {
            gifs: [
                {
                    id: 1,
                    url: 'http://fakeimg.pl/300/?text=Image+1',
                },
                {
                    id: 2,
                    url: 'http://fakeimg.pl/300/?text=Image+2',
                },
                {
                    id: 3,
                    url: 'http://fakeimg.pl/300/?text=Image+3',
                },
            ]
        };
    }

    handleTermChange (term)
    {
        console.log(term);
    }

    render ()
    {
        return (

                <SearchBar onTermChange={this.handleTermChange} />
                <GifList gifs={this.state.gifs} />

        );
    }
}

ReactDOM.render(<App />, document.getElementById('app'));
<|endoftext|>


<commit_before>// Declare variables to reference outside initMap
// Google map
var map;
// TODO: remove
// All map markers
var markers = [];
// Google API Services
var geocoder;
var placesService;
// Google maps info window
var infowindow;

// Set Playa Vista center
var playaVistaCenter = {lat: 33.9739136, lng: -118.4161883};

function initMap() {
  // Create a map object
  map = new google.maps.Map(document.getElementById('map'), {
    center: playaVistaCenter,
    scrollwheel: true,
    zoom: 15,
    mapTypeControlOptions: {
      mapTypeIds: ['styled_map', 'roadmap']
    }
  });

  // TODO: remove map style
  // Map style from https://snazzymaps.com/style/27/shift-worker
  var styledMapType = new google.maps.StyledMapType(
    [
      {
        "stylers": [
          {
            "saturation": -100
          },
          {
            "gamma": 1
          }
        ]
      },
      {
        "elementType": "labels.text.stroke",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.business",
        "elementType": "labels.text",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.business",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.place_of_worship",
        "elementType": "labels.text",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.place_of_worship",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "road",
        "elementType": "geometry",
        "stylers": [
          {
            "visibility": "simplified"
          }
        ]
      },
      {
        "featureType": "water",
        "stylers": [
          {
            "visibility": "on"
          },
          {
            "saturation": 50
          },
          {
            "gamma": 0
          },
          {
            "hue": "#50a5d1"
          }
        ]
      },
      {
        "featureType": "administrative.neighborhood",
        "elementType": "labels.text.fill",
        "stylers": [
          {
            "color": "#333333"
          }
        ]
      },
      {
        "featureType": "road.local",
        "elementType": "labels.text",
        "stylers": [
          {
            "weight": 0.5
          },
          {
            "color": "#333333"
          }
        ]
      },
      {
        "featureType": "transit.station",
        "elementType": "labels.icon",
        "stylers": [
          {
            "gamma": 1
          },
          {
            "saturation": 50
          }
        ]
      }
    ], {name: 'Styled Map'});
  // Associate the styled map with the MapTypeId and set it to display.
  map.mapTypes.set('styled_map', styledMapType);
  map.setMapTypeId('styled_map');

  // Initialize geocoder service
  geocoder = new google.maps.Geocoder();
  // Initialize places service
  placesService = new google.maps.places.PlacesService(map);
  // Initialize infowinfow
  infowindow = new google.maps.InfoWindow();

  // Toogle off canvas list once map has loaded
  google.maps.event.addListenerOnce(map, 'idle', function() {
    // Show offcanvas menu by default when window >= 768
    if ($(window).width() >= 768) {
      toggleOffcanvas();
    }
    // Hide spinning loader
    hideLoader();
  });
}

// Creates a default marker for map
function createMarker(position, location) {
  var marker = new google.maps.Marker({
    position: position,
    title: location.name,
    animation: google.maps.Animation.DROP,
    location: location
  });
  // Add listener to fire actions when marker selected
  marker.addListener('click', function() {
    selectMarker(marker, location);
  });
  return marker;
}

// Adjust map bounds to fit all location markers
function fitLocationMarkers(locations) {
  var bounds = new google.maps.LatLngBounds();
  locations.forEach(function(location) {
    bounds.extend(location.position);
  });
  map.fitBounds(bounds);
}

// When marker focused on (ie, click from list item), open info window
function selectMarker(marker, business) {
  openInfoWindow(marker, business);
}

// Open infowindow on marker with defined content
function openInfoWindow(marker, business) {
  populateInfoWindow(business);
  infowindow.open(map, marker);
}

// Populate info window with business information
function populateInfoWindow(business) {
  console.log(business);
  var content = '';
  content += '
' + business.name + '
';
  content += '
Rating: ' + business.rating || 'N/A' + '
';
  // Check if there are categories
  if (business.categories) {
    content += '
Categories: ';
    // Loop through categories and add their title
    content += business.categories.map(function(category) {
      return category.title;
    }).join(', ');
    content += '
';
  }
  if (business.location.display_address) {
    content += '

Address:
';
    content += business.location.display_address.join('
');
    content += '
';
  }
  infowindow.setContent(content);
}

// Turns a location into a location using geocode service, and creates marker
// function geocodeAddressToMarker(location, map, geocoder, markers) {
//   geocoder.geocode({
//     address: location.address
//   }, function(results, status) {
//     if (status === 'OK') {
//       markers.push(createMarker(results[0].geometry.location, map, location.name));
//     } else {
//       alert('Geocode was not successful for the following reason: ' + status);
//     }
//   });
// }
<commit_msg>Add new map style<commit_after>// Declare variables to reference outside initMap
// Google map
var map;
// TODO: remove
// All map markers
var markers = [];
// Google API Services
var geocoder;
var placesService;
// Google maps info window
var infowindow;

// Set Playa Vista center
var playaVistaCenter = {lat: 33.9739136, lng: -118.4161883};

function initMap() {
  // Create a map object
  map = new google.maps.Map(document.getElementById('map'), {
    center: playaVistaCenter,
    scrollwheel: true,
    zoom: 15,
    mapTypeControlOptions: {
      mapTypeIds: ['styled_map', 'roadmap']
    }
  });

  // TODO: remove map style
  // Map style from https://snazzymaps.com/style/27/shift-worker
  var styledMapType = new google.maps.StyledMapType(
    [
      {
        "elementType": "geometry",
        "stylers": [
          {
            "color": "#f5f5f5"
          }
        ]
      },
      {
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "elementType": "labels.text.fill",
        "stylers": [
          {
            "color": "#616161"
          }
        ]
      },
      {
        "elementType": "labels.text.stroke",
        "stylers": [
          {
            "color": "#f5f5f5"
          }
        ]
      },
      {
        "featureType": "administrative.land_parcel",
        "elementType": "labels.text.fill",
        "stylers": [
          {
            "color": "#bdbdbd"
          }
        ]
      },
      {
        "featureType": "poi",
        "elementType": "geometry",
        "stylers": [
          {
            "color": "#eeeeee"
          }
        ]
      },
      {
        "featureType": "poi",
        "elementType": "labels.text",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi",
        "elementType": "labels.text.fill",
        "stylers": [
          {
            "color": "#757575"
          }
        ]
      },
      {
        "featureType": "poi.business",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "poi.park",
        "elementType": "geometry",
        "stylers": [
          {
            "color": "#e5e5e5"
          }
        ]
      },
      {
        "featureType": "poi.park",
        "elementType": "labels.text.fill",
        "stylers": [
          {
            "color": "#9e9e9e"
          }
        ]
      },
      {
        "featureType": "road",
        "elementType": "geometry",
        "stylers": [
          {
            "color": "#ffffff"
          }
        ]
      },
      {
        "featureType": "road",
        "elementType": "labels.icon",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "road.arterial",
        "elementType": "labels.text.fill",
        "stylers": [
          {
            "color": "#757575"
          }
        ]
      },
      {
        "featureType": "road.highway",
        "elementType": "geometry",
        "stylers": [
          {
            "color": "#dadada"
          }
        ]
      },
      {
        "featureType": "road.highway",
        "elementType": "labels.text.fill",
        "stylers": [
          {
            "color": "#616161"
          }
        ]
      },
      {
        "featureType": "road.local",
        "elementType": "labels.text.fill",
        "stylers": [
          {
            "color": "#9e9e9e"
          }
        ]
      },
      {
        "featureType": "transit",
        "stylers": [
          {
            "visibility": "off"
          }
        ]
      },
      {
        "featureType": "transit.line",
        "elementType": "geometry",
        "stylers": [
          {
            "color": "#e5e5e5"
          }
        ]
      },
      {
        "featureType": "transit.station",
        "elementType": "geometry",
        "stylers": [
          {
            "color": "#eeeeee"
          }
        ]
      },
      {
        "featureType": "water",
        "elementType": "geometry",
        "stylers": [
          {
            "color": "#c9c9c9"
          }
        ]
      },
      {
        "featureType": "water",
        "elementType": "labels.text.fill",
        "stylers": [
          {
            "color": "#9e9e9e"
          }
        ]
      }
    ], {name: 'Styled Map'});
  // Associate the styled map with the MapTypeId and set it to display.
  map.mapTypes.set('styled_map', styledMapType);
  map.setMapTypeId('styled_map');

  // Initialize geocoder service
  geocoder = new google.maps.Geocoder();
  // Initialize places service
  placesService = new google.maps.places.PlacesService(map);
  // Initialize infowinfow
  infowindow = new google.maps.InfoWindow();

  // Toogle off canvas list once map has loaded
  google.maps.event.addListenerOnce(map, 'idle', function() {
    // Show offcanvas menu by default when window >= 768
    if ($(window).width() >= 768) {
      toggleOffcanvas();
    }
    // Hide spinning loader
    hideLoader();
  });
}

// Creates a default marker for map
function createMarker(position, location) {
  var marker = new google.maps.Marker({
    position: position,
    title: location.name,
    animation: google.maps.Animation.DROP,
    location: location
  });
  // Add listener to fire actions when marker selected
  marker.addListener('click', function() {
    selectMarker(marker, location);
  });
  return marker;
}

// Adjust map bounds to fit all location markers
function fitLocationMarkers(locations) {
  var bounds = new google.maps.LatLngBounds();
  locations.forEach(function(location) {
    bounds.extend(location.position);
  });
  map.fitBounds(bounds);
}

// When marker focused on (ie, click from list item), open info window
function selectMarker(marker, business) {
  openInfoWindow(marker, business);
}

// Open infowindow on marker with defined content
function openInfoWindow(marker, business) {
  populateInfoWindow(business);
  infowindow.open(map, marker);
}

// Populate info window with business information
function populateInfoWindow(business) {
  console.log(business);
  var content = '';
  content += '
' + business.name + '
';
  content += '
Rating: ' + business.rating || 'N/A' + '
';
  // Check if there are categories
  if (business.categories) {
    content += '
Categories: ';
    // Loop through categories and add their title
    content += business.categories.map(function(category) {
      return category.title;
    }).join(', ');
    content += '
';
  }
  if (business.location.display_address) {
    content += '

Address:
';
    content += business.location.display_address.join('
');
    content += '
';
  }
  infowindow.setContent(content);
}

// Turns a location into a location using geocode service, and creates marker
// function geocodeAddressToMarker(location, map, geocoder, markers) {
//   geocoder.geocode({
//     address: location.address
//   }, function(results, status) {
//     if (status === 'OK') {
//       markers.push(createMarker(results[0].geometry.location, map, location.name));
//     } else {
//       alert('Geocode was not successful for the following reason: ' + status);
//     }
//   });
// }
<|endoftext|>


<commit_before>
//public row object
var RowComponent = function (row){
	this.row = row;
};

RowComponent.prototype.getData = function(transform){
	return this.row.getData(transform);
};

RowComponent.prototype.getElement = function(){
	return this.row.getElement();
};

RowComponent.prototype.getCells = function(){
	var cells = [];

	this.row.getCells().forEach(function(cell){
		cells.push(cell.getComponent());
	});

	return cells;
};

RowComponent.prototype.getCell = function(column){
	return this.row.getCell(column).getComponent();
};

RowComponent.prototype.getIndex = function(){
	return this.row.getData("data")[this.row.table.options.index];
};

RowComponent.prototype.getPosition = function(active){
	return this.row.table.rowManager.getRowPosition(this.row, active);
};

RowComponent.prototype.delete = function(){
	this.row.delete();
};

RowComponent.prototype.scrollTo = function(){
	this.row.table.rowManager.scrollToRow(this.row);
};

RowComponent.prototype.update = function(data){
	this.row.updateData(data);
};

RowComponent.prototype.normalizeHeight = function(){
	this.row.normalizeHeight(true);
};

RowComponent.prototype.select = function(){
	this.row.table.extensions.selectRow.selectRows(this.row);
};

RowComponent.prototype.deselect = function(){
	this.row.table.extensions.selectRow.deselectRows(this.row);
};

RowComponent.prototype.toggleSelect = function(){
	this.row.table.extensions.selectRow.toggleRow(this.row);
};

RowComponent.prototype._getSelf = function(){
	return this.row;
};

RowComponent.prototype.freeze = function(){
	if(this.row.table.extExists("frozenRows", true)){
		this.row.table.extensions.frozenRows.freezeRow(this.row);
	}
};

RowComponent.prototype.unfreeze = function(){
	if(this.row.table.extExists("frozenRows", true)){
		this.row.table.extensions.frozenRows.unfreezeRow(this.row);
	}
};

RowComponent.prototype.reformat = function(){
	return this.row.reinitialize();
};

RowComponent.prototype.getGroup = function(){
	return this.row.getGroup().getComponent();
};

var Row = function(data, parent){
	this.table = parent.table;
	this.parent = parent;
	this.data = {};
	this.type = "row"; //type of element
	this.element = $("

");
	this.extensions = {}; //hold extension variables;
	this.cells = [];
	this.height = 0; //hold element height
	this.outerHeight = 0; //holde lements outer height
	this.initialized = false; //element has been rendered
	this.heightInitialized = false; //element has resized cells to fit

	this.setData(data);
	this.generateElement();
};

Row.prototype.getElement = function(){
	return this.element;
};

Row.prototype.generateElement = function(){
	var self = this,
	dblTap,	tapHold, tap;

	//set row selection characteristics
	if(self.table.options.selectable !== false && self.table.extExists("selectRow")){
		self.table.extensions.selectRow.initializeRow(this);
	}

	//setup movable rows
	if(self.table.options.movableRows !== false && self.table.extExists("moveRow")){
		self.table.extensions.moveRow.initializeRow(this);
	}

	//handle row click events
	if (self.table.options.rowClick){
		self.element.on("click", function(e){
			self.table.options.rowClick(e, self.getComponent());
		})
	}

	if (self.table.options.rowDblClick){
		self.element.on("dblclick", function(e){
			self.table.options.rowDblClick(e, self.getComponent());
		})
	}

	if (self.table.options.rowContext){
		self.element.on("contextmenu", function(e){
			self.table.options.rowContext(e, self.getComponent());
		})
	}

	if (self.table.options.rowTap){

		tap = false;

		self.element.on("touchstart", function(e){
			tap = true;
		});

		self.element.on("touchend", function(e){
			if(tap){
				self.table.options.rowTap(e, self.getComponent());
			}

			tap = false;
		});
	}

	if (self.table.options.rowDblTap){

		dblTap = null;

		self.element.on("touchend", function(e){

			if(dblTap){
				clearTimeout(dblTap);
				dblTap = null;

				self.table.options.rowDblTap(e, self.getComponent());
			}else{

				dblTap = setTimeout(function(){
					clearTimeout(dblTap);
					dblTap = null;
				}, 300);
			}

		});
	}

	if (self.table.options.rowTapHold){

		tapHold = null;

		self.element.on("touchstart", function(e){
			clearTimeout(tapHold);

			tapHold = setTimeout(function(){
				clearTimeout(tapHold);
				tapHold = null;
				tap = false;
				self.table.options.rowTapHold(e, self.getComponent());
			}, 1000)

		});

		self.element.on("touchend", function(e){
			clearTimeout(tapHold);
			tapHold = null;
		});
	}
};

Row.prototype.generateCells = function(){
	this.cells = this.table.columnManager.generateCells(this);
}

//functions to setup on first render
Row.prototype.initialize = function(force){
	var self = this;

	if(!self.initialized || force){

		self.deleteCells();

		self.element.empty();

		//handle frozen cells
		if(this.table.extExists("frozenColumns")){
			this.table.extensions.frozenColumns.layoutRow(this);
		}

		this.generateCells();

		self.cells.forEach(function(cell){
			self.element.append(cell.getElement());
		});

		if(force){
			self.normalizeHeight();
		}

		//setup movable rows
		if(self.table.options.responsiveLayout === "collapse" && self.table.extExists("responsiveLayout")){
			self.table.extensions.responsiveLayout.layoutRow(this);
		}

		if(self.table.options.rowFormatter){
			self.table.options.rowFormatter(self.getComponent());
		}

		//set resizable handles
		if(self.table.options.resizableRows && self.table.extExists("resizeRows")){
			self.table.extensions.resizeRows.initializeRow(self);
		}

		self.initialized = true;
	}
};

Row.prototype.reinitializeHeight = function(){
	this.heightInitialized = false;

	if(this.element[0].offsetParent !== null){
		this.normalizeHeight(true);
	}
};

Row.prototype.reinitialize = function(){
	this.initialized = false;
	this.heightInitialized = false;
	this.height = 0;

	if(this.element[0].offsetParent !== null){
		this.initialize(true);
	}
};

//get heights when doing bulk row style calcs in virtual DOM
Row.prototype.calcHeight = function(){
	this.height = this.element[0].clientHeight;
	this.outerHeight = this.element[0].offsetHeight;
};

//set of cells
Row.prototype.setCellHeight = function(){
	var height = this.height;

	this.cells.forEach(function(cell){
		cell.setHeight(height);
	});

	this.heightInitialized = true;
};

Row.prototype.clearCellHeight = function(){
	this.cells.forEach(function(cell){
		cell.clearHeight();
	});
}

//normalize the height of elements in the row
Row.prototype.normalizeHeight = function(force){

	if(force){
		this.clearCellHeight();
	}

	this.calcHeight();

	this.setCellHeight();
};

Row.prototype.setHeight = function(height){
	this.height = height;

	this.setCellHeight();
};

//set height of rows
Row.prototype.setHeight = function(height, force){
	if(this.height != height || force){

		this.height = height;

		this.setCellHeight();

		// this.outerHeight = this.element.outerHeight();
		this.outerHeight = this.element[0].offsetHeight;
	}
};

//return rows outer height
Row.prototype.getHeight = function(){
	return this.outerHeight;
};

//return rows outer Width
Row.prototype.getWidth = function(){
	return this.element.outerWidth();
};

//////////////// Cell Management /////////////////

Row.prototype.deleteCell = function(cell){
	var index = this.cells.indexOf(cell);

	if(index > -1){
		this.cells.splice(index, 1);
	}
};

//////////////// Data Management /////////////////

Row.prototype.setData = function(data){
	var self = this;

	if(self.table.extExists("mutator")){
		self.data = self.table.extensions.mutator.transformRow(data, "data");
	}else{
		self.data = data;
	}
};

//update the rows data
Row.prototype.updateData = function(data){
	var self = this;

	if(typeof data === "string"){
		data = JSON.parse(data);
	}

	//mutate incomming data if needed
	if(self.table.extExists("mutator")){
		data = self.table.extensions.mutator.transformRow(data, "data");
	}

	//set data
	for (var attrname in data) {
		self.data[attrname] = data[attrname];
	}

	//update affected cells only
	for (var attrname in data) {
		let cell = this.getCell(attrname);

		if(cell){
			if(cell.getValue() != data[attrname]){
				cell.setValueProcessData(data[attrname]);
			}
		}
	}

	//Partial reinitialization if visible
	if(this.element.is(":visible")){
		self.normalizeHeight();

		if(self.table.options.rowFormatter){
			self.table.options.rowFormatter(self.getComponent());
		}
	}else{
		this.initialized = false;
		this.height = 0;
	}

	//self.reinitialize();

	self.table.options.rowUpdated(self.getComponent());
};

Row.prototype.getData = function(transform){
	var self = this;

	if(transform){
		if(self.table.extExists("accessor")){
			return self.table.extensions.accessor.transformRow(self.data, transform);
		}
	}else{
		return this.data;
	}

};

Row.prototype.getCell = function(column){
	var match = false,
	column = this.table.columnManager.findColumn(column);

	match = this.cells.find(function(cell){
		return cell.column === column;
	});

	return match;
},

Row.prototype.getCellIndex = function(findCell){
	return this.cells.findIndex(function(cell){
		return cell === findCell;
	});
},

Row.prototype.findNextEditableCell = function(index){

	var nextCell = false;

	if(index < this.cells.length-1){
		for(var i = index+1; i < this.cells.length; i++){
			let cell = this.cells[i];

			if(cell.column.extensions.edit && cell.getElement().is(":visible")){
				let allowEdit = true;

				if(typeof cell.column.extensions.edit.check == "function"){
					allowEdit = cell.column.extensions.edit.check(cell.getComponent());
				}

				if(allowEdit){
					nextCell = cell;
					break;
				}
			}
		}
	}

	return nextCell;
},

Row.prototype.findPrevEditableCell = function(index){
	var prevCell = false;

	if(index > 0){
		for(var i = index-1; i >= 0; i--){
			let cell = this.cells[i],
			allowEdit = true;

			if(cell.column.extensions.edit && cell.getElement().is(":visible")){
				if(typeof cell.column.extensions.edit.check == "function"){
					allowEdit = cell.column.extensions.edit.check(cell.getComponent());
				}

				if(allowEdit){
					prevCell = cell;
					break;
				}
			}
		}
	}

	return prevCell;
},

Row.prototype.getCells = function(){
	return this.cells;
},

///////////////////// Actions  /////////////////////

Row.prototype.delete = function(){
	var index;

	this.deleteActual();

	if(this.table.options.history && this.table.extExists("history")){

		index = this.table.rowManager.getRowIndex(this);

		if(index){
			index = this.table.rowManager.rows[index-1];
		}

		this.table.extensions.history.action("rowDelete", this, {data:this.getData(), pos:!index, index:index});
	};

};

Row.prototype.deleteActual = function(){

	var index = this.table.rowManager.getRowIndex(this);

	//deselect row if it is selected
	if(this.table.extExists("selectRow")){
		this.table.extensions.selectRow._deselectRow(this.row, true);
	}

	this.table.rowManager.deleteRow(this);

	this.deleteCells();

	//remove from group
	if(this.extensions.group){
		this.extensions.group.removeRow(this);
	}

	//recalc column calculations if present
	if(this.table.extExists("columnCalcs")){
		if(this.table.options.groupBy && this.table.extExists("groupRows")){
			this.table.extensions.columnCalcs.recalcRowGroup(this);
		}else{
			this.table.extensions.columnCalcs.recalc(this.table.rowManager.activeRows);
		}
	}
};

Row.prototype.deleteCells = function(){
	var cellCount = this.cells.length;

	for(let i = 0; i < cellCount; i++){
		this.cells[0].delete();
	}
};

Row.prototype.wipe = function(){
	this.deleteCells();

	this.element.children().each(function(){
		$(this).remove();
	})

	this.element.empty();
	this.element.remove();
}

Row.prototype.getGroup = function(){
	return this.extensions.group || false;
}

//////////////// Object Generation /////////////////
Row.prototype.getComponent = function(){
	return new RowComponent(this);
};<commit_msg>fixed missing index scope issue on row deletion with history mode enabled<commit_after>
//public row object
var RowComponent = function (row){
	this.row = row;
};

RowComponent.prototype.getData = function(transform){
	return this.row.getData(transform);
};

RowComponent.prototype.getElement = function(){
	return this.row.getElement();
};

RowComponent.prototype.getCells = function(){
	var cells = [];

	this.row.getCells().forEach(function(cell){
		cells.push(cell.getComponent());
	});

	return cells;
};

RowComponent.prototype.getCell = function(column){
	return this.row.getCell(column).getComponent();
};

RowComponent.prototype.getIndex = function(){
	return this.row.getData("data")[this.row.table.options.index];
};

RowComponent.prototype.getPosition = function(active){
	return this.row.table.rowManager.getRowPosition(this.row, active);
};

RowComponent.prototype.delete = function(){
	this.row.delete();
};

RowComponent.prototype.scrollTo = function(){
	this.row.table.rowManager.scrollToRow(this.row);
};

RowComponent.prototype.update = function(data){
	this.row.updateData(data);
};

RowComponent.prototype.normalizeHeight = function(){
	this.row.normalizeHeight(true);
};

RowComponent.prototype.select = function(){
	this.row.table.extensions.selectRow.selectRows(this.row);
};

RowComponent.prototype.deselect = function(){
	this.row.table.extensions.selectRow.deselectRows(this.row);
};

RowComponent.prototype.toggleSelect = function(){
	this.row.table.extensions.selectRow.toggleRow(this.row);
};

RowComponent.prototype._getSelf = function(){
	return this.row;
};

RowComponent.prototype.freeze = function(){
	if(this.row.table.extExists("frozenRows", true)){
		this.row.table.extensions.frozenRows.freezeRow(this.row);
	}
};

RowComponent.prototype.unfreeze = function(){
	if(this.row.table.extExists("frozenRows", true)){
		this.row.table.extensions.frozenRows.unfreezeRow(this.row);
	}
};

RowComponent.prototype.reformat = function(){
	return this.row.reinitialize();
};

RowComponent.prototype.getGroup = function(){
	return this.row.getGroup().getComponent();
};

var Row = function(data, parent){
	this.table = parent.table;
	this.parent = parent;
	this.data = {};
	this.type = "row"; //type of element
	this.element = $("

");
	this.extensions = {}; //hold extension variables;
	this.cells = [];
	this.height = 0; //hold element height
	this.outerHeight = 0; //holde lements outer height
	this.initialized = false; //element has been rendered
	this.heightInitialized = false; //element has resized cells to fit

	this.setData(data);
	this.generateElement();
};

Row.prototype.getElement = function(){
	return this.element;
};

Row.prototype.generateElement = function(){
	var self = this,
	dblTap,	tapHold, tap;

	//set row selection characteristics
	if(self.table.options.selectable !== false && self.table.extExists("selectRow")){
		self.table.extensions.selectRow.initializeRow(this);
	}

	//setup movable rows
	if(self.table.options.movableRows !== false && self.table.extExists("moveRow")){
		self.table.extensions.moveRow.initializeRow(this);
	}

	//handle row click events
	if (self.table.options.rowClick){
		self.element.on("click", function(e){
			self.table.options.rowClick(e, self.getComponent());
		})
	}

	if (self.table.options.rowDblClick){
		self.element.on("dblclick", function(e){
			self.table.options.rowDblClick(e, self.getComponent());
		})
	}

	if (self.table.options.rowContext){
		self.element.on("contextmenu", function(e){
			self.table.options.rowContext(e, self.getComponent());
		})
	}

	if (self.table.options.rowTap){

		tap = false;

		self.element.on("touchstart", function(e){
			tap = true;
		});

		self.element.on("touchend", function(e){
			if(tap){
				self.table.options.rowTap(e, self.getComponent());
			}

			tap = false;
		});
	}

	if (self.table.options.rowDblTap){

		dblTap = null;

		self.element.on("touchend", function(e){

			if(dblTap){
				clearTimeout(dblTap);
				dblTap = null;

				self.table.options.rowDblTap(e, self.getComponent());
			}else{

				dblTap = setTimeout(function(){
					clearTimeout(dblTap);
					dblTap = null;
				}, 300);
			}

		});
	}

	if (self.table.options.rowTapHold){

		tapHold = null;

		self.element.on("touchstart", function(e){
			clearTimeout(tapHold);

			tapHold = setTimeout(function(){
				clearTimeout(tapHold);
				tapHold = null;
				tap = false;
				self.table.options.rowTapHold(e, self.getComponent());
			}, 1000)

		});

		self.element.on("touchend", function(e){
			clearTimeout(tapHold);
			tapHold = null;
		});
	}
};

Row.prototype.generateCells = function(){
	this.cells = this.table.columnManager.generateCells(this);
}

//functions to setup on first render
Row.prototype.initialize = function(force){
	var self = this;

	if(!self.initialized || force){

		self.deleteCells();

		self.element.empty();

		//handle frozen cells
		if(this.table.extExists("frozenColumns")){
			this.table.extensions.frozenColumns.layoutRow(this);
		}

		this.generateCells();

		self.cells.forEach(function(cell){
			self.element.append(cell.getElement());
		});

		if(force){
			self.normalizeHeight();
		}

		//setup movable rows
		if(self.table.options.responsiveLayout === "collapse" && self.table.extExists("responsiveLayout")){
			self.table.extensions.responsiveLayout.layoutRow(this);
		}

		if(self.table.options.rowFormatter){
			self.table.options.rowFormatter(self.getComponent());
		}

		//set resizable handles
		if(self.table.options.resizableRows && self.table.extExists("resizeRows")){
			self.table.extensions.resizeRows.initializeRow(self);
		}

		self.initialized = true;
	}
};

Row.prototype.reinitializeHeight = function(){
	this.heightInitialized = false;

	if(this.element[0].offsetParent !== null){
		this.normalizeHeight(true);
	}
};

Row.prototype.reinitialize = function(){
	this.initialized = false;
	this.heightInitialized = false;
	this.height = 0;

	if(this.element[0].offsetParent !== null){
		this.initialize(true);
	}
};

//get heights when doing bulk row style calcs in virtual DOM
Row.prototype.calcHeight = function(){
	this.height = this.element[0].clientHeight;
	this.outerHeight = this.element[0].offsetHeight;
};

//set of cells
Row.prototype.setCellHeight = function(){
	var height = this.height;

	this.cells.forEach(function(cell){
		cell.setHeight(height);
	});

	this.heightInitialized = true;
};

Row.prototype.clearCellHeight = function(){
	this.cells.forEach(function(cell){
		cell.clearHeight();
	});
}

//normalize the height of elements in the row
Row.prototype.normalizeHeight = function(force){

	if(force){
		this.clearCellHeight();
	}

	this.calcHeight();

	this.setCellHeight();
};

Row.prototype.setHeight = function(height){
	this.height = height;

	this.setCellHeight();
};

//set height of rows
Row.prototype.setHeight = function(height, force){
	if(this.height != height || force){

		this.height = height;

		this.setCellHeight();

		// this.outerHeight = this.element.outerHeight();
		this.outerHeight = this.element[0].offsetHeight;
	}
};

//return rows outer height
Row.prototype.getHeight = function(){
	return this.outerHeight;
};

//return rows outer Width
Row.prototype.getWidth = function(){
	return this.element.outerWidth();
};

//////////////// Cell Management /////////////////

Row.prototype.deleteCell = function(cell){
	var index = this.cells.indexOf(cell);

	if(index > -1){
		this.cells.splice(index, 1);
	}
};

//////////////// Data Management /////////////////

Row.prototype.setData = function(data){
	var self = this;

	if(self.table.extExists("mutator")){
		self.data = self.table.extensions.mutator.transformRow(data, "data");
	}else{
		self.data = data;
	}
};

//update the rows data
Row.prototype.updateData = function(data){
	var self = this;

	if(typeof data === "string"){
		data = JSON.parse(data);
	}

	//mutate incomming data if needed
	if(self.table.extExists("mutator")){
		data = self.table.extensions.mutator.transformRow(data, "data");
	}

	//set data
	for (var attrname in data) {
		self.data[attrname] = data[attrname];
	}

	//update affected cells only
	for (var attrname in data) {
		let cell = this.getCell(attrname);

		if(cell){
			if(cell.getValue() != data[attrname]){
				cell.setValueProcessData(data[attrname]);
			}
		}
	}

	//Partial reinitialization if visible
	if(this.element.is(":visible")){
		self.normalizeHeight();

		if(self.table.options.rowFormatter){
			self.table.options.rowFormatter(self.getComponent());
		}
	}else{
		this.initialized = false;
		this.height = 0;
	}

	//self.reinitialize();

	self.table.options.rowUpdated(self.getComponent());
};

Row.prototype.getData = function(transform){
	var self = this;

	if(transform){
		if(self.table.extExists("accessor")){
			return self.table.extensions.accessor.transformRow(self.data, transform);
		}
	}else{
		return this.data;
	}

};

Row.prototype.getCell = function(column){
	var match = false,
	column = this.table.columnManager.findColumn(column);

	match = this.cells.find(function(cell){
		return cell.column === column;
	});

	return match;
},

Row.prototype.getCellIndex = function(findCell){
	return this.cells.findIndex(function(cell){
		return cell === findCell;
	});
},

Row.prototype.findNextEditableCell = function(index){

	var nextCell = false;

	if(index < this.cells.length-1){
		for(var i = index+1; i < this.cells.length; i++){
			let cell = this.cells[i];

			if(cell.column.extensions.edit && cell.getElement().is(":visible")){
				let allowEdit = true;

				if(typeof cell.column.extensions.edit.check == "function"){
					allowEdit = cell.column.extensions.edit.check(cell.getComponent());
				}

				if(allowEdit){
					nextCell = cell;
					break;
				}
			}
		}
	}

	return nextCell;
},

Row.prototype.findPrevEditableCell = function(index){
	var prevCell = false;

	if(index > 0){
		for(var i = index-1; i >= 0; i--){
			let cell = this.cells[i],
			allowEdit = true;

			if(cell.column.extensions.edit && cell.getElement().is(":visible")){
				if(typeof cell.column.extensions.edit.check == "function"){
					allowEdit = cell.column.extensions.edit.check(cell.getComponent());
				}

				if(allowEdit){
					prevCell = cell;
					break;
				}
			}
		}
	}

	return prevCell;
},

Row.prototype.getCells = function(){
	return this.cells;
},

///////////////////// Actions  /////////////////////

Row.prototype.delete = function(){
	var index = this.table.rowManager.getRowIndex(this);

	this.deleteActual();

	if(this.table.options.history && this.table.extExists("history")){

		if(index){
			index = this.table.rowManager.rows[index-1];
		}

		this.table.extensions.history.action("rowDelete", this, {data:this.getData(), pos:!index, index:index});
	};

};

Row.prototype.deleteActual = function(){

	var index = this.table.rowManager.getRowIndex(this);

	//deselect row if it is selected
	if(this.table.extExists("selectRow")){
		this.table.extensions.selectRow._deselectRow(this.row, true);
	}

	this.table.rowManager.deleteRow(this);

	this.deleteCells();

	//remove from group
	if(this.extensions.group){
		this.extensions.group.removeRow(this);
	}

	//recalc column calculations if present
	if(this.table.extExists("columnCalcs")){
		if(this.table.options.groupBy && this.table.extExists("groupRows")){
			this.table.extensions.columnCalcs.recalcRowGroup(this);
		}else{
			this.table.extensions.columnCalcs.recalc(this.table.rowManager.activeRows);
		}
	}
};

Row.prototype.deleteCells = function(){
	var cellCount = this.cells.length;

	for(let i = 0; i < cellCount; i++){
		this.cells[0].delete();
	}
};

Row.prototype.wipe = function(){
	this.deleteCells();

	this.element.children().each(function(){
		$(this).remove();
	})

	this.element.empty();
	this.element.remove();
}

Row.prototype.getGroup = function(){
	return this.extensions.group || false;
}

//////////////// Object Generation /////////////////
Row.prototype.getComponent = function(){
	return new RowComponent(this);
};<|endoftext|>


<commit_before>import Global from './global';

var Keeper = function (options) {

	this._ = {};
	this._.token;

	this.scheme = 'Bearer';
	this.type = 'sessionStorage';

	Object.defineProperties(this, {
		token: {
			enumerable: true,
			get: function () {
				return this._.token = this._.token || window[this.type].getItem('token');
			}
		},
		user: {
			enumerable: true,
			get: function () {
				return this._.user = this._.user || JSON.parse(window[this.type].getItem('user'));
			}
		}
	});

	this.setup(options);
};

Keeper.prototype.setup = function (options) {
	options = options || {};

	this._.forbidden = options.forbidden || this._.forbidden;
	this._.unauthorized = options.unauthorized || this._.unauthorized;
	this._.authenticated = options.authenticated || this._.authenticated;
	this._.unauthenticated = options.unauthenticated || this._.unauthenticated;

	if (options.type) {
		this.type = options.type + 'Storage';
	}

	if (options.scheme) {
		this.scheme = options.scheme.slice(0, 1).toUpperCase() + options.scheme.slice(1);
	}

};

Keeper.prototype.setToken = function (token) {
	if (!token) return;
	if (this.scheme === 'Basic') token = this.encode(token);
	this._.token = window[this.type].setItem('token', token);
};

Keeper.prototype.setUser = function (user) {
	if (!user) return;
	user = JSON.stringify(user);
	this._.user = window[this.type].setItem('user', user);
};

Keeper.prototype.removeToken = function () {
	this._.token = null;
	window[this.type].removeItem('token');
};

Keeper.prototype.removeUser = function () {
	this._.user = null;
	window[this.type].removeItem('user');
};

Keeper.prototype.authenticate = function (token, user) {
	this.setToken(token);
	this.setUser(user);

	if (typeof this._.authenticated === 'string') {
		Global.router.navigate(this._.authenticated);
	} else if (typeof this._.authenticated === 'function') {
		this._.authenticated();
	}

};

Keeper.prototype.unauthenticate = function () {
	this.removeToken();
	this.removeUser();

	if (typeof this._.unauthenticated === 'string') {
		Global.router.navigate(this._.unauthenticated);
	} else if (typeof this._.unauthenticated === 'function') {
		this._.unauthenticated();
	}

};

Keeper.prototype.forbidden = function (result) {

	if (typeof this._.forbidden === 'string') {
		Global.router.navigate(this._.forbidden);
	} else if (typeof this._.forbidden === 'function') {
		this._.forbidden(result);
	}

	return false;
};

Keeper.prototype.unauthorized = function (result) {
	// NOTE might want to remove token and user
	// this.removeToken();
	// this.removeUser();

	if (typeof this._.unauthorized === 'string') {
		Global.router.navigate(this._.unauthorized);
	} else if (typeof this._.unauthorized === 'function') {
		this._.unauthorized(result);
	}

	return false;
};

Keeper.prototype.route = function (result) {

	if (result.auth === false) {
		return true;
	} else if (!this.token) {
		return this.unauthorized(result);
	} else {
		return true;
	}

};

Keeper.prototype.request = function (result) {

	if (result.opt.auth === false) {
		return true;
	} else if (!this.token) {
		return this.unauthorized(result);
	} else {
		result.xhr.setRequestHeader('Authorization', this.scheme + ' ' + this.token);
		return true;
	}

};

Keeper.prototype.response = function (result) {

	if (result.statusCode === 401) {
		return this.unauthorized(result);
	} else if (result.statusCode === 403) {
		return this.forbidden(result);
	} else {
		return true;
	}

};

Keeper.prototype.encode = function (data) {
	return window.btoa(data);
};

Keeper.prototype.decode = function (data) {
    return window.atob(data);
};

export default Keeper;

/*

	https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding

	// Keeper.prototype.encode = function (data) {
	// 	// encodeURIComponent to get percent-encoded UTF-8
	// 	// convert the percent encodings into raw bytes which
	// 	return window.btoa(window.encodeURIComponent(data).replace(/%([0-9A-F]{2})/g, function (match, char) {
	// 		return String.fromCharCode('0x' + char);
	// 	}));
	// };
	//
	// Keeper.prototype.decode = function (data) {
	// 	// from bytestream to percent-encoding to original string
	//     return window.decodeURIComponent(window.atob(data).split('').map(function(char) {
	//         return '%' + ('00' + char.charCodeAt(0).toString(16)).slice(-2);
	//     }).join(''));
	// };

*/
<commit_msg>updated from old api<commit_after>import Global from './global';

var Keeper = function (options) {

	this._ = {};
	this._.token;

	this.scheme = 'Bearer';
	this.type = 'sessionStorage';

	Object.defineProperties(this, {
		token: {
			enumerable: true,
			get: function () {
				return this._.token = this._.token || window[this.type].getItem('token');
			}
		},
		user: {
			enumerable: true,
			get: function () {
				return this._.user = this._.user || JSON.parse(window[this.type].getItem('user'));
			}
		}
	});

	this.setup(options);
};

Keeper.prototype.setup = function (options) {
	options = options || {};

	this._.forbidden = options.forbidden || this._.forbidden;
	this._.unauthorized = options.unauthorized || this._.unauthorized;
	this._.authenticated = options.authenticated || this._.authenticated;
	this._.unauthenticated = options.unauthenticated || this._.unauthenticated;

	if (options.type) {
		this.type = options.type + 'Storage';
	}

	if (options.scheme) {
		this.scheme = options.scheme.slice(0, 1).toUpperCase() + options.scheme.slice(1);
	}

};

Keeper.prototype.setToken = function (token) {
	if (!token) return;
	if (this.scheme === 'Basic') token = this.encode(token);
	this._.token = window[this.type].setItem('token', token);
};

Keeper.prototype.setUser = function (user) {
	if (!user) return;
	user = JSON.stringify(user);
	this._.user = window[this.type].setItem('user', user);
};

Keeper.prototype.removeToken = function () {
	this._.token = null;
	window[this.type].removeItem('token');
};

Keeper.prototype.removeUser = function () {
	this._.user = null;
	window[this.type].removeItem('user');
};

Keeper.prototype.authenticate = function (token, user) {
	this.setToken(token);
	this.setUser(user);

	if (typeof this._.authenticated === 'string') {
		Global.router.route(this._.authenticated);
	} else if (typeof this._.authenticated === 'function') {
		this._.authenticated();
	}

};

Keeper.prototype.unauthenticate = function () {
	this.removeToken();
	this.removeUser();

	if (typeof this._.unauthenticated === 'string') {
		Global.router.route(this._.unauthenticated);
	} else if (typeof this._.unauthenticated === 'function') {
		this._.unauthenticated();
	}

};

Keeper.prototype.forbidden = function (result) {

	if (typeof this._.forbidden === 'string') {
		Global.router.route(this._.forbidden);
	} else if (typeof this._.forbidden === 'function') {
		this._.forbidden(result);
	}

	return false;
};

Keeper.prototype.unauthorized = function (result) {
	// NOTE might want to remove token and user
	// this.removeToken();
	// this.removeUser();

	if (typeof this._.unauthorized === 'string') {
		Global.router.route(this._.unauthorized);
	} else if (typeof this._.unauthorized === 'function') {
		this._.unauthorized(result);
	}

	return false;
};

Keeper.prototype.route = function (result) {

	if (result.auth === false) {
		return true;
	} else if (!this.token) {
		return this.unauthorized(result);
	} else {
		return true;
	}

};

Keeper.prototype.request = function (result) {

	if (result.opt.auth === false) {
		return true;
	} else if (!this.token) {
		return this.unauthorized(result);
	} else {
		result.xhr.setRequestHeader('Authorization', this.scheme + ' ' + this.token);
		return true;
	}

};

Keeper.prototype.response = function (result) {

	if (result.statusCode === 401) {
		return this.unauthorized(result);
	} else if (result.statusCode === 403) {
		return this.forbidden(result);
	} else {
		return true;
	}

};

Keeper.prototype.encode = function (data) {
	return window.btoa(data);
};

Keeper.prototype.decode = function (data) {
    return window.atob(data);
};

export default Keeper;

/*

	https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding

	// Keeper.prototype.encode = function (data) {
	// 	// encodeURIComponent to get percent-encoded UTF-8
	// 	// convert the percent encodings into raw bytes which
	// 	return window.btoa(window.encodeURIComponent(data).replace(/%([0-9A-F]{2})/g, function (match, char) {
	// 		return String.fromCharCode('0x' + char);
	// 	}));
	// };
	//
	// Keeper.prototype.decode = function (data) {
	// 	// from bytestream to percent-encoding to original string
	//     return window.decodeURIComponent(window.atob(data).split('').map(function(char) {
	//         return '%' + ('00' + char.charCodeAt(0).toString(16)).slice(-2);
	//     }).join(''));
	// };

*/
<|endoftext|>