Skip to content

Instantly share code, notes, and snippets.

@ifours
Last active August 29, 2015 14:24
Show Gist options
  • Save ifours/58566d1ce00d896eff43 to your computer and use it in GitHub Desktop.
Save ifours/58566d1ce00d896eff43 to your computer and use it in GitHub Desktop.
/** Example of angular factory.
Using promises, this service guarantees that any API calls to google services
will happen only after map object was initialized.
**/
angular.module('services')
.factory('GoogleServices', function($q, $http, $rootScope, $map) {
var PlacesService,
DirectionsService;
var mapReady = $q.defer();
$rootScope.$watch(function() {
return $map.map;
}, function(map, old) {
if (!map) {
return;
}
mapReady.resolve(map);
});
var ready = mapReady.promise.then(function(map) {
PlacesService = new google.maps.places.PlacesService(map);
DirectionsService = new google.maps.DirectionsService();
return {
nearbySearch: function(request) {
var q = $q.defer();
PlacesService.nearbySearch(request, function(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
q.resolve(results);
}
});
return q.promise;
},
placeDetails: function(request) {
var q = $q.defer();
PlacesService.getDetails(request, function(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
q.resolve(results);
}
});
return q.promise;
},
route: function(request) {
var q = $q.defer();
DirectionsService.route(request, function(response, status) {
if (status === google.maps.DirectionsStatus.OK) {
q.resolve(response);
}
});
return q.promise;
}
}
})
return {
ready: ready,
}
});
// Usage
this.nearbySearch = function(startPoint) {
return GoogleServices.ready.then(function(services) {
return services.nearbySearch({
location: {lat: startPoint.lat(), lng: startPoint.lng()},
radius: SettingsData.radius,
types: makeCategories(),
});
});
};
/** Same realization as above but service guarantees
that controllers will work with data using one interface
**/
'use strict';
angular.module('incitesApp.analytics')
.factory('exploreState', function ($q, userStorage, metadataRepository) {
return {
load: function (entity, tile) {
var state = userStorage.loadExploreState(entity) || {},
requestParams = state.request || { take: 25, skip: 0 },
indicators = metadataRepository.getIndicators(entity)
.then(function (metadata) {
var requiredIndicators = _(metadata.indicators).filter('required').pluck('name').value();
requestParams.sortBy = requestParams.sortBy || metadata.primaryIndicator;
requestParams.sortOrder = requestParams.sortOrder || metadata.primaryOrder;
requestParams.indicators = _.union(requestParams.indicators || metadata.enabledIndicators, requiredIndicators);
return metadata;
}),
filtersReady = $q.defer(),
filters = this.filters = $q.all({ metadata: metadataRepository.getFilters(entity), tile: tile })
.then(function (result) {
var metadata = result.metadata, tile = result.tile;
metadata.values = tile && tile.request ? tile.request.filters : angular.copy(requestParams.filters); // TODO
metadata.ready = filtersReady;
return metadata;
}),
benchmarks = metadataRepository.getBenchmarks(entity)
.then(function (benchmarks) {
benchmarks.forEach(function (benchmark) {
benchmark.selected = _.contains(state.benchmarks, benchmark.name);
});
return benchmarks;
});
filtersReady.promise.then(function (filters) {
requestParams.filters = filters;
});
this.ready = $q.all({
indicators: indicators,
filters: filters,
benchmarks: benchmarks,
request: requestParams,
ready: filtersReady.promise,
visualization: state.visualization,
dimensions: state.dimensions
}).then(function (state) {
return angular.extend({
getEnabledIndicators: function () {
return this.request.indicators.map(function (i) {
return _.find(state.indicators.indicators, { name: i });
});
},
getEnabledBenchmarks: function () {
return _.filter(state.benchmarks, 'selected');
},
save: function () {
userStorage.saveExploreState(entity, {
request: this.request,
benchmarks: _.pluck(this.getEnabledBenchmarks(), 'name'),
visualization: this.visualization,
dimensions: this.dimensions
});
}
}, state);
});
return this.ready;
}
};
});
// Usage
// Main Ctrl
exploreState.load($stateParams.entity, tile).then(function(state){})
// Other Ctrl
exploreState.ready.then(function(state){})
/** Grunt task for export and import translation files
Our translation team asked us to give them xml file with needed structure.
**/
module.exports = function (grunt) {
var _log = grunt.log,
_file = grunt.file,
_ = grunt.util._,
xml2js = require('xml2js');
grunt.registerTask('locale', 'Export and import translation files', function (target) {
if (arguments.length === 0 || arguments.length > 1) {
_log.error('Missing target.');
return false;
} else {
_log.ok(('Starting translations:' + target + ' task').green);
grunt.task.run('translations:' + target);
}
});
grunt.registerMultiTask('translations', 'Export and import translation files', function () {
var files = _file.expand(this.data.src),
type = this.data.type,
dest = this.data.dest;
var flatObj = function (obj, keys) {
keys = keys || [];
return Object.getOwnPropertyNames(obj).reduce(function (container, key) {
keys.push(key);
var value = obj[key];
if (_.isObject(value)) {
_.merge(container, flatObj(value, keys));
keys.pop();
} else {
container[keys.join('.')] = value;
keys.pop();
}
return container;
}, {});
};
var buildBranch = function (key, value) {
var parts = key.split('.'), result = {};
if (parts.length > 1) {
result[parts[0]] = buildBranch(parts.slice(1).join('.'), value);
} else {
result[key] = value;
}
return result;
};
var buildTree = function (map) {
return Object.getOwnPropertyNames(map).reduce(function (obj, prop) {
return _.merge(obj, buildBranch(prop, map[prop]));
}, {});
};
function sort(object) {
if (Array.isArray(object) || typeof(object) !== 'object') {
return object;
}
var sorted = {};
var keys = Object.keys(object).sort(function (a, b) {
return a > b ? 1 : -1;
});
keys.forEach(function (key) {
sorted[key] = sort(object[key]);
});
return sorted;
}
files.forEach(function (file) {
_log.debug('Process extra file: ' + file);
var path = file.split('/'), name = path[path.length - 1].split('.');
name.pop();
var destFilename = dest + name.join('.') + '.' + type,
input = type === 'xml' ? _file.readJSON(file) : _file.read(file),
output = '';
if (type === 'xml') {
var builder = new xml2js.Builder({ doctype: { sysID: 'http://java.sun.com/dtd/properties.dtd' }}),
json = flatObj(input),
obj = {
properties: {
entry: _.map(json, function (value, key) {
return {_: value, $: {key: key}};
}).sort(function (a, b) {
return a.$.key > b.$.key ? 1 : -1;
})
}
};
output = builder.buildObject(obj);
} else if (type === 'json') {
xml2js.parseString(input, function (err, result) {
if (err) {
throw err;
}
var entries = result.properties.entry.reduce(function (obj, property) {
obj[property.$.key] = property._;
return obj;
}, {});
output = JSON.stringify(sort(buildTree(entries)), null, 2);
});
}
_log.ok('File ' + destFilename + ' converted.' + ' OK'.green);
_file.write(destFilename, output);
});
});
};
/** Class example with inheritance
**/
define([
'lib/underscore',
'helpers/global'
], function(_, global) {
var helpers = {
/** More helpers **/
inherit: function(Child, Parent) {
var F = function() { };
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.superclass = Parent.prototype;
},
/** More helpers **/
};
return helpers;
});
// Usage
// var helpers = require('./helpers.js'),
define([
'lib/underscore',
'helpers/helpers',
'events/events',
'helpers/global'
], function(_, helpers, Events, global) {
var messagePattern = '[token:{0}][topic:{1}][data:{2}]',
reg = /^\[token:(.*)\]\[topic:(.*)\]\[data:(.*)\]$/,
prototype;
prototype = {
init: function() {
if(this.initialized) {
throw new Error('Already initialized', this);
}
this.attachListener();
this.bindTopics();
this.bindActions();
this.initialized = true;
},
subscribe: function(topic, callback) {
if(!topic || !callback) {
return false;
}
if(!this.subscriptions[topic]) {
this.subscriptions[topic] = [];
}
return this.subscriptions[topic].push(callback);
},
/** More properties **/
publish: function(topic, data, immediately) {
if(!topic) {
return false;
}
this.sendMessage(topic, data, immediately);
},
/** More properties **/
sendMessage: function(topic, data, immediately) {
var message, that = this;
if(!this.target || !this.target.postMessage) {
return;
}
message = this.buildMessage(topic, data);
if(immediately) {
this.target.postMessage(message, this.targetOrigin);
} else {
global.setTimeout(function() {
that.target.postMessage(message, that.targetOrigin);
}, 0);
}
this.log("Message sent", message, topic, data);
},
recieveMessage: function(e) {
var parsed = this.parseMessage(e.data),
handler;
if(parsed && parsed.topic && this.subscriptions[parsed.topic] && parsed.token === this.token && (!this.iframe || e.source == this.iframe.contentWindow)) {
this.log("Message accepted", parsed, handler);
for(var i=0, callbacks = this.subscriptions[parsed.topic], l = callbacks.length; i < l; i++) {
this.log("Callback invoked");
callbacks[i].call(this, parsed.data);
}
} else {
this.log("Message rejected", parsed);
}
},
buildMessage: function(topic, data) {
return helpers.format(messagePattern)(this.token, topic, JSON.stringify(data || {}));
},
/** More properties **/
setDefaultState: function() {
this.token = 'token',
this.targetOrigin = '*';
},
/** More properties **/
};
function Connection() {
this.events = new Events();
this.target = '';
this.initialized = false;
this.subscriptions = {};
this.recieveMessage = _.bind(this.recieveMessage, this);
this.setDefaultState();
}
_.extend(Connection.prototype, prototype);
return Connection;
});
define([
'lib/underscore',
'connection/connection',
'helpers/helpers'
], function(_, Connection, helpers) {
var prototype = {
init: function(iframe) {
this.constructor.superclass.init.apply(this);
if(!iframe) {
throw new Error('iframe parameter should not be empty', this);
}
this.iframe = iframe;
this.target = iframe.contentWindow;
this._attachIframe();
},
processQueue: function() {
// body
},
_attachIframe: function() {
var that = this;
this.subscribe('connection.request', function(data) {
var newToken = helpers.generateToken();
that.token = data.token;
that.targetOrigin = data.origin;
that.publish('connection.approve', {
token: newToken,
origin: that._getCurrentOrigin()
});
that.token = newToken;
});
this.subscribe('connection.connected', function(data) {
that.events.trigger('connection.connected', {host: that});
});
this.subscribe('connection.before.unload', function(data) {
this.events.trigger('connection.before.unload', data);
this.setDefaultState();
});
},
loadWidget: function(options) {
// body
}
};
function Host(options) {
Host.superclass.constructor.apply(this, arguments);
this.logAlias = 'Host';
this.widgetQueue = [];
this.connectionApproved = false;
}
helpers.inherit(Host, Connection);
Host.prototype = _.extend(Host.prototype, prototype);
return Host;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment