<commit_before>/*
Copyright 2015 OpenMarket Ltd

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 MatrixClientPeg = require("../../MatrixClientPeg");
var RoomListSorter = require("../../RoomListSorter");
var Presence = require("../../Presence");
var dis = require("../../dispatcher");

var sdk = require('../../index');
var MatrixTools = require('../../MatrixTools');
var linkifyMatrix = require("../../linkify-matrix");

var Cas = require("../../CasLogic");

module.exports = {
    PageTypes: {
        RoomView: "room_view",
        UserSettings: "user_settings",
        CreateRoom: "create_room",
        RoomDirectory: "room_directory",
    },

    AuxPanel: {
        RoomSettings: "room_settings",
    },

    getInitialState: function() {
        var s = {
            logged_in: !!(MatrixClientPeg.get() && MatrixClientPeg.get().credentials),
            collapse_lhs: false,
            collapse_rhs: false,
            ready: false,
        };
        if (s.logged_in) {
            if (MatrixClientPeg.get().getRooms().length) {
                s.page_type = this.PageTypes.RoomView;
            } else {
                s.page_type = this.PageTypes.RoomDirectory;
            }
        }
        return s;
    },

    componentDidMount: function() {
        this.dispatcherRef = dis.register(this.onAction);
        if (this.state.logged_in) {
            this.startMatrixClient();
        }
        this.focusComposer = false;
        document.addEventListener("keydown", this.onKeyDown);
        window.addEventListener("focus", this.onFocus);
        if (this.state.logged_in) {
            this.notifyNewScreen('');
        } else {
            this.notifyNewScreen('login');
        }

        // this can technically be done anywhere but doing this here keeps all
        // the routing url path logic together.
        linkifyMatrix.onAliasClick = function(event, alias) {
            dis.dispatch({action: 'view_room_alias', room_alias: alias});
            event.preventDefault();
        };
    },

    componentWillUnmount: function() {
        dis.unregister(this.dispatcherRef);
        document.removeEventListener("keydown", this.onKeyDown);
        window.removeEventListener("focus", this.onFocus);
    },

    componentDidUpdate: function() {
        if (this.focusComposer) {
            dis.dispatch({action: 'focus_composer'});
            this.focusComposer = false;
        }
    },

    onAction: function(payload) {
        var roomIndexDelta = 1;
        var Notifier = sdk.getComponent('organisms.Notifier');

        var self = this;
        switch (payload.action) {
            case 'logout':
                if (window.localStorage) {
                    window.localStorage.clear();
                }
                Notifier.stop();
                Presence.stop();
                MatrixClientPeg.get().stopClient();
                MatrixClientPeg.get().removeAllListeners();
                MatrixClientPeg.unset();
                this.notifyNewScreen('login');
                this.replaceState({
                    logged_in: false,
                    ready: false
                });
                break;
            case 'start_registration':
                if (this.state.logged_in) return;
                var newState = payload.params || {};
                newState.screen = 'register';
                if (
                    payload.params &&
                    payload.params.client_secret &&
                    payload.params.session_id &&
                    payload.params.hs_url &&
                    payload.params.is_url &&
                    payload.params.sid
                ) {
                    newState.register_client_secret = payload.params.client_secret;
                    newState.register_session_id = payload.params.session_id;
                    newState.register_hs_url = payload.params.hs_url;
                    newState.register_is_url = payload.params.is_url;
                    newState.register_id_sid = payload.params.sid;
                }
                this.replaceState(newState);
                this.notifyNewScreen('register');
                break;
            case 'start_login':
                if (this.state.logged_in) return;
                this.replaceState({
                    screen: 'login'
                });
                this.notifyNewScreen('login');
                break;
            case 'cas_login':
                if (this.state.logged_in) return;

                var self = this;
                var client = MatrixClientPeg.get();
                var serviceUrl = Cas.getServiceUrl();

                client.loginWithCas(payload.params.ticket, serviceUrl).done(function(data) {
                    MatrixClientPeg.replaceUsingAccessToken(
                        client.getHomeserverUrl(), client.getIdentityServerUrl(),
                        data.user_id, data.access_token
                    );
                    self.setState({
                        screen: undefined,
                        logged_in: true
                    });
                    self.startMatrixClient();
                    self.notifyNewScreen('');
                }, function(error) {
                    self.notifyNewScreen('login');
                    self.setState({errorText: 'Login failed.'});
                });

                break;
            case 'view_room':
                this.focusComposer = true;
                var newState = {
                    currentRoom: payload.room_id,
                    page_type: this.PageTypes.RoomView,
                };
                if (this.sdkReady) {
                    // if the SDK is not ready yet, remember what room
                    // we're supposed to be on but don't notify about
                    // the new screen yet (we won't be showing it yet)
                    // The normal case where this happens is navigating
                    // to the room in the URL bar on page load.
                    var presentedId = payload.room_id;
                    var room = MatrixClientPeg.get().getRoom(payload.room_id);
                    if (room) {
                        var theAlias = MatrixTools.getCanonicalAliasForRoom(room);
                        if (theAlias) presentedId = theAlias;
                    }
                    this.notifyNewScreen('room/'+presentedId);
                    newState.ready = true;
                }
                this.setState(newState);
                break;
            case 'view_prev_room':
                roomIndexDelta = -1;
            case 'view_next_room':
                var allRooms = RoomListSorter.mostRecentActivityFirst(
                    MatrixClientPeg.get().getRooms()
                );
                var roomIndex = -1;
                for (var i = 0; i < allRooms.length; ++i) {
                    if (allRooms[i].roomId == this.state.currentRoom) {
                        roomIndex = i;
                        break;
                    }
                }
                roomIndex = (roomIndex + roomIndexDelta) % allRooms.length;
                if (roomIndex < 0) roomIndex = allRooms.length - 1;
                this.focusComposer = true;
                this.setState({
                    currentRoom: allRooms[roomIndex].roomId
                });
                this.notifyNewScreen('room/'+allRooms[roomIndex].roomId);
                break;
            case 'view_indexed_room':
                var allRooms = RoomListSorter.mostRecentActivityFirst(
                    MatrixClientPeg.get().getRooms()
                );
                var roomIndex = payload.roomIndex;
                if (allRooms[roomIndex]) {
                    this.focusComposer = true;
                    this.setState({
                        currentRoom: allRooms[roomIndex].roomId
                    });
                    this.notifyNewScreen('room/'+allRooms[roomIndex].roomId);
                }
                break;
            case 'view_room_alias':
                var foundRoom = MatrixTools.getRoomForAlias(
                    MatrixClientPeg.get().getRooms(), payload.room_alias
                );
                if (foundRoom) {
                    dis.dispatch({
                        action: 'view_room',
                        room_id: foundRoom.roomId
                    });
                    return;
                }
                // resolve the alias and *then* view it
                MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias).done(
                function(result) {
                    dis.dispatch({
                        action: 'view_room',
                        room_id: result.room_id
                    });
                });
                break;
            case 'view_user_settings':
                this.setState({
                    page_type: this.PageTypes.UserSettings,
                });
                break;
            case 'view_create_room':
                this.setState({
                    page_type: this.PageTypes.CreateRoom,
                });
                break;
            case 'view_room_directory':
                this.setState({
                    page_type: this.PageTypes.RoomDirectory,
                });
                break;
            case 'notifier_enabled':
                this.forceUpdate();
                break;
            case 'hide_left_panel':
                this.setState({
                    collapse_lhs: true,
                });
                break;
            case 'show_left_panel':
                this.setState({
                    collapse_lhs: false,
                });
                break;
            case 'hide_right_panel':
                this.setState({
                    collapse_rhs: true,
                });
                break;
            case 'show_right_panel':
                this.setState({
                    collapse_rhs: false,
                });
                break;
        }
    },

    onLoggedIn: function() {
        this.setState({
            screen: undefined,
            logged_in: true
        });
        this.startMatrixClient();
        this.notifyNewScreen('');
    },

    startMatrixClient: function() {
        var Notifier = sdk.getComponent('organisms.Notifier');
        var cli = MatrixClientPeg.get();
        var self = this;
        cli.on('syncComplete', function() {
            self.sdkReady = true;

            if (self.starting_room_alias) {
                dis.dispatch({
                    action: 'view_room_alias',
                    room_alias: self.starting_room_alias
                });
                delete self.starting_room_alias;
            } else {
                if (!self.state.currentRoom) {
                    var firstRoom = null;
                    if (cli.getRooms() && cli.getRooms().length) {
                        firstRoom = RoomListSorter.mostRecentActivityFirst(
                            cli.getRooms()
                        )[0].roomId;
                        self.setState({ready: true, currentRoom: firstRoom, page_type: self.PageTypes.RoomView});
                    } else {
                        self.setState({ready: true, page_type: self.PageTypes.RoomDirectory});
                    }
                } else {
                    self.setState({ready: true, page_type: self.PageTypes.RoomView});
                }

                // we notifyNewScreen now because now the room will actually be displayed,
                // and (mostly) now we can get the correct alias.
                var presentedId = self.state.currentRoom;
                var room = MatrixClientPeg.get().getRoom(self.state.currentRoom);
                if (room) {
                    var theAlias = MatrixTools.getCanonicalAliasForRoom(room);
                    if (theAlias) presentedId = theAlias;
                }
                self.notifyNewScreen('room/'+presentedId);
                dis.dispatch({action: 'focus_composer'});
            }
        });
        cli.on('Call.incoming', function(call) {
            dis.dispatch({
                action: 'incoming_call',
                call: call
            });
        });
        Notifier.start();
        Presence.start();
        cli.startClient();
    },

    onKeyDown: function(ev) {
        if (ev.altKey) {
            if (ev.ctrlKey && ev.keyCode > 48 && ev.keyCode < 58) {
                dis.dispatch({
                    action: 'view_indexed_room',
                    roomIndex: ev.keyCode - 49,
                });
                ev.stopPropagation();
                ev.preventDefault();
                return;
            }
            switch (ev.keyCode) {
                case 38:
                    dis.dispatch({action: 'view_prev_room'});
                    ev.stopPropagation();
                    ev.preventDefault();
                    break;
                case 40:
                    dis.dispatch({action: 'view_next_room'});
                    ev.stopPropagation();
                    ev.preventDefault();
                    break;
            }
        }
    },

    onFocus: function(ev) {
        dis.dispatch({action: 'focus_composer'});
    },

    showScreen: function(screen, params) {
        if (screen == 'register') {
            dis.dispatch({
                action: 'start_registration',
                params: params
            });
        } else if (screen == 'login') {
            dis.dispatch({
                action: 'start_login',
                params: params
            });
        } else if (screen == 'cas_login') {
            dis.dispatch({
                action: 'cas_login',
                params: params
            });
        } else if (screen.indexOf('room/') == 0) {
            var roomString = screen.split('/')[1];
            if (roomString[0] == '#') {
                if (this.state.logged_in) {
                    dis.dispatch({
                        action: 'view_room_alias',
                        room_alias: roomString
                    });
                } else {
                    // Okay, we'll take you here soon...
                    this.starting_room_alias = roomString;
                    // ...but you're still going to have to log in.
                    this.notifyNewScreen('login');
                }
            } else {
                dis.dispatch({
                    action: 'view_room',
                    room_id: roomString
                });
            }
        }
    },

    notifyNewScreen: function(screen) {
        if (this.props.onNewScreen) {
            this.props.onNewScreen(screen);
        }
    }
};
<commit_msg>Defer entirely to the end app for handling links<commit_after>/*
Copyright 2015 OpenMarket Ltd

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 MatrixClientPeg = require("../../MatrixClientPeg");
var RoomListSorter = require("../../RoomListSorter");
var Presence = require("../../Presence");
var dis = require("../../dispatcher");

var sdk = require('../../index');
var MatrixTools = require('../../MatrixTools');
var linkifyMatrix = require("../../linkify-matrix");

var Cas = require("../../CasLogic");

module.exports = {
    PageTypes: {
        RoomView: "room_view",
        UserSettings: "user_settings",
        CreateRoom: "create_room",
        RoomDirectory: "room_directory",
    },

    AuxPanel: {
        RoomSettings: "room_settings",
    },

    getInitialState: function() {
        var s = {
            logged_in: !!(MatrixClientPeg.get() && MatrixClientPeg.get().credentials),
            collapse_lhs: false,
            collapse_rhs: false,
            ready: false,
        };
        if (s.logged_in) {
            if (MatrixClientPeg.get().getRooms().length) {
                s.page_type = this.PageTypes.RoomView;
            } else {
                s.page_type = this.PageTypes.RoomDirectory;
            }
        }
        return s;
    },

    componentDidMount: function() {
        this.dispatcherRef = dis.register(this.onAction);
        if (this.state.logged_in) {
            this.startMatrixClient();
        }
        this.focusComposer = false;
        document.addEventListener("keydown", this.onKeyDown);
        window.addEventListener("focus", this.onFocus);
        if (this.state.logged_in) {
            this.notifyNewScreen('');
        } else {
            this.notifyNewScreen('login');
        }

        // this can technically be done anywhere but doing this here keeps all
        // the routing url path logic together.
        if (this.onAliasClick) {
            linkifyMatrix.onAliasClick = this.onAliasClick;
        }
        if (this.onUserClick) {
            linkifyMatrix.onUserClick = this.onUserClick;
        }
    },

    componentWillUnmount: function() {
        dis.unregister(this.dispatcherRef);
        document.removeEventListener("keydown", this.onKeyDown);
        window.removeEventListener("focus", this.onFocus);
    },

    componentDidUpdate: function() {
        if (this.focusComposer) {
            dis.dispatch({action: 'focus_composer'});
            this.focusComposer = false;
        }
    },

    onAction: function(payload) {
        var roomIndexDelta = 1;
        var Notifier = sdk.getComponent('organisms.Notifier');

        var self = this;
        switch (payload.action) {
            case 'logout':
                if (window.localStorage) {
                    window.localStorage.clear();
                }
                Notifier.stop();
                Presence.stop();
                MatrixClientPeg.get().stopClient();
                MatrixClientPeg.get().removeAllListeners();
                MatrixClientPeg.unset();
                this.notifyNewScreen('login');
                this.replaceState({
                    logged_in: false,
                    ready: false
                });
                break;
            case 'start_registration':
                if (this.state.logged_in) return;
                var newState = payload.params || {};
                newState.screen = 'register';
                if (
                    payload.params &&
                    payload.params.client_secret &&
                    payload.params.session_id &&
                    payload.params.hs_url &&
                    payload.params.is_url &&
                    payload.params.sid
                ) {
                    newState.register_client_secret = payload.params.client_secret;
                    newState.register_session_id = payload.params.session_id;
                    newState.register_hs_url = payload.params.hs_url;
                    newState.register_is_url = payload.params.is_url;
                    newState.register_id_sid = payload.params.sid;
                }
                this.replaceState(newState);
                this.notifyNewScreen('register');
                break;
            case 'start_login':
                if (this.state.logged_in) return;
                this.replaceState({
                    screen: 'login'
                });
                this.notifyNewScreen('login');
                break;
            case 'cas_login':
                if (this.state.logged_in) return;

                var self = this;
                var client = MatrixClientPeg.get();
                var serviceUrl = Cas.getServiceUrl();

                client.loginWithCas(payload.params.ticket, serviceUrl).done(function(data) {
                    MatrixClientPeg.replaceUsingAccessToken(
                        client.getHomeserverUrl(), client.getIdentityServerUrl(),
                        data.user_id, data.access_token
                    );
                    self.setState({
                        screen: undefined,
                        logged_in: true
                    });
                    self.startMatrixClient();
                    self.notifyNewScreen('');
                }, function(error) {
                    self.notifyNewScreen('login');
                    self.setState({errorText: 'Login failed.'});
                });

                break;
            case 'view_room':
                this.focusComposer = true;
                var newState = {
                    currentRoom: payload.room_id,
                    page_type: this.PageTypes.RoomView,
                };
                if (this.sdkReady) {
                    // if the SDK is not ready yet, remember what room
                    // we're supposed to be on but don't notify about
                    // the new screen yet (we won't be showing it yet)
                    // The normal case where this happens is navigating
                    // to the room in the URL bar on page load.
                    var presentedId = payload.room_id;
                    var room = MatrixClientPeg.get().getRoom(payload.room_id);
                    if (room) {
                        var theAlias = MatrixTools.getCanonicalAliasForRoom(room);
                        if (theAlias) presentedId = theAlias;
                    }
                    this.notifyNewScreen('room/'+presentedId);
                    newState.ready = true;
                }
                this.setState(newState);
                break;
            case 'view_prev_room':
                roomIndexDelta = -1;
            case 'view_next_room':
                var allRooms = RoomListSorter.mostRecentActivityFirst(
                    MatrixClientPeg.get().getRooms()
                );
                var roomIndex = -1;
                for (var i = 0; i < allRooms.length; ++i) {
                    if (allRooms[i].roomId == this.state.currentRoom) {
                        roomIndex = i;
                        break;
                    }
                }
                roomIndex = (roomIndex + roomIndexDelta) % allRooms.length;
                if (roomIndex < 0) roomIndex = allRooms.length - 1;
                this.focusComposer = true;
                this.setState({
                    currentRoom: allRooms[roomIndex].roomId
                });
                this.notifyNewScreen('room/'+allRooms[roomIndex].roomId);
                break;
            case 'view_indexed_room':
                var allRooms = RoomListSorter.mostRecentActivityFirst(
                    MatrixClientPeg.get().getRooms()
                );
                var roomIndex = payload.roomIndex;
                if (allRooms[roomIndex]) {
                    this.focusComposer = true;
                    this.setState({
                        currentRoom: allRooms[roomIndex].roomId
                    });
                    this.notifyNewScreen('room/'+allRooms[roomIndex].roomId);
                }
                break;
            case 'view_room_alias':
                var foundRoom = MatrixTools.getRoomForAlias(
                    MatrixClientPeg.get().getRooms(), payload.room_alias
                );
                if (foundRoom) {
                    dis.dispatch({
                        action: 'view_room',
                        room_id: foundRoom.roomId
                    });
                    return;
                }
                // resolve the alias and *then* view it
                MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias).done(
                function(result) {
                    dis.dispatch({
                        action: 'view_room',
                        room_id: result.room_id
                    });
                });
                break;
            case 'view_user_settings':
                this.setState({
                    page_type: this.PageTypes.UserSettings,
                });
                break;
            case 'view_create_room':
                this.setState({
                    page_type: this.PageTypes.CreateRoom,
                });
                break;
            case 'view_room_directory':
                this.setState({
                    page_type: this.PageTypes.RoomDirectory,
                });
                break;
            case 'notifier_enabled':
                this.forceUpdate();
                break;
            case 'hide_left_panel':
                this.setState({
                    collapse_lhs: true,
                });
                break;
            case 'show_left_panel':
                this.setState({
                    collapse_lhs: false,
                });
                break;
            case 'hide_right_panel':
                this.setState({
                    collapse_rhs: true,
                });
                break;
            case 'show_right_panel':
                this.setState({
                    collapse_rhs: false,
                });
                break;
        }
    },

    onLoggedIn: function() {
        this.setState({
            screen: undefined,
            logged_in: true
        });
        this.startMatrixClient();
        this.notifyNewScreen('');
    },

    startMatrixClient: function() {
        var Notifier = sdk.getComponent('organisms.Notifier');
        var cli = MatrixClientPeg.get();
        var self = this;
        cli.on('syncComplete', function() {
            self.sdkReady = true;

            if (self.starting_room_alias) {
                dis.dispatch({
                    action: 'view_room_alias',
                    room_alias: self.starting_room_alias
                });
                delete self.starting_room_alias;
            } else {
                if (!self.state.currentRoom) {
                    var firstRoom = null;
                    if (cli.getRooms() && cli.getRooms().length) {
                        firstRoom = RoomListSorter.mostRecentActivityFirst(
                            cli.getRooms()
                        )[0].roomId;
                        self.setState({ready: true, currentRoom: firstRoom, page_type: self.PageTypes.RoomView});
                    } else {
                        self.setState({ready: true, page_type: self.PageTypes.RoomDirectory});
                    }
                } else {
                    self.setState({ready: true, page_type: self.PageTypes.RoomView});
                }

                // we notifyNewScreen now because now the room will actually be displayed,
                // and (mostly) now we can get the correct alias.
                var presentedId = self.state.currentRoom;
                var room = MatrixClientPeg.get().getRoom(self.state.currentRoom);
                if (room) {
                    var theAlias = MatrixTools.getCanonicalAliasForRoom(room);
                    if (theAlias) presentedId = theAlias;
                }
                self.notifyNewScreen('room/'+presentedId);
                dis.dispatch({action: 'focus_composer'});
            }
        });
        cli.on('Call.incoming', function(call) {
            dis.dispatch({
                action: 'incoming_call',
                call: call
            });
        });
        Notifier.start();
        Presence.start();
        cli.startClient();
    },

    onKeyDown: function(ev) {
        if (ev.altKey) {
            if (ev.ctrlKey && ev.keyCode > 48 && ev.keyCode < 58) {
                dis.dispatch({
                    action: 'view_indexed_room',
                    roomIndex: ev.keyCode - 49,
                });
                ev.stopPropagation();
                ev.preventDefault();
                return;
            }
            switch (ev.keyCode) {
                case 38:
                    dis.dispatch({action: 'view_prev_room'});
                    ev.stopPropagation();
                    ev.preventDefault();
                    break;
                case 40:
                    dis.dispatch({action: 'view_next_room'});
                    ev.stopPropagation();
                    ev.preventDefault();
                    break;
            }
        }
    },

    onFocus: function(ev) {
        dis.dispatch({action: 'focus_composer'});
    },

    showScreen: function(screen, params) {
        if (screen == 'register') {
            dis.dispatch({
                action: 'start_registration',
                params: params
            });
        } else if (screen == 'login') {
            dis.dispatch({
                action: 'start_login',
                params: params
            });
        } else if (screen == 'cas_login') {
            dis.dispatch({
                action: 'cas_login',
                params: params
            });
        } else if (screen.indexOf('room/') == 0) {
            var roomString = screen.split('/')[1];
            if (roomString[0] == '#') {
                if (this.state.logged_in) {
                    dis.dispatch({
                        action: 'view_room_alias',
                        room_alias: roomString
                    });
                } else {
                    // Okay, we'll take you here soon...
                    this.starting_room_alias = roomString;
                    // ...but you're still going to have to log in.
                    this.notifyNewScreen('login');
                }
            } else {
                dis.dispatch({
                    action: 'view_room',
                    room_id: roomString
                });
            }
        }
    },

    notifyNewScreen: function(screen) {
        if (this.props.onNewScreen) {
            this.props.onNewScreen(screen);
        }
    }
};
<|endoftext|>


<commit_before>$(document).ready(function() {
  /*This function returns a tweetable string*/
  function tweetSize(quote, author) {
    var tweet = "";
    var len = quote.length + author.length +2;

    if (len > 140) {
      tweet += quote.substring(0, 133 - author.length);
      tweet += "... -" + author;
    }
    else {
      tweet += quote + " -" + author;
    }
    return escape(tweet);
  }

  /*This function calls the API, gets the quote and metadata and updates the html*/
  function getQuote() {
    $("#getQuote").html("Loading...");
    $.getJSON("http://api.forismatic.com/api/1.0/?method=getQuote&lang=en&format=jsonp&jsonp=?", function(data){
      var html = "
" + data.quoteText;
      if (data.quoteAuthor != "") {
        html += "

" + data.quoteAuthor + "
" +
          "" +
          "" +
          "
";
      }
      else {
        html += "

Author Unknown
";
      }
      $(".message").html(html);
      $("#getQuote").html("New Quote");
      $("#quoteLink").attr("href", data.quoteLink);
      //http://twitter.com/home?status=Today is the tomorrow we worried about yesterday.  http://en.forismatic.com/6750845f01/ @forismatic
    });
  }

  /*Initialize*/
  getQuote(); //comment out when editing to reduce API calls

  /*the following calls getQuote() when button is pressed*/
  $("#getQuote").on("click", function(){
    getQuote();
  });
});<commit_msg>Update index.js<commit_after>$(document).ready(function() {
  /*This function returns a tweetable string*/
  function tweetSize(quote, author) {
    var tweet = "";
    var len = quote.length + author.length +2;

    if (len > 140) {
      tweet += quote.substring(0, 133 - author.length);
      tweet += "... -" + author;
    }
    else {
      tweet += quote + " -" + author;
    }
    return escape(tweet);
  }

  /*This function calls the API, gets the quote and metadata and updates the html*/
  function getQuote() {
    $("#getQuote").html("Loading...");
    $.getJSON("http://api.forismatic.com/api/1.0/?method=getQuote&lang=en&format=jsonp&jsonp=?", function(data){
      var html = "
" + data.quoteText;
      if (data.quoteAuthor != "") {
        html += "

" + data.quoteAuthor + "
" +
          "" +
          "" +
          "
";
      }
      else {
        html += "

Author Unknown
" +
          "" +
          "
";
      }
      $(".message").html(html);
      $("#getQuote").html("New Quote");
      $("#quoteLink").attr("href", data.quoteLink);
      //http://twitter.com/home?status=Today is the tomorrow we worried about yesterday.  http://en.forismatic.com/6750845f01/ @forismatic
    });
  }

  /*Initialize*/
  getQuote(); //comment out when editing to reduce API calls

  /*the following calls getQuote() when button is pressed*/
  $("#getQuote").on("click", function(){
    getQuote();
  });
});
<|endoftext|>


<commit_before>var RLS = require('./util/RequestLocalStorage').getNamespace()
,	Cache = require("./TritonAgent/Cache")
,	Request = require("./TritonAgent/Request")
,	RequestPlugins = require("./TritonAgent/RequestPlugins")
;

// wrapper for superagent
function makeRequest (method, url) {
	return new Request(method, url, makeRequest.cache());
}

var API = {

	get (url, data) {
		var req = makeRequest('GET', url);
		if (data) req.query(data);
		return req;
	},

	head (url, data) {
		var req = makeRequest('HEAD', url);
		if (data) req.send(data);
		return req;
	},

	del (url) {
		return makeRequest('DELETE', url);
	},

	patch (url, data) {
		var req = makeRequest('PATCH', url);
		if (data) req.send(data);
		return req;
	},

	post (url, data) {
		var req = makeRequest('POST', url);
		if (data) req.send(data);
		return req;
	},

	put (url, data) {
		var req = makeRequest('PUT', url);
		if (data) req.send(data);
		return req;
	},

	/**
	 * Exposes the TritonAgent request data cache from RequestLocalStorage.
	 */
	cache () {
		var cache = RLS().cache;
		if (!cache) {
			cache = RLS().cache = new Cache();
		}
		return cache;
	},

	_clearCache () {
		delete RLS().cache;
	},

	/**
	 * Adds a plugin function that can be used to modify the Request
	 * object before the request is actually
	 * triggered.
	 *
	 * The callback function will take the Request instance as a parameter:
	 * ```
	 * var defaultHeaders = { ... };
	 * TritonAgent.plugRequest(function (request) {
	 *     // e.g.
	 *     request.set(defaultHeaders)
	 * })
	 * ```
	 */
	plugRequest (pluginFunc) {
		RequestPlugins.add(pluginFunc);
	},

}

module.exports = API;
<commit_msg>Fixing bug in TritonAgent<commit_after>var RLS = require('./util/RequestLocalStorage').getNamespace()
,	Cache = require("./TritonAgent/Cache")
,	Request = require("./TritonAgent/Request")
,	RequestPlugins = require("./TritonAgent/RequestPlugins")
;

// wrapper for superagent
function makeRequest (method, url) {
	return new Request(method, url, API.cache());
}

var API = {

	get (url, data) {
		var req = makeRequest('GET', url);
		if (data) req.query(data);
		return req;
	},

	head (url, data) {
		var req = makeRequest('HEAD', url);
		if (data) req.send(data);
		return req;
	},

	del (url) {
		return makeRequest('DELETE', url);
	},

	patch (url, data) {
		var req = makeRequest('PATCH', url);
		if (data) req.send(data);
		return req;
	},

	post (url, data) {
		var req = makeRequest('POST', url);
		if (data) req.send(data);
		return req;
	},

	put (url, data) {
		var req = makeRequest('PUT', url);
		if (data) req.send(data);
		return req;
	},

	/**
	 * Exposes the TritonAgent request data cache from RequestLocalStorage.
	 */
	cache () {
		var cache = RLS().cache;
		if (!cache) {
			cache = RLS().cache = new Cache();
		}
		return cache;
	},

	_clearCache () {
		delete RLS().cache;
	},

	/**
	 * Adds a plugin function that can be used to modify the Request
	 * object before the request is actually
	 * triggered.
	 *
	 * The callback function will take the Request instance as a parameter:
	 * ```
	 * var defaultHeaders = { ... };
	 * TritonAgent.plugRequest(function (request) {
	 *     // e.g.
	 *     request.set(defaultHeaders)
	 * })
	 * ```
	 */
	plugRequest (pluginFunc) {
		RequestPlugins.add(pluginFunc);
	},

}

module.exports = API;
<|endoftext|>


<commit_before>/**
* @fileoverview Interprets a given command and calls workspace controller_.functions.
* @author pandori@wisc.edu (Sahib Pandori)
* @author david.liang@wisc.edu (David Liang)
*/

'use strict';

goog.provide('SpeechBlocks.Interpreter');

goog.require('SpeechBlocks.Predecessor');
goog.require('SpeechBlocks.StatementInput')
goog.require('SpeechBlocks.Successor');
goog.require('SpeechBlocks.Translation');
goog.require('SpeechBlocks.ValueInput');
goog.require('goog.structs.Map');

