<commit_before>/* eslint-disable no-unused-expressions */
import { mount } from '@cypress/vue'
import WrapperOne from './../../../components/menu/__tests__/WrapperOne.vue'
import WrapperTwo from './../../../components/menu/__tests__/WrapperTwo.vue'
import { ref } from 'vue'

describe('use-model-toggle API', () => {
  describe('Props', () => {
    describe('Category: model', () => {
      describe('(prop): model-value', () => {
        it('should open the dialog when modifying the model-value', () => {
          const modelValue = ref(false)
          mount(WrapperOne, {
            attrs: {
              modelValue
            }
          })
          cy.dataCy('wrapper')
          cy.dataCy('menu')
            .should('not.exist')
            .then(() => {
              modelValue.value = true
              cy.dataCy('menu')
                .should('exist')
            })
        })

        it('should close the dialog when modifying the model-value', () => {
          const modelValue = ref(true)
          mount(WrapperOne, {
            attrs: {
              modelValue
            }
          })
          cy.dataCy('wrapper')
          cy.dataCy('menu')
            .should('exist')
            .then(() => {
              modelValue.value = false
              cy.dataCy('menu')
                .should('not.exist')
            })
        })
      })
    })
  })

  describe('Events', () => {
    describe('(event): update:model-value', () => {
      it('should emit @update:model-value event when state changes', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            'onUpdate:modelValue': fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).to.be.called
          })
      })
    })

    describe('(event): show', () => {
      it('should emit @show event when menu is triggered by parent', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onShow: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
          .wait(300) // Await menu animation
          .then(() => {
            expect(fn).to.be.called
          })
      })

      it('should emit @show event when component is triggered with the show() method', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onShow: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
        cy.dataCy('method-show')
          .click({ force: true }) // Element is hidden to prevent clogging the window
        cy.dataCy('menu')
          .should('exist')
          .wait(300) // Await menu animation
          .then(() => {
            expect(fn).to.be.called
          })
      })
    })

    describe('(event): before-show', () => {
      it('should emit @before-show event when menu is triggered by parent', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onBeforeShow: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).to.be.called
          })
      })

      it('should emit @before-show event when component is triggered with the show() method', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onBeforeShow: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
        cy.dataCy('method-show')
          .click({ force: true }) // Element is hidden to prevent clogging the window
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).to.be.called
          })
      })
    })

    describe('(event): hide', () => {
      it('should emit @hide event when menu is triggered by parent', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onHide: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).not.to.be.called
          })
        cy.get('body')
          .click(499, 0)
        cy.dataCy('menu')
          .should('not.exist')
          .then(() => {
            expect(fn).to.be.called
          })
      })

      it('should emit @hide event when component is triggered with the show() method', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onHide: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
        cy.dataCy('method-show')
          .click({ force: true }) // Element is hidden to prevent clogging the window
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).not.to.be.called
          })
        cy.dataCy('method-hide')
          .click({ force: true })
        cy.dataCy('menu')
          .should('not.exist') // Element is hidden to prevent clogging the window
          .then(() => {
            expect(fn).to.be.called
          })
      })
    })

    describe('(event): before-hide', () => {
      it('should emit @before-hide event when menu is triggered by parent', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onBeforeHide: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).not.to.be.called
          })
        cy.get('body')
          .click(499, 0)
          .then(() => {
            expect(fn).to.be.called
          })
        cy.dataCy('menu')
          .should('not.exist')
      })

      it('should emit @before-hide event when component is triggered with the show() method', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onBeforeHide: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
        cy.dataCy('method-show')
          .click({ force: true }) // Element is hidden to prevent clogging the window
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).not.to.be.called
          })
        cy.dataCy('method-hide')
          .click({ force: true })
          .then(() => {
            expect(fn).to.be.called
          })
        cy.dataCy('menu')
          .should('not.exist')
      })
    })
  })

  describe('Methods', () => {
    describe('(method): show', () => {
      it('should tigger the menu to show', () => {
        mount(WrapperOne)

        cy.dataCy('wrapper')
        cy.dataCy('method-show')
          .click({ force: true })
        cy.dataCy('menu')
          .should('exist')
      })
    })

    describe('(method): hide', () => {
      it('should tigger the menu to hide', () => {
        mount(WrapperOne)

        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
        cy.dataCy('method-hide')
          .click({ force: true })
        cy.dataCy('menu')
          .should('not.exist')
      })
    })

    describe('(method): toggle', () => {
      it('should toggle the menu', () => {
        mount(WrapperTwo)

        cy.dataCy('wrapper')
          .then(() => {
            // Need to call method from wrapper
            // Click a button closes the menu
            Cypress.vueWrapper.vm.toggle()
          })
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            // Need to call method from wrapper
            // Click a button closes the menu
            Cypress.vueWrapper.vm.toggle()
          })
        cy.dataCy('menu')
          .should('not.exist')
      })
    })
  })
})
<commit_msg>test(ui): fix typos (#13378)<commit_after>/* eslint-disable no-unused-expressions */
import { mount } from '@cypress/vue'
import WrapperOne from './../../../components/menu/__tests__/WrapperOne.vue'
import WrapperTwo from './../../../components/menu/__tests__/WrapperTwo.vue'
import { ref } from 'vue'

describe('use-model-toggle API', () => {
  describe('Props', () => {
    describe('Category: model', () => {
      describe('(prop): model-value', () => {
        it('should open the dialog when modifying the model-value', () => {
          const modelValue = ref(false)
          mount(WrapperOne, {
            attrs: {
              modelValue
            }
          })
          cy.dataCy('wrapper')
          cy.dataCy('menu')
            .should('not.exist')
            .then(() => {
              modelValue.value = true
              cy.dataCy('menu')
                .should('exist')
            })
        })

        it('should close the dialog when modifying the model-value', () => {
          const modelValue = ref(true)
          mount(WrapperOne, {
            attrs: {
              modelValue
            }
          })
          cy.dataCy('wrapper')
          cy.dataCy('menu')
            .should('exist')
            .then(() => {
              modelValue.value = false
              cy.dataCy('menu')
                .should('not.exist')
            })
        })
      })
    })
  })

  describe('Events', () => {
    describe('(event): update:model-value', () => {
      it('should emit @update:model-value event when state changes', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            'onUpdate:modelValue': fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).to.be.called
          })
      })
    })

    describe('(event): show', () => {
      it('should emit @show event when menu is triggered by parent', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onShow: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
          .wait(300) // Await menu animation
          .then(() => {
            expect(fn).to.be.called
          })
      })

      it('should emit @show event when component is triggered with the show() method', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onShow: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
        cy.dataCy('method-show')
          .click({ force: true }) // Element is hidden to prevent clogging the window
        cy.dataCy('menu')
          .should('exist')
          .wait(300) // Await menu animation
          .then(() => {
            expect(fn).to.be.called
          })
      })
    })

    describe('(event): before-show', () => {
      it('should emit @before-show event when menu is triggered by parent', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onBeforeShow: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).to.be.called
          })
      })

      it('should emit @before-show event when component is triggered with the show() method', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onBeforeShow: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
        cy.dataCy('method-show')
          .click({ force: true }) // Element is hidden to prevent clogging the window
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).to.be.called
          })
      })
    })

    describe('(event): hide', () => {
      it('should emit @hide event when menu is triggered by parent', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onHide: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).not.to.be.called
          })
        cy.get('body')
          .click(499, 0)
        cy.dataCy('menu')
          .should('not.exist')
          .then(() => {
            expect(fn).to.be.called
          })
      })

      it('should emit @hide event when component is triggered with the show() method', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onHide: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
        cy.dataCy('method-show')
          .click({ force: true }) // Element is hidden to prevent clogging the window
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).not.to.be.called
          })
        cy.dataCy('method-hide')
          .click({ force: true })
        cy.dataCy('menu')
          .should('not.exist') // Element is hidden to prevent clogging the window
          .then(() => {
            expect(fn).to.be.called
          })
      })
    })

    describe('(event): before-hide', () => {
      it('should emit @before-hide event when menu is triggered by parent', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onBeforeHide: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).not.to.be.called
          })
        cy.get('body')
          .click(499, 0)
          .then(() => {
            expect(fn).to.be.called
          })
        cy.dataCy('menu')
          .should('not.exist')
      })

      it('should emit @before-hide event when component is triggered with the show() method', () => {
        const fn = cy.stub()
        mount(WrapperOne, {
          attrs: {
            onBeforeHide: fn
          }
        })

        expect(fn).not.to.be.called
        cy.dataCy('wrapper')
        cy.dataCy('method-show')
          .click({ force: true }) // Element is hidden to prevent clogging the window
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            expect(fn).not.to.be.called
          })
        cy.dataCy('method-hide')
          .click({ force: true })
          .then(() => {
            expect(fn).to.be.called
          })
        cy.dataCy('menu')
          .should('not.exist')
      })
    })
  })

  describe('Methods', () => {
    describe('(method): show', () => {
      it('should trigger the menu to show', () => {
        mount(WrapperOne)

        cy.dataCy('wrapper')
        cy.dataCy('method-show')
          .click({ force: true })
        cy.dataCy('menu')
          .should('exist')
      })
    })

    describe('(method): hide', () => {
      it('should trigger the menu to hide', () => {
        mount(WrapperOne)

        cy.dataCy('wrapper')
          .click()
        cy.dataCy('menu')
          .should('exist')
        cy.dataCy('method-hide')
          .click({ force: true })
        cy.dataCy('menu')
          .should('not.exist')
      })
    })

    describe('(method): toggle', () => {
      it('should toggle the menu', () => {
        mount(WrapperTwo)

        cy.dataCy('wrapper')
          .then(() => {
            // Need to call method from wrapper
            // Click a button closes the menu
            Cypress.vueWrapper.vm.toggle()
          })
        cy.dataCy('menu')
          .should('exist')
          .then(() => {
            // Need to call method from wrapper
            // Click a button closes the menu
            Cypress.vueWrapper.vm.toggle()
          })
        cy.dataCy('menu')
          .should('not.exist')
      })
    })
  })
})
<|endoftext|>


<commit_before>const mongoose = require('mongoose');
const dotenv = require('dotenv');
const dotenvExpand = require('dotenv-expand');
const crypto = require('crypto');
const util = require('util');
const debug = require('debug')('sylow:cli');

const scryptAsync = require('scrypt-async');

// make bluebird default Promise
Promise = require('bluebird'); // eslint-disable-line no-global-assign

module.exports = {
  mongooseConnect() {
    // plugin bluebird promise in mongoose
    mongoose.Promise = Promise;

    const myEnv = dotenv.config();
    dotenvExpand(myEnv);
    const envConfig = Object.create(myEnv.parsed);

    const mongooseDebug = process.env.NODE_ENV === 'development';

    if (!envConfig.MONGO_HOST) {
      throw new Error('MONGO_HOST is not set, and was not found in a .env file.');
    }

    // connect to mongo db
    mongoose.connect(envConfig.MONGO_HOST, { server: { socketOptions: { keepAlive: 1 } } });
    mongoose.connection.on('error', () => {
      throw new Error(`unable to connect to database: ${envConfig.MONGO_HOST}`);
    });

    // print mongoose logs in dev env
    if (mongooseDebug) {
      mongoose.set('debug', (collectionName, method, query, doc) => {
        debug(`${collectionName}.${method}`, util.inspect(query, false, 20), doc);
      });
    }
  },

  generateSalt() {
    return crypto.randomBytes(8).toString('hex');
  },

  scrypt(pwd, salt, cb) {
    const options = {
      N: 16384, r: 8, dkLen: 64, encoding: 'hex'
    };
    return scryptAsync(pwd, salt, options, cb);
  },
};
<commit_msg>Fixe to the server-add command<commit_after>const mongoose = require('mongoose');
const dotenv = require('dotenv');
const dotenvExpand = require('dotenv-expand');
const crypto = require('crypto');
const util = require('util');
const debug = require('debug')('sylow:cli');

const scryptAsync = require('scrypt-async');

// make bluebird default Promise
Promise = require('bluebird'); // eslint-disable-line no-global-assign

module.exports = {
  mongooseConnect() {
    // plugin bluebird promise in mongoose
    mongoose.Promise = Promise;

    const myEnv = dotenv.config({path: '../.env'});
    dotenvExpand(myEnv);
    const envConfig = Object.create(myEnv.parsed);

    const mongooseDebug = process.env.NODE_ENV === 'development';

    if (!envConfig.MONGO_HOST) {
      throw new Error('MONGO_HOST is not set, and was not found in a .env file.');
    }

    // connect to mongo db
    mongoose.connect(envConfig.MONGO_HOST, { server: { socketOptions: { keepAlive: 1 } } });
    mongoose.connection.on('error', () => {
      throw new Error(`unable to connect to database: ${envConfig.MONGO_HOST}`);
    });

    // print mongoose logs in dev env
    if (mongooseDebug) {
      mongoose.set('debug', (collectionName, method, query, doc) => {
        debug(`${collectionName}.${method}`, util.inspect(query, false, 20), doc);
      });
    }
  },

  generateSalt() {
    return crypto.randomBytes(8).toString('hex');
  },

  scrypt(pwd, salt, cb) {
    const options = {
      N: 16384, r: 8, dkLen: 64, encoding: 'hex'
    };
    return scryptAsync(pwd, salt, options, cb);
  },
};
<|endoftext|>


<commit_before>/**
 * App.io.broadcast     - send to all
 * req.io.broadcast     - send to others
 * req.io.emit          - send to me
 * req.io.response(d)   - send http
 * req.io.join(r)    - join room
 * req.io.leave(r)   - leave room
 * req.io.room(r).broadcast(event, data)    - send to other members
 * app.io.room(r).broadcast(e,d)            - send to all members
 *
 * */
var User = require(__appname + '/model/user');
var Question = require(__appname + '/model/question');
var Room = require(__appname + '/model/room');

var mongoDb = require(__appname + '/mongodb/mongodb');

var altp = {
    rooms: [],
    dummyUsers: [
        new User(0, 'lam tam nhu', 'china', 'fb_id_0', 'http://www.nhipsongphunu.com/public/default/content/Images/Lam%20dep/avatar%20-20150311-14030457.jpg'),
        new User(1, 'trieu vy', 'hongkong', 'fb_id_1', 'http://avatar.nct.nixcdn.com/playlist/2013/11/07/2/e/6/4/1383813832087_500.jpg'),
        new User(2, 'michele', 'america', 'fb_id_2', 'http://media.todaybirthdays.com/thumb_x256x256/upload/2015/11/30/michelle-rodriguez.jpg'),
        new User(3, 'arvigne', 'brazin', 'fb_id_3', 'http://images2.fanpop.com/image/photos/9800000/beautiful-face-avril-lavigne-9812919-453-500.jpg')
    ]
};

