from a service, turning one function into two different functions - javascript

I have a function inside a service which has lots of lines and I want to convert that function into two different functions
this is the function
angular.module('capilleira.clickAndGambleMobile.services')
.factory('SportsFactory', function($http, $q, AuthFactory, LocalForageFactory, LeaguesFactory, CONSTANT_VARS) {
return {
getSports: function(customer) {
var defer = $q.defer(),
_this = this;
LocalForageFactory.retrieve(CONSTANT_VARS.LOCALFORAGE_SPORTS)
.then(function(sports) {
if (!_.isNull(sports)) {
defer.resolve(sports);
}else {
$http.get(CONSTANT_VARS.BACKEND_URL + '/lines/sports/' + customer.agent)
.success(function(sports) {
sports = _.sortBy(sports, function(sport) {
return sport.priority;
});
//THIS THE PART THAT I WANT TO MOVE FROM HERE
_this.getSportChecked(customer).then(function(sportChecked) {
var sportIds = _.pluck(sports, 'id'),
intersectedSports = _.intersection(sportIds, sportChecked.sport);
if (sports.length) {
sports = _.map(sports, function(sport) {
sport.checked = !_.includes(intersectedSports, sport.id);
return sport;
});
}else {
AuthFactory.logout();
}
});
LocalForageFactory.set(CONSTANT_VARS.LOCALFORAGE_SPORTS, sports);
defer.resolve(sports);
})
.error(function(err) {
defer.reject(err);
});
}
});
return defer.promise;
}
});
and here is what I have so far but I am receiving an error sports is not defined
getSports: function(customer) {
var defer = $q.defer(),
_this = this;
LocalForageFactory.retrieve(CONSTANT_VARS.LOCALFORAGE_SPORTS)
.then(function(sports) {
if (!_.isNull(sports)) {
defer.resolve(sports);
}else {
$http.get(CONSTANT_VARS.BACKEND_URL + '/lines/sports/' + customer.agent)
.success(function(sports) {
sports = _.sortBy(sports, function(sport) {
return sport.priority;
});
// HERE I AM CALLING THE NEW FUNCTION
_this.intersectedSportsChecked(customer);
LocalForageFactory.set(CONSTANT_VARS.LOCALFORAGE_SPORTS, sports);
defer.resolve(sports);
})
.error(function(err) {
defer.reject(err);
});
}
});
return defer.promise;
},
// HERE IS THE NEW FUNCTION
// UPDATED
intersectedSportsChecked: function(customer) {
var _this = this,
defer = $q.defer(),
rejection = function(err) {
defer.reject(err);
};
_this.getSports(customer).then(function(sports) {
_this.getSportChecked(customer).then(function(sportChecked) {
var sportIds = _.pluck(sports, 'id'),
intersectedSports = _.intersection(sportIds, sportChecked.sport);
if (sports.length) {
sports = _.map(sports, function(sport) {
sport.checked = !_.includes(intersectedSports, sport.id);
return sport;
});
}else {
AuthFactory.logout();
}
});
}, rejection);
},
so, what am I missing here ?

Related

How to access to a function from world.js?

I'm trying to access to this.addScreenshotToReport from a function of world.js
This is the code I been trying to export the world.js:
module.exports = function() {
var worldPath = path.join(config.paths.root, '../support/world')
this.World = require(worldPath).World;
}
And i put this.addScreenshotToReport() to access in that specific tunction
This is the code from world.js:
function CustomWorld({attach, parameters}) {
this.waitForTestController = testControllerHolder.get()
.then(function(tc) {
return testController = tc;
});
this.attach = attach;
this.setBrowser = function() {
if (parameters.browser === undefined) {
return 'chrome';
} else {
return parameters.browser;
}
};
this.addScreenshotToReport = function() {
if (process.argv.includes('--format') || process.argv.includes('-f') || process.argv.includes('--format-options')) {
testController.takeScreenshot()
.then(function(screenshotPath) {
const imgInBase64 = base64Img.base64Sync(screenshotPath);
const imageConvertForCuc = imgInBase64.substring(imgInBase64.indexOf(',') + 1);
return attach(imageConvertForCuc, 'image/png');
})
.catch(function(error) {
console.warn('The screenshot was not attached to the report');
});
} else {
return new Promise((resolve) => {
resolve(null);
});
}
};
The actual output is:
TypeError: this.addScreenshotToReport is not a function

Mocking service when testing controller in Karma for angularjs

I am working on the Single Page Application with AngularJS project for the Treehouse Full Stack JavaScript TechDegree and I am trying to do unit tests on the controllers. To test the controllers that make api calls to the dataService I have to mock the dataService and I can not figure out how to do this correctly. I have read article after article on unit testing angular and I am so lost that I have no idea what to do next.
controllers.js:
(function() {
'use strict';
angular.module('app')
.controller('RecipesController', function(dataService,$location) {
const vm = this;
vm.init = () => {
vm.hidden = true;
dataService.getAllRecipes(function(response) {
vm.recipes = response.data;
vm.getCategories(response.data);
});
}
vm.selectCategory = (category) => {
if (category === null) {
vm.init();
} else {
dataService.getCategory(category,function(response) {
vm.recipes = response.data;
});
}
};
vm.getCategories = (data) => {
let categories = new Set();
for (let item of data) {
categories.add(item.category);
}
vm.categories = Array.from(categories);
};
vm.addRecipe = () => {
$location.path('/add');
}
vm.deleteRecipe = (recipe,$index) => {
vm.toDelete = recipe.name;
vm.hidden = false;
vm.deleteIt = () => {
vm.hidden = true;
dataService.deleteRecipe(recipe._id,function(response) {
vm.init();
});
}
}
vm.init();
})
.controller('RecipeDetailController', function($scope,dataService,$location) {
const vm = this;
const init = () => {
const path = $location.path();
if (path.includes("edit")) {
let id = path.slice(6);
dataService.getID(id,function(response) {
vm.recipe = response.data;
vm.title = response.data.name;
vm.editCategory = response.data.category;
});
} else if (path.includes("add")) {
vm.recipe = {
name: "",
description: "",
category: "",
prepTime: 0,
cookTime: 0,
ingredients: [
{
foodItem: "",
condition: "",
amount: ""
}
],
steps: [
{
description: ""
}
]
}
vm.title = 'Add New Recipe.'
}
dataService.getAllCategories(function (response) {
vm.categories = response.data;
let index = response.data.findIndex(item => item.name === $scope.editCategory);
if (index === -1) {
vm.initial = {"name": "Choose a Category"};
} else {
vm.initial = $scope.categories[index];
}
});
dataService.getAllFoodItems(function (response) {
vm.foods = response.data;
});
}
vm.addItem = (item) => {
if (item === 'ingredient') {
vm.recipe.ingredients.push({amount: "amount", condition: "condition", foodItem: ""});
} else if (item === 'step') {
vm.recipe.steps.push({description: "description"});
}
};
vm.deleteItem = (item,$index) => {
if (item === 'ingredient') {
vm.recipe.ingredients.splice($index,1);
} else if (item === 'step') {
vm.recipe.steps.splice($index,1);
}
}
vm.saveChanges = (recipe) => {
vm.errors = [];
const buildErrorArray = (errorArray) => {
for (let item of errorArray) {
vm.errors.push(item.userMessage);
}
}
const collectErrors = (response) => {
if (response.data.errors.category) { buildErrorArray(response.data.errors.category) }
if (response.data.errors.ingredients) { buildErrorArray(response.data.errors.ingredients) }
if (response.data.errors.name) { buildErrorArray(response.data.errors.name) }
if (response.data.errors.steps) { buildErrorArray(response.data.errors.steps) }
}
if (recipe._id) {
dataService.updateID(recipe,function(response) {
$location.path('/');
}, function(response) {
collectErrors(response)
});
} else {
dataService.addRecipe(recipe,function(response) {
$location.path('/');
}, function(response) {
collectErrors(response)
});
}
}
vm.cancelChanges = () => {
$location.path('/');
}
init();
});
}());
services.js:
(function() {
'use strict';
angular.module('app')
.service('dataService', function($http,errors,httpErrors) {
this.getAllRecipes = function (callback) {
$http.get('http://localhost:5000/api/recipes')
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
this.getAllCategories = function (callback) {
$http.get('http://localhost:5000/api/categories')
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
this.getAllFoodItems = function (callback) {
$http.get('http://localhost:5000/api/fooditems')
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
this.getCategory = function(category,callback) {
$http.get('http://localhost:5000/api/recipes?category=' + category)
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
this.getID = function (id,callback) {
$http.get('http://localhost:5000/api/recipes/' + id)
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
this.updateID = function (data,success,error) {
$http.put('http://localhost:5000/api/recipes/' + data._id, data)
.then(success,error).catch(errors.catch());
};
this.addRecipe = function (data,success,error) {
$http.post('http://localhost:5000/api/recipes', data)
.then(success,error).catch(errors.catch());
};
this.deleteRecipe = function (id,callback) {
$http.delete('http://localhost:5000/api/recipes/' + id)
.then(callback,httpErrors.display('HTTP Error'))
.catch(errors.catch());
};
});
}());
controllersSpec.js:
describe("Unit Testing Controllers", function() {
beforeEach(angular.mock.module('app'));
let $scope;
let getAllRecipesMock;
beforeEach(inject(function(_$controller_,_$rootScope_,$q) {
$controller = _$controller_;
$scope = _$rootScope_.$new();
getAllRecipesMock = {
getAllRecipes: function() {
var deferred = $q.defer();
deferred.resolve([{name: "recipename"}]);
return deferred.promise;
}
}
}));
it('has a test to test that tests are testing', function() {
expect(2 + 2).toEqual(4);
});
it('should have a RecipesController', function() {
const controller = $controller('RecipesController',{$scope:$scope});
expect(controller).toBeDefined();
});
it('should have a RecipeDetailController', function() {
const controller = $controller('RecipeDetailController',{$scope:$scope});
expect(controller).toBeDefined();
});
it('should call the getAllRecipes service and return response', inject(function() {
const controller = $controller('RecipesController',{$scope:$scope,dataService:getAllRecipesMock});
$scope.$digest();
expect(controller.recipes).toBe([{name: "recipename"}]);
}));
it('should remove duplicate categories', function() {
const controller = $controller('RecipesController',{$scope:$scope});
let data = [{'category':'dog'},{'category':'cat'},{'category':'horse'},{'category':'dog'},{'category':'cow'}];
controller.getCategories(data);
expect(controller.categories).toEqual(['dog','cat','horse','cow']);
});
it('should take you to the /add route when the addRecipe method is called', inject(function($location) {
const controller = $controller('RecipesController',{$scope:$scope});
controller.addRecipe();
expect($location.path()).toEqual('/add');
}));
});
This is the result I get when I run the tests:
Unit Testing Controllers
√has a test to test that tests are testing
√should have a RecipesController
√should have a RecipeDetailController
×should call the getAllRecipes service and return response
Expected undefined to be [ Object({ name: 'recipename' }) ].
at Object.<anonymous> (test/controllersSpec.js:38:32)
at Object.invoke (node_modules/angular/angular.js:4839:19)
at Object.WorkFn (node_modules/angular-mocks/angular-mocks.js:3155:20)
√should remove duplicate categories
√should take you to the /add route when the addRecipe method is called
Chrome 55.0.2883 (Windows 10 0.0.0): Executed 6 of 6 (1 FAILED) (0.235 secs / 0.084 secs)
TOTAL: 1 FAILED, 5 SUCCESS
1) should call the getAllRecipes service and return response
Unit Testing Controllers
Expected undefined to be [ Object({ name: 'recipename' }) ].
at Object.<anonymous> (test/controllersSpec.js:38:32)
at Object.invoke (node_modules/angular/angular.js:4839:19)
at Object.WorkFn (node_modules/angular-mocks/angular-mocks.js:3155:20)
EDIT
I decided to change the service to return a promise instead of a callback:
this.getAllRecipes = function () {
return $http.get('http://localhost:5000/api/recipes');
};
Then I changed the corresponding function in the controller:
vm.init = () => {
vm.hidden = true;
let allRecipes = dataService.getAllRecipes();
allRecipes.then(function(response) {
vm.recipes = response.data;
vm.getCategories(response.data);
},httpErrors.display('HTTP Error'))
.catch(errors.catch());
}
but I'm still getting
Expected undefined to be [ Object({ name: 'recipename' }) ].
Am I not implementing the promise correctly? Is there still something in my test that I'm missing?
You are currently mixing callbacks and promises.
The method getAllRecipes in the real service implementation takes a callback as an argument and executes it when the internal ajax call is done. The consumer of the method has no idea that the implementation uses promises internally.
The mock implementation of getAllRecipes however does not take or use a callback function but instead returns a promise.
You have in your controller:
dataService.getAllRecipes(function(response) {
vm.recipes = response.data;
vm.getCategories(response.data);
});
But with the mock implementation you would need:
dataService.getAllRecipes(function(response) {
vm.recipes = response.data;
vm.getCategories(response.data);
}).then(function (response) {
// Code
});
With your current implementation of getAllRecipes your mock could look like this:
getAllRecipesMock = {
getAllRecipes: function(callback) {
var response = {
data: [{
name: "recipename"
}]
};
callback(response);
}
};
Also note that unless you want to compare for reference equality, use toEqual instead of toBe:
expect(controller.recipes).toEqual([{
name: "recipename"
}]);
Demo: http://plnkr.co/edit/5BQBt4tTxohXEN0Drq3f?p=preview
An alternative is to change the service implementation to return a promise instead of using callbacks.

How test Service working with IndexedDB in AngularJS

I have app in AngularJS, where I make services, which stores data to IndexedDb.
It's look like this:
var IndexedDbServices = angular.module('IndexedDbServices', []);
IndexedDbServices.factory('IndexedDb', ['$window', '$q', function($window, $q){
var indexedDB = $window.indexedDB;
var db=null;
var open = function() {
var deferred = $q.defer();
var version = 3;
var request = indexedDB.open("lCApp", version);
request.onupgradeneeded = function(e) {
db = e.target.result;
e.target.transaction.onerror = indexedDB.onerror;
if(db.objectStoreNames.contains("collections")) {
db.deleteObjectStore("collections");
}
var store = db.createObjectStore("collections", {
keyPath: "id", autoIncrement : true
});
store.createIndex("name", "name", { unique: true });
store.createIndex("description", "description", { unique: false });
store.transaction.oncomplete = function(event) {
var customerObjectStore = db.transaction("collections", "readwrite").objectStore("collections");
customerObjectStore.add({name: "coll1", description: "desc for coll1"});
customerObjectStore.add({name: "coll2", description: "desc for coll2"});
};
};
request.onsuccess = function(e) {
db = e.target.result;
deferred.resolve();
};
request.onerror = function(){
deferred.reject();
};
return deferred.promise;
};
var findAll = function() {
var deferred = $q.defer();
if(db === null || db === undefined) {
deferred.reject("IndexDB is not opened yet!");
} else{
var trans = db.transaction(["collections"], "readwrite");
var store = trans.objectStore("collections");
var data = [];
// Get everything in the store;
var keyRange = IDBKeyRange.lowerBound(0);
var cursorRequest = store.openCursor(keyRange);
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
if(result === null || result === undefined)
{
deferred.resolve(data);
}
else{
data.push(result.value);
result.continue();
}
};
cursorRequest.onerror = function(e){
console.log(e.value);
deferred.reject("Something went wrong!!!");
};
}
return deferred.promise;
};
return {
open: open,
add: add,
findAll: findAll
};
}]);
And I want test this code using unit test (jasmine). So i wrote this:
describe('IndexedDB service', function() {
beforeEach(function() {
module('IndexedDbServices');
});
it('should open db and find 2 collections', inject(function(IndexedDb) {
IndexedDb.open().then(function(e){
console.log(e);
}, function(err){
$window.alert(err);
});
console.log(IndexedDb.findAll());
}));
});
Would you advise me how test if function open in IndexedDb service create IndexedDb and add rows. And next I function open in IndexedDB service return all that records?
I don't know why, but in this test db is not created console.log(IndexedDb.findAll()); print: Promise{$$state: Object{status: 2, value: 'IndexDB is not opened yet!'}}
So Db is not created.
And next how use expect(..).toEqual() or something this in returned promises?
Let's have the service:
/*global window: false */
'use strict';
angular.module('main')
.config(['$provide', function ($provide) {
$provide.constant('indexedDB', window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
}])
.service('idb', function idbService($q, $rootScope, indexedDB) {
var service = this;
var db;
service.open = function () {
console.log('idb.open');
var deferred = $q.defer();
var request = indexedDB.open('mydb', 1);
request.onupgradeneeded = function (e) {
console.log('idb.open onupgradeneeded');
db = e.target.result;
if (!db.objectStoreNames.contains('mystore')) {
db.createObjectStore('mystore', {
keyPath: 'id'
});
}
};
request.onsuccess = function (e) {
console.log('idb.open onsuccess');
db = e.target.result;
deferred.resolve();
$rootScope.$apply(); // Propagate promise resolution to 'then' functions using $apply().
};
request.onerror = function (e) {
console.log('idb.open onerror ', e);
deferred.reject();
};
return deferred.promise;
};
service.put = function (key, value) {
console.log('idb.put(' + key + ', ' + value + ')');
var deferred = $q.defer();
var store = db.transaction(['mystore'], 'readwrite').objectStore('mystore');
var request = store.put({
id: key,
data: value
});
request.onsuccess = function () {
console.log('idb.put onsuccess');
deferred.resolve();
$rootScope.$apply(); // Propagate promise resolution to 'then' functions using $apply().
};
request.onerror = function (e) {
console.log('idb.put onerror ', e);
deferred.reject(e);
};
return deferred.promise;
};
service.get = function (key) {
console.log('idb.get' + '(' + key + ')');
var deferred = $q.defer();
var store = db.transaction(['mystore'], 'readwrite').objectStore('mystore');
var request = store.get(key);
request.onsuccess = function (e) {
console.log('idb.get onsuccess ', e.target.result);
deferred.resolve(e.target.result.data);
$rootScope.$apply(); // Propagate promise resolution to 'then' functions using $apply().
};
request.onerror = function (e) {
console.log('idb.get onerror', e);
deferred.reject(e);
};
return deferred.promise;
};
});
Test can be:
'use strict';
describe('idb', function () {
beforeEach(module('main'));
var idb;
var idbOpened;
beforeEach(angular.mock.inject(function (_idb_) {
idb = _idb_;
}));
beforeEach(function (done) {
idbOpened = false;
console.log(1);
idb.open().then(function () {
console.log(3);
idbOpened = true;
done();
})
console.log(2);
});
it('opens', function () {
expect(idbOpened).toBe(true);
console.log(4);
});
it('gets the put', function (done) {
console.log(10);
idb.put('666', 'bob').then(function () {
console.log(12);
idb.get('666').then(function (value) {
console.log(13);
expect(value).toBe('bob');
done();
console.log(14);
})
})
console.log(11);
});
});
Test output would be then:
LOG: 1
LOG: 'idb.open'
LOG: 2
LOG: 'idb.open onsuccess'
LOG: 3
LOG: 4
LOG: 1
LOG: 'idb.open'
LOG: 2
LOG: 'idb.open onsuccess'
LOG: 3
LOG: 10
LOG: 'idb.put(666, bob)'
LOG: 11
LOG: 'idb.put onsuccess'
LOG: 12
LOG: 'idb.get(666)'
LOG: 'idb.get onsuccess ', Object{id: '666', data: 'bob'}
LOG: 13
LOG: 14
Ugly stuff is a need to call
$rootScope.$apply();
to propagate promise resolution to 'then' functions in the test, because
it is not needed for the service itself.

API calls in angularJS right after each other

I have a problem using angular in a Ionic mobile project , I have this piece of code working great in my desktop environment. I do three API call to a web server 500ms after each other. But in the phone using a lower connection sometimes one of the call fails so the whole process fail.
Is there some way to do the API calls in the exact moment that the previous one finish? I mean, not using fixed amount of time.
//get member information
$timeout(function() {
membersService.getMember(community.url, community.user.api_key, community.user.auth_token, $stateParams.userId).
success(function(data) {
$scope.member = data.result;
});
}, 500);
$timeout(function() {
messagesService.getConversation(community.url, community.user.api_key, community.user.auth_token, community.user.user_info.guid, $stateParams.userId, "from").
success(function(data) {
if(data.result["entities"].length > 0) {
messages = messages.concat(data.result["entities"]);
subject = "Re: "+data.result["entities"][data.result["entities"].length-1].title;
}
$scope.messageData.subject = subject;
});
}, 1000);
$timeout(function() {
messagesService.getConversation(community.url, community.user.api_key, community.user.auth_token, community.user.user_info.guid, $stateParams.userId, "to").
success(function(data) {
log = [];
if(data.result["entities"].length > 0) {
angular.forEach(data.result["entities"], function(v, k) {
v.owner_guid = $stateParams.userId;
log.push(v);
}, log);
messages = messages.concat(log);
}
var log = [];
var count = 0;
angular.forEach(messages, function(v, k) {
messages_reorder.push(v);
}, log);
});
}, 1500);
This was the result of implementing nesting promise chains:
var loadMemberInfo = function( userId )
{
return membersService
.getMember(community.url, community.user.api_key, community.user.auth_token, $stateParams.userId)
.then(function(data)
{
$scope.member = data.result;
});
},
getConversationFrom = function() {
return messagesService
.getConversation(community.url, community.user.api_key, community.user.auth_token, community.user.user_info.guid, $stateParams.userId, "from")
.then(function(cf) {
if(cf.data.result["entities"].length > 0) {
messages = messages.concat(cf.data.result["entities"]);
subject = "Re: "+cf.data.result["entities"][cf.data.result["entities"].length-1].title;
}
$scope.messageData.subject = subject;
});
},
getConversationTo = function() {
messagesService
.getConversation(community.url, community.user.api_key, community.user.auth_token, community.user.user_info.guid, $stateParams.userId, "to")
.then(function(ct) {
log = [];
if(ct.data.result["entities"].length > 0) {
angular.forEach(ct.data.result["entities"], function(v, k) {
v.owner_guid = $stateParams.userId;
log.push(v);
}, log);
messages = messages.concat(log);
}
//order array
messages = messages.sort(function(a,b) { return a.time_created - b.time_created } );
var log = [];
var count = 0;
angular.forEach(messages, function(v, k) {
messages_reorder.push(v);
}, log);
});
},
orderFullConversation = function() {
$ionicLoading.hide();
console.log(messages);
if(messages_reorder.length > 5) {
var messages_partial = messages_reorder.slice(messages_reorder.length-5,messages_reorder.length);
}
else {
var messages_partial = messages_reorder;
}
$scope.messages = messages_partial;
$scope.community = community;
};
loadMemberInfo( $stateParams.userId )
.then( getConversationFrom )
.then( getConversationTo )
.then( orderFullConversation );
More details here
You can use angular $q service for that.
You should look at the Angular Promise API. it is meant for the same purpose. It allows you to chain ajax calls one after another..
// this
$http.get('/api/v1/movies/avengers')
.success(function(data, status, headers, config) {
$scope.movieContent = data;
});
// is the same as
var promise = $http.get('/api/v1/movies/avengers');
promise.then(
function(payload) {
$scope.movieContent = payload.data;
});
More Details here

How to get proper Strophe.js callback on successful connection

I am developing a generic library for communicating xmpp users through BOSH service. I use Strophe.js
I cannot understand why in class BoshCommunicator method onConnect I have a Strophe object, but not BoshCommunicator as expected.
When I console.log(this) I get Object { service="http://myboshim/http-bind", jid="aivaras37#myboshim/29785298701381498988721337", rid=4092107607, more...}
Also, before establishing connection I set listener property for BoshCommunicator class. When I console.log(this.listener) I get undefined, but if I console.log(this.listener) in connect() method I get expected dump of listener object. Can you explain me how to get initialized BoshCommunicator in BoshCommunicator.prototype.onConnect()? Also please explain why I loose my object and get Strophe instead.
Here is a particular code I use:
function BoshCommunicator(boshUri, host)
{
this.connection = null;
this.boshUri = null;
this.host = null;
this.listener = null;
this.setBoshUri(boshUri);
this.setHost(host);
}
BoshCommunicator.prototype.setBoshUri = function(boshUri)
{
this.boshUri = boshUri;
};
BoshCommunicator.prototype.setHost = function(host)
{
this.host = host;
};
BoshCommunicator.prototype.setListener = function(listener)
{
this.listener = listener;
this.listener.setListenHost(this.host);
};
BoshCommunicator.prototype.connect = function(jid, jpass)
{
this.connection = new Strophe.Connection(this.boshUri);
this.connection.connect(jid, jpass, this.onConnect);
};
BoshCommunicator.prototype.onConnect = function(status)
{
if (status === Strophe.Status.CONNECTED) {
console.log("Send me messages!");
console.log(this); // dumps strophe object. Paste from console: Object { service="http://myboshim/http-bind", jid="aivaras37#myboshim/29785298701381498988721337", rid=4092107607, more...}
console.log(this.listener); // undefined - how come?
this.connection.addHandler(this.listener.onReceivedMessage, null, 'message', null, null, null);
this.connection.send($pres().tree());
}
};
function MessageListener()
{
this.host = null;
}
MessageListener.prototype.setListenHost = function(host)
{
this.host = host;
};
function ReceivedMessageNotify()
{
MessageListener.call(this);
}
ReceivedMessageNotify.prototype = new MessageListener();
ReceivedMessageNotify.prototype.constructor = ReceivedMessageNotify;
ReceivedMessageNotify.prototype.onReceivedMessage = function(message)
{
console.log(message);
var elems = message.getElementsByTagName('body');
var body = elems[0];
if (Strophe.getText(body).length > 0) {
this.sendNewMessageNotify(message.getAttribute('from'), Strophe.getText(body));
}
return true;
};
ReceivedMessageNotify.prototype.sendNewMessageNotify = function(sender, messageBody)
{
alert("New message: " + sender + " wrote: " + messageBody);
};
$(document).ready(function() {
var communicator = new BoshCommunicator('http://myboshim/http-bind', 'myboshim');
communicator.setListener(new ReceivedMessageNotify());
communicator.connect('jabberId', 'accPasswd');
});
Have a look at following code mentioned below:
Usage Instructions:
var demo = DEMOPROJECT.Xmpp.init();
demo.connction.connect(username, password, function() {
//success callback
}, function() {
//errror callback
});
(function(MODULE) {
"use strict";
MODULE.Xmpp = function() {
var _self;
function _getInstance(xmpp_bosh_url) {
try {
return new Strophe.Connection(xmpp_bosh_url);
} catch (e) {
_self.log("Strophe Connection Failed: " + e.message);
}
};
function _onConnect(status, callback, errorCallback) {
var error = '';
switch (status) {
case Strophe.Status.ERROR:
error = "Error: " + Strophe.Status.ERROR;
break;
case Strophe.Status.CONNECTING:
_self.log('Connecting...');
break;
case Strophe.Status.CONNFAIL:
error = "Connection Failed: " + Strophe.Status.ERROR;
break;
case Strophe.Status.AUTHENTICATING:
_self.log('Authenticating client...');
break;
case Strophe.Status.AUTHFAIL:
error = "Authorization Fail: " + Strophe.Status.AUTHFAIL;
break;
case Strophe.Status.CONNECTED:
_self.log('Connected...');
_onConnected(callback);
break;
case Strophe.Status.DISCONNECTING:
_self.log('Diconnecting...');
break;
case Strophe.Status.DISCONNECTED:
_self.log('Diconnected...');
break;
case Strophe.Status.ATTACHED:
_self.log('Attached...');
break;
}
if (error) {
_onError(errorCallback, status, error);
}
return true;
};
function _onError(errorCallback, errorCode, error) {
_self.disconnect();
(typeof errorCallback == 'function') ? errorCallback.call(this, errorCode, error): '';
};
function _onConnected(callback) {
(typeof callback == 'function') ? callback.call(this): '';
};
return {
init: function(xmpp_bosh_url) {
_self = this;
if (!_self.connection) {
_self.connection = _getInstance(xmpp_bosh_url);
if (MODULE.config.debug) {
this.debugInfo("html");
}
return _self;
}
return _self;
},
connect: function(userName, password, callback, errorCallback) {
_self.userName = userName;
_self.password = password;
this.connection.connect(userName, password, function(status) {
_onConnect(status, callback, errorCallback);
});
},
isConnected: function() {
return _self.connection.connected;
},
getType: function() {
return _self.connection.servtype;
},
getDomain: function() {
return _self.connection.domain;
},
sendMessage: function(message) {
if (!message) {
return false;
} else {
this.connection.sendIQ(message.tree(), function(data) {
console.log("message success");
}, function(err) {
console.log("message errror");
});
}
},
removeListener: function(listener) {
this.connection.deleteHandler(listener);
},
disconnect: function() {
if (this.connection !== null) {
this.connection.disconnect();
this.connection.flush();
this.connection = null;
}
},
debugInfo: function(stream) {
console.log(message);
}
}
}();
})(window.DEMOPROJECT = window.DEMOPROJECT || {});
var demo = DEMOPROJECT.Xmpp.init();
demo.connction.connect(username, password, function() {
//success callback
}, function() {
//errror callback
});

Categories

Resources