<commit_before>// allow access from anywhere, since all functions will require authentication
const cors = require('cors')({origin: true});
const express = require('express');
const functions = require('firebase-functions');

// Can only initialize firebase once, so doing here and passing where needed
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

const middleware = require('./middleware')(admin);
const oauth = require('./oauth');
const profile = require('./profile');
const slots = require('./slots')(admin);

function makeHttpFunction(fn, middlewares) {
  const router = new express.Router();
  middlewares.forEach(m => {
    router.use(m);
  });
  router.all('*', fn);
  return functions.https.onRequest((req, res) => {
    // NOTE: Adding a temporary fix for issue https://github.com/firebase/firebase-functions/issues/27
    req.url = req.path ? req.url : `/${req.url}`;
    return router(req, res);
  });
}

/*
 * Slots Functions
 */
exports.joinEvent = makeHttpFunction(slots.join, [cors, middleware.userAuthRequired]);
exports.leaveEvent = makeHttpFunction(slots.leave, [cors, middleware.userAuthRequired]);
exports.closeEvent = makeHttpFunction(slots.close, [cors, middleware.userAuthRequired, middleware.adminOnly]);

/*
 * Profile Functions
 */
exports.enqueueUpdateProfileLegacy = functions.database.ref("/accounts/{userId}/githubToken")
  .onWrite(event => {
    // Ignore deletes
    if (!event.data.exists()) {
      return;
    }
    return profile.enqueueUpdateLegacy(event.data.ref);
  });

exports.enqueueUpdateProfile = functions.database.ref("/accounts/{userId}/profileNeedsUpdate")
  .onWrite(event => {
    // Ignore non-truthy values (either a delete or setting to false)
    if (!event.data.val()) {
      return;
    }

    const db = admin.database();
    const userId = event.params.userId;
    return profile.enqueueUpdate(db, userId);
  });

exports.updateProfile = functions.database.ref("/updateProfileQueue/{userId}")
  .onWrite(event => {
    // Ignore deletes
    if (!event.data.exists()) {
      return;
    }

    const db = admin.database();
    const userId = event.params.userId;
    return profile.update(db, userId);
  });

exports.updateProfileCron = functions.https.onRequest((req, res) => {
  return profile.cron(admin.database())
    .then(() => {
      res.sendStatus(200);
    })
    .catch(err => {
      console.error(err);
      res.sendStatus(500);
    });
});

exports.githubToken = functions.https.onRequest((req, res) => {
  const config = functions.config().github;
  const github = new oauth.GitHub(config.client_id, config.client_secret);
  return github.getToken(req.body.code)
    .then(data => {
      res.send(data);
    })
    .catch(err => {
      console.error(err);
      res.sendStatus(500);
    });
});
<commit_msg>Document githubToken HTTPS function<commit_after>// allow access from anywhere, since all functions will require authentication
const cors = require('cors')({origin: true});
const express = require('express');
const functions = require('firebase-functions');

// Can only initialize firebase once, so doing here and passing where needed
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

const middleware = require('./middleware')(admin);
const oauth = require('./oauth');
const profile = require('./profile');
const slots = require('./slots')(admin);

function makeHttpFunction(fn, middlewares) {
  const router = new express.Router();
  middlewares.forEach(m => {
    router.use(m);
  });
  router.all('*', fn);
  return functions.https.onRequest((req, res) => {
    // NOTE: Adding a temporary fix for issue https://github.com/firebase/firebase-functions/issues/27
    req.url = req.path ? req.url : `/${req.url}`;
    return router(req, res);
  });
}

/*
 * Slots Functions
 */
exports.joinEvent = makeHttpFunction(slots.join, [cors, middleware.userAuthRequired]);
exports.leaveEvent = makeHttpFunction(slots.leave, [cors, middleware.userAuthRequired]);
exports.closeEvent = makeHttpFunction(slots.close, [cors, middleware.userAuthRequired, middleware.adminOnly]);

/*
 * Profile Functions
 */
exports.enqueueUpdateProfileLegacy = functions.database.ref("/accounts/{userId}/githubToken")
  .onWrite(event => {
    // Ignore deletes
    if (!event.data.exists()) {
      return;
    }
    return profile.enqueueUpdateLegacy(event.data.ref);
  });

exports.enqueueUpdateProfile = functions.database.ref("/accounts/{userId}/profileNeedsUpdate")
  .onWrite(event => {
    // Ignore non-truthy values (either a delete or setting to false)
    if (!event.data.val()) {
      return;
    }

    const db = admin.database();
    const userId = event.params.userId;
    return profile.enqueueUpdate(db, userId);
  });

exports.updateProfile = functions.database.ref("/updateProfileQueue/{userId}")
  .onWrite(event => {
    // Ignore deletes
    if (!event.data.exists()) {
      return;
    }

    const db = admin.database();
    const userId = event.params.userId;
    return profile.update(db, userId);
  });

exports.updateProfileCron = functions.https.onRequest((req, res) => {
  return profile.cron(admin.database())
    .then(() => {
      res.sendStatus(200);
    })
    .catch(err => {
      console.error(err);
      res.sendStatus(500);
    });
});

// HTTPS function for performing the final step in the GitHub OAuth2 flow.
// Called by the mobile clients to exchange an oauth code for a valid access
// token, enabling signup via the GitHub provider in Firebase Authentication.
//
// Requires that GitHub OAuth configuration has been made available through
// the Firebase CLI as follows, substituting your app's values for <client_id>
// and <client_secret>:
//     firebase functions:config:set github.client_id="<client_id>"
//     firebase functions:config:set github.client_secret="<client_secret>"
//
// Request should be a POST with a JSON body containing the oauth code:
//     {"code": "<oauth_code>"}
//
// JSON Response will contain the new access token:
//     {"access_token": "<oauth_access_token>"}
exports.githubToken = functions.https.onRequest((req, res) => {
  const config = functions.config().github;
  const github = new oauth.GitHub(config.client_id, config.client_secret);
  return github.getToken(req.body.code)
    .then(data => {
      res.send(data);
    })
    .catch(err => {
      console.error(err);
      res.sendStatus(500);
    });
});
<|endoftext|>


<commit_before>var functions = require('firebase-functions')
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

const genreSimScore = require('./genres');
const recentSongsSimScore = require('./recentTracks');
const topArtistsSimScore = require('./topArtists');
const topTrackSimScore = require('./topTracks');

exports.findMatches = functions.database.ref('/Users/{uid}')
  .onWrite(event => {
    //we need top tracks, top artists, recent tracks, genres
    const userId = event.params.uid
    console.log('userId', userId)

    const user1TopArtists = event.data.val().topArtists.artists
    const user1TopTracks = event.data.val().topTracks.tracks
    const user1RecentSongs = event.data.val().recentSongs.songs

    // //we also need all of this for all other users
    // //dict  of key userId; value of matchScore
    const matchDict = {};
    let uid;

    event.data.ref.parent.once('value', function(snapshot){

        const users = Object.keys(snapshot.val())

        users.forEach(user => {

          const userInfo = (snapshot.val()[user])
          console.log('user in loop', userInfo)

          const user2TopArtists = userInfo.topArtists.artists
          const user2TopTracks = userInfo.topTracks.tracks
          const user2RecentSongs = userInfo.recentSongs.songs

          const genreScore = genreSimScore(user1TopArtists, user2TopArtists)
          const recentSongsScore = recentSongsSimScore(user1RecentSongs, user2RecentSongs)
          const artistsScore = topArtistsSimScore(user1TopArtists, user2TopArtists)
          const tracksScore = topTrackSimScore(user1TopTracks, user2TopTracks)

          const matchScore = (genreScore + recentSongsScore + artistsScore + tracksScore)/4

          if (!matchDict[user] & matchScore !== 0.5) matchDict[user.toString()] = matchScore

          if (matchScore === 0.5) {
            uid = user
            console.log('i think ive matched with user1 uid', uid)
          }

        })

        return matchDict
    })
    .then(u => {
      console.log('where im writing to', `/Users/${uid}/matches`)
      return admin.database().ref(`/Users/${uid}/matches`).update({matchScores: matchDict})
    })
    .then(result => console.log('new matches written'))

})
<commit_msg>add: (addmittedly a bit buggy) 2-way  matches<commit_after>var functions = require('firebase-functions')
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

const genreSimScore = require('./genres');
const recentSongsSimScore = require('./recentTracks');
const topArtistsSimScore = require('./topArtists');
const topTrackSimScore = require('./topTracks');

exports.findMatches = functions.database.ref('/Users/{uid}/')
  .onWrite(event => {
    //we need top tracks, top artists, recent tracks, genres
    const userId = event.params.uid
    console.log('userId', userId)

    const user1TopArtists = event.data.val().topArtists.artists
    const user1TopTracks = event.data.val().topTracks.tracks
    const user1RecentSongs = event.data.val().recentSongs.songs

    // //we also need all of this for all other users
    // //dict  of key userId; value of matchScore
    const matchDict = {};
    let uid;

    event.data.ref.parent.once('value', function(snapshot){

        const users = Object.keys(snapshot.val())
        console.log(users)

        users.forEach(user => {

          const userInfo = (snapshot.val()[user])
          console.log('user in loop', userInfo)

          const user2TopArtists = userInfo.topArtists.artists
          const user2TopTracks = userInfo.topTracks.tracks
          const user2RecentSongs = userInfo.recentSongs.songs

          const genreScore = genreSimScore(user1TopArtists, user2TopArtists)
          const recentSongsScore = recentSongsSimScore(user1RecentSongs, user2RecentSongs)
          const artistsScore = topArtistsSimScore(user1TopArtists, user2TopArtists)
          const tracksScore = topTrackSimScore(user1TopTracks, user2TopTracks)

          const matchScore = (genreScore + recentSongsScore + artistsScore + tracksScore)/4

          if (!matchDict[user] & matchScore !== 0.5) {
            console.log(`/Users/${user.toString()}/matches/matchScores/${userId}`)
            return admin.database().ref(`/Users/${user.toString()}/matches/matchScores/${userId}`).set(matchScore)
            .then(valy => {
              console.log(`/Users/${userId}/matches/matchScores/${user.toString()}`)
              return admin.database().ref(`/Users/${userId}/matches/matchScores/${user.toString()}`).set(matchScore)
            })
          }

          if (matchScore === 0.5) {
            uid = user
            console.log('i think ive matched with user1 uid', uid)
          }

        })

        return matchDict
    })
    // .then(u => {
    //   console.log('where im writing to', `/Users/${uid}/matches`)
    //   return admin.database().ref(`/Users/${uid}/matches`).update({matchScores: matchDict})
    // })
    .then(result => console.log('new matches written'))

})
<|endoftext|>