altp.init = function (io) {
    io.on('connection', function (socket) {
        var sock = socket;

        /**
         * user click login (with FB or username/address)
         * @param data (name,address,fbId)
         * */
        var login = function (data) {
            var reqUser = data.user;

            console.log('login: ' + reqUser.name);

            if (!reqUser || reqUser.name.length == 0) {
                sock.emit('login', {success: false});
                return;
            }
            getUserById(reqUser.id, function (err, user) {
                if (user == null) {
                    user = new User(
                        reqUser.id || (Math.random() * 10000000),
                        reqUser.name || '',
                        reqUser.address || '',
                        reqUser.fbId || -1,
                        reqUser.avatar || '');

                    mongoDb.users.insert(user, function (err, user) {
                        console.log('login:insert:user:' + JSON.stringify(user));
                        console.log('login:insert:err:' + JSON.stringify(err));

                    });
                }
                sock.emit('login', {success: true, user: user});
            });
        };

        /**
         * user click search button. Get 2 users into a room.
         * @param data = {user.id}
         * */
        var search = function (data) {
            console.log(JSON.stringify(data));
            getUserById(data.user.id, function (err, user) {

                if (user == null) {
                    sock.emit('search', {err: 'user not found'});
                    return;
                }

                var room = null;
                var i;

                console.log('search: ' + JSON.stringify(user) + ' searching');

                for (i = 0; i < altp.rooms.length; i++) {
                    if (altp.rooms[i].users.length == 1) {
                        if (altp.rooms[i].users[0].id != user.id) {
                            console.log('user id: ' + altp.rooms[i].users[0].id + ' name:' + altp.rooms[i].users[0].name);
                            room = altp.rooms[i];
                            room.users.push(user);
                            break;
                        }
                    }
                }

                var processRoom = function(room){
                    // refresh state users
                    for (i = 0; i < room.users.length; i++) {
                        room.users[i].ready = false;
                        room.users[i].answerIndex = -1;
                        room.users[i].score = 0;
                    }

                    room.answerRight = 0;
                    room.questionIndex = 0;

                    sock.leave(user.room);
                    user.room = room.id;
                    sock.join(room.id);

                    var dataSearch = {
                        room: room,
                        dummyUsers: altp.dummyUsers
                    };

                    console.log('searchCallback: room:' + dataSearch.room.id + ' with user:' + room.users.length);

                    __io.to(room.id).emit('search', dataSearch);
                };

                if (room != null) {
                    processRoom(room);
                    return;
                }

                // create a new room
                getRandomQuestion(function(questions){
                    room = new Room('room#' + altp.rooms.length, [user], questions);
                    altp.rooms.push(room);

                    console.log('create room: '+ JSON.stringify(room));

                    processRoom(room);
                });
            });
        };

        /**
         * user click play after search
         * @param data = {user.id, room.id}
         * */
        var play = function (data) {
            getUserById(data.user.id, function (err, user) {
                var room = getRoomById(data.room.id);
                var i;
                var isAllReady = true;

                console.log('play: ' + user.name + ' ready!');

                for (i = 0; i < room.users.length; i++) {
                    if (room.users[i].id == user.id) {
                        room.users[i].ready = true;
                        break;
                    }
                }

                for (i = 0; i < room.users.length; i++) {
                    if (!room.users[i].ready) {
                        isAllReady = false;
                        break;
                    }
                }

                // if others user is not ready --> show waiting dialog
                if (!isAllReady) {
                    sock.emit('play', {notReady: true});
                    return;
                }

                var dataResponse = {
                    question: room.questions[room.questionIndex]
                };

                console.log('playCallback: question:' + dataResponse.question.question);

                __io.to(room.id).emit('play', dataResponse);
            });
        };

        /**
         * user answer an question
         * @param data = {user.id, room.id, answerIndex}
         * */
        var answer = function (data) {
            getUserById(data.user.id, function (err, user) {
                var room = getRoomById(data.room.id);
                var answerIndex = data.answerIndex;

                var i;
                var dataResponse;

                //console.log('answer: ' + user.name + ' answered '+data.answerIndex);

                for (var j = 0; j < room.users.length; j++) {
                    if (room.users[j].id == user.id) {
                        user.answerIndex = answerIndex;
                        room.users[j].answerIndex = answerIndex;
                        break;
                    }
                }

                var isAllAnswered = true;

                for (i = 0; i < room.users.length; i++) {
                    if (room.users[i].answerIndex < 0) {
                        isAllAnswered = false;
                        break;
                    }
                }

                if (!isAllAnswered) {
                    __io.to(room.id).emit('answer', {notAllAnswered: true});
                    return;
                }

                console.log('user ' + room.users[0].name + ' answered: ' + room.users[0].answerIndex);
                console.log('user ' + room.users[1].name + ' answered: ' + room.users[1].answerIndex);

                // calculate gameOver
                var answerRightIndex = room.questions[room.questionIndex].answerRight;

                // user 1 win
                if (answerRightIndex == room.users[0].answerIndex
                    && answerRightIndex != room.users[1].answerIndex) {
                    getUserById(room.users[0].id, function (err, winnerUser) {
                        addScore(winnerUser, 100);
                        addScore(room.users[0], 100);

                        dataResponse = {
                            answerRight: room.questions[room.questionIndex].answerRight,
                            user: user,
                            room: room
                        };

                        gameOver(dataResponse);
                    });
                    return;
                }
                // user 2 win
                else if (answerRightIndex != room.users[0].answerIndex
                    && answerRightIndex == room.users[1].answerIndex) {
                    getUserById(room.users[1].id, function (err, winnerUser) {
                        addScore(winnerUser, 100);
                        addScore(room.users[1], 100);
                        dataResponse = {
                            answerRight: room.questions[room.questionIndex].answerRight,
                            user: user,
                            room: room
                        };

                        gameOver(dataResponse);
                    });
                    return;
                }
                // draw: both wrong
                else if (answerRightIndex != room.users[0].answerIndex
                    && answerRightIndex != room.users[1].answerIndex) {

                    dataResponse = {
                        answerRight: room.questions[room.questionIndex].answerRight,
                        user: user,
                        room: room
                    };

                    gameOver(dataResponse);
                    return;
                }

                // next question
                for (i = 0; i < room.users.length; i++) {
                    if (room.questions[room.questionIndex].answerRight == room.users[i].answerIndex) {
                        addScore(room.users[i], 100);
                    }
                }

                dataResponse = {
                    answerRight: room.questions[room.questionIndex].answerRight,
                    answerUsers: room.users
                };

                console.log('answerCallback: answerRight:' + dataResponse.answerRight);

                room.questionIndex++;
                __io.to(room.id).emit('answer', dataResponse);

                // game over
                if (room.questionIndex == room.questions.length) {
                    setTimeout(function(){
                        data.lastQuestion = true;
                        gameOver(data);
                    }, 5000);
                }
            });
        };

        /**
         * get next question
         * @param data = {user.id, room.id}
         * */
        var answerNext = function (data) {
            getUserById(data.user.id, function (err, user) {
                var room = getRoomById(data.room.id);

                console.log('answerNext: ' + user.name + ' get nextQuestion');

                var numUserAnswer = 0;
                var i;
                for (i = 0; i < room.users.length; i++) {
                    if (room.users[i].answerIndex > -1) {
                        numUserAnswer++;
                    }
                }

                // if all users doesn't answer, not fired event callback
                if (numUserAnswer < 2) {
                    return;
                }

                for (i = 0; i < room.users.length; i++) {
                    room.users[i].answerIndex = -1;
                }

                if (room.questionIndex == room.questions.length) {
                    return;
                }

                var dataResponse = {
                    question: room.questions[room.questionIndex]
                };

                __io.to(room.id).emit('answerNext', dataResponse);
            });
        };

        /**
         * the game over, called by answer()
         * @param data = {user.id, room.id}
         * */
        var gameOver = function (data) {
            getUserById(data.user.id, function (err, user) {
                var room = getRoomById(data.room.id);

                console.log('gameOver: ' + user.name);

                var dataResponse = data;
                dataResponse.answerRight = data.answerRight;
                dataResponse.users = room.users;
                dataResponse.room = room;

                console.log('gameOverCallback: total users: ' + JSON.stringify(dataResponse));

                __io.to(room.id).emit('gameOver', dataResponse);
            });
        };

        var quit = function (data) {
            getUserById(data.user.id, function (err, user) {
                var room = getRoomById(data.room.id);

                // delete current room (one user quit)

                var dataResponse = {
                    user: user,
                    room: room
                };

                __io.to(room.id).emit('quit', dataResponse);
            });
        };

        socket.on('login', login);
        socket.on('search', search);
        socket.on('play', play);
        socket.on('answer', answer);
        socket.on('answerNext', answerNext);
        socket.on('gameOver', gameOver);
        socket.on('quit', quit);
    });
};

/************** UTILITIES **************/

/**
 * add score to user
 * @return user object
 * */
var addScore = function (user, score) {
    user.score += score;
};

/**
 * @param userId id of user
 * @return user object
 * */
var getUserById = function (userId, callback) {
    mongoDb.users.findOne({id: userId}, callback);
};

/**
 * @param roomId id of room
 * @return room object
 * */
var getRoomById = function (roomId) {
    for (var i = 0; i < altp.rooms.length; i++) {
        if (roomId == altp.rooms[i].id) {
            return altp.rooms[i];
        }
    }
    return null;
};

/**
 * get random 15 questions from database
 * */
var getRandomQuestion = function (callback) {
    var QUESTION_NUMBERS = 15;
    var questions = [];
    // using: abc.find({ _id: ObjectId(req.params.id) }, function(...) { ... });

    // get one question for each level (1... 15)
    for (var i = 1; i <= QUESTION_NUMBERS; i++) {
        var query = {
            level: i
        };
        var n = mongoDb.questions.count(query);
        var r = Math.floor(Math.random() * n);
        mongoDb.questions.findOne(query, function(err, item){

            var question = new Question(item.question, item.answers, item.answerRight-1, item.level);
            questions.push(question);

            console.log('from db: '+ JSON.stringify(question));

            if(questions.length == QUESTION_NUMBERS){
                callback(questions);
            }
        });
    }
};

module.exports = altp;<commit_msg>add process room<commit_after>/**
 * App.io.broadcast     - send to all
 * req.io.broadcast     - send to others
 * req.io.emit          - send to me
 * req.io.response(d)   - send http
 * req.io.join(r)    - join room
 * req.io.leave(r)   - leave room
 * req.io.room(r).broadcast(event, data)    - send to other members
 * app.io.room(r).broadcast(e,d)            - send to all members
 *
 * */
var User = require(__appname + '/model/user');
var Question = require(__appname + '/model/question');
var Room = require(__appname + '/model/room');

var mongoDb = require(__appname + '/mongodb/mongodb');

var altp = {
    rooms: [],
    dummyUsers: [
        new User(0, 'lam tam nhu', 'china', 'fb_id_0', 'http://www.nhipsongphunu.com/public/default/content/Images/Lam%20dep/avatar%20-20150311-14030457.jpg'),
        new User(1, 'trieu vy', 'hongkong', 'fb_id_1', 'http://avatar.nct.nixcdn.com/playlist/2013/11/07/2/e/6/4/1383813832087_500.jpg'),
        new User(2, 'michele', 'america', 'fb_id_2', 'http://media.todaybirthdays.com/thumb_x256x256/upload/2015/11/30/michelle-rodriguez.jpg'),
        new User(3, 'arvigne', 'brazin', 'fb_id_3', 'http://images2.fanpop.com/image/photos/9800000/beautiful-face-avril-lavigne-9812919-453-500.jpg')
    ]
};

altp.init = function (io) {
    io.on('connection', function (socket) {
        var sock = socket;

        /**
         * user click login (with FB or username/address)
         * @param data (name,address,fbId)
         * */
        var login = function (data) {
            var reqUser = data.user;

            console.log('login: ' + reqUser.name);

            if (!reqUser || reqUser.name.length == 0) {
                sock.emit('login', {success: false});
                return;
            }
            getUserById(reqUser.id, function (err, user) {
                if (user == null) {
                    user = new User(
                        reqUser.id || (Math.random() * 10000000),
                        reqUser.name || '',
                        reqUser.address || '',
                        reqUser.fbId || -1,
                        reqUser.avatar || '');

                    mongoDb.users.insert(user, function (err, user) {
                        console.log('login:insert:user:' + JSON.stringify(user));
                        console.log('login:insert:err:' + JSON.stringify(err));

                    });
                }
                sock.emit('login', {success: true, user: user});
            });
        };

        /**
         * user click search button. Get 2 users into a room.
         * @param data = {user.id}
         * */
        var search = function (data) {
            console.log(JSON.stringify(data));
            getUserById(data.user.id, function (err, user) {

                if (user == null) {
                    sock.emit('search', {err: 'user not found'});
                    return;
                }

                var room = null;
                var i;

                console.log('search: ' + JSON.stringify(user) + ' searching');

                for (i = 0; i < altp.rooms.length; i++) {
                    if (altp.rooms[i].users.length == 1) {
                        if (altp.rooms[i].users[0].id != user.id) {
                            console.log('user id: ' + altp.rooms[i].users[0].id + ' name:' + altp.rooms[i].users[0].name);
                            room = altp.rooms[i];
                            room.users.push(user);
                            break;
                        }
                    }
                }

                var processRoom = function(room){
                    // refresh state users
                    for (i = 0; i < room.users.length; i++) {
                        room.users[i].ready = false;
                        room.users[i].answerIndex = -1;
                        room.users[i].score = 0;
                    }

                    room.answerRight = 0;
                    room.questionIndex = 0;

                    sock.leave(user.room);
                    user.room = room.id;
                    sock.join(room.id);

                    var dataSearch = {
                        room: room,
                        dummyUsers: altp.dummyUsers
                    };

                    console.log('searchCallback: room:' + dataSearch.room.id + ' with user:' + room.users.length);

                    __io.to(room.id).emit('search', dataSearch);
                };

                if (room != null) {
                    processRoom(room);
                    return;
                }

                // create a new room
                getRandomQuestion(function(questions){
                    room = new Room('room#' + altp.rooms.length, [user], questions);
                    altp.rooms.push(room);

                    console.log('create room: '+ JSON.stringify(room));

                    processRoom(room);
                });
            });
        };

        /**
         * user click play after search
         * @param data = {user.id, room.id}
         * */
        var play = function (data) {
            getUserById(data.user.id, function (err, user) {
                var room = getRoomById(data.room.id);
                var i;
                var isAllReady = true;

                console.log('play: ' + user.name + ' ready!');

                for (i = 0; i < room.users.length; i++) {
                    if (room.users[i].id == user.id) {
                        room.users[i].ready = true;
                        break;
                    }
                }

                for (i = 0; i < room.users.length; i++) {
                    if (!room.users[i].ready) {
                        isAllReady = false;
                        break;
                    }
                }

                // if others user is not ready --> show waiting dialog
                if (!isAllReady) {
                    sock.emit('play', {notReady: true});
                    return;
                }

                var dataResponse = {
                    question: room.questions[room.questionIndex]
                };

                console.log('playCallback: question:' + dataResponse.question.question);

                __io.to(room.id).emit('play', dataResponse);
            });
        };

        /**
         * user answer an question
         * @param data = {user.id, room.id, answerIndex}
         * */
        var answer = function (data) {
            getUserById(data.user.id, function (err, user) {
                var room = getRoomById(data.room.id);
                var answerIndex = data.answerIndex;

                var i;
                var dataResponse;

                //console.log('answer: ' + user.name + ' answered '+data.answerIndex);

                for (var j = 0; j < room.users.length; j++) {
                    if (room.users[j].id == user.id) {
                        user.answerIndex = answerIndex;
                        room.users[j].answerIndex = answerIndex;
                        break;
                    }
                }

                var isAllAnswered = true;

                for (i = 0; i < room.users.length; i++) {
                    if (room.users[i].answerIndex < 0) {
                        isAllAnswered = false;
                        break;
                    }
                }

                if (!isAllAnswered) {
                    __io.to(room.id).emit('answer', {notAllAnswered: true});
                    return;
                }

                console.log('user ' + room.users[0].name + ' answered: ' + room.users[0].answerIndex);
                console.log('user ' + room.users[1].name + ' answered: ' + room.users[1].answerIndex);

                // calculate gameOver
                var answerRightIndex = room.questions[room.questionIndex].answerRight;

                // user 1 win
                if (answerRightIndex == room.users[0].answerIndex
                    && answerRightIndex != room.users[1].answerIndex) {
                    getUserById(room.users[0].id, function (err, winnerUser) {
                        addScore(winnerUser, 100);
                        addScore(room.users[0], 100);

                        dataResponse = {
                            answerRight: room.questions[room.questionIndex].answerRight,
                            user: user,
                            room: room
                        };

                        gameOver(dataResponse);
                    });
                    return;
                }
                // user 2 win
                else if (answerRightIndex != room.users[0].answerIndex
                    && answerRightIndex == room.users[1].answerIndex) {
                    getUserById(room.users[1].id, function (err, winnerUser) {
                        addScore(winnerUser, 100);
                        addScore(room.users[1], 100);
                        dataResponse = {
                            answerRight: room.questions[room.questionIndex].answerRight,
                            user: user,
                            room: room
                        };

                        gameOver(dataResponse);
                    });
                    return;
                }
                // draw: both wrong
                else if (answerRightIndex != room.users[0].answerIndex
                    && answerRightIndex != room.users[1].answerIndex) {

                    dataResponse = {
                        answerRight: room.questions[room.questionIndex].answerRight,
                        user: user,
                        room: room
                    };

                    gameOver(dataResponse);
                    return;
                }

                // next question
                for (i = 0; i < room.users.length; i++) {
                    if (room.questions[room.questionIndex].answerRight == room.users[i].answerIndex) {
                        addScore(room.users[i], 100);
                    }
                }

                dataResponse = {
                    answerRight: room.questions[room.questionIndex].answerRight,
                    answerUsers: room.users
                };

                console.log('answerCallback: answerRight:' + dataResponse.answerRight);

                room.questionIndex++;
                __io.to(room.id).emit('answer', dataResponse);

                // game over
                if (room.questionIndex == room.questions.length) {
                    setTimeout(function(){
                        data.lastQuestion = true;
                        gameOver(data);
                    }, 5000);
                }
            });
        };

        /**
         * get next question
         * @param data = {user.id, room.id}
         * */
        var answerNext = function (data) {
            getUserById(data.user.id, function (err, user) {
                var room = getRoomById(data.room.id);

                console.log('answerNext: ' + user.name + ' get nextQuestion');

                var numUserAnswer = 0;
                var i;
                for (i = 0; i < room.users.length; i++) {
                    if (room.users[i].answerIndex > -1) {
                        numUserAnswer++;
                    }
                }

                // if all users doesn't answer, not fired event callback
                if (numUserAnswer < 2) {
                    return;
                }

                for (i = 0; i < room.users.length; i++) {
                    room.users[i].answerIndex = -1;
                }

                if (room.questionIndex == room.questions.length) {
                    return;
                }

                var dataResponse = {
                    question: room.questions[room.questionIndex]
                };

                __io.to(room.id).emit('answerNext', dataResponse);
            });
        };

        /**
         * the game over, called by answer()
         * @param data = {user.id, room.id}
         * */
        var gameOver = function (data) {
            getUserById(data.user.id, function (err, user) {
                var room = getRoomById(data.room.id);

                console.log('gameOver: ' + user.name);

                var dataResponse = data;
                dataResponse.answerRight = data.answerRight;
                dataResponse.users = room.users;
                dataResponse.room = room;

                console.log('gameOverCallback: total users: ' + JSON.stringify(dataResponse));

                __io.to(room.id).emit('gameOver', dataResponse);
            });
        };

        var quit = function (data) {
            getUserById(data.user.id, function (err, user) {
                var room = getRoomById(data.room.id);

                // delete current room (one user quit)

                var dataResponse = {
                    user: user,
                    room: room
                };

                __io.to(room.id).emit('quit', dataResponse);
            });
        };

        socket.on('login', login);
        socket.on('search', search);
        socket.on('play', play);
        socket.on('answer', answer);
        socket.on('answerNext', answerNext);
        socket.on('gameOver', gameOver);
        socket.on('quit', quit);
    });
};

/************** UTILITIES **************/

/**
 * add score to user
 * @return user object
 * */
var addScore = function (user, score) {
    user.score += score;
};

/**
 * @param userId id of user
 * @return user object
 * */
var getUserById = function (userId, callback) {
    mongoDb.users.findOne({id: userId}, callback);
};

/**
 * @param roomId id of room
 * @return room object
 * */
var getRoomById = function (roomId) {
    for (var i = 0; i < altp.rooms.length; i++) {
        if (roomId == altp.rooms[i].id) {
            return altp.rooms[i];
        }
    }
    return null;
};

/**
 * get random 15 questions from database
 * */
var getRandomQuestion = function (callback) {
    var QUESTION_NUMBERS = 15;
    var questions = [];
    // using: abc.find({ _id: ObjectId(req.params.id) }, function(...) { ... });

    // get one question for each level (1... 15)
    for (var i = 1; i <= QUESTION_NUMBERS; i++) {
        var query = {
            level: i
        };
        var n = mongoDb.questions.count(query);

        console.log('count: '+n+' questions');

        var r = Math.floor(Math.random() * n);
        mongoDb.questions.findOne(query, function(err, item){

            var question = new Question(item.question, item.answers, item.answerRight-1, item.level);
            questions.push(question);

            console.log('from db: '+ JSON.stringify(question));

            if(questions.length == QUESTION_NUMBERS){
                callback(questions);
            }
        });
    }
};

module.exports = altp;<|endoftext|>