/**
* Constructs an interpreter that takes actions as input and controls the Blockly Workspace.
* @param {!SpeechBlocks.Controller} controller_.The workspace controller_.
*/
SpeechBlocks.Interpreter = function(controller) {
  /** @private @const */
  this.controller_ = controller;
  /** @private */
  this.id_ = 1;
  /** @private */
  /**
  this.blockTypeMap_ = new goog.structs.Map();
  this.blockTypeMap_.set('if','controls_if');
  this.blockTypeMap_.set('comparison','logic_compare');
  this.blockTypeMap_.set('repeat','controls_repeat_ext');
  this.blockTypeMap_.set('number','math_number');
  this.blockTypeMap_.set('arithmetic','math_arithmetic');
  this.blockTypeMap_.set('text','text');
  this.blockTypeMap_.set('print','text_print');
  this.blockTypeMap_.set('set','variables_set');
  this.blockTypeMap_.set('variable','variables_get');
  */
  // temporary
  try {
    var rawFile = new XMLHttpRequest();
    rawFile.open("GET", 'https://aravart.github.io/speech-blocks/grammar/blockTypeMap.txt', true);
    rawFile.onreadystatechange = function () {
      if(rawFile.readyState == 4) {
        if(rawFile.status == 200 || rawFile.status == 0) {
          var inputText = rawFile.responseText;
          inputText = inputText.split(/\r\n|\r|\n/g);
          for (var i = 0; i < allText.length; i++) {
            var keyValuePair = inputText[i].split(":");
            this.blockTypeMap_.set(keyValuePair[0], keyValuePair[1]);
          }
          console.log(inputText);
        }
      }
      rawFile.send(null);
    }
    rawFile.onreadystatechange();
  } catch(err) { console.log(err.message); }
  console.log(this.blockTypeMap_.get('set');
}

/**
* Interprets a given command by calling the corresponding action function.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.interpret = function(command) {
  switch (command.action) {
    case 'run': this.run(command); break;
    case 'add': this.addBlock(command); break;
    case 'move': this.moveBlock(command); break;
    case 'modify': this.modifyBlock(command); break;
    case 'delete': this.deleteBlock(command); break;
    default: console.log('Unsupported command');
  }
};

/**
* Compiles the Blockly code into JavaScript and runs it.
* @param {Object=} command Object with command specifics from the parser.
*/
SpeechBlocks.Interpreter.prototype.run = function(command) {
  Blockly.JavaScript.addReservedWords('code');
  var code = Blockly.JavaScript.workspaceToCode(this.controller_.workspace);
  eval(code);
};

/**
* Adds a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.addBlock = function(command) {
  var type = this.blockTypeMap_.get(command.type);
  if (type != null) { this.controller_.addBlock(type, (this.id_++).toString(), new SpeechBlocks.Translation(0,0)); }
};

/**
* @TODO Implement error checking
* Moves a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.moveBlock = function(command) {
  // ensure these fields are strings, so validity checking works properly
  command.block = command.block.toString();
  command.where.block = command.where.block.toString();
  if (this.isBlockIdValid(command.block)) {
    if (command.where == 'trash') {
      this.deleteBlock(command.block);
    } else {
      if (this.isBlockIdValid(command.where.block)) {
        switch (command.where.position) {
          // modify these so the 'where' field is right
          case 'after': this.controller_.moveBlock(command.block, new SpeechBlocks.Successor(command.where.block)); break;
          case 'before': this.controller_.moveBlock(command.block, new SpeechBlocks.Predecessor(command.where.block)); break;
          case 'lhs': case 'rhs': case 'to the right of':
          var inputList_ = this.controller_.getBlockValueInputs(command.where.block);
          if (inputList_.length < 1) { console.log('NO VALUE INPUTS FOR SPECIFIED BLOCK'); }
          else if (command.where.position == 'rhs' || command.where.position == 'to the right of') { this.controller_.moveBlock(command.block, new SpeechBlocks.ValueInput(command.where.block, inputList_[inputList_.length-1]));	}
          else { this.controller_.moveBlock(command.block, new SpeechBlocks.ValueInput(command.where.block, inputList_[0])); }
          case 'inside':
          var statementList_ = this.controller_.getBlockStatementInputs(command.where.block);
          if (statementList_.length < 1) { console.log('NO STATEMENT INPUTS FOR SPECIFIED BLOCK'); }
          else { this.controller_.moveBlock(command.block, new SpeechBlocks.StatementInput(command.where.block, statementList_[statementList_.length-1])); }
          break;
          default:
          console.log('Unsupported position');
        }
      }
    }
  }
  else {
    console.log('Invalid block Id');
  }
};

/**
* @TODO Implement each case of property
* Modifies a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.modifyBlock = function(command) {
  if (this.isBlockIdValid(command.block)) {
    switch(command.property) {
      case 'number':
      command.value = Number(command.value);
      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'text':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'comparison':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'operation':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'name':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      default:
      console.log('Unsupported property');
    }
    console.log('MODIFY NOT YET SUPPORTED');
  }
  else {
    console.log('Invalid block Id');
  }
};

/**
* Delete a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.deleteBlock = function(blockId) {
  if (this.isBlockIdValid(blockId)) { this.controller_.removeBlock(blockId); }
  else { console.log('Invalid block Id'); }
};

/**
* Checks to see if a block Id is valid.
* @param {!String=} blockId as string.
*/
SpeechBlocks.Interpreter.prototype.isBlockIdValid = function(blockRequestId) {
  return this.controller_.getAllBlockIds().contains(blockRequestId);
}
<commit_msg>File IO testing<commit_after>/**
* @fileoverview Interprets a given command and calls workspace controller_.functions.
* @author pandori@wisc.edu (Sahib Pandori)
* @author david.liang@wisc.edu (David Liang)
*/

'use strict';

goog.provide('SpeechBlocks.Interpreter');

goog.require('SpeechBlocks.Predecessor');
goog.require('SpeechBlocks.StatementInput')
goog.require('SpeechBlocks.Successor');
goog.require('SpeechBlocks.Translation');
goog.require('SpeechBlocks.ValueInput');
goog.require('goog.structs.Map');

/**
* Constructs an interpreter that takes actions as input and controls the Blockly Workspace.
* @param {!SpeechBlocks.Controller} controller_.The workspace controller_.
*/
SpeechBlocks.Interpreter = function(controller) {
  /** @private @const */
  this.controller_ = controller;
  /** @private */
  this.id_ = 1;
  /** @private */
  /**
  this.blockTypeMap_ = new goog.structs.Map();
  this.blockTypeMap_.set('if','controls_if');
  this.blockTypeMap_.set('comparison','logic_compare');
  this.blockTypeMap_.set('repeat','controls_repeat_ext');
  this.blockTypeMap_.set('number','math_number');
  this.blockTypeMap_.set('arithmetic','math_arithmetic');
  this.blockTypeMap_.set('text','text');
  this.blockTypeMap_.set('print','text_print');
  this.blockTypeMap_.set('set','variables_set');
  this.blockTypeMap_.set('variable','variables_get');
  */
  // temporary
  try {
    var rawFile = new XMLHttpRequest();
    rawFile.open("GET", 'https://aravart.github.io/speech-blocks/grammar/blockTypeMap.txt', true);
    rawFile.onreadystatechange = function () {
      if(rawFile.readyState == 4) {
        if(rawFile.status == 200 || rawFile.status == 0) {
          var inputText = rawFile.responseText;
          inputText = inputText.split(/\r\n|\r|\n/g);
          for (var i = 0; i < allText.length; i++) {
            var keyValuePair = inputText[i].split(":");
            this.blockTypeMap_.set(keyValuePair[0], keyValuePair[1]);
          }
          console.log(inputText);
        }
      }
      rawFile.send(null);
    }
    rawFile.onreadystatechange();
  } catch(err) { console.log(err.message); }
  console.log(this.blockTypeMap_.get('set'));
}

/**
* Interprets a given command by calling the corresponding action function.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.interpret = function(command) {
  switch (command.action) {
    case 'run': this.run(command); break;
    case 'add': this.addBlock(command); break;
    case 'move': this.moveBlock(command); break;
    case 'modify': this.modifyBlock(command); break;
    case 'delete': this.deleteBlock(command); break;
    default: console.log('Unsupported command');
  }
};

/**
* Compiles the Blockly code into JavaScript and runs it.
* @param {Object=} command Object with command specifics from the parser.
*/
SpeechBlocks.Interpreter.prototype.run = function(command) {
  Blockly.JavaScript.addReservedWords('code');
  var code = Blockly.JavaScript.workspaceToCode(this.controller_.workspace);
  eval(code);
};

/**
* Adds a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.addBlock = function(command) {
  var type = this.blockTypeMap_.get(command.type);
  if (type != null) { this.controller_.addBlock(type, (this.id_++).toString(), new SpeechBlocks.Translation(0,0)); }
};

/**
* @TODO Implement error checking
* Moves a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.moveBlock = function(command) {
  // ensure these fields are strings, so validity checking works properly
  command.block = command.block.toString();
  command.where.block = command.where.block.toString();
  if (this.isBlockIdValid(command.block)) {
    if (command.where == 'trash') {
      this.deleteBlock(command.block);
    } else {
      if (this.isBlockIdValid(command.where.block)) {
        switch (command.where.position) {
          // modify these so the 'where' field is right
          case 'after': this.controller_.moveBlock(command.block, new SpeechBlocks.Successor(command.where.block)); break;
          case 'before': this.controller_.moveBlock(command.block, new SpeechBlocks.Predecessor(command.where.block)); break;
          case 'lhs': case 'rhs': case 'to the right of':
          var inputList_ = this.controller_.getBlockValueInputs(command.where.block);
          if (inputList_.length < 1) { console.log('NO VALUE INPUTS FOR SPECIFIED BLOCK'); }
          else if (command.where.position == 'rhs' || command.where.position == 'to the right of') { this.controller_.moveBlock(command.block, new SpeechBlocks.ValueInput(command.where.block, inputList_[inputList_.length-1]));	}
          else { this.controller_.moveBlock(command.block, new SpeechBlocks.ValueInput(command.where.block, inputList_[0])); }
          case 'inside':
          var statementList_ = this.controller_.getBlockStatementInputs(command.where.block);
          if (statementList_.length < 1) { console.log('NO STATEMENT INPUTS FOR SPECIFIED BLOCK'); }
          else { this.controller_.moveBlock(command.block, new SpeechBlocks.StatementInput(command.where.block, statementList_[statementList_.length-1])); }
          break;
          default:
          console.log('Unsupported position');
        }
      }
    }
  }
  else {
    console.log('Invalid block Id');
  }
};

/**
* @TODO Implement each case of property
* Modifies a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.modifyBlock = function(command) {
  if (this.isBlockIdValid(command.block)) {
    switch(command.property) {
      case 'number':
      command.value = Number(command.value);
      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'text':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'comparison':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'operation':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      case 'name':

      this.controller.setBlockField(command.block, fieldName, command.value);
      break;
      default:
      console.log('Unsupported property');
    }
    console.log('MODIFY NOT YET SUPPORTED');
  }
  else {
    console.log('Invalid block Id');
  }
};

/**
* Delete a specified block.
* @param {Object=} command Command object from parser.
*/
SpeechBlocks.Interpreter.prototype.deleteBlock = function(blockId) {
  if (this.isBlockIdValid(blockId)) { this.controller_.removeBlock(blockId); }
  else { console.log('Invalid block Id'); }
};

/**
* Checks to see if a block Id is valid.
* @param {!String=} blockId as string.
*/
SpeechBlocks.Interpreter.prototype.isBlockIdValid = function(blockRequestId) {
  return this.controller_.getAllBlockIds().contains(blockRequestId);
}
<|endoftext|>


<commit_before>'use strict'

const bufferapp = require('buffer-node')
const CONFIG = require('config').buffer
const {each} = require('async')
const {get} = require('lodash')

const compose = require('./compose')

const accessToken = get(global, CONFIG.access_token)
const client = bufferapp(accessToken)

function update (doc, cb) {
  const text = compose(doc)
  return client.updates.create(text, CONFIG.accounts).nodeify(cb)
}

const updateDocs = (docs, cb) => each(docs, update, cb)

module.exports = updateDocs
<commit_msg>shuffle new promotions<commit_after>'use strict'

const bufferapp = require('buffer-node')
const CONFIG = require('config').buffer
const {each, waterfall} = require('async')
const {get} = require('lodash')

const compose = require('./compose')
const {accounts, access_token} = CONFIG

const accessToken = get(global, access_token)
const client = bufferapp(accessToken)

function createUpdate (doc, cb) {
  const text = compose(doc)
  return client.updates.create(text, accounts).nodeify(cb)
}

const createUpdates = (docs, cb) => each(docs, createUpdate, cb)
const shuffleAccount = (account, cb) => client.profile(account).updates.shuffle().nodeify(cb)
const shuffle = (cb) => each(accounts, shuffleAccount, cb)

function share (docs, cb) {
  const tasks = [
    (next) => createUpdates(docs, next),
    (res, next) => shuffle(next)
  ]
  return waterfall(tasks, cb)
}

module.exports = share
<|endoftext|>


<commit_before>const _ = require('lodash');
const Promise = require('bluebird');
const errors = require('@tryghost/errors');
const logging = require('@tryghost/logging');
const tpl = require('@tryghost/tpl');

const settingsCache = require('./settings-cache');
const config = require('./config');

const messages = {
    errorMessage: 'The \\{\\{{helperName}\\}\\} helper is not available.',
    errorContext: 'The {flagName} flag must be enabled in labs if you wish to use the \\{\\{{helperName}\\}\\} helper.',
    errorHelp: 'See {url}'
};

// flags in this list always return `true`, allows quick global enable prior to full flag removal
const GA_FEATURES = [
    'multipleProducts',
    'tierWelcomePages',
    'tierName',
    'selectablePortalLinks',
    'membersTableStatus',
    'improvedOnboarding',
    'membersActivityFeed'
];

// NOTE: this allowlist is meant to be used to filter out any unexpected
//       input for the "labs" setting value
const BETA_FEATURES = [
    'activitypub'
];

const ALPHA_FEATURES = [
    'oauthLogin',
    'membersActivity',
    'urlCache',
    'beforeAfterCard',
    'tweetGridCard'
];

module.exports.GA_KEYS = [...GA_FEATURES];
module.exports.WRITABLE_KEYS_ALLOWLIST = [...BETA_FEATURES, ...ALPHA_FEATURES];

module.exports.getAll = () => {
    const labs = _.cloneDeep(settingsCache.get('labs')) || {};

    ALPHA_FEATURES.forEach((alphaKey) => {
        if (labs[alphaKey] && !(config.get('enableDeveloperExperiments') || process.env.NODE_ENV.startsWith('test'))) {
            delete labs[alphaKey];
        }
    });

    GA_FEATURES.forEach((gaKey) => {
        labs[gaKey] = true;
    });

    labs.members = settingsCache.get('members_signup_access') !== 'none';

    return labs;
};

/**
 * @param {string} flag
 * @returns {boolean}
 */
module.exports.isSet = function isSet(flag) {
    const labsConfig = module.exports.getAll();

    return !!(labsConfig && labsConfig[flag] && labsConfig[flag] === true);
};

/**
 *
 * @param {object} options
 * @param {string} options.flagKey the internal lookup key of the flag e.g. labs.isSet(matchHelper)
 * @param {string} options.flagName the user-facing name of the flag e.g. Match helper
 * @param {string} options.helperName Name of the helper to be enabled/disabled
 * @param {string} [options.errorMessage] Optional replacement error message
 * @param {string} [options.errorContext] Optional replacement context message
 * @param {string} [options.errorHelp] Optional replacement help message
 * @param {string} [options.helpUrl] Url to show in the help message
 * @param {string} [options.async] is the helper async?
 * @param {function} callback
 * @returns {Promise<Handlebars.SafeString>|Handlebars.SafeString}
 */
module.exports.enabledHelper = function enabledHelper(options, callback) {
    const errDetails = {};
    let errString;

    if (module.exports.isSet(options.flagKey) === true) {
        // helper is active, use the callback
        return callback();
    }

    // Else, the helper is not active and we need to handle this as an error
    errDetails.message = tpl(options.errorMessage || messages.errorMessage, {helperName: options.helperName});
    errDetails.context = tpl(options.errorContext || messages.errorContext, {
        helperName: options.helperName,
        flagName: options.flagName
    });
    errDetails.help = tpl(options.errorHelp || messages.errorHelp, {url: options.helpUrl});

    // eslint-disable-next-line no-restricted-syntax
    logging.error(new errors.DisabledFeatureError(errDetails));

    const {SafeString} = require('express-hbs');
    errString = new SafeString(`<script>console.error("${_.values(errDetails).join(' ')}");</script>`);

    if (options.async) {
        return Promise.resolve(errString);
    }

    return errString;
};

module.exports.enabledMiddleware = flag => (req, res, next) => {
    if (module.exports.isSet(flag) === true) {
        return next();
    } else {
        return next(new errors.NotFoundError());
    }
};
<commit_msg>Added multiple newsletters flag<commit_after>const _ = require('lodash');
const Promise = require('bluebird');
const errors = require('@tryghost/errors');
const logging = require('@tryghost/logging');
const tpl = require('@tryghost/tpl');

const settingsCache = require('./settings-cache');
const config = require('./config');

const messages = {
    errorMessage: 'The \\{\\{{helperName}\\}\\} helper is not available.',
    errorContext: 'The {flagName} flag must be enabled in labs if you wish to use the \\{\\{{helperName}\\}\\} helper.',
    errorHelp: 'See {url}'
};

// flags in this list always return `true`, allows quick global enable prior to full flag removal
const GA_FEATURES = [
    'multipleProducts',
    'tierWelcomePages',
    'tierName',
    'selectablePortalLinks',
    'membersTableStatus',
    'improvedOnboarding',
    'membersActivityFeed'
];

// NOTE: this allowlist is meant to be used to filter out any unexpected
//       input for the "labs" setting value
const BETA_FEATURES = [
    'activitypub'
];

const ALPHA_FEATURES = [
    'oauthLogin',
    'membersActivity',
    'urlCache',
    'beforeAfterCard',
    'tweetGridCard',
    'multipleNewsletters'
];

module.exports.GA_KEYS = [...GA_FEATURES];
module.exports.WRITABLE_KEYS_ALLOWLIST = [...BETA_FEATURES, ...ALPHA_FEATURES];

module.exports.getAll = () => {
    const labs = _.cloneDeep(settingsCache.get('labs')) || {};

    ALPHA_FEATURES.forEach((alphaKey) => {
        if (labs[alphaKey] && !(config.get('enableDeveloperExperiments') || process.env.NODE_ENV.startsWith('test'))) {
            delete labs[alphaKey];
        }
    });

    GA_FEATURES.forEach((gaKey) => {
        labs[gaKey] = true;
    });

    labs.members = settingsCache.get('members_signup_access') !== 'none';

    return labs;
};

/**
 * @param {string} flag
 * @returns {boolean}
 */
module.exports.isSet = function isSet(flag) {
    const labsConfig = module.exports.getAll();

    return !!(labsConfig && labsConfig[flag] && labsConfig[flag] === true);
};

/**
 *
 * @param {object} options
 * @param {string} options.flagKey the internal lookup key of the flag e.g. labs.isSet(matchHelper)
 * @param {string} options.flagName the user-facing name of the flag e.g. Match helper
 * @param {string} options.helperName Name of the helper to be enabled/disabled
 * @param {string} [options.errorMessage] Optional replacement error message
 * @param {string} [options.errorContext] Optional replacement context message
 * @param {string} [options.errorHelp] Optional replacement help message
 * @param {string} [options.helpUrl] Url to show in the help message
 * @param {string} [options.async] is the helper async?
 * @param {function} callback
 * @returns {Promise<Handlebars.SafeString>|Handlebars.SafeString}
 */
module.exports.enabledHelper = function enabledHelper(options, callback) {
    const errDetails = {};
    let errString;

    if (module.exports.isSet(options.flagKey) === true) {
        // helper is active, use the callback
        return callback();
    }

    // Else, the helper is not active and we need to handle this as an error
    errDetails.message = tpl(options.errorMessage || messages.errorMessage, {helperName: options.helperName});
    errDetails.context = tpl(options.errorContext || messages.errorContext, {
        helperName: options.helperName,
        flagName: options.flagName
    });
    errDetails.help = tpl(options.errorHelp || messages.errorHelp, {url: options.helpUrl});

    // eslint-disable-next-line no-restricted-syntax
    logging.error(new errors.DisabledFeatureError(errDetails));

    const {SafeString} = require('express-hbs');
    errString = new SafeString(`<script>console.error("${_.values(errDetails).join(' ')}");</script>`);

    if (options.async) {
        return Promise.resolve(errString);
    }

    return errString;
};

module.exports.enabledMiddleware = flag => (req, res, next) => {
    if (module.exports.isSet(flag) === true) {
        return next();
    } else {
        return next(new errors.NotFoundError());
    }
};
<|endoftext|>


<commit_before>(function() {

var sliders = [ ];
var hpSlider = null;
var hpLast = 1;

/* * * * * Functions * * * * */

var parseUnit = function(element,n) {
    return {
        'name'    : element[0]  , 'type'     : element[1]  ,
        'class'   : element[2]  , 'stars'    : element[3]  ,
        'cost'    : element[4]  , 'maxLevel' : element[5]  ,
        'minHP'   : element[6]  , 'minATK'   : element[7]  ,
        'minRCV'  : element[8]  , 'maxHP'    : element[9]  ,
        'maxATK'  : element[10] , 'maxRCV'   : element[11] ,
        'number' : n
    };
};

//var getCoordinates = function(n) {
    //var source = ('000' + Math.ceil((n+1) / 100)).slice(-3);
    //var x = Math.floor((n % 100) / 10) * 112;
    //var y = ((n % 100) % 10) * 112;
    //return [source,-y-1,-x-1];
//};

var getThumbnailUrl = function(n) {
    var id = ('0000' + (n+1)).slice(-4).replace(/(057[54])/,'0$1'); // missing aokiji image
    return 'http://onepiece-treasurecruise.com/wp-content/uploads/f' + id + '.png';
};

var updateSlot = function(slotNumber,unitNumber) {
    var slot = $('.unit')[slotNumber];
    var unit = units[unitNumber];
    // change background
    //var coordinates = getCoordinates(unitNumber);
    //slot.style.backgroundImage = 'url(images/' + coordinates[0] + '.jpg)';
    //slot.style.backgroundPosition = coordinates[1] + 'px ' + coordinates[2] + 'px';
    slot.classList.remove('empty');
    slot.style.backgroundImage = 'url(' + getThumbnailUrl(unitNumber) + ')';
    // update slider
    var index = $(slot).index();
    sliders[index].setRange(1,units[unitNumber].maxLevel);
    // reset level
    changeLevel(index,1);
};

var changeLevel = function(slotNumber,level) {
    var slot = $($('.unit')[slotNumber]);
    slot.find('.unitLevel').text('Lv.' + level);
};

var updateHP = function(currentHP,skipTrigger) {
    currentHP = Math.floor(currentHP);
    var percHP = Math.round(currentHP / hpLast * 10000) / 100;
    $('#hpLabel').text(currentHP + ' HP (' + percHP + '%)');
    if (!skipTrigger) $(document).trigger('hpChanged',[ currentHP, hpLast, percHP ]);
};

var changeHP = function(event,value) {
    updateHP(value,false);
};

var slideHP = function(event,value) {
    updateHP(value,true);
};

var onButtonClick = function() {
    if (this.classList.contains('selected')) return;
    var bonus = parseFloat(this.textContent,10);
    if (isNaN(bonus)) bonus = 1;
    $(document).trigger('merryBonusUpdated',bonus);
};

/* * * * * Body * * * * */

$(function() {

    // bootstrap

    units = units.map(parseUnit);

    // attach events

    $('.unit').mouseup(function(e) {
        if (e.which == 1 && !this.classList.contains('slide'))
            $(document).trigger('unitClick',$(this).index());
    });

    $('.unitLevel').mouseup(function(e) {
        if (e.which == 1 && !this.parentNode.classList.contains('empty'))
            $(this)[0].parentNode.classList.add('slide');
        e.preventDefault();
        e.stopPropagation();
    });

    $('.unitSlider').each(function(n,x) {
        sliders.push($(x).CircularSlider({
            radius: 44,
            onSlideEnd: function(ui,value) {
                $(ui).parent()[0].classList.remove('slide');
                $(document).trigger('unitLevelChanged',[n,value]);
            },
            slide: function() { }
        }));
    });

    $(document).on('unitPicked',function(event,slotNumber,unitNumber) {
        updateSlot(slotNumber,unitNumber);
    });

    $(document).on('unitLevelChanged',function(event,slotNumber,level) {
        changeLevel(slotNumber,level);
    });

    $(document).on('numbersCrunched',function(event,numbers) {
        // set damage
        Object.keys(numbers).forEach(function(type) {
            if (type == 'HP') return;
            var damage = ''+Math.floor(numbers[type]);
            damage = damage.split('').reverse().join('')
                           .replace(/(\d{3,3})/g,'$1,')
                           .split('').reverse().join('')
                           .replace(/^,|,$/g,'');
            $('#' + type.toLowerCase()).text(damage);
        });
        // set hp
        if (numbers.HP == hpLast) return;
        var currentPosition = hpSlider.val() / hpLast;
        hpLast = numbers.HP;
        $('#hpSlider').noUiSlider({
            range: { min: [ 1 ], max: [ numbers.HP ] }
        },true);
        var currentHP = Math.floor(currentPosition * numbers.HP);
        hpSlider.val(currentHP);
        updateHP(currentHP,true);
    });

    $(document).on('merryBonusUpdated',function(event,merry) {
        $('button.selected')[0].classList.remove('selected');
        $('button')[merry == 1.0 ? 0 : merry == 1.2 ? 1 : 2].classList.add('selected');
    });

    // set up ui elements

    hpSlider = $('#hpSlider').noUiSlider({
        start: [ 0 ],
        range: { min: [ 1 ], max: [ 1 ] },
        connect: 'lower'
    });

    hpSlider.on({
        change: changeHP,
        slide: slideHP
    });

    $('button').click(onButtonClick);

});

})();
<commit_msg>fixed hp not loading<commit_after>(function() {

var sliders = [ ];
var hpSlider = null;
var hpLast = 1;

/* * * * * Functions * * * * */

var parseUnit = function(element,n) {
    return {
        'name'    : element[0]  , 'type'     : element[1]  ,
        'class'   : element[2]  , 'stars'    : element[3]  ,
        'cost'    : element[4]  , 'maxLevel' : element[5]  ,
        'minHP'   : element[6]  , 'minATK'   : element[7]  ,
        'minRCV'  : element[8]  , 'maxHP'    : element[9]  ,
        'maxATK'  : element[10] , 'maxRCV'   : element[11] ,
        'number' : n
    };
};

//var getCoordinates = function(n) {
    //var source = ('000' + Math.ceil((n+1) / 100)).slice(-3);
    //var x = Math.floor((n % 100) / 10) * 112;
    //var y = ((n % 100) % 10) * 112;
    //return [source,-y-1,-x-1];
//};

var getThumbnailUrl = function(n) {
    var id = ('0000' + (n+1)).slice(-4).replace(/(057[54])/,'0$1'); // missing aokiji image
    return 'http://onepiece-treasurecruise.com/wp-content/uploads/f' + id + '.png';
};

var updateSlot = function(slotNumber,unitNumber) {
    var slot = $('.unit')[slotNumber];
    var unit = units[unitNumber];
    // change background
    //var coordinates = getCoordinates(unitNumber);
    //slot.style.backgroundImage = 'url(images/' + coordinates[0] + '.jpg)';
    //slot.style.backgroundPosition = coordinates[1] + 'px ' + coordinates[2] + 'px';
    slot.classList.remove('empty');
    slot.style.backgroundImage = 'url(' + getThumbnailUrl(unitNumber) + ')';
    // update slider
    var index = $(slot).index();
    sliders[index].setRange(1,units[unitNumber].maxLevel);
    // reset level
    changeLevel(index,1);
};

var changeLevel = function(slotNumber,level) {
    var slot = $($('.unit')[slotNumber]);
    slot.find('.unitLevel').text('Lv.' + level);
};

var updateHP = function(currentHP,skipTrigger) {
    currentHP = Math.floor(currentHP);
    var percHP = Math.round(currentHP / hpLast * 10000) / 100;
    $('#hpLabel').text(currentHP + ' HP (' + percHP + '%)');
    if (!skipTrigger) $(document).trigger('hpChanged',[ currentHP, hpLast, percHP, true ]);
};

var changeHP = function(event,value) {
    updateHP(value,false);
};

var slideHP = function(event,value) {
    updateHP(value,true);
};

var onButtonClick = function() {
    if (this.classList.contains('selected')) return;
    var bonus = parseFloat(this.textContent,10);
    if (isNaN(bonus)) bonus = 1;
    $(document).trigger('merryBonusUpdated',bonus);
};

/* * * * * Body * * * * */

$(function() {

    // bootstrap

    units = units.map(parseUnit);

    // attach events

    $('.unit').mouseup(function(e) {
        if (e.which == 1 && !this.classList.contains('slide'))
            $(document).trigger('unitClick',$(this).index());
    });

    $('.unitLevel').mouseup(function(e) {
        if (e.which == 1 && !this.parentNode.classList.contains('empty'))
            $(this)[0].parentNode.classList.add('slide');
        e.preventDefault();
        e.stopPropagation();
    });

    $('.unitSlider').each(function(n,x) {
        sliders.push($(x).CircularSlider({
            radius: 44,
            onSlideEnd: function(ui,value) {
                $(ui).parent()[0].classList.remove('slide');
                $(document).trigger('unitLevelChanged',[n,value]);
            },
            slide: function() { }
        }));
    });

    $(document).on('unitPicked',function(event,slotNumber,unitNumber) {
        updateSlot(slotNumber,unitNumber);
    });

    $(document).on('unitLevelChanged',function(event,slotNumber,level) {
        changeLevel(slotNumber,level);
    });

    $(document).on('numbersCrunched',function(event,numbers) {
        // set damage
        Object.keys(numbers).forEach(function(type) {
            if (type == 'HP') return;
            var damage = ''+Math.floor(numbers[type]);
            damage = damage.split('').reverse().join('')
                           .replace(/(\d{3,3})/g,'$1,')
                           .split('').reverse().join('')
                           .replace(/^,|,$/g,'');
            $('#' + type.toLowerCase()).text(damage);
        });
        // set hp
        if (numbers.HP == hpLast) return;
        var currentPosition = hpSlider.val() / hpLast;
        hpLast = numbers.HP;
        $('#hpSlider').noUiSlider({
            range: { min: [ 1 ], max: [ numbers.HP ] }
        },true);
        var currentHP = Math.floor(currentPosition * numbers.HP);
        hpSlider.val(currentHP);
        updateHP(currentHP,true);
    });

    $(document).on('merryBonusUpdated',function(event,merry) {
        $('button.selected')[0].classList.remove('selected');
        $('button')[merry == 1.0 ? 0 : merry == 1.2 ? 1 : 2].classList.add('selected');
    });

    $(document).on('hpChanged',function(event,current,max,perc,skip) {
        if (skip) return;
        $('#hpSlider').noUiSlider({
            range: { min: [ 1 ], max: [ max ] }
        },true);
        hpSlider.val(current);
        updateHP(current,true);
    });

    // set up ui elements

    hpSlider = $('#hpSlider').noUiSlider({
        start: [ 0 ],
        range: { min: [ 1 ], max: [ 1 ] },
        connect: 'lower'
    });

    hpSlider.on({
        change: changeHP,
        slide: slideHP
    });

    $('button').click(onButtonClick);

});

})();
<|endoftext|>


<commit_before>angular.module('ion-google-place', [])
    .directive('ionGooglePlace', [
        '$ionicTemplateLoader',
        '$ionicBackdrop',
        '$ionicPlatform',
        '$q',
        '$timeout',
        '$rootScope',
        '$document',
        function($ionicTemplateLoader, $ionicBackdrop, $ionicPlatform, $q, $timeout, $rootScope, $document) {
            return {
                require: '?ngModel',
                restrict: 'E',
                template: '<input type="text" readonly="readonly" class="ion-google-place" autocomplete="off">',
                replace: true,
                scope: {
                    ngModel: '=?',
                    geocodeOptions: '=',
                    currentLocation: '@'
                },
                link: function(scope, element, attrs, ngModel) {
                    var unbindBackButtonAction;

                    scope.locations = [];
                    var geocoder = new google.maps.Geocoder();
                    var searchEventTimeout = undefined;

                    scope.displayCurrentLocation = false;
                    scope.currentLocation = scope.currentLocation === "true"? true:false;

                    if(!!navigator.geolocation && scope.currentLocation){
                        scope.displayCurrentLocation = true;
                    }
                    var POPUP_TPL = [
                        '
',
                            '
',
                                '',
                                    '',
                                    '<input class="google-place-search" type="search" ng-model="searchQuery" placeholder="' + (attrs.searchPlaceholder || 'Enter an address, place or ZIP code') + '">',
                                '',
                                '<button class="button button-clear">',
                                    attrs.labelCancel || 'Cancel',
                                '</button>',
                            '
',
                            '<ion-content class="has-header has-header">',
                                '<ion-list>',
                                    '<ion-item type="item-text-wrap" ng-click="setCurrentLocation()" ng-if="displayCurrentLocation">',
                                        'Use current location',
                                    '</ion-item>',
                                    '<ion-item ng-repeat="location in locations" type="item-text-wrap" ng-click="selectLocation(location)">',
                                        '{{location.formatted_address}}',
                                    '</ion-item>',
                                '</ion-list>',
                            '</ion-content>',
                        '
'
                    ].join('');

                    var popupPromise = $ionicTemplateLoader.compile({
                        template: POPUP_TPL,
                        scope: scope,
                        appendTo: $document[0].body
                    });

                    popupPromise.then(function(el){
                        var searchInputElement = angular.element(el.element.find('input'));

                        scope.selectLocation = function(location){
                            ngModel.$setViewValue(location);
                            ngModel.$render();
                            el.element.css('display', 'none');
                            $ionicBackdrop.release();

                            if (unbindBackButtonAction) {
                                unbindBackButtonAction();
                                unbindBackButtonAction = null;
                            }
                            scope.$emit('ionGooglePlaceSetLocation',location);
                        };

                        scope.setCurrentLocation = function(){
                            var location = {
                                formatted_address: 'getting current location...'
                            };
                            ngModel.$setViewValue(location);
                            ngModel.$render();
                            el.element.css('display', 'none');
                            $ionicBackdrop.release();
                            getLocation()
                                .then(reverseGeocoding)
                                .then(function(location){
                                    ngModel.$setViewValue(location);
                                    element.attr('value', location.formatted_address);
                                    ngModel.$render();
                                    el.element.css('display', 'none');
                                    $ionicBackdrop.release();
                                })
                                .catch(function(error){
                                    console.log('erreur catch',error);
                                    //if(error.from == 'getLocation'){
                                    //    getLocationError(error);
                                    //} else {
                                    //    //TODO when error from reverse geocode
                                    //}
                                    var location = {
                                        formatted_address: 'Error in getting current location'
                                    };
                                    ngModel.$setViewValue(location);
                                    ngModel.$render();
                                    el.element.css('display', 'none');
                                    $ionicBackdrop.release();
                                    $timeout(function(){
                                        ngModel.$setViewValue(null);
                                        ngModel.$render();
                                        el.element.css('display', 'none');
                                        $ionicBackdrop.release();
                                    }, 2000);
                                });
                        };

                        scope.$watch('searchQuery', function(query){
                            if (searchEventTimeout) $timeout.cancel(searchEventTimeout);
                            searchEventTimeout = $timeout(function() {
                                if(!query) return;
                                if(query.length < 3);

                                var req = scope.geocodeOptions || {};
                                req.address = query;
                                geocoder.geocode(req, function(results, status) {
                                    if (status == google.maps.GeocoderStatus.OK) {
                                        scope.$apply(function(){
                                            scope.locations = results;
                                        });
                                    } else {
                                        // @TODO: Figure out what to do when the geocoding fails
                                    }
                                });
                            }, 350); // we're throttling the input by 350ms to be nice to google's API
                        });

                        var onClick = function(e){
                            e.preventDefault();
                            e.stopPropagation();

                            $ionicBackdrop.retain();
                            unbindBackButtonAction = $ionicPlatform.registerBackButtonAction(closeOnBackButton, 250);

                            el.element.css('display', 'block');
                            searchInputElement[0].focus();
                            setTimeout(function(){
                                searchInputElement[0].focus();
                            },0);
                        };

                        var onCancel = function(e){
                            scope.searchQuery = '';
                            $ionicBackdrop.release();
                            el.element.css('display', 'none');

                            if (unbindBackButtonAction){
                                unbindBackButtonAction();
                                unbindBackButtonAction = null;
                            }
                        };

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

                            el.element.css('display', 'none');
                            $ionicBackdrop.release();

                            if (unbindBackButtonAction){
                                unbindBackButtonAction();
                                unbindBackButtonAction = null;
                            }
                        }

                        element.bind('click', onClick);
                        element.bind('touchend', onClick);

                        el.element.find('button').bind('click', onCancel);
                    });

                    if(attrs.placeholder){
                        element.attr('placeholder', attrs.placeholder);
                    }

                    ngModel.$formatters.unshift(function (modelValue) {
                        if (!modelValue) return '';
                        return modelValue;
                    });

                    ngModel.$parsers.unshift(function (viewValue) {
                        return viewValue;
                    });

                    ngModel.$render = function(){
                        if(!ngModel.$viewValue){
                            element.val('');
                        } else {
                            element.val(ngModel.$viewValue.formatted_address || '');
                        }
                    };

                    scope.$on("$destroy", function(){
                        if (unbindBackButtonAction){
                            unbindBackButtonAction();
                            unbindBackButtonAction = null;
                        }
                    });

                    function getLocation() {
                        return $q(function (resolve, reject) {
                            navigator.geolocation.getCurrentPosition(function (position) {
                                resolve(position);
                            }, function (error) {
                                error.from = 'getLocation';
                                reject(error);
                            });
                        });
                    }

                    function reverseGeocoding(location) {
                        return $q(function (resolve, reject) {
                            var latlng = {
                                lat: location.coords.latitude,
                                lng: location.coords.longitude
                            };
                            geocoder.geocode({'location': latlng}, function (results, status) {
                                if (status == google.maps.GeocoderStatus.OK) {
                                    if (results[1]) {
                                        resolve(results[1]);
                                    } else {
                                        resolve(results[0])
                                    }
                                } else {
                                    var error = {
                                        status: status,
                                        from: 'reverseGeocoding'
                                    };
                                    reject(error);
                                }
                            })
                        });
                    }
                }
            };
        }
    ]);
<commit_msg>Minor fix<commit_after>angular.module('ion-google-place', [])
    .directive('ionGooglePlace', [
        '$ionicTemplateLoader',
        '$ionicBackdrop',
        '$ionicPlatform',
        '$q',
        '$timeout',
        '$rootScope',
        '$document',
        function($ionicTemplateLoader, $ionicBackdrop, $ionicPlatform, $q, $timeout, $rootScope, $document) {
            return {
                require: '?ngModel',
                restrict: 'E',
                template: '<input type="text" readonly="readonly" class="ion-google-place" autocomplete="off">',
                replace: true,
                scope: {
                    ngModel: '=?',
                    geocodeOptions: '=',
                    currentLocation: '@'
                },
                link: function(scope, element, attrs, ngModel) {
                    var unbindBackButtonAction;

                    console.log(attrs);

                    scope.locations = [];
                    var geocoder = new google.maps.Geocoder();
                    var searchEventTimeout = undefined;

                    scope.displayCurrentLocation = false;
                    scope.currentLocation = scope.currentLocation === "true"? true:false;

                    if(!!navigator.geolocation && scope.currentLocation){
                        scope.displayCurrentLocation = true;
                    }
                    var POPUP_TPL = [
                        '
',
                            '
',
                                '',
                                    '',
                                    '<input class="google-place-search" type="search" ng-model="searchQuery" placeholder="' + (attrs.searchPlaceholder || 'Enter an address, place or ZIP code') + '">',
                                '',
                                '<button class="button button-clear">',
                                    attrs.labelCancel || 'Cancel',
                                '</button>',
                            '
',
                            '<ion-content class="has-header has-header">',
                                '<ion-list>',
                                    '<ion-item type="item-text-wrap" ng-click="setCurrentLocation()" ng-if="displayCurrentLocation">',
                                        'Use current location',
                                    '</ion-item>',
                                    '<ion-item ng-repeat="location in locations" type="item-text-wrap" ng-click="selectLocation(location)">',
                                        '{{location.formatted_address}}',
                                    '</ion-item>',
                                '</ion-list>',
                            '</ion-content>',
                        '
'
                    ].join('');

                    var popupPromise = $ionicTemplateLoader.compile({
                        template: POPUP_TPL,
                        scope: scope,
                        appendTo: $document[0].body
                    });

                    popupPromise.then(function(el){
                        var searchInputElement = angular.element(el.element.find('input'));

                        scope.selectLocation = function(location){
                            ngModel.$setViewValue(location);
                            ngModel.$render();
                            el.element.css('display', 'none');
                            $ionicBackdrop.release();

                            if (unbindBackButtonAction) {
                                unbindBackButtonAction();
                                unbindBackButtonAction = null;
                            }
                            scope.$emit('ionGooglePlaceSetLocation',location);
                        };

                        scope.setCurrentLocation = function(){
                            var location = {
                                formatted_address: 'getting current location...'
                            };
                            ngModel.$setViewValue(location);
                            ngModel.$render();
                            el.element.css('display', 'none');
                            $ionicBackdrop.release();
                            getLocation()
                                .then(reverseGeocoding)
                                .then(function(location){
                                    ngModel.$setViewValue(location);
                                    element.attr('value', location.formatted_address);
                                    ngModel.$render();
                                    el.element.css('display', 'none');
                                    $ionicBackdrop.release();
                                })
                                .catch(function(error){
                                    console.log('erreur catch',error);
                                    //if(error.from == 'getLocation'){
                                    //    getLocationError(error);
                                    //} else {
                                    //    //TODO when error from reverse geocode
                                    //}
                                    var location = {
                                        formatted_address: 'Error in getting current location'
                                    };
                                    ngModel.$setViewValue(location);
                                    ngModel.$render();
                                    el.element.css('display', 'none');
                                    $ionicBackdrop.release();
                                    $timeout(function(){
                                        ngModel.$setViewValue(null);
                                        ngModel.$render();
                                        el.element.css('display', 'none');
                                        $ionicBackdrop.release();
                                    }, 2000);
                                });
                        };

                        scope.$watch('searchQuery', function(query){
                            if (searchEventTimeout) $timeout.cancel(searchEventTimeout);
                            searchEventTimeout = $timeout(function() {
                                if(!query) return;
                                if(query.length < 3);

                                var req = scope.geocodeOptions || {};
                                req.address = query;
                                geocoder.geocode(req, function(results, status) {
                                    if (status == google.maps.GeocoderStatus.OK) {
                                        scope.$apply(function(){
                                            scope.locations = results;
                                        });
                                    } else {
                                        // @TODO: Figure out what to do when the geocoding fails
                                    }
                                });
                            }, 350); // we're throttling the input by 350ms to be nice to google's API
                        });

                        var onClick = function(e){
                            e.preventDefault();
                            e.stopPropagation();

                            $ionicBackdrop.retain();
                            unbindBackButtonAction = $ionicPlatform.registerBackButtonAction(closeOnBackButton, 250);

                            el.element.css('display', 'block');
                            searchInputElement[0].focus();
                            setTimeout(function(){
                                searchInputElement[0].focus();
                            },0);
                        };

                        var onCancel = function(e){
                            scope.searchQuery = '';
                            $ionicBackdrop.release();
                            el.element.css('display', 'none');

                            if (unbindBackButtonAction){
                                unbindBackButtonAction();
                                unbindBackButtonAction = null;
                            }
                        };

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

                            el.element.css('display', 'none');
                            $ionicBackdrop.release();

                            if (unbindBackButtonAction){
                                unbindBackButtonAction();
                                unbindBackButtonAction = null;
                            }
                        }

                        element.bind('click', onClick);
                        element.bind('touchend', onClick);

                        el.element.find('button').bind('click', onCancel);
                    });

                    if(attrs.placeholder){
                        element.attr('placeholder', attrs.placeholder);
                    }

                    ngModel.$formatters.unshift(function (modelValue) {
                        if (!modelValue) return '';
                        return modelValue;
                    });

                    ngModel.$parsers.unshift(function (viewValue) {
                        return viewValue;
                    });

                    ngModel.$render = function(){
                        if(!ngModel.$viewValue){
                            element.val('');
                        } else {
                            element.val(ngModel.$viewValue.formatted_address || '');
                        }
                    };

                    scope.$on("$destroy", function(){
                        if (unbindBackButtonAction){
                            unbindBackButtonAction();
                            unbindBackButtonAction = null;
                        }
                    });

                    function getLocation() {
                        return $q(function (resolve, reject) {
                            navigator.geolocation.getCurrentPosition(function (position) {
                                resolve(position);
                            }, function (error) {
                                error.from = 'getLocation';
                                reject(error);
                            });
                        });
                    }

                    function reverseGeocoding(location) {
                        return $q(function (resolve, reject) {
                            var latlng = {
                                lat: location.coords.latitude,
                                lng: location.coords.longitude
                            };
                            geocoder.geocode({'location': latlng}, function (results, status) {
                                if (status == google.maps.GeocoderStatus.OK) {
                                    if (results[1]) {
                                        resolve(results[1]);
                                    } else {
                                        resolve(results[0])
                                    }
                                } else {
                                    var error = {
                                        status: status,
                                        from: 'reverseGeocoding'
                                    };
                                    reject(error);
                                }
                            })
                        });
                    }
                }
            };
        }
    ]);