<commit_before>'use strict';

var resolveFrom = require('resolve-from');
var path = require('path');
var fs = require('fs');

function isTemplateMainEntry(context) {
    let filename = path.basename(context.filename);
    let ext = path.extname(filename);

    if (ext === '.js') {
        return false;
    }

    if (ext) {
        filename = filename.slice(0, 0 - ext.length);
    }

    return filename === 'index';
}

const esprima = require('esprima');
const estraverse = require('estraverse');
const escodegen = require('escodegen');

function isModuleExports(node) {
    return node.type === 'AssignmentExpression' &&
           node.operator === '=' &&
           node.left.type === 'MemberExpression' &&
           node.left.object.type === 'Identifier' &&
           node.left.object.name === 'module' &&
           node.left.property.type === 'Identifier' &&
           node.left.property.name === 'exports';
}

function isModuleExportsStatement(node) {
    return node.type === 'ExpressionStatement' &&
           isModuleExports(node.expression);
}

function handleScriptElement(scriptEl, transformHelper) {
    let builder = transformHelper.builder;

    let hasExport = false;
    let needsComponentVar;

    var scriptCode = scriptEl.bodyText;

    let tree = esprima.parse(scriptCode, { sourceType:'module' });
    let updatedTree = estraverse.replace(tree, {
        enter: function(node) {
            if (isModuleExports(node)) {
                hasExport = true;
                needsComponentVar = true;
                node.left = {
                    type: 'Identifier',
                    name: 'marko_component'
                };
                this.break();
            } else if (isModuleExportsStatement(node)) {
                hasExport = true;
                return createComponentDeclaration(node.expression.right);
            } else if (node.type === 'ExportDefaultDeclaration') {
                hasExport = true;
                return createComponentDeclaration(node.declaration);
            }
        }
    });

    function createComponentDeclaration(value) {
        return {
            type: 'VariableDeclaration',
            declarations: [
                {
                    type: 'VariableDeclarator',
                    id: {
                        type: 'Identifier',
                        name: 'marko_component'
                    },
                    init: value
                }
            ],
            kind: 'var'
        };
    }

    if (hasExport) {
        let componentVar;

        if (needsComponentVar) {
            componentVar = transformHelper.context.addStaticVar('marko_component');
        } else {
            componentVar = builder.identifier('marko_component');
        }

        transformHelper.setHasBoundWidgetForTemplate();
        transformHelper.setInlineComponent(componentVar);
        transformHelper.context.addStaticCode(escodegen.generate(updatedTree));
        scriptEl.detach();
    }
}

function handleStyleElement(styleEl, transformHelper) {
    var styleCode = styleEl.bodyText;
    var langAttr = styleEl.getAttribute('lang');
    var lang = langAttr ? langAttr.value.value : 'css';
    var context = transformHelper.context;
    context.addDependency({
        type:lang,
        code:styleCode,
        virtualPath:'./'+path.basename(context.filename)+'.'+lang,
        path: './'+path.basename(context.filename)
    });
    styleEl.detach();
}

function methodToProperty(method) {
    return {
        type: 'Property',
        key: method.key,
        computed: false,
        value: method.value,
        kind: 'init',
        method: true,
        shorthand: false
    };
}

function classToObject(cls, transformHelper) {
    return {
        type: 'ObjectExpression',
        properties: cls.body.body.map((method) => {
            if(method.type != 'MethodDefinition') {
                throw Error('Only methods are allowed on single file component class definitions.');
            }
            return methodToProperty(method);
        })
    };
}