<commit_before>/**
 * @license
 * Copyright (c) 2015 MediaMath Inc. All rights reserved.
 * This code may only be used under the BSD style license found at http://mediamath.github.io/strand/LICENSE.txt

*/
/*jshint -W030 */
(function () {

	function _paramaterize(name, value) {
		return encodeURIComponent(name) + "=" + encodeURIComponent(value);
	}

	function _serialize(data, parent, depth, paramaterize) {

		paramaterize = paramaterize || _paramaterize;
		var obj,
			output = [];
		parent = parent || "";
		depth = depth || 0;

		for(var i in data) {
			obj = data[i];
			name = (depth === 0) ? i : "[" + i + "]";
			if (typeof obj === "object") {
				output = output.concat( _serialize(obj, name, depth+1) );
			} else {
				output.push( paramaterize(parent + name, obj) );
			}
		}
		return output;
	}

	Polymer('mm-ajax', {
		ver:"<<version>>",

		GET: "GET",
		POST: "POST",
		PUT: "PUT",
		DELETE: "DELETE",

		publish: {
			contentType: 'application/x-www-form-urlencoded',
			method: "GET",
			auto: false,
			debug: false,
			body: null,
			withCredentials: false,
			timeout: 10000
		},

		created: function() {
			this.reset();
		},

		ready: function() {
			if (this.auto && this.url && this.method) {
				this.exec();
			}
		},

		reset: function() {
			this._xhr = new XMLHttpRequest();
			this.promise = pinkySwear();
			this.headers = [];
			this.params = [];
			this.urlParams = [];
		},

		exec: function() {
			var data,
				fd,
				message,
				url = this.url;

			if (!this.method || !url) {
				message = "url and method are required!!";
				this.fire("data-error", {message:message});
				this.promise(false, [this, this.promise, message]);
				return this.promise;
			}

			if (this.urlParams && this.urlParams.length > 0) {
				if (url.slice(-1) === "/") {
					url += this.serializeUrl(this.urlParams);
				} else {
					url += "/" + this.serializeUrl(this.urlParams);
				}
			}

			if (this.method.match(/(POST|PUT|DELETE)/i)) {
				if (this.contentType === "application/json") {
					data = this.body;
				} else if(this.contentType === "multipart/form-data") {
					if (this.body instanceof FormData) {
						data = this.body;
					} else {
						//TODO: expose this outside of body
						fd = new FormData();
						if (this.body instanceof FormData) {
							data = this.body;
						} else {
							this.serialize(this.body, fd.append);
							data = fd;
						}
					}
				} else {
					data = this.serialize( this.body ).join("&");
				}
			}

			if (this.params && this.params.length) {
				if (url.indexOf("?") !== -1) {
					var last = url.slice(-1);
					if (last !== "&") {
						url += "&";
					}
				} else {
					url += "?";
				}
				url += this.serialize(this.params).join("&");
			}

			//open(DOMString method, DOMString url, optional boolean async, optional DOMString? user, optional DOMString? password);
			this.xhr.open(this.method, url, true, this.username, this.password);

			this.xhr.timeout = this.timeout || 10000;
			this.xhr.withCredentials = this.withCredentials;
			this.xhr.onreadystatechange = this.readyStateChange.bind(this);
			this.xhr.addEventListener("abort", this.handleAbort.bind(this));
			this.xhr.addEventListener("progress", this.handleProgress.bind(this));

			this.contentType && this.addHeader("content-type",this.contentType);

			this.headers && this.headers.forEach(function(header) {
				this.xhr.setRequestHeader(header.name, header.value);
			}.bind(this));

			this.xhr.send(data);

			return this.promise;

		},

		abort: function() {
			if (this.xhr) {
				this.xhr.abort();
			}
		},

		handleAbort: function(e) {
			this.fire("data-abort");
			if (this.promise) {
				this.promise(false, [this, this.promise, 'aborted']);
			}
		},

		handleProgress: function(e) {
			this.fire("data-progress", {
				percent: e.totalSize/e.position,
				total: e.totalSize,
				current: e.position
			});
		},

		addHeader: function(name, value) {
			this.headers = this.headers || [];
			this.headers.push({name:name, value:value});
		},

		addParam: function(name, value) {
			this.params = this.params || [];
			this.params.push({name:name, value:value});
		},

		addUrlParam: function(param) {
			this.urlParams = this.urlParams || [];
			this.urlParams.push(param);
		},

		serializeUrl: function(array) {
			return array.join("/");
		},

		serialize: function(data, paramaterize) {

			paramaterize = paramaterize || _paramaterize;
			var i, obj, output = [];
			if (typeof data === "string") {
				try {
					data = JSON.parse(data);
				} catch(e) {
					this.fire("data-error", {error: e.message, instance: this});
				}
			}
			if ( DataUtils.isType(data, "array") ) {
				for (i = data.length - 1; i >= 0; i--) {
					obj = data[i];
					if (obj.name !== null && obj.value !== null) {
						output.push( paramaterize(obj.name, obj.value) );
					}
				}

			} else {
				output = _serialize(data, null);
			}

			return output;
		},

		readyStateChange: function() {
			var result = {};
			if (this.xhr.readyState === 4) {
				this.fire("data-result");
				this.response = this.responseHandler[this.responseType || 'json'].call(this);
				if (!this.xhr.status || (this.xhr.status >= 200 && this.xhr.status < 300)) {
					result = {response: this.response, instance: this};
					this.fire("data-ready", result);
					if (this.promise) {
						this.promise(true, [this, this.promise, result]);
					}
				} else {
					result = {error: this.xhr.status, instance: this, response: this.response};
					this.fire("data-error", result);
					if (this.promise) {
						this.promise(false, [this, this.promise, result]);
					}
				}
			}
		},

		responseHandler: {

			xml: function() {
				return this.xhr.responseXML;
			},

			text: function() {
			return this.xhr.responseText;
			},

			json: function() {
				var response = this.xhr.responseText;
				try {
					return JSON.parse(response);
				} catch (e) {
					this.fire("data-error", {error: e.message, instance: this});
					return response;
				}
			},

			document: function() {
				return this.xhr.response;
			},

			blob: function() {
				return this.xhr.response;
			},

			arrayBuffer: function() {
				return this.xhr.response;
			},

		},

		get status() {
			return this.xhr && this.xhr.status;
		},

		get state() {
			return this.xhr && this.xhr.readyState;
		},

		get xhr() {
			return this._xhr;
		}
	});

})(); <commit_msg>removed some unneeded logic fixed a case where a url could end with ? and have an & improperly appended before any query params<commit_after>/**
 * @license
 * Copyright (c) 2015 MediaMath Inc. All rights reserved.
 * This code may only be used under the BSD style license found at http://mediamath.github.io/strand/LICENSE.txt

*/
/*jshint -W030 */
(function () {

	function _paramaterize(name, value) {
		return encodeURIComponent(name) + "=" + encodeURIComponent(value);
	}

	function _serialize(data, parent, depth, paramaterize) {

		paramaterize = paramaterize || _paramaterize;
		var obj,
			output = [];
		parent = parent || "";
		depth = depth || 0;

		for(var i in data) {
			obj = data[i];
			name = (depth === 0) ? i : "[" + i + "]";
			if (typeof obj === "object") {
				output = output.concat( _serialize(obj, name, depth+1) );
			} else {
				output.push( paramaterize(parent + name, obj) );
			}
		}
		return output;
	}

	Polymer('mm-ajax', {
		ver:"<<version>>",

		GET: "GET",
		POST: "POST",
		PUT: "PUT",
		DELETE: "DELETE",

		publish: {
			contentType: 'application/x-www-form-urlencoded',
			method: "GET",
			auto: false,
			debug: false,
			body: null,
			withCredentials: false,
			timeout: 10000
		},

		created: function() {
			this.reset();
		},

		ready: function() {
			if (this.auto && this.url && this.method) {
				this.exec();
			}
		},

		reset: function() {
			this._xhr = new XMLHttpRequest();
			this.promise = pinkySwear();
			this.headers = [];
			this.params = [];
			this.urlParams = [];
		},

		exec: function() {
			var data,
				fd,
				message,
				url = this.url;

			if (!this.method || !url) {
				message = "url and method are required!!";
				this.fire("data-error", {message:message});
				this.promise(false, [this, this.promise, message]);
				return this.promise;
			}

			if (this.urlParams && this.urlParams.length > 0) {
				if (url.slice(-1) === "/") {
					url += this.serializeUrl(this.urlParams);
				} else {
					url += "/" + this.serializeUrl(this.urlParams);
				}
			}

			if (this.method.match(/(POST|PUT|DELETE)/i)) {
				if (this.contentType === "application/json") {
					data = this.body;
				} else if(this.contentType === "multipart/form-data") {
					if (this.body instanceof FormData) {
						data = this.body;
					} else {
						fd = new FormData();
						this.serialize(this.body, fd.append.bind(fd));
						data = fd;
					}
				} else {
					data = this.serialize( this.body ).join("&");
				}
			}

			if (this.params && this.params.length) {
				if (url.indexOf("?") !== -1) {
					var last = url.slice(-1);
					if (last !== "&" && last !== "?") {
						url += "&";
					}
				} else {
					url += "?";
				}
				url += this.serialize(this.params).join("&");
			}

			//open(DOMString method, DOMString url, optional boolean async, optional DOMString? user, optional DOMString? password);
			this.xhr.open(this.method, url, true, this.username, this.password);

			this.xhr.timeout = this.timeout || 10000;
			this.xhr.withCredentials = this.withCredentials;
			this.xhr.onreadystatechange = this.readyStateChange.bind(this);
			this.xhr.addEventListener("abort", this.handleAbort.bind(this));
			this.xhr.addEventListener("progress", this.handleProgress.bind(this));

			this.contentType && this.addHeader("content-type",this.contentType);

			this.headers && this.headers.forEach(function(header) {
				this.xhr.setRequestHeader(header.name, header.value);
			}.bind(this));

			this.xhr.send(data);

			return this.promise;

		},

		abort: function() {
			if (this.xhr) {
				this.xhr.abort();
			}
		},

		handleAbort: function(e) {
			this.fire("data-abort");
			if (this.promise) {
				this.promise(false, [this, this.promise, 'aborted']);
			}
		},

		handleProgress: function(e) {
			this.fire("data-progress", {
				percent: e.totalSize/e.position,
				total: e.totalSize,
				current: e.position
			});
		},

		addHeader: function(name, value) {
			this.headers = this.headers || [];
			this.headers.push({name:name, value:value});
		},

		addParam: function(name, value) {
			this.params = this.params || [];
			this.params.push({name:name, value:value});
		},

		addUrlParam: function(param) {
			this.urlParams = this.urlParams || [];
			this.urlParams.push(param);
		},

		serializeUrl: function(array) {
			return array.join("/");
		},

		serialize: function(data, paramaterize) {

			paramaterize = paramaterize || _paramaterize;
			var i, obj, output = [];
			if (typeof data === "string") {
				try {
					data = JSON.parse(data);
				} catch(e) {
					this.fire("data-error", {error: e.message, instance: this});
				}
			}
			if ( DataUtils.isType(data, "array") ) {
				for (i = data.length - 1; i >= 0; i--) {
					obj = data[i];
					if (obj.name !== null && obj.value !== null) {
						output.push( paramaterize(obj.name, obj.value) );
					}
				}

			} else {
				output = _serialize(data, null);
			}

			return output;
		},

		readyStateChange: function() {
			var result = {};
			if (this.xhr.readyState === 4) {
				this.fire("data-result");
				this.response = this.responseHandler[this.responseType || 'json'].call(this);
				if (!this.xhr.status || (this.xhr.status >= 200 && this.xhr.status < 300)) {
					result = {response: this.response, instance: this};
					this.fire("data-ready", result);
					if (this.promise) {
						this.promise(true, [this, this.promise, result]);
					}
				} else {
					result = {error: this.xhr.status, instance: this, response: this.response};
					this.fire("data-error", result);
					if (this.promise) {
						this.promise(false, [this, this.promise, result]);
					}
				}
			}
		},

		responseHandler: {

			xml: function() {
				return this.xhr.responseXML;
			},

			text: function() {
			return this.xhr.responseText;
			},

			json: function() {
				var response = this.xhr.responseText;
				try {
					return JSON.parse(response);
				} catch (e) {
					this.fire("data-error", {error: e.message, instance: this});
					return response;
				}
			},

			document: function() {
				return this.xhr.response;
			},

			blob: function() {
				return this.xhr.response;
			},

			arrayBuffer: function() {
				return this.xhr.response;
			},

		},

		get status() {
			return this.xhr && this.xhr.status;
		},

		get state() {
			return this.xhr && this.xhr.readyState;
		},

		get xhr() {
			return this._xhr;
		}
	});

})(); <|endoftext|>


<commit_before>
/**
 *
 * Converts given text into a multilevel (paragraph, sentence, word) fragmented XHTML document.
 *
 * @param  {String} text        Text string to be fragmented and converted to XHTML
 * @return {String}             Source string of the fragmented XHTML document.
 */

function fragJS(text) {

	text = text.trim();
	if (!text) throw "No text";

	// normalize newlines
	text = text.replace(/\r\n/g, "\n");
	text = text.replace(/\r/g, "\n");

	/* Create an iframe for DOM manipulations */
	fragJSFrame = document.createElement('iframe');
	document.body.appendChild(fragJSFrame);
	fragJSFrameWindow = (fragJSFrame.contentWindow) ? fragJSFrame.contentWindow : (fragJSFrame.contentDocument.document) ? fragJSFrame.contentDocument.document : fragJSFrame.contentDocument;
	fragJSFrameWindow.document.open();
	fragJSFrameWindow.document.write(text);
	fragJSFrameWindow.document.close();
	fragJSFrameHead = fragJSFrameWindow.document.head;
	fragJSFrameBody = fragJSFrameWindow.document.body;

	splitToParagraphs();
	splitParagraphsToSentences();
	splitSentencesToWords();

	var bodyMarkup = fragJSFrameBody.innerHTML;
	document.body.removeChild(fragJSFrame);
	var xhtml = generateXHTML(bodyMarkup);
	return xhtml;

	/* Paragraph Level Fragmentation */
	function splitToParagraphs() {
		htmlText = text.replace(/(.)\n(.)/g, "$1
$2"); // single newlines to breaks
		htmlText = htmlText.replace(/^(.+)$/mg, "
$1
"); // multiple newlines to paragraphs
		htmlText = htmlText.replace(/^$/mg, "
"); // empty lines to breaks
		htmlText = htmlText.replace(/
/g, "
´´``pBegins´´``");
		htmlText = htmlText.replace(/<\/p>/g, "´´``pEnds´´``
");
		htmlText = htmlText.replace(/(.)
(.)/g, "$1´´``pEnds´´``
´´``pBegins´´``$2");
		htmlText = htmlText.replace(/´´``pBegins´´``(\s*)´´``pEnds´´``/gi, '$1'); // remove unnecessary spans
		htmlText = htmlText.replace(/´´``pBegins´´``(\s*)/gi, '$1<tempspanp class="fragjs-p">');
		htmlText = htmlText.replace(/(\s*)´´``pEnds´´``/gi, '<\/tempspanp>$1');
		fragJSFrameBody.innerHTML = htmlText;
		removeEmptyFragments("p");
		enumerateFragments("p");
	}

	/* Sentence Level Fragmentation */
	function splitParagraphsToSentences() {
		allParagraphSpans = fragJSFrameBody.getElementsByClassName("fragjs-p");
		var allParagraphsArray = [];
		for (i=0; i<allParagraphSpans.length; i++) {
			allParagraphsArray.push(allParagraphSpans[i]);
		}
		for (i=0; i<allParagraphsArray.length; i++) {

			var paragraphText = allParagraphsArray[i].textContent;

			// first some corrections
			paragraphText = paragraphText.replace(/(\s)([^\s])/g, capitalCheck); // rule out lower case letters as beginnings
			paragraphText = paragraphText.replace(/,\s/g, ',´´``ws´´``'); // rule out commas as ends
			paragraphText = paragraphText.replace(/\s([\.!?])/g, '´´``ws´´``$1'); // rule out spaces before punctuation
			paragraphText = paragraphText.replace(/\b(([^0-9])\.\s)(([^0-9])\.\s*)+[\s\b]/g, fixInitials); // fix name initials
			paragraphText = paragraphText.replace(/(Mr|Dr|Ms|Mrs|St|Sr|Rev)\.\s/g, '$1.´´``ws´´``'); // rule out title abbr.
			paragraphText = paragraphText.replace(/No\.\s([0-9])/g, 'No.´´``ws´´``$1'); // rule out "No."

			// now split
			paragraphText = paragraphText.replace(/([\.!?]["'”’»\]\)]?)(\s+)/g, '$1´´``sEnds´´``$2´´``sBegins´´``');
			paragraphText = paragraphText.replace(/([\.!?])—(.)/g, emDashCapitalCheck); // split sentences that are followed by em-dash instead of space

			// beginnings and ends
			paragraphText = paragraphText.replace(/^([^]+)$/g, "´´``sBegins´´``$1´´``sEnds´´``");

			allParagraphsArray[i].textContent = paragraphText;
		}
		htmlText = fragJSFrameBody.innerHTML;
		htmlText = htmlText.replace(/´´``sEnds´´``(\s*)´´``sBegins´´``([,;.!?'"\- ]+)´´``sEnds´´``/g, "$2´´``sEnds´´``$1");
		htmlText = htmlText.replace(/´´``sBegins´´``(\s*)´´``sEnds´´``/g, '$1'); // remove whitespace-only spans
		htmlText = htmlText.replace(/´´``sBegins´´``(\s*)/g, '$1<tempspans class="fragjs-s">');
		htmlText = htmlText.replace(/´´``ws´´``/g, ' ');

		fragJSFrameBody.innerHTML = htmlText.replace(/(\s*)´´``sEnds´´``/gi, '<\/tempspans>$1');
		htmlText = fragJSFrameBody.innerHTML; //this step is necessary for auto-corrections by the browser
		fragJSFrameBody.innerHTML = htmlText;
		removeEmptyFragments("s");
		enumerateFragments("s");
	}

	function splitSentencesToWords() {

		allSentenceSpans = fragJSFrameBody.getElementsByClassName("fragjs-s");
		var allSentencesArray = [];
		for (i=0; i<allSentenceSpans.length; i++) {
			allSentencesArray.push(allSentenceSpans[i]);
		}

		for (i=0; i<allSentencesArray.length; i++) {

			sentenceText = allSentencesArray[i].textContent;

			// first some corrections
			sentenceText = sentenceText.replace(/\s([\.!?])/g, '´´``ws´´``$1'); // rule out spaces before punctuation
			// now split
			sentenceText = sentenceText.replace(/(\s)/g, '´´``wEnds´´``$1´´``wBegins´´``'); // divide
			sentenceText = sentenceText.replace(/([^\s])([—])([^\s])/g, '$1´´``wEnds´´``$2´´``wBegins´´``$3');  // divide at em dash

			// beginnings and ends
			sentenceText = sentenceText.replace(/^([^]+)$/g, "´´``wBegins´´``$1´´``wEnds´´``");

			allSentencesArray[i].textContent = sentenceText;

		}

		htmlText = fragJSFrameBody.innerHTML;
		htmlText = htmlText.replace(/´´``ws´´``/g, ' ');
		htmlText = htmlText.replace(/´´``wBegins´´``([,;:.!?'"“”‘’«»*\-—\(\)\[\]\}\{\s]*)/g, '$1<tempspanw class="fragjs-w">');
		htmlText = htmlText.replace(/([,;:.!?'"“”‘’«»*\-—\(\)\[\]\}\{\s]*)´´``wEnds´´``/g, '<\/tempspanw>$1');
		htmlText = htmlText.replace(/(&(#[0-9]+|[a-z]+))<\/tempspanw>;/gi, '$1;<\/tempspanw>'); // fix for html entities

		htmlText = htmlText.replace(/<tempspanw class="fragjs-w"><\/tempspanw>/gi, '');

		fragJSFrameBody.innerHTML = htmlText
		htmlText = fragJSFrameBody.innerHTML; //this conversion is necessary for auto-corrections by the browser
		fragJSFrameBody.innerHTML = htmlText;
		removeEmptyFragments("w");
		enumerateFragments("w");
	}

	function capitalCheck(match, p1, p2){
		if(p2 !== p2.toUpperCase()){
			return '´´``ws´´``' + p2;
		}
		else return match;
	}
	function abbrCheck(match, p1, p2, p3, p4, p5){
		if(p1.toUpperCase() === p1.toLowerCase() && p2 !== p2.toLowerCase() && p4 !== p4.toLowerCase() && p5 !== p5.toUpperCase()){
			return p1 + p2 + ".´´``sEnds´´`` ´´``sBegins´´``" + p3 + p4 +p5;
		}
		else{
			return match;
		}

	}

	function fixInitials(match, p1, p2, p3, p4){
		if(p2.toLowerCase() !== p2 && p4.toLowerCase() !== p4){
			return match.replace(/\s/g, "´´``ws´´``");
		}
		else return match;
	}
	function emDashCapitalCheck(match, p1, p2){
		if(p2 !== p2.toLowerCase()){
			return p1 + '´´``sEnds´´``—´´``sBegins´´``' + p2;
		}
		else return match;
	}

   /* Generate fragJS XHTML output */
    function generateXHTML(text) {
		text = text.replace(/ /gi, ' '); // normalize nbsp
		text = text.replace(/tempspanp/g, 'span');
		text = text.replace(/tempspans/g, 'span');
		text = text.replace(/tempspanw/g, 'span');
		text = text.replace(/
(\s*
)+/g, '

');  // replace multiple breaks with two breaks
		text = text.replace(/
<\/div>(\s*
<\/div>)*/g, '
');  // replace multiple empty divs with hr
        text = text.replace(/
/g, '
');  // proper break tag for XHTML is "
"
        text = text.replace(/^$/g, '');  // remove blank lines
		text = text.replace(/(
(
\n)+<\/p>\n){2,}/gi, ''); // having too many breaks is pointless. espceially targets image 'div's of gutenberg books & excludes intentional ones.
        var xhtml = '<?xml version="1.0" encoding="UTF-8"?>\n';
        xhtml += '\n\n';
        xhtml += '\n<meta charset="utf-8"/>\n<meta name="generator" content="fragjs 1.0"/>\n';
        xhtml += '<meta name="originator" content="' + ("Plain Text") + '"/>\n';
        xhtml += '<meta name="viewport" content="width=device-width,height=1024"/>\n';
        xhtml += '<title>fragjs output</title>\n';
		xhtml += "\n";
		xhtml += '\n\n';
        xhtml += '\n' + text + '\n\n\n';
        xhtml += '\n';
        return xhtml;
    }

	function removeEmptyFragments(granularity){
		var className = "fragjs-" + granularity;
		allFragments = fragJSFrameBody.getElementsByClassName(className);
		for (i=allFragments.length-1; i>=0; i--) {
			if (!allFragments[i].innerText) {
				allFragments[i].outerHTML = allFragments[i].innerHTML;
			}
		}
	}

	function enumerateFragments(granularity){
		var className = "fragjs-" + granularity;
		allFragments = fragJSFrameBody.getElementsByClassName(className);
		for (i=allFragments.length-1; i>=0; i--) {
			if(!allFragments[i].innerText.replace(/^[,;:.!?'"“”‘’«»*\-–—\(\)\[\]\}\{\s]+$/,"")) {
				allFragments[i].outerHTML = allFragments[i].innerHTML;
			}
		}
		allFragments = fragJSFrameBody.getElementsByClassName(className);
		for (i=allFragments.length-1; i>=0; i--) {
			allFragments[i].id = granularity + ("00000" + (i + 1)).slice(-6);
		}
	}

}
<commit_msg>punctuations set to be included in word fragments<commit_after>
/**
 *
 * Converts given text into a multilevel (paragraph, sentence, word) fragmented XHTML document.
 *
 * @param  {String} text        Text string to be fragmented and converted to XHTML
 * @return {String}             Source string of the fragmented XHTML document.
 */

function fragJS(text) {

	text = text.trim();
	if (!text) throw "No text";

	// normalize newlines
	text = text.replace(/\r\n/g, "\n");
	text = text.replace(/\r/g, "\n");

	/* Create an iframe for DOM manipulations */
	fragJSFrame = document.createElement('iframe');
	document.body.appendChild(fragJSFrame);
	fragJSFrameWindow = (fragJSFrame.contentWindow) ? fragJSFrame.contentWindow : (fragJSFrame.contentDocument.document) ? fragJSFrame.contentDocument.document : fragJSFrame.contentDocument;
	fragJSFrameWindow.document.open();
	fragJSFrameWindow.document.write(text);
	fragJSFrameWindow.document.close();
	fragJSFrameHead = fragJSFrameWindow.document.head;
	fragJSFrameBody = fragJSFrameWindow.document.body;

	splitToParagraphs();
	splitParagraphsToSentences();
	splitSentencesToWords();

	var bodyMarkup = fragJSFrameBody.innerHTML;
	document.body.removeChild(fragJSFrame);
	var xhtml = generateXHTML(bodyMarkup);
	return xhtml;

	/* Paragraph Level Fragmentation */
	function splitToParagraphs() {
		htmlText = text.replace(/(.)\n(.)/g, "$1
$2"); // single newlines to breaks
		htmlText = htmlText.replace(/^(.+)$/mg, "
$1
"); // multiple newlines to paragraphs
		htmlText = htmlText.replace(/^$/mg, "
"); // empty lines to breaks
		htmlText = htmlText.replace(/
/g, "
´´``pBegins´´``");
		htmlText = htmlText.replace(/<\/p>/g, "´´``pEnds´´``
");
		htmlText = htmlText.replace(/(.)
(.)/g, "$1´´``pEnds´´``
´´``pBegins´´``$2");
		htmlText = htmlText.replace(/´´``pBegins´´``(\s*)´´``pEnds´´``/gi, '$1'); // remove unnecessary spans
		htmlText = htmlText.replace(/´´``pBegins´´``(\s*)/gi, '$1<tempspanp class="fragjs-p">');
		htmlText = htmlText.replace(/(\s*)´´``pEnds´´``/gi, '<\/tempspanp>$1');
		fragJSFrameBody.innerHTML = htmlText;
		removeEmptyFragments("p");
		enumerateFragments("p");
	}

	/* Sentence Level Fragmentation */
	function splitParagraphsToSentences() {
		allParagraphSpans = fragJSFrameBody.getElementsByClassName("fragjs-p");
		var allParagraphsArray = [];
		for (i=0; i<allParagraphSpans.length; i++) {
			allParagraphsArray.push(allParagraphSpans[i]);
		}
		for (i=0; i<allParagraphsArray.length; i++) {

			var paragraphText = allParagraphsArray[i].textContent;

			// first some corrections
			paragraphText = paragraphText.replace(/(\s)([^\s])/g, capitalCheck); // rule out lower case letters as beginnings
			paragraphText = paragraphText.replace(/,\s/g, ',´´``ws´´``'); // rule out commas as ends
			paragraphText = paragraphText.replace(/\s([\.!?])/g, '´´``ws´´``$1'); // rule out spaces before punctuation
			paragraphText = paragraphText.replace(/\b(([^0-9])\.\s)(([^0-9])\.\s*)+[\s\b]/g, fixInitials); // fix name initials
			paragraphText = paragraphText.replace(/(Mr|Dr|Ms|Mrs|St|Sr|Rev)\.\s/g, '$1.´´``ws´´``'); // rule out title abbr.
			paragraphText = paragraphText.replace(/No\.\s([0-9])/g, 'No.´´``ws´´``$1'); // rule out "No."

			// now split
			paragraphText = paragraphText.replace(/([\.!?]["'”’»\]\)]?)(\s+)/g, '$1´´``sEnds´´``$2´´``sBegins´´``');
			paragraphText = paragraphText.replace(/([\.!?])—(.)/g, emDashCapitalCheck); // split sentences that are followed by em-dash instead of space

			// beginnings and ends
			paragraphText = paragraphText.replace(/^([^]+)$/g, "´´``sBegins´´``$1´´``sEnds´´``");

			allParagraphsArray[i].textContent = paragraphText;
		}
		htmlText = fragJSFrameBody.innerHTML;
		htmlText = htmlText.replace(/´´``sEnds´´``(\s*)´´``sBegins´´``([,;.!?'"\- ]+)´´``sEnds´´``/g, "$2´´``sEnds´´``$1");
		htmlText = htmlText.replace(/´´``sBegins´´``(\s*)´´``sEnds´´``/g, '$1'); // remove whitespace-only spans
		htmlText = htmlText.replace(/´´``sBegins´´``(\s*)/g, '$1<tempspans class="fragjs-s">');
		htmlText = htmlText.replace(/´´``ws´´``/g, ' ');

		fragJSFrameBody.innerHTML = htmlText.replace(/(\s*)´´``sEnds´´``/gi, '<\/tempspans>$1');
		htmlText = fragJSFrameBody.innerHTML; //this step is necessary for auto-corrections by the browser
		fragJSFrameBody.innerHTML = htmlText;
		removeEmptyFragments("s");
		enumerateFragments("s");
	}

	function splitSentencesToWords() {

		allSentenceSpans = fragJSFrameBody.getElementsByClassName("fragjs-s");
		var allSentencesArray = [];
		for (i=0; i<allSentenceSpans.length; i++) {
			allSentencesArray.push(allSentenceSpans[i]);
		}

		for (i=0; i<allSentencesArray.length; i++) {

			sentenceText = allSentencesArray[i].textContent;

			// first some corrections
			sentenceText = sentenceText.replace(/\s([\.!?])/g, '´´``ws´´``$1'); // rule out spaces before punctuation
			// now split
			sentenceText = sentenceText.replace(/(\s)/g, '´´``wEnds´´``$1´´``wBegins´´``'); // divide
			sentenceText = sentenceText.replace(/([^\s])([—])([^\s])/g, '$1´´``wEnds´´``$2´´``wBegins´´``$3');  // divide at em dash

			// beginnings and ends
			sentenceText = sentenceText.replace(/^([^]+)$/g, "´´``wBegins´´``$1´´``wEnds´´``");

			allSentencesArray[i].textContent = sentenceText;

		}

		htmlText = fragJSFrameBody.innerHTML;
		htmlText = htmlText.replace(/´´``ws´´``/g, ' ');

		// htmlText = htmlText.replace(/´´``wBegins´´``([,;:.!?'"“”‘’«»*\-—\(\)\[\]\}\{\s]*)/g, '$1<tempspanw class="fragjs-w">');
		// htmlText = htmlText.replace(/([,;:.!?'"“”‘’«»*\-—\(\)\[\]\}\{\s]*)´´``wEnds´´``/g, '<\/tempspanw>$1');
		// htmlText = htmlText.replace(/(&(#[0-9]+|[a-z]+))<\/tempspanw>;/gi, '$1;<\/tempspanw>'); // fix for html entities

		htmlText = htmlText.replace(/´´``wBegins´´``/g, '<tempspanw class="fragjs-w">');
		htmlText = htmlText.replace(/´´``wEnds´´``/g, '<\/tempspanw>');

		htmlText = htmlText.replace(/<tempspanw class="fragjs-w"><\/tempspanw>/gi, '');

		fragJSFrameBody.innerHTML = htmlText
		htmlText = fragJSFrameBody.innerHTML; //this conversion is necessary for auto-corrections by the browser
		fragJSFrameBody.innerHTML = htmlText;
		removeEmptyFragments("w");
		enumerateFragments("w");
	}

	function capitalCheck(match, p1, p2){
		if(p2 !== p2.toUpperCase()){
			return '´´``ws´´``' + p2;
		}
		else return match;
	}
	function abbrCheck(match, p1, p2, p3, p4, p5){
		if(p1.toUpperCase() === p1.toLowerCase() && p2 !== p2.toLowerCase() && p4 !== p4.toLowerCase() && p5 !== p5.toUpperCase()){
			return p1 + p2 + ".´´``sEnds´´`` ´´``sBegins´´``" + p3 + p4 +p5;
		}
		else{
			return match;
		}

	}

	function fixInitials(match, p1, p2, p3, p4){
		if(p2.toLowerCase() !== p2 && p4.toLowerCase() !== p4){
			return match.replace(/\s/g, "´´``ws´´``");
		}
		else return match;
	}
	function emDashCapitalCheck(match, p1, p2){
		if(p2 !== p2.toLowerCase()){
			return p1 + '´´``sEnds´´``—´´``sBegins´´``' + p2;
		}
		else return match;
	}

   /* Generate fragJS XHTML output */
    function generateXHTML(text) {
		text = text.replace(/ /gi, ' '); // normalize nbsp
		text = text.replace(/tempspanp/g, 'span');
		text = text.replace(/tempspans/g, 'span');
		text = text.replace(/tempspanw/g, 'span');
		text = text.replace(/
(\s*
)+/g, '

');  // replace multiple breaks with two breaks
		text = text.replace(/
<\/div>(\s*
<\/div>)*/g, '
');  // replace multiple empty divs with hr
        text = text.replace(/
/g, '
');  // proper break tag for XHTML is "
"
        text = text.replace(/^$/g, '');  // remove blank lines
		text = text.replace(/(
(
\n)+<\/p>\n){2,}/gi, ''); // having too many breaks is pointless. espceially targets image 'div's of gutenberg books & excludes intentional ones.
        var xhtml = '<?xml version="1.0" encoding="UTF-8"?>\n';
        xhtml += '\n\n';
        xhtml += '\n<meta charset="utf-8"/>\n<meta name="generator" content="fragjs 1.0"/>\n';
        xhtml += '<meta name="originator" content="' + ("Plain Text") + '"/>\n';
        xhtml += '<meta name="viewport" content="width=device-width,height=1024"/>\n';
        xhtml += '<title>fragjs output</title>\n';
		xhtml += "\n";
		xhtml += '\n\n';
        xhtml += '\n' + text + '\n\n\n';
        xhtml += '\n';
        return xhtml;
    }

	function removeEmptyFragments(granularity){
		var className = "fragjs-" + granularity;
		allFragments = fragJSFrameBody.getElementsByClassName(className);
		for (i=allFragments.length-1; i>=0; i--) {
			if (!allFragments[i].innerText) {
				allFragments[i].outerHTML = allFragments[i].innerHTML;
			}
		}
	}

	function enumerateFragments(granularity){
		var className = "fragjs-" + granularity;
		allFragments = fragJSFrameBody.getElementsByClassName(className);
		for (i=allFragments.length-1; i>=0; i--) {
			if(!allFragments[i].innerText.replace(/^[,;:.!?'"“”‘’«»*\-–—\(\)\[\]\}\{\s]+$/,"")) {
				allFragments[i].outerHTML = allFragments[i].innerHTML;
			}
		}
		allFragments = fragJSFrameBody.getElementsByClassName(className);
		for (i=allFragments.length-1; i>=0; i--) {
			allFragments[i].id = granularity + ("00000" + (i + 1)).slice(-6);
		}
	}

}
<|endoftext|>


<commit_before>define([
	'models/location'
], function(
		LocationModel
) {

	var baseUrl = 'api/locations';

	var collection = {

		model: LocationModel,

		url: baseUrl,

		/**
		 * Clear any currently applied filters so that future
		 * fetch calls will return ALL locations
		 *
		 * @returns {undefined}
		 */
		clearFilter: function() {
			this.url = baseUrl;
		},

		/**
		 * Apply a filter, causing any future fetch calls to return
		 * only the locations that match the given filter string
		 *
		 * @param {string} filterStr
		 * @returns {undefined}
		 */
		setFilter: function(filterStr) {
			this.url = baseUrl + '/search/' + encodeURIComponent(filterStr);
		}

	};

	return Backbone.Collection.extend(collection);

});

<commit_msg>Update location search to match new API<commit_after>define([
	'models/location'
], function(
		LocationModel
) {

	var baseUrl = 'api/locations';

	var collection = {

		model: LocationModel,

		url: baseUrl,

		/**
		 * Clear any currently applied filters so that future
		 * fetch calls will return ALL locations
		 *
		 * @returns {undefined}
		 */
		clearFilter: function() {
			this.url = baseUrl;
		},

		/**
		 * Apply a filter, causing any future fetch calls to return
		 * only the locations that match the given filter string
		 *
		 * @param {string} filterStr
		 * @returns {undefined}
		 */
		setFilter: function(filterStr) {
			this.url = baseUrl + '?search=' + encodeURIComponent(filterStr);
		}

	};

	return Backbone.Collection.extend(collection);

});

<|endoftext|>