<|endoftext|>


<commit_before>// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('starter', ['ionic'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if(window.cordova && window.cordova.plugins.Keyboard) {
      // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
      // for form inputs)
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);

      // Don't remove this line unless you know what you are doing. It stops the viewport
      // from snapping when text inputs are focused. Ionic handles this internally for
      // a much nicer keyboard experience.
      cordova.plugins.Keyboard.disableScroll(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }

    document.addEventListener("deviceready", onDeviceReady, false);
  });
})

function onDeviceReady() {
  initPushNotifications();
}

function initPushNotifications() {
  var id = "209803454821" // this is static for GCM
  // need to figure out APNS...

  var push = PushNotification.init({
      "android": {"senderID": id}
      //"ios": {"alert":"true", "badge":"true", "sound":"true"},
      //"windows": {}

  });

  if(push) {
    alert('It works!!');
  }
  else {
    alert("It doesn't work!");
  }

  push.on('registration', function(data) {
      console.log("Registration: " + JSON.stringify(data));

      postData = {
                  "service":"gcm" ,
                  "token":data.registrationId ,
                  "kpTrigger":1
                }

      console.log(JSON.stringify(postData));

      postNewToken(postData);
  });

  push.on('notification', function(data) {
      alert("Notification: " + JSON.stringify(data["message"]));
  });

  function postNewToken(params) {
    xhttp = new XMLHttpRequest();
    xhttp.withCredentials = false;

    xhttp.addEventListener("readystatechange", function() {
      console.log("State changed: " + xhttp.readyState + ' ' + "Status: " + xhttp.status);
      if (xhttp.readyState == 4 /*&& xhttp.status == 200*/) {
        alert("Key has been added to push server!");
      }
    });

    xhttp.open("POST", "http://aurora.cs.uaf.edu/push_notification/");
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send(JSON.stringify(params));
  }
}
<commit_msg>Added call to splashscreen.hide when ionic is ready.<commit_after>// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('starter', ['ionic'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if(window.cordova && window.cordova.plugins.Keyboard) {
      // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
      // for form inputs)
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);

      // Don't remove this line unless you know what you are doing. It stops the viewport
      // from snapping when text inputs are focused. Ionic handles this internally for
      // a much nicer keyboard experience.
      cordova.plugins.Keyboard.disableScroll(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }

    document.addEventListener("deviceready", onDeviceReady, false);
    navigator.splashscreen.hide();
  });
})