function handleClassDeclaration(classEl, transformHelper) {
    if(!/^class\s*\{/.test(classEl.tagString)) return;

    let tree = esprima.parse('('+classEl.tagString+')');
    let expression = tree.body[0].expression;
    let object = classToObject(expression);
    let componentVar = transformHelper.context.addStaticVar('marko_component', escodegen.generate(object));

    transformHelper.setHasBoundWidgetForTemplate();
    transformHelper.setInlineComponent(componentVar);
    classEl.detach()
}

module.exports = function handleRootNodes() {
    var context = this.context;
    var builder = this.builder;

    if (!isTemplateMainEntry(context)) {
        // We only support implicit binds in `index.marko`
        return;
    }

    var templateRoot = this.el;

    var dirname = this.dirname;
    var hasBindTarget = false;

    if (resolveFrom(dirname, './component')) {
        hasBindTarget = true;
    } else if (resolveFrom(dirname, './widget')) {
        hasBindTarget = true;
    }

    fs.readdirSync(dirname).forEach(file => {
        if(/^style\.\w+$/.test(file)) {
            context.addDependency('./' + file);
        }
    });

    var rootNodes = [];
    var hasExplicitBind = false;
    var hasIdCount = 0;
    var nodeWithAssignedId;
    var assignedId;
    var transformHelper = this;

    let walker = context.createWalker({
        enter(node) {
            if (node.type === 'TemplateRoot' || !node.type) {
                // Don't worry about the TemplateRoot or an Container node
            } else if (node.type === 'HtmlElement') {
                if (node.hasAttribute('w-bind')) {
                    transformHelper.setHasBoundWidgetForTemplate();
                    hasExplicitBind = true;
                } else {
                    if (node.hasAttribute('id')) {
                        hasIdCount++;
                        nodeWithAssignedId = node;
                        assignedId = node.getAttributeValue('id');
                    }

                    var tagName = node.tagName && node.tagName.toLowerCase();

                    if (tagName === 'script') {
                        handleScriptElement(node, transformHelper);
                    } else if (tagName === 'style') {
                        handleStyleElement(node, transformHelper);
                    } else {
                        rootNodes.push(node);
                    }
                }
                walker.skip();

                return;
            } else if (node.type === 'CustomTag') {
                rootNodes.push(node);

                walker.skip();
                return;
            } else {
                var tagName = node.tagName && node.tagName.toLowerCase();

                if (tagName === 'class') {
                    handleClassDeclaration(node, transformHelper);
                }

                walker.skip();
                return;
            }
        }
    });

    walker.walk(templateRoot);

    if (this.hasInlineComponent()) {
        hasBindTarget = true;
    }

    if (hasExplicitBind) {
        //There is an explicit bind so nothing to do
        return;
    }

    if (!hasBindTarget) {
        return;
    }

    if (rootNodes.length === 0) {
        return;
    }

    if (rootNodes.length > 1 && hasIdCount > 0) {
        // We can only bind a widget to multiple top-level elements if we can assign
        // all of the IDs
        return;
    }

    transformHelper.setHasBoundWidgetForTemplate();

    var nextRef = 0;

    rootNodes.forEach((curNode, i) => {
        curNode.setAttributeValue('_widgetbind');

        if (!curNode.hasAttribute('ref')) {
            if (curNode.type === 'CustomTag' || rootNodes.length > 1) {
                curNode.setAttributeValue('ref', builder.literal('_r' + (nextRef++)));
            }
        }
    });
};<commit_msg>begin removal of restriction to index.marko for single-file components<commit_after>'use strict';

var path = require('path');
var fs = require('fs');

function getFileNameNoExt(context) {
    let filename = path.basename(context.filename);
    let ext = path.extname(filename);

    if (ext === '.js') {
        return false;
    }

    if (ext) {
        filename = filename.slice(0, 0 - ext.length);
    }

    return filename;
}

const esprima = require('esprima');
const estraverse = require('estraverse');
const escodegen = require('escodegen');

function isModuleExports(node) {
    return node.type === 'AssignmentExpression' &&
           node.operator === '=' &&
           node.left.type === 'MemberExpression' &&
           node.left.object.type === 'Identifier' &&
           node.left.object.name === 'module' &&
           node.left.property.type === 'Identifier' &&
           node.left.property.name === 'exports';
}

function isModuleExportsStatement(node) {
    return node.type === 'ExpressionStatement' &&
           isModuleExports(node.expression);
}

function handleScriptElement(scriptEl, transformHelper) {
    let builder = transformHelper.builder;

    let hasExport = false;
    let needsComponentVar;

    var scriptCode = scriptEl.bodyText;

    let tree = esprima.parse(scriptCode, { sourceType:'module' });
    let updatedTree = estraverse.replace(tree, {
        enter: function(node) {
            if (isModuleExports(node)) {
                hasExport = true;
                needsComponentVar = true;
                node.left = {
                    type: 'Identifier',
                    name: 'marko_component'
                };
                this.break();
            } else if (isModuleExportsStatement(node)) {
                hasExport = true;
                return createComponentDeclaration(node.expression.right);
            } else if (node.type === 'ExportDefaultDeclaration') {
                hasExport = true;
                return createComponentDeclaration(node.declaration);
            }
        }
    });

    function createComponentDeclaration(value) {
        return {
            type: 'VariableDeclaration',
            declarations: [
                {
                    type: 'VariableDeclarator',
                    id: {
                        type: 'Identifier',
                        name: 'marko_component'
                    },
                    init: value
                }
            ],
            kind: 'var'
        };
    }

    if (hasExport) {
        let componentVar;

        if (needsComponentVar) {
            componentVar = transformHelper.context.addStaticVar('marko_component');
        } else {
            componentVar = builder.identifier('marko_component');
        }

        transformHelper.setHasBoundWidgetForTemplate();
        transformHelper.setInlineComponent(componentVar);
        transformHelper.context.addStaticCode(escodegen.generate(updatedTree));
        scriptEl.detach();
    }
}

function handleStyleElement(styleEl, transformHelper) {
    var styleCode = styleEl.bodyText;
    var langAttr = styleEl.getAttribute('lang');
    var lang = langAttr ? langAttr.value.value : 'css';
    var context = transformHelper.context;
    context.addDependency({
        type:lang,
        code:styleCode,
        virtualPath:'./'+path.basename(context.filename)+'.'+lang,
        path: './'+path.basename(context.filename)
    });
    styleEl.detach();
}

function methodToProperty(method) {
    return {
        type: 'Property',
        key: method.key,
        computed: false,
        value: method.value,
        kind: 'init',
        method: true,
        shorthand: false
    };
}

function classToObject(cls, transformHelper) {
    return {
        type: 'ObjectExpression',
        properties: cls.body.body.map((method) => {
            if(method.type != 'MethodDefinition') {
                throw Error('Only methods are allowed on single file component class definitions.');
            }
            return methodToProperty(method);
        })
    };
}

function handleClassDeclaration(classEl, transformHelper) {
    if(!/^class\s*\{/.test(classEl.tagString)) return;

    let tree = esprima.parse('('+classEl.tagString+')');
    let expression = tree.body[0].expression;
    let object = classToObject(expression);
    let componentVar = transformHelper.context.addStaticVar('marko_component', escodegen.generate(object));

    transformHelper.setHasBoundWidgetForTemplate();
    transformHelper.setInlineComponent(componentVar);
    classEl.detach();
}

module.exports = function handleRootNodes() {
    var context = this.context;
    var builder = this.builder;
    var filename = getFileNameNoExt(context);
    var isEntry = 'index' === filename;

    if(!filename) {
        return; // inline component
    }

    var filematch = '('+filename.replace(/\./g, '\\.') + '\\.' + (isEntry ? '|' : '') + ')';
    var stylematch = new RegExp('^'+filematch+'style\\.\\w+');
    var componentmatch = new RegExp('^'+filematch+'component\\.\\w+');
    var widgetmatch = new RegExp('^'+filematch+'widget\\.\\w+');

    var templateRoot = this.el;

    var dirname = this.dirname;
    var hasBindTarget = false;

    fs.readdirSync(dirname).forEach(file => {
        if(stylematch.test(file)) {
            context.addDependency('./' + file);
        } else if(componentmatch.test(file) || widgetmatch.test(file)) {
            hasBindTarget = true;
        }
    });

    var rootNodes = [];
    var hasExplicitBind = false;
    var hasIdCount = 0;
    var nodeWithAssignedId;
    var assignedId;
    var transformHelper = this;

    let walker = context.createWalker({
        enter(node) {
            var tagName = node.tagName && node.tagName.toLowerCase();

            if (node.type === 'TemplateRoot' || !node.type) {
                // Don't worry about the TemplateRoot or an Container node
            } else if (node.type === 'HtmlElement') {
                if (node.hasAttribute('w-bind')) {
                    transformHelper.setHasBoundWidgetForTemplate();
                    hasExplicitBind = true;
                } else {
                    if (node.hasAttribute('id')) {
                        hasIdCount++;
                        nodeWithAssignedId = node;
                        assignedId = node.getAttributeValue('id');
                    }

                    if (isEntry && tagName === 'script') {
                        handleScriptElement(node, transformHelper);
                    } else if (tagName === 'style') {
                        handleStyleElement(node, transformHelper);
                    } else {
                        rootNodes.push(node);
                    }
                }
                walker.skip();

                return;
            } else if (node.type === 'CustomTag') {
                rootNodes.push(node);

                walker.skip();
                return;
            } else {
                if (tagName === 'class') {
                    handleClassDeclaration(node, transformHelper);
                }

                walker.skip();
                return;
            }
        }
    });

    walker.walk(templateRoot);

    if (this.hasInlineComponent()) {
        hasBindTarget = true;
    }

    if (hasExplicitBind) {
        //There is an explicit bind so nothing to do
        return;
    }

    if (!hasBindTarget) {
        return;
    }

    if (rootNodes.length === 0) {
        return;
    }

    if (rootNodes.length > 1 && hasIdCount > 0) {
        // We can only bind a widget to multiple top-level elements if we can assign
        // all of the IDs
        return;
    }

    transformHelper.setHasBoundWidgetForTemplate();

    var nextRef = 0;

    rootNodes.forEach((curNode, i) => {
        curNode.setAttributeValue('_widgetbind');

        if (!curNode.hasAttribute('ref')) {
            if (curNode.type === 'CustomTag' || rootNodes.length > 1) {
                curNode.setAttributeValue('ref', builder.literal('_r' + (nextRef++)));
            }
        }
    });
};<|endoftext|>


<commit_before>function Container () {
	this.data = {};
	this.configData = {};
	this.plugins = {};
}

Container.prototype = {
	constructor: Container,

	add: function(id, dep) {
		if (this.data[id])
			throw new Error('A dependency with a provided id already exist');
		this.data[id] = dep;
		this.configData[id] = dep.containerConfig || {};
	},

	get: function(id) {
		if (!this.data[id])
			throw new Error('A dependency with a provided id does not exist');
		return this.data[id];
	},

	change: function(id, cb) {
		var dep = this.get(id);
		var newDep = cb(dep);
		if (this._checkType(dep));
		this.data[id] = newDep;
	},

	_checkType: function(dep) {
		if (typeof dep != 'function' && typeof dep != 'object')
			throw new TypeError('Depenedency type can be an object or a function');
	},

	_getDepId: function(dep) {
		return dep.name || dep._name;
	},

	plugin: function(plugin) {
		this.plugins[plugin._name] = plugin;
	},

	runPlugin: function(name, options) {
		options.container = this;
		this.plugins[name].run(options);
	},
};

Container.make = function() {
	return new this;
};

module.exports = Container;<commit_msg>feat: add 'Registrar' module to namespace<commit_after>Container.Registarar = require('./Registarar/Index');

function Container () {
	this.data = {};
	this.configData = {};
	this.plugins = {};
}

Container.prototype = {
	constructor: Container,

	add: function(id, dep) {
		if (this.data[id])
			throw new Error('A dependency with a provided id already exist');
		this.data[id] = dep;
		this.configData[id] = dep.containerConfig || {};
	},

	get: function(id) {
		if (!this.data[id])
			throw new Error('A dependency with a provided id does not exist');
		return this.data[id];
	},

	change: function(id, cb) {
		var dep = this.get(id);
		var newDep = cb(dep);
		if (this._checkType(dep));
		this.data[id] = newDep;
	},

	_checkType: function(dep) {
		if (typeof dep != 'function' && typeof dep != 'object')
			throw new TypeError('Depenedency type can be an object or a function');
	},

	_getDepId: function(dep) {
		return dep.name || dep._name;
	},

	plugin: function(plugin) {
		this.plugins[plugin._name] = plugin;
	},

	runPlugin: function(name, options) {
		options.container = this;
		this.plugins[name].run(options);
	},
};

Container.make = function() {
	return new this;
};

module.exports = Container;<|endoftext|>


<commit_before>var GameController = function(args) {
  this.keyStates = {
    up: false,
    down: false,
    left: false,
    right: false
  }

  this.actorCanvas = args.actorCanvas;
  this.boardCanvas = args.boardCanvas;
  this.pelletCanvas = args.pelletCanvas;

  this.pac = new Actor({
    context: this.actorCanvas.context,
    startX: 113,
    startY: 212,
    name: "m",
    direction: "right"
  });
  this.blinky = new Ghost({
    context: this.actorCanvas.context,
    direction: "left",
    name: "b",
    startX: 112,
    startY: 116
  });
  this.inky = new Ghost({
    context: this.actorCanvas.context,
    direction: "up",
    mode: "house",
    name: "i",
    startX: 96,
    startY: 139
  });
  this.pinky = new Ghost({
    context: this.actorCanvas.context,
    direction: "right",
    mode: "exitting",
    name: "p",
    startX: 112,
    startY: 139
  });
  this.clyde = new Ghost({
    context: this.actorCanvas.context,
    direction: "down",
    mode: "house",
    name: "c",
    startX: 128,
    startY: 139
  });

  this.drawPellets();
  this.pac.render();

  addEventListener("keydown", this.handleKeyDown.bind(this));
  addEventListener("keyup", this.handleKeyUp.bind(this));

  setInterval(function() {
    this.blinky.move();
    this.inky.move();
    this.pinky.move();
    this.clyde.move();
  }.bind(this), GHOST_MOVE_DELAY);

  setTimeout(function() {
    this.inky.setMode("exitting");
  }.bind(this), INKY_EXIT_DELAY);
  setTimeout(function() {
    this.clyde.setMode("exitting");
  }.bind(this), CLYDE_EXIT_DELAY);
}
GameController.prototype.drawPellets = function() {
  this.pelletCanvas.clearRect({
    x: 0,
    y: 0,
    w: BOARD_WIDTH,
    h: BOARD_HEIGHT
  });
  gameBoard.board.matrix.forEach(function(row, rIndex) {
    row.forEach(function(col, cIndex) {
      if(col == ".") {
        this.pelletCanvas.drawRect({
          x: (8 * cIndex) + 3,
          y: (8 * rIndex) + 27,
          w: 2,
          h: 2
        });
      }
      else if(col == "o") {
        this.pelletCanvas.drawCircle({
          x: (8 * cIndex) + 4,
          y: (8 * rIndex) + 28,
          rad: 4
        });
      }
      else if(col == "-") {
        this.pelletCanvas.drawRect({
          x: 8 * cIndex,
          y: (8 * rIndex) + 29,
          w: 8,
          h: 2
        });
      }
    });
  });
};
GameController.prototype.moveActor = function() {
  var collision = this.pac.move();
};
GameController.prototype.handleKeyDown = function(event) {
  var keyPressed = keyCodes[event.keyCode];
  if(keyPressed) {
    event.preventDefault();
    if(this.pac.keyStates[keyPressed] === false) {
      this.pac.keyStates[keyPressed] = true;
      this.pac.clear();
      if(this.pac.moveIntervalID === false && this.pac.detectCollision(keyPressed) != "wall") {
        this.pac.moveIntervalID = setInterval(this.moveActor.bind(this), this.pac.speed);
      }
      this.pac.render();
    }
  }
};
GameController.prototype.handleKeyUp = function(event) {
  var keyPressed = keyCodes[event.keyCode];
  if(keyPressed) {
    event.preventDefault();
    this.pac.handleKeyUp(keyPressed);
  }
};
<commit_msg>Update GameController.moveActor to handle moving and collision detection<commit_after>var GameController = function(args) {
  this.keyStates = {
    up: false,
    down: false,
    left: false,
    right: false
  }

  this.actorCanvas = args.actorCanvas;
  this.boardCanvas = args.boardCanvas;
  this.pelletCanvas = args.pelletCanvas;

  this.pac = new Actor({
    context: this.actorCanvas.context,
    startX: 113,
    startY: 212,
    name: "m",
    direction: "right"
  });
  this.blinky = new Ghost({
    context: this.actorCanvas.context,
    direction: "left",
    name: "b",
    startX: 112,
    startY: 116
  });
  this.inky = new Ghost({
    context: this.actorCanvas.context,
    direction: "up",
    mode: "house",
    name: "i",
    startX: 96,
    startY: 139
  });
  this.pinky = new Ghost({
    context: this.actorCanvas.context,
    direction: "right",
    mode: "exitting",
    name: "p",
    startX: 112,
    startY: 139
  });
  this.clyde = new Ghost({
    context: this.actorCanvas.context,
    direction: "down",
    mode: "house",
    name: "c",
    startX: 128,
    startY: 139
  });

  this.drawPellets();
  this.pac.render();

  addEventListener("keydown", this.handleKeyDown.bind(this));
  addEventListener("keyup", this.handleKeyUp.bind(this));

  setInterval(function() {
    this.blinky.move();
    this.inky.move();
    this.pinky.move();
    this.clyde.move();
  }.bind(this), GHOST_MOVE_DELAY);

  setTimeout(function() {
    this.inky.setMode("exitting");
  }.bind(this), INKY_EXIT_DELAY);
  setTimeout(function() {
    this.clyde.setMode("exitting");
  }.bind(this), CLYDE_EXIT_DELAY);
}
GameController.prototype.drawPellets = function() {
  this.pelletCanvas.clearRect({
    x: 0,
    y: 0,
    w: BOARD_WIDTH,
    h: BOARD_HEIGHT
  });
  gameBoard.board.matrix.forEach(function(row, rIndex) {
    row.forEach(function(col, cIndex) {
      if(col == ".") {
        this.pelletCanvas.drawRect({
          x: (8 * cIndex) + 3,
          y: (8 * rIndex) + 27,
          w: 2,
          h: 2
        });
      }
      else if(col == "o") {
        this.pelletCanvas.drawCircle({
          x: (8 * cIndex) + 4,
          y: (8 * rIndex) + 28,
          rad: 4
        });
      }
      else if(col == "-") {
        this.pelletCanvas.drawRect({
          x: 8 * cIndex,
          y: (8 * rIndex) + 29,
          w: 8,
          h: 2
        });
      }
    });
  });
};
GameController.prototype.moveActor = function() {
  this.pac.clear();
  var coords = {
    x: this.pac.x,
    y: this.pac.y
  }

  var newDirection = false;
  for(var prop in this.pac.keyStates) {
    if(this.pac.keyStates.hasOwnProperty(prop) && this.pac.keyStates[prop]) {
      newDirection = prop;
      break;
    }
  }

  var collision;
  if(this.pac.keyStates[this.pac.direction] === false && newDirection) {
    collision = gameBoard.detectCollision(coords, newDirection);
    if(collision != "door" && collision != "wall") {
      this.pac.direction = newDirection;
    }
  }

  collision = gameBoard.detectCollision(coords, this.pac.direction);
  if(collision == "wall" || collision == "door") {
    clearInterval(this.pac.moveIntervalID);
    this.pac.moveIntervalID = false;
  }
  else {
    this.pac.move();
  }
  this.pac.moveTowardCenter();

  this.pac.render();
};
GameController.prototype.handleKeyDown = function(event) {
  var keyPressed = keyCodes[event.keyCode];
  if(keyPressed) {
    event.preventDefault();
    if(this.pac.keyStates[keyPressed] === false) {
      this.pac.keyStates[keyPressed] = true;
      this.pac.clear();
      if(this.pac.moveIntervalID === false) {
        this.pac.moveIntervalID = setInterval(this.moveActor.bind(this), this.pac.speed);
      }
      this.pac.render();
    }
  }
};
GameController.prototype.handleKeyUp = function(event) {
  var keyPressed = keyCodes[event.keyCode];
  if(keyPressed) {
    event.preventDefault();
    this.pac.handleKeyUp(keyPressed);
  }
};
<|endoftext|>


<commit_before>import assign from 'object-assign'

// Style constructor, takes an optional default set of rulesets
export default function Style(defaults) {
  if (!(this instanceof Style)) return new Style(defaults)
  this._rules = {}

  if (typeof defaults === 'object') {
    this.set(defaults)
  }
}

assign(Style.prototype, {

  // .set() takes a selector name and an object of properties
  // and nested rulesets (passing an object as a property value)
  // Alternatively, it takes an object of rulesets, the keys
  // being selectors and the values being rulesets (incl. nested)
  //
  //   style.set('.selector', { 'css-prop': 'value' })
  //   style.set('.selector', {
  //     '.nested': { 'prop': 'value' },
  //     'sibling-prop': 'sibling'
  //   })
  //   style.set({
  //     '.selector-1': { 'css-prop': 'one' },
  //     '.selector-2': { 'css-prop': 'two' }
  //   })
  set(sel, props) {
    const rules = this._rules
    if (props) {
      Object.keys(props).forEach(prop => {
        const val = props[prop]
        if (typeof val === 'object') {
          // nested rules
          this.set(`${sel} ${prop}`, val)
        }
        else {
          if (!(sel in this._rules)) {
            this._rules[sel] = {}
          }
          this._rules[sel][prop] = val
        }
      })
    }
    else {
      Object.keys(sel).forEach(selector => {
        this.set(selector, sel[selector])
      })
    }

    return this
  },

  // returns the flattened rulesets on this Style object
  // i.e. after
  //
  //   style.set({ '.parent': { '.child': {} } })
  //
  // `style.rulesets()` will return
  //
  //   { '.parent .child': {} }
  //
  rulesets() {
    return this._rules
  },

  // formats the current rulesets as a valid CSS string
  // (unless you set invalid property values, but then
  // you're to blame!)
  toString() {
    let str = ''
    const rules = this._rules
    Object.keys(rules).forEach(selector => {
      const ruleset = rules[selector]
      str += `${selector} {\n`
      Object.keys(ruleset).forEach(property => {
        str += `  ${property}: ${ruleset[property]};\n`
      })
      str += '}\n\n'
    })
    return str
  }

})<commit_msg>treat sistyl instances as nested rulesets<commit_after>import assign from 'object-assign'

// Style constructor, takes an optional default set of rulesets
export default function Style(defaults) {
  if (!(this instanceof Style)) return new Style(defaults)
  this._rules = {}

  if (typeof defaults === 'object') {
    this.set(defaults)
  }
}

assign(Style.prototype, {

  // .set() takes a selector name and an object of properties
  // and nested rulesets (passing an object as a property value)
  // Alternatively, it takes an object of rulesets, the keys
  // being selectors and the values being rulesets (incl. nested)
  //
  //   style.set('.selector', { 'css-prop': 'value' })
  //   style.set('.selector', {
  //     '.nested': { 'prop': 'value' },
  //     'sibling-prop': 'sibling'
  //   })
  //   style.set({
  //     '.selector-1': { 'css-prop': 'one' },
  //     '.selector-2': { 'css-prop': 'two' }
  //   })
  set(sel, props) {
    const rules = this._rules
    if (props) {
      if (props instanceof Style) props = props.rulesets()
      Object.keys(props).forEach(prop => {
        const val = props[prop]
        if (typeof val === 'object') {
          // nested rules
          this.set(`${sel} ${prop}`, val)
        }
        else {
          if (!(sel in this._rules)) {
            this._rules[sel] = {}
          }
          this._rules[sel][prop] = val
        }
      })
    }
    else {
      Object.keys(sel).forEach(selector => {
        this.set(selector, sel[selector])
      })
    }

    return this
  },

  // returns the flattened rulesets on this Style object
  // i.e. after
  //
  //   style.set({ '.parent': { '.child': {} } })
  //
  // `style.rulesets()` will return
  //
  //   { '.parent .child': {} }
  //
  rulesets() {
    return this._rules
  },

  // formats the current rulesets as a valid CSS string
  // (unless you set invalid property values, but then
  // you're to blame!)
  toString() {
    let str = ''
    const rules = this._rules
    Object.keys(rules).forEach(selector => {
      const ruleset = rules[selector]
      str += `${selector} {\n`
      Object.keys(ruleset).forEach(property => {
        str += `  ${property}: ${ruleset[property]};\n`
      })
      str += '}\n\n'
    })
    return str
  }

})<|endoftext|>


<commit_before>import React from 'react';
import TableRow from './TableRow';

class TBody extends React.Component {

  render() {
    const { totals, columns } = this.props;
    return (
      <tbody>
        {this.props.data.map(entry => (<TableRow
          columns={this.props.columns}
          row={entry}
          key={Object.values(entry).join('-')}
        />))}
        {Object.keys(totals).length ? <TableRow
          rowClass={this.props.totalsRowClass}
          key={Object.values(totals).join('-')}
          row={totals}
          columns={columns} totals
        /> : null}
      </tbody>
    );
  }
}

TBody.propTypes = {
  data: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
  columns: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
  totals: React.PropTypes.object,
  totalsRowClass: React.PropTypes.string
};

TBody.defaultProps = {
  totals: {}
};

export default TBody;
<commit_msg>fix key for tr when two rows have the same values<commit_after>import React from 'react';
import TableRow from './TableRow';

class TBody extends React.Component {

  render() {
    const { totals, columns } = this.props;
    return (
      <tbody>
        {this.props.data.map((entry, i) => (<TableRow
          columns={this.props.columns}
          row={entry}
          key={i}
        />))}
        {Object.keys(totals).length ? <TableRow
          rowClass={this.props.totalsRowClass}
          key={-1}
          row={totals}
          columns={columns} totals
        /> : null}
      </tbody>
    );
  }
}

TBody.propTypes = {
  data: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
  columns: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
  totals: React.PropTypes.object,
  totalsRowClass: React.PropTypes.string
};

TBody.defaultProps = {
  totals: {}
};

export default TBody;
<|endoftext|>


<commit_before>(function() {
  var jsdom = require("jsdom").jsdom;
  global.document = jsdom("");
  global.window = document.createWindow();
  global.jQuery = global.$ = require('jquery');;

  global.navigator = { userAgent: ''};
  require('../Base/jquery/jquery.inherit.min.js');
  require('../Base/Object');
  require("../Service/ServiceContainer");
  require("./FakeResourceLoader");
  require("./MockFactory");

  global.jQuery.ready();
}());

var fs = require("fs");

/**
 * Provides environment for running tests.
 *
 * @class Environment
 * @namespace Consoloid.Test
 */
defineClass('Consoloid.Test.Environment', 'Consoloid.Base.Object',
  {
    __constructor: function()
    {
      $.fx.off = true;
      this.initializeContainer();
      this.consoleLog = undefined;
      this.consoleDir = undefined;
      this.mockFactory = new Consoloid.Test.MockFactory({sinon: require('sinon') });
    },

    /**
     * Initializes the service container in the environment.
     *
     * @returns Consoloid.Test.Environment Self.
     */
    initializeContainer: function()
    {
      this.container = new Consoloid.Service.ServiceContainer();
      this.addServiceMock('server', { url: 'testUrl' });
      this.addServiceMock('resource_loader', new Consoloid.Test.FakeResourceLoader({
        container: this.container
      }));

      this.addServiceMock('logger', { log: function() {} });

      return this;
    },

    /**
     * Add a service mock to the service container in the environment.
     *
     * The mock will be added as a shared object.
     *
     * @param name Name of the service.
     * @param object Object that provides the service.
     * @returns Consoloid.Test.Environment Self.
     */
    addServiceMock: function(name, object)
    {
      this.container.addSharedObject(name, object);
      return this;
    },

    /**
     * Create a new object with container passed in options.
     *
     * @param cls string|object Class of the new object. Can be given as string.
     * @param options object Options passed to the constructor of cls.
     *                        The container property will be the service container of
     *                        the environment.
     * @returns object The created object.
     */
    create: function(cls, options)
    {
      options['container'] = this.container;
      return this.__base(cls, options);
    },

    mock: function(cls)
    {
      return this.mockFactory.create(cls);
    },

    /**
     * Shutdown test environment.
     *
     * Some event listeners prevent deleting the service container when the environment is
     * deleted. This function ensures that the enviroment will be deleted when the testcase
     * loses all references to it.
     */
    shutdown: function() {
      $('html').unbind();
      $(document).unbind();
      document.body.innerHTML = '';
      $.fx.off = false;
    },

    /**
     * Reads template file into dom.
     *
     * @param filename string Name of file.
     */
    readTemplate: function(filename)
    {
      $(document.body).append(fs.readFileSync(filename, 'utf8'));
    },

    mockConsoleLog: function()
    {
      if (!this.consoleLog) {
        this.consoleLog = console.log;
        console.log = function() {};
      }
    },

    unmockConsoleLog: function()
    {
      if (this.consoleLog) {
        console.log = this.consoleLog;
        this.consoleLog = undefined;
      }
    },

    mockConsoleDir: function()
    {
      if (!this.consoleDir) {
        this.consoleDir = console.dir;
        console.dir = function() {};
      }
    },

    unmockConsoleDir: function()
    {
      if (this.consoleDir) {
        console.dir = this.consoleDir;
        this.consoleDir = undefined;
      }
    }
  }
);
<commit_msg>Consoloid.Test.Environment shotdown remove the listeneres from body<commit_after>(function() {
  var jsdom = require("jsdom").jsdom;
  global.document = jsdom("");
  global.window = document.createWindow();
  global.jQuery = global.$ = require('jquery');;

  global.navigator = { userAgent: ''};
  require('../Base/jquery/jquery.inherit.min.js');
  require('../Base/Object');
  require("../Service/ServiceContainer");
  require("./FakeResourceLoader");
  require("./MockFactory");

  global.jQuery.ready();
}());

var fs = require("fs");

/**
 * Provides environment for running tests.
 *
 * @class Environment
 * @namespace Consoloid.Test
 */
defineClass('Consoloid.Test.Environment', 'Consoloid.Base.Object',
  {
    __constructor: function()
    {
      $.fx.off = true;
      this.initializeContainer();
      this.consoleLog = undefined;
      this.consoleDir = undefined;
      this.mockFactory = new Consoloid.Test.MockFactory({sinon: require('sinon') });
    },

    /**
     * Initializes the service container in the environment.
     *
     * @returns Consoloid.Test.Environment Self.
     */
    initializeContainer: function()
    {
      this.container = new Consoloid.Service.ServiceContainer();
      this.addServiceMock('server', { url: 'testUrl' });
      this.addServiceMock('resource_loader', new Consoloid.Test.FakeResourceLoader({
        container: this.container
      }));

      this.addServiceMock('logger', { log: function() {} });

      return this;
    },

    /**
     * Add a service mock to the service container in the environment.
     *
     * The mock will be added as a shared object.
     *
     * @param name Name of the service.
     * @param object Object that provides the service.
     * @returns Consoloid.Test.Environment Self.
     */
    addServiceMock: function(name, object)
    {
      this.container.addSharedObject(name, object);
      return this;
    },

    /**
     * Create a new object with container passed in options.
     *
     * @param cls string|object Class of the new object. Can be given as string.
     * @param options object Options passed to the constructor of cls.
     *                        The container property will be the service container of
     *                        the environment.
     * @returns object The created object.
     */
    create: function(cls, options)
    {
      options['container'] = this.container;
      return this.__base(cls, options);
    },

    mock: function(cls)
    {
      return this.mockFactory.create(cls);
    },

    /**
     * Shutdown test environment.
     *
     * Some event listeners prevent deleting the service container when the environment is
     * deleted. This function ensures that the enviroment will be deleted when the testcase
     * loses all references to it.
     */
    shutdown: function() {
      $('body').unbind();
      $('html').unbind();
      $(document).unbind();
      document.body.innerHTML = '';
      $.fx.off = false;
    },

    /**
     * Reads template file into dom.
     *
     * @param filename string Name of file.
     */
    readTemplate: function(filename)
    {
      $(document.body).append(fs.readFileSync(filename, 'utf8'));
    },

    mockConsoleLog: function()
    {
      if (!this.consoleLog) {
        this.consoleLog = console.log;
        console.log = function() {};
      }
    },

    unmockConsoleLog: function()
    {
      if (this.consoleLog) {
        console.log = this.consoleLog;
        this.consoleLog = undefined;
      }
    },

    mockConsoleDir: function()
    {
      if (!this.consoleDir) {
        this.consoleDir = console.dir;
        console.dir = function() {};
      }
    },

    unmockConsoleDir: function()
    {
      if (this.consoleDir) {
        console.dir = this.consoleDir;
        this.consoleDir = undefined;
      }
    }
  }
);
<|endoftext|>


<commit_before>/**
 * Dense - Device pixel ratio aware images
 *
 * @link    http://dense.rah.pw
 * @license MIT
 */

/*
 * Copyright (C) 2013 Jukka Svahn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @name jQuery
 * @class
 */

/**
 * @name fn
 * @class
 * @memberOf jQuery
 */

(function (factory)
{
    'use strict';

    if (typeof define === 'function' && define.amd)
    {
        define(['jquery'], factory);
    }
    else
    {
        factory(window.jQuery || window.Zepto);
    }
}(function ($)
{
    'use strict';

    /**
     * An array of checked image URLs.
     */

    var pathStack = [],

    /**
     * Methods.
     */

    methods = {},

    /**
     * Regular expression to check whether the URL has a protocol.
     *
     * Is used to check whether the image URL is external.
     */

    regexProtocol = /^https?:\/\//,

    /**
     * Regular expression that split extensions from the file.
     *
     * Is used to inject the DPR suffix to the name.
     */

    regexSuffix = /\.\w+$/,

    /**
     * Device pixel ratio.
     */

    devicePixelRatio,

    /**
     * Skipped image file extensions.
     *
     * Vectors don't need automatic pixel ratio support.
     */

    skipExtensions =
    [
        'svg'
    ];

    /**
     * Init is the default method responsible for rendering
     * a pixel-ratio-aware images.
     *
     * This method is used to select the images that
     * should display retina-size images on high pixel ratio
     * devices. Dense defaults to the init method if no
     * method is specified.
     *
     * When attached to an image, the correct image variation is
     * selected based on the device's pixel ratio. If the image element
     * defines data-{ratio}x attributes (e.g. data-1x, data-2x, data-3x),
     * the most appropriate of those is selected.
     *
     * If no data-ratio attributes are defined, the retina image is
     * constructed from the src attribute.
     * The searched high pixel ratio images follows
     * a {imageName}_{ratio}x.{ext} naming convention.
     * For an image found in /path/to/images/image.jpg, the 2x retina
     * image would be looked from /path/to/images/image_2x.jpg.
     *
     * When image is constructed from the src, the image existance is
     * verified using HTTP HEAD request, if ping option is
     * true. The check makes sure no HTTP error code is returned,
     * and that the received content-type is of an image. Vector image formats,
     * like svg, are skipped based on the file extension.
     *
     * This method can also be used to load image in semi-lazy fashion,
     * and avoid larger extra HTTP requests due to retina replacements.
     * The data-1x attribute can be used to supstitute the src, making
     * sure the browser doesn't try to download the normal image variation
     * before the JavaScript driven behaviour kicks in.
     *
     * @param    {Object}  [options={}]                  Options
     * @param    {Boolean} [options.ping=true]           Check that the retina image exists before applying
     * @param    {String}  [options.dimensions=preserve] What to do with the image's width and height attributes. Either update, remove or preserve
     * @return   {Object}  this
     * @method   init
     * @memberof jQuery.fn.dense
     * @fires    jQuery.fn.dense#dense-retina-loaded
     * @example
     * $('img').dense({
     *  'ping'      : false,
     *  'dimension' : 'update'
     * });
     */

    methods.init = function (options)
    {
        options = $.extend({
            ping       : true,
            dimensions : 'preserve'
        }, options);

        this.filter('img').not('.dense').addClass('dense dense-loading').each(function ()
        {
            var $this = $(this),
                image = methods.getImageAttribute.call(this),
                originalImage = $this.attr('src'),
                ping = false,
                updateImage;

            if (!image)
            {
                if (!originalImage || devicePixelRatio === 1 || $.inArray(originalImage.split('.').pop().split(/[\?\#]/).shift(), skipExtensions))
                {
                    $this.removeClass('dense dense-loading');
                    return;
                }

                image = originalImage.replace(regexSuffix, function (extension)
                {
                    return '_' + devicePixelRatio + 'x' + extension;
                });

                ping = options.ping && $.inArray(image, pathStack) === -1 && (!regexProtocol.test(image) || image.indexOf('://' + document.domain) !== -1);
            }

            updateImage = function ()
            {
                var readyImage = function ()
                {
                    $this.removeClass('dense-loading').addClass('dense-ready').trigger('dense-retina-loaded');
                };

                $this.attr('src', image);

                if (options.dimensions === 'update')
                {
                    $this.dense('updateDimensions').one('dense-dimensions-updated', readyImage);
                }
                else
                {
                    if (options.dimensions === 'remove')
                    {
                        $this.removeAttr('width height');
                    }

                    readyImage();
                }
            };

            if (ping)
            {
                $.ajax({
                    url  : image,
                    type : 'HEAD'
                })
                    .done(function (data, textStatus, jqXHR)
                    {
                        var type = jqXHR.getResponseHeader('Content-type');

                        if (!type || type.indexOf('image/') === 0)
                        {
                            pathStack.push(image);
                            updateImage();
                        }
                    });
            }
            else
            {
                updateImage();
            }
        });

        return this;
    };

    /**
     * Sets an image's width and height attributes to its native values.
     *
     * Updates an img element's dimensions to the source image's
     * real values. This method is asynchronous, so you can not directly
     * return its values. Instead, use the 'dense-dimensions-updated'
     * event to detect when the action is done.
     *
     * @return   {Object} this
     * @method   updateDimensions
     * @memberof jQuery.fn.dense
     * @fires    jQuery.fn.dense#dense-dimensions-updated
     * @example
     * var image = $('img').dense('updateDimensions');
     */

    methods.updateDimensions = function ()
    {
        return this.each(function ()
        {
            var img, $this = $(this), src = $this.attr('src');

            if (src)
            {
                img = new Image();
                img.src = src;

                $(img).on('load.dense', function ()
                {
                    $this.attr({
                        width  : img.width,
                        height : img.height
                    }).trigger('dense-dimensions-updated');
                });
            }
        });
    };

    /**
     * Gets device pixel ratio rounded up to the closest integer.
     *
     * @return   {Integer} The pixel ratio
     * @method   devicePixelRatio
     * @memberof jQuery.fn.dense
     * @example
     * var ratio = $(window).dense('devicePixelRatio');
     * alert(ratio);
     */

    methods.devicePixelRatio = function ()
    {
        var pixelRatio = 1;

        if ($.type(window.devicePixelRatio) !== 'undefined')
        {
            pixelRatio = window.devicePixelRatio;
        }
        else if ($.type(window.matchMedia) !== 'undefined')
        {
            $.each([1.3, 1.5, 2, 3, 4, 5, 6], function (key, ratio)
            {
                var mediaQuery = [
                    '(-webkit-min-device-pixel-ratio: '+ratio+')',
                    '(-o-min-device-pixel-ratio: '+ratio+')',
                    '(min-resolution: '+ratio+'dppx)'
                ].join(',');

                if (!window.matchMedia(mediaQuery).matches)
                {
                    return false;
                }

                pixelRatio = ratio;
            });
        }

        return Math.ceil(pixelRatio);
    };

    /**
     * Gets an appropriate URL for the pixel ratio from the data attribute list.
     *
     * Selects the most appropriate data-{ratio}x attribute from
     * the given element's attributes. If the devices pixel ratio is greater
     * than the largest specified image, the largest one of the available is used.
     *
     * @return   {String|Boolean} The attribute value
     * @method   getImageAttribute
     * @memberof jQuery.fn.dense
     * @example
     * var image = $('
').dense('getImageAttribute');
     * $('body').css('background-image', 'url(' + image + ')');
     */

    methods.getImageAttribute = function ()
    {
        var $this = $(this).eq(0), image = false, url;

        for (var i = 1; i <= devicePixelRatio; i++)
        {
            url = $this.attr('data-' + i + 'x');

            if (url)
            {
                image = url;
            }
        }

        return image;
    };

    devicePixelRatio = methods.devicePixelRatio();

    /**
     * Dense offers few methods and options that can be used to both customize the
     * plugin's functionality and return resulting values. All interaction is done through
     * the $.fn.dense() method, that accepts a called method and its options
     * object as its arguments. Both arguments are optional, and either one can be omitted.
     *
     * @param    {String}  [method=init] The called method
     * @param    {Object}  [options={}]  Options passed to the method
     * @class    dense
     * @memberof jQuery.fn
     */

    $.fn.dense = function (method, options)
    {
        if ($.type(method) !== 'string' || $.type(methods[method]) !== 'function')
        {
            options = method;
            method = 'init';
        }

        return methods[method].call(this, options);
    };

    /**
     * Initialize automatically when document is ready.
     *
     * Dense is initialized automatically if the body element
     * has a dense-retina class.
     */

    $(document).ready(function ()
    {
        $('body.dense-retina img').dense();
    });

    /**
     * This event is invoked when an retina image has finished loading.
     *
     * @event    jQuery.fn.dense#dense-retina-loaded
     * @type     {Object}
     */

    /**
     * This event is invoked when an image's dimensions are
     * have been updated by the updateDimensions
     * method.
     *
     * @event    jQuery.fn.dense#dense-dimensions-updated
     * @type     {Object}
     */
}));<commit_msg>Operas attribute expects fractions.<commit_after>/**
 * Dense - Device pixel ratio aware images
 *
 * @link    http://dense.rah.pw
 * @license MIT
 */

/*
 * Copyright (C) 2013 Jukka Svahn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @name jQuery
 * @class
 */

/**
 * @name fn
 * @class
 * @memberOf jQuery
 */

(function (factory)
{
    'use strict';

    if (typeof define === 'function' && define.amd)
    {
        define(['jquery'], factory);
    }
    else
    {
        factory(window.jQuery || window.Zepto);
    }
}(function ($)
{
    'use strict';

    /**
     * An array of checked image URLs.
     */

    var pathStack = [],

    /**
     * Methods.
     */

    methods = {},

    /**
     * Regular expression to check whether the URL has a protocol.
     *
     * Is used to check whether the image URL is external.
     */

    regexProtocol = /^https?:\/\//,

    /**
     * Regular expression that split extensions from the file.
     *
     * Is used to inject the DPR suffix to the name.
     */

    regexSuffix = /\.\w+$/,

    /**
     * Device pixel ratio.
     */

    devicePixelRatio,

    /**
     * Skipped image file extensions.
     *
     * Vectors don't need automatic pixel ratio support.
     */

    skipExtensions =
    [
        'svg'
    ];

    /**
     * Init is the default method responsible for rendering
     * a pixel-ratio-aware images.
     *
     * This method is used to select the images that
     * should display retina-size images on high pixel ratio
     * devices. Dense defaults to the init method if no
     * method is specified.
     *
     * When attached to an image, the correct image variation is
     * selected based on the device's pixel ratio. If the image element
     * defines data-{ratio}x attributes (e.g. data-1x, data-2x, data-3x),
     * the most appropriate of those is selected.
     *
     * If no data-ratio attributes are defined, the retina image is
     * constructed from the src attribute.
     * The searched high pixel ratio images follows
     * a {imageName}_{ratio}x.{ext} naming convention.
     * For an image found in /path/to/images/image.jpg, the 2x retina
     * image would be looked from /path/to/images/image_2x.jpg.
     *
     * When image is constructed from the src, the image existance is
     * verified using HTTP HEAD request, if ping option is
     * true. The check makes sure no HTTP error code is returned,
     * and that the received content-type is of an image. Vector image formats,
     * like svg, are skipped based on the file extension.
     *
     * This method can also be used to load image in semi-lazy fashion,
     * and avoid larger extra HTTP requests due to retina replacements.
     * The data-1x attribute can be used to supstitute the src, making
     * sure the browser doesn't try to download the normal image variation
     * before the JavaScript driven behaviour kicks in.
     *
     * @param    {Object}  [options={}]                  Options
     * @param    {Boolean} [options.ping=true]           Check that the retina image exists before applying
     * @param    {String}  [options.dimensions=preserve] What to do with the image's width and height attributes. Either update, remove or preserve
     * @return   {Object}  this
     * @method   init
     * @memberof jQuery.fn.dense
     * @fires    jQuery.fn.dense#dense-retina-loaded
     * @example
     * $('img').dense({
     *  'ping'      : false,
     *  'dimension' : 'update'
     * });
     */

    methods.init = function (options)
    {
        options = $.extend({
            ping       : true,
            dimensions : 'preserve'
        }, options);

        this.filter('img').not('.dense').addClass('dense dense-loading').each(function ()
        {
            var $this = $(this),
                image = methods.getImageAttribute.call(this),
                originalImage = $this.attr('src'),
                ping = false,
                updateImage;

            if (!image)
            {
                if (!originalImage || devicePixelRatio === 1 || $.inArray(originalImage.split('.').pop().split(/[\?\#]/).shift(), skipExtensions))
                {
                    $this.removeClass('dense dense-loading');
                    return;
                }

                image = originalImage.replace(regexSuffix, function (extension)
                {
                    return '_' + devicePixelRatio + 'x' + extension;
                });

                ping = options.ping && $.inArray(image, pathStack) === -1 && (!regexProtocol.test(image) || image.indexOf('://' + document.domain) !== -1);
            }

            updateImage = function ()
            {
                var readyImage = function ()
                {
                    $this.removeClass('dense-loading').addClass('dense-ready').trigger('dense-retina-loaded');
                };

                $this.attr('src', image);

                if (options.dimensions === 'update')
                {
                    $this.dense('updateDimensions').one('dense-dimensions-updated', readyImage);
                }
                else
                {
                    if (options.dimensions === 'remove')
                    {
                        $this.removeAttr('width height');
                    }

                    readyImage();
                }
            };

            if (ping)
            {
                $.ajax({
                    url  : image,
                    type : 'HEAD'
                })
                    .done(function (data, textStatus, jqXHR)
                    {
                        var type = jqXHR.getResponseHeader('Content-type');

                        if (!type || type.indexOf('image/') === 0)
                        {
                            pathStack.push(image);
                            updateImage();
                        }
                    });
            }
            else
            {
                updateImage();
            }
        });

        return this;
    };

    /**
     * Sets an image's width and height attributes to its native values.
     *
     * Updates an img element's dimensions to the source image's
     * real values. This method is asynchronous, so you can not directly
     * return its values. Instead, use the 'dense-dimensions-updated'
     * event to detect when the action is done.
     *
     * @return   {Object} this
     * @method   updateDimensions
     * @memberof jQuery.fn.dense
     * @fires    jQuery.fn.dense#dense-dimensions-updated
     * @example
     * var image = $('img').dense('updateDimensions');
     */

    methods.updateDimensions = function ()
    {
        return this.each(function ()
        {
            var img, $this = $(this), src = $this.attr('src');

            if (src)
            {
                img = new Image();
                img.src = src;

                $(img).on('load.dense', function ()
                {
                    $this.attr({
                        width  : img.width,
                        height : img.height
                    }).trigger('dense-dimensions-updated');
                });
            }
        });
    };

    /**
     * Gets device pixel ratio rounded up to the closest integer.
     *
     * @return   {Integer} The pixel ratio
     * @method   devicePixelRatio
     * @memberof jQuery.fn.dense
     * @example
     * var ratio = $(window).dense('devicePixelRatio');
     * alert(ratio);
     */

    methods.devicePixelRatio = function ()
    {
        var pixelRatio = 1;

        if ($.type(window.devicePixelRatio) !== 'undefined')
        {
            pixelRatio = window.devicePixelRatio;
        }
        else if ($.type(window.matchMedia) !== 'undefined')
        {
            $.each([1.3, 1.5, 2, 3, 4, 5, 6], function (key, ratio)
            {
                var mediaQuery = [
                    '(-webkit-min-device-pixel-ratio: '+ratio+')',
                    '(min-resolution: '+ratio+'dppx)'
                ].join(',');

                if (!window.matchMedia(mediaQuery).matches)
                {
                    return false;
                }

                pixelRatio = ratio;
            });
        }

        return Math.ceil(pixelRatio);
    };

    /**
     * Gets an appropriate URL for the pixel ratio from the data attribute list.
     *
     * Selects the most appropriate data-{ratio}x attribute from
     * the given element's attributes. If the devices pixel ratio is greater
     * than the largest specified image, the largest one of the available is used.
     *
     * @return   {String|Boolean} The attribute value
     * @method   getImageAttribute
     * @memberof jQuery.fn.dense
     * @example
     * var image = $('
').dense('getImageAttribute');
     * $('body').css('background-image', 'url(' + image + ')');
     */

    methods.getImageAttribute = function ()
    {
        var $this = $(this).eq(0), image = false, url;

        for (var i = 1; i <= devicePixelRatio; i++)
        {
            url = $this.attr('data-' + i + 'x');

            if (url)
            {
                image = url;
            }
        }

        return image;
    };

    devicePixelRatio = methods.devicePixelRatio();

    /**
     * Dense offers few methods and options that can be used to both customize the
     * plugin's functionality and return resulting values. All interaction is done through
     * the $.fn.dense() method, that accepts a called method and its options
     * object as its arguments. Both arguments are optional, and either one can be omitted.
     *
     * @param    {String}  [method=init] The called method
     * @param    {Object}  [options={}]  Options passed to the method
     * @class    dense
     * @memberof jQuery.fn
     */

    $.fn.dense = function (method, options)
    {
        if ($.type(method) !== 'string' || $.type(methods[method]) !== 'function')
        {
            options = method;
            method = 'init';
        }

        return methods[method].call(this, options);
    };

    /**
     * Initialize automatically when document is ready.
     *
     * Dense is initialized automatically if the body element
     * has a dense-retina class.
     */

    $(document).ready(function ()
    {
        $('body.dense-retina img').dense();
    });

    /**
     * This event is invoked when an retina image has finished loading.
     *
     * @event    jQuery.fn.dense#dense-retina-loaded
     * @type     {Object}
     */

    /**
     * This event is invoked when an image's dimensions are
     * have been updated by the updateDimensions
     * method.
     *
     * @event    jQuery.fn.dense#dense-dimensions-updated
     * @type     {Object}
     */
}));<|endoftext|>


<commit_before>var applyTypography = function (newStyles, sharedStyles) {

  var alignmentHash = {
    'left': 0,
    'right': 1,
    'center': 2,
    'justified': 3
  };

  removeAllStyles();

  for(var i=0; i<newStyles.length; i++) {
    createStyle(newStyles[i]);
  }

  function createStyle(style) {
    if(style.Style == "") { return; }

    var textLayer = [[MSTextLayer alloc] initWithFrame:nil];

    if("Size"      in style)  { textLayer.setFontSize(style.Size); }
    if("Line"      in style)  { textLayer.setLineHeight(style.Line); }
    if("Character" in style)  {
      var characterSpacing = Number(style.Character);
      textLayer.setCharacterSpacing(characterSpacing);
    }
    if("Alignment" in style)  { textLayer.setTextAlignment(alignmentHash[style.Alignment]); }
    if("Typeface"  in style)  { textLayer.setFontPostscriptName(style.Typeface); }
    if("Color"     in style)  {
      var color = MSColor.colorWithSVGString("#" + style.Color);
      color.alpha = style.Opacity;
      textLayer.setTextColor(color);
    }

    sharedStyles.addSharedStyleWithName_firstInstance(style.Style, textLayer.style());
  }

  function removeAllStyles() {
    var existingStyles = sharedStyles.objects();

    while(existingStyles.count() > 0) {
      style = existingStyles.objectAtIndex(0);
      [sharedStyles removeSharedObjectAtIndex:0];
    }
  }
}
<commit_msg>clears existing type styles before importing because sketch will freeze if the to be imported styles already exist<commit_after>var applyTypography = function (newStyles, sharedStyles) {

  var alignmentHash = {
    'left': 0,
    'right': 1,
    'center': 2,
    'justified': 3
  };

  // removes existing styles before importing
  // keeps sketch from shitting its pants the the styles already exist
  // probably need to check for matching names though. This will wipe out other existing styles
  [sharedStyles removeAllSharedObjects];

  for(var i=0; i<newStyles.length; i++) {
    createStyle(newStyles[i]);
  }

  function createStyle(style) {
    if(style.Style == "") { return; }

    var textLayer = [[MSTextLayer alloc] initWithFrame:nil];

    if("Size"      in style)  { textLayer.setFontSize(style.Size); }
    if("Line"      in style)  { textLayer.setLineHeight(style.Line); }
    if("Character" in style)  {
      var characterSpacing = Number(style.Character);
      textLayer.setCharacterSpacing(characterSpacing);
    }
    if("Alignment" in style)  { textLayer.setTextAlignment(alignmentHash[style.Alignment]); }
    if("Typeface"  in style)  { textLayer.setFontPostscriptName(style.Typeface); }
    if("Color"     in style)  {
      var color = MSColor.colorWithSVGString("#" + style.Color);
      color.alpha = style.Opacity;
      textLayer.setTextColor(color);
    }

    sharedStyles.addSharedStyleWithName_firstInstance(style.Style, textLayer.style());
  }

  function removeAllStyles() {
    var existingStyles = sharedStyles.objects();

    while(existingStyles.count() > 0) {
      style = existingStyles.objectAtIndex(0);
      [sharedStyles removeSharedObjectAtIndex:0];
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.

// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

/**
 * WebDAV server used to provide files for unit tests and manual testing of
 * the extension.
 * The skeleton directory that is served is located in `test/assets`.
 */

'use strict';

var jsdav = require('jsDAV/lib/jsdav');
var config = require('./config');

var argv = process.argv.slice(2);

console.log(argv);

var flags = ['--debug', '-d'];

if (argv.length > 0) {
  if (flags.indexOf(argv[0]) !== -1) {
    jsdav.debugMode = true;
  }
}

jsdav.createServer({node: __dirname + config.ASSETS_DIRECTORY}, config.PORT);
<commit_msg>remove log<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.

// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

/**
 * WebDAV server used to provide files for unit tests and manual testing of
 * the extension.
 * The skeleton directory that is served is located in `test/assets`.
 */

'use strict';

var jsdav = require('jsDAV/lib/jsdav');
var config = require('./config');

var argv = process.argv.slice(2);

var flags = ['--debug', '-d'];

// Enable debug mode if the command-line flag is set.
if (argv.length > 0) {
  if (flags.indexOf(argv[0]) !== -1) {
    jsdav.debugMode = true;
  }
}

jsdav.createServer({node: __dirname + config.ASSETS_DIRECTORY}, config.PORT);
<|endoftext|>


<commit_before>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

var domready = require('domready');

function osmify() {}

// Allow calling this from the button event handler.
window.osmify = osmify;

/// Look up name as a key in the query string.
function getParameterByName(name)
{
    name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
    var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'),
        results = regex.exec(location.search);
    return results === null ? '' : results[1].replace(/\+/g, ' ');
}

domready(function() {
    var url = getParameterByName('url');
    if (url)
    {
        var urlInput = document.getElementById('url-input');
        urlInput.value = url;
    }
});

// vim: shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>addr-osmify-js: construct overpass string<commit_after>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

var domready = require('domready');

function osmify()
{
    var url = document.getElementById('url-input').value;
    var tokens = url.split('/');
    // E.g. node or way.
    objectType = tokens[tokens.length - 2];
    // Numeric ID.
    var objectId = tokens[tokens.length - 1];

    // Turn the ID into an address.
    var query = '[out:json];\n(\n    ' + objectType + '(' + objectId +
                ');\n);\nout body;';
    // TODO query overpass.
}

// Allow calling this from the button event handler.
window.osmify = osmify;

/// Look up name as a key in the query string.
function getParameterByName(name)
{
    name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
    var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'),
        results = regex.exec(location.search);
    return results === null ? '' : results[1].replace(/\+/g, ' ');
}

domready(function() {
    var url = getParameterByName('url');
    if (url)
    {
        var urlInput = document.getElementById('url-input');
        urlInput.value = url;
    }
});

// vim: shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>/* eslint-env browser */

import renderGraph from './lib/displayProjectsGraph';

let projects = document.querySelector('#projects');
let hierarchy = document.querySelector('#hierarchy');
let selectedProject;
let selectedHierarchyItem = null;
let graphData;

// TODO: Hook this up to the log out button on the graph view. It is currently not hooked up to anything,
// but functions properly
document.addEventListener('DOMContentLoaded', () => {
  document.getElementById('logOut').addEventListener('click', () => {
    document.location.href = '/logout';
  });

  // Manage the selection of a project and item hierarchy
  buildProjectAnchors().then(() => getGraph(selectedProject)).then(graphJSON => {
    graphData = graphJSON;
    console.log(graphData);
    buildItemHierarchyAnchors();
  });

  document.getElementById('renderButton').addEventListener('click', event => {
    toggle(hierarchy);
    console.log(selectedHierarchyItem);
    renderGraph(graphData, selectedProject, parseInt(selectedHierarchyItem));
  });
});

function buildProjectAnchors () {
  return new Promise((resolve) => {
    querySelectorAll('#projects a').forEach(projectAnchor => {
      projectAnchor.addEventListener('click', event => {
        selectedProject = event.target.getAttribute('data-id');
        // Wait until loadHierarchy retrieves the new partial view and updates it with the item hierarchy
        // to display the hierarchy selection div and toggle projects view
        document.body.style.cursor = 'wait';
        getHierarchy(selectedProject).then(hierarchyPayload => {
          renderHierarchy(hierarchyPayload);
          toggle(projects);
          toggle(hierarchy);
          document.body.style.cursor = 'default';
          resolve(true);
        });
      });
    });
  });
}

/**
 * Listens for mouse clicks on the Item hierarchy list and sets the selected
 * variable to that items ID
 */
function buildItemHierarchyAnchors () {
  return new Promise(resolve => {
    querySelectorAll('#itemHierarchyList a').forEach(hierarchyAnchor => {
      hierarchyAnchor.addEventListener('click', event => {
        selectedHierarchyItem = event.target.getAttribute('data-id');
        resolve(true);
      });
    });
  });
}

/**
 * Query the page for a set of elements given a CSS selector.
 *
 * @param selector CSS selector
 * @returns {*} Array of matched elements
 */
function querySelectorAll (selector) {
  return Array.from(document.querySelectorAll(selector));
}

function toggle (element) {
  if (element.classList.contains('hidden')) {
    element.classList.remove('hidden');
  } else {
    element.classList.add('hidden');
  }
}

/**
 * Makes an AJAX request to the provided endpoint for the item hierarchy tree.
 *
 * @param projectId
 * @returns {*}
 */
function getHierarchy (projectId) {
  // TODO: Refactor to use the request module?
  return new Promise((resolve, reject) => {
    let httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = () => {
      if (httpRequest.readyState === XMLHttpRequest.DONE) {
        if (httpRequest.status === 200) {
          resolve(JSON.parse(httpRequest.responseText));
        } else {
          console.log('There was a problem requesting to the hierarchy endpoint.');
          reject({status: httpRequest.status, response: httpRequest.responseText});
        }
      }
    };
    httpRequest.open('GET', '/hierarchy?project=' + projectId);
    httpRequest.send();
  });
}

function renderHierarchy (hierarchyPayload) {
  let itemHierarchyList = document.getElementById('itemHierarchyList');
  if (hierarchyPayload) {
    hierarchyPayload.forEach(item => {
      itemHierarchyList.appendChild(getHierarchyItemWithChildren(item));
    });
  } else {
    itemHierarchyList.appendChild(document.createTextNode('Sorry, this project has no items to display.'));
  }
}

function getHierarchyItemWithChildren (item) {
  let listItem = document.createElement('li');
  let itemAnchor = document.createElement('a');
  itemAnchor.setAttribute('href', '#rootId=' + item.id);
  itemAnchor.appendChild(document.createTextNode(item.name));
  itemAnchor.setAttribute('data-id', item.id);
  listItem.appendChild(itemAnchor);
  if (item.children) {
    let unorderedList = document.createElement('ul');
    item.children.forEach(function (subItem) {
      unorderedList.appendChild(getHierarchyItemWithChildren(subItem));
    });
    listItem.appendChild(unorderedList);
  }
  return listItem;
}

/**
 * Makes an AJAX request to the provided endpoint for the project graph.
 *
 * @param projectId
 * @returns {*}
 */
function getGraph (projectId) {
  // TODO: Refactor to use the request module and promises
  return new Promise((resolve, reject) => {
    let httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = () => {
      if (httpRequest.readyState === XMLHttpRequest.DONE) {
        if (httpRequest.status === 200) {
          resolve(JSON.parse(httpRequest.responseText));
        } else {
          console.log('There was a problem requesting to the graph endpoint.');
          reject({status: httpRequest.status, response: httpRequest.responseText});
        }
      }
    };
    httpRequest.open('GET', '?project=' + projectId);
    httpRequest.send();
  });
}
<commit_msg>Refactor away promise when building hierarchy anchors<commit_after>/* eslint-env browser */

import renderGraph from './lib/displayProjectsGraph';

let projects = document.querySelector('#projects');
let hierarchy = document.querySelector('#hierarchy');
let selectedProject;
let selectedHierarchyItem = null;
let graphData;

// TODO: Hook this up to the log out button on the graph view. It is currently not hooked up to anything,
// but functions properly
document.addEventListener('DOMContentLoaded', () => {
  document.getElementById('logOut').addEventListener('click', () => {
    document.location.href = '/logout';
  });

  // Manage the selection of a project and item hierarchy
  buildProjectAnchors().then(() => getGraph(selectedProject)).then(graphJSON => {
    graphData = graphJSON;
    console.log(graphData);
    buildItemHierarchyAnchors();
  });

  document.getElementById('renderButton').addEventListener('click', event => {
    toggle(hierarchy);
    console.log(selectedHierarchyItem);
    renderGraph(graphData, selectedProject, parseInt(selectedHierarchyItem));
  });
});

function buildProjectAnchors () {
  return new Promise((resolve) => {
    querySelectorAll('#projects a').forEach(projectAnchor => {
      projectAnchor.addEventListener('click', event => {
        selectedProject = event.target.getAttribute('data-id');
        // Wait until loadHierarchy retrieves the new partial view and updates it with the item hierarchy
        // to display the hierarchy selection div and toggle projects view
        document.body.style.cursor = 'wait';
        getHierarchy(selectedProject).then(hierarchyPayload => {
          renderHierarchy(hierarchyPayload);
          toggle(projects);
          toggle(hierarchy);
          document.body.style.cursor = 'default';
          resolve(true);
        });
      });
    });
  });
}

/**
 * Listens for mouse clicks on the Item hierarchy list and sets the selected
 * variable to that items ID
 */
function buildItemHierarchyAnchors () {
  querySelectorAll('#itemHierarchyList a').forEach(hierarchyAnchor => {
    hierarchyAnchor.addEventListener('click', event => {
      selectedHierarchyItem = event.target.getAttribute('data-id');
    });
  });
}

/**
 * Query the page for a set of elements given a CSS selector.
 *
 * @param selector CSS selector
 * @returns {*} Array of matched elements
 */
function querySelectorAll (selector) {
  return Array.from(document.querySelectorAll(selector));
}

function toggle (element) {
  if (element.classList.contains('hidden')) {
    element.classList.remove('hidden');
  } else {
    element.classList.add('hidden');
  }
}

/**
 * Makes an AJAX request to the provided endpoint for the item hierarchy tree.
 *
 * @param projectId
 * @returns {*}
 */
function getHierarchy (projectId) {
  // TODO: Refactor to use the request module?
  return new Promise((resolve, reject) => {
    let httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = () => {
      if (httpRequest.readyState === XMLHttpRequest.DONE) {
        if (httpRequest.status === 200) {
          resolve(JSON.parse(httpRequest.responseText));
        } else {
          console.log('There was a problem requesting to the hierarchy endpoint.');
          reject({status: httpRequest.status, response: httpRequest.responseText});
        }
      }
    };
    httpRequest.open('GET', '/hierarchy?project=' + projectId);
    httpRequest.send();
  });
}

function renderHierarchy (hierarchyPayload) {
  let itemHierarchyList = document.getElementById('itemHierarchyList');
  if (hierarchyPayload) {
    hierarchyPayload.forEach(item => {
      itemHierarchyList.appendChild(getHierarchyItemWithChildren(item));
    });
  } else {
    itemHierarchyList.appendChild(document.createTextNode('Sorry, this project has no items to display.'));
  }
}

function getHierarchyItemWithChildren (item) {
  let listItem = document.createElement('li');
  let itemAnchor = document.createElement('a');
  itemAnchor.setAttribute('href', '#rootId=' + item.id);
  itemAnchor.appendChild(document.createTextNode(item.name));
  itemAnchor.setAttribute('data-id', item.id);
  listItem.appendChild(itemAnchor);
  if (item.children) {
    let unorderedList = document.createElement('ul');
    item.children.forEach(function (subItem) {
      unorderedList.appendChild(getHierarchyItemWithChildren(subItem));
    });
    listItem.appendChild(unorderedList);
  }
  return listItem;
}

/**
 * Makes an AJAX request to the provided endpoint for the project graph.
 *
 * @param projectId
 * @returns {*}
 */
function getGraph (projectId) {
  // TODO: Refactor to use the request module and promises
  return new Promise((resolve, reject) => {
    let httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = () => {
      if (httpRequest.readyState === XMLHttpRequest.DONE) {
        if (httpRequest.status === 200) {
          resolve(JSON.parse(httpRequest.responseText));
        } else {
          console.log('There was a problem requesting to the graph endpoint.');
          reject({status: httpRequest.status, response: httpRequest.responseText});
        }
      }
    };
    httpRequest.open('GET', '?project=' + projectId);
    httpRequest.send();
  });
}
<|endoftext|>