function onDeviceReady() {
  initPushNotifications();
}

function initPushNotifications() {
  var id = "209803454821" // this is static for GCM
  // need to figure out APNS...

  var push = PushNotification.init({
      "android": {"senderID": id}
      //"ios": {"alert":"true", "badge":"true", "sound":"true"},
      //"windows": {}

  });

  if(push) {
    alert('It works!!');
  }
  else {
    alert("It doesn't work!");
  }

  push.on('registration', function(data) {
      console.log("Registration: " + JSON.stringify(data));

      postData = {
                  "service":"gcm" ,
                  "token":data.registrationId ,
                  "kpTrigger":1
                }

      console.log(JSON.stringify(postData));

      postNewToken(postData);
  });

  push.on('notification', function(data) {
      alert("Notification: " + JSON.stringify(data["message"]));
  });

  function postNewToken(params) {
    xhttp = new XMLHttpRequest();
    xhttp.withCredentials = false;

    xhttp.addEventListener("readystatechange", function() {
      console.log("State changed: " + xhttp.readyState + ' ' + "Status: " + xhttp.status);
      if (xhttp.readyState == 4 /*&& xhttp.status == 200*/) {
        alert("Key has been added to push server!");
      }
    });

    xhttp.open("POST", "http://aurora.cs.uaf.edu/push_notification/");
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send(JSON.stringify(params));
  }
}
<|endoftext|>