<commit_before>var request = require('request');
var template = require('url-template');
var RSVP = require('rsvp');

module.exports = GithubClient;

// Responsible for interacting with Github. This isn't a complete
// Github client right now, it just does a set of things needed for
// the Hubbub project.
function GithubClient (user, auth) {
  this.user = user;
  this.auth = auth;
}

function getBody(ressponse) {
  return response.body;
}

GithubClient.prototype = {

  // The request library's main function promisified, easy to overide
  // for tests
  _request: function (options) {
    var me = this;
    return new RSVP.Promise(function (resolve, reject) {
      request(options, function (err, response, body) {
        if (err) {
          reject(err);
        } else {
          response.body = body;
          resolve(response);
        }
      });
    });
  },

  request: function (method, url, params, body) {
    var me = this;
    url = template.parse("https://api.github.com" + url).expand(params);
    // console.log('------------');
    // console.log(body);
    // console.log('requests', url);
    var options = {
      method: method,
      url: url,
      json: true,
      body: body,
      auth: me.auth,
      headers: {
        'User-Agent': 'hubbub'
      }
    };

    return this._request(options)
      .then(function (response) {
        // Turn all responses with status codes 400 and above into
        // errors on the promise
        if (response.statusCode >= 400) {
          throw (response);
        } else {
          return response;
        }
      });
  },

  get: function (url, params) {
    return this.request('GET', url, params, null);
  },

  post: function (url, params, body) {
    return this.request('POST', url, params, body);
  },

  put: function (url, params, body) {
    return this.request('PUT', url, params, body);
  },

  "delete": function (url, params) {
    return this.request('DELETE', url, params, null);
  },

  // Create a new fork of a repo (on the authenticated user's
  // account). Forks are created asynchronously.
  createFork: function (user, repo) {
    return this.post('/repos/{user}/{repo}/forks', {user: user, repo: repo})
      .then(function (response) {
        if (response.statusCode !== 202) {
          throw new Error("Got unexpected status code when creating fork: " + response.statusCode);
        }
        return response;
      });
  },

  // Update origin-fork

  // Massive hack but the only way I could find to update a fork
  // through the API was to create a Pull Request then merge it. Fails
  // if there's already a pull request.
  updateFork: function (originUser, forkUser, repo, branch) {
    var me = this;
    return this.post(
      "/repos/{user}/{repo}/pulls",
      {user: forkUser, repo: repo},
      {
        title: "Update from origin",
        head: originUser + ":" + branch,
        base: branch,
        body: "Update from origin"
      })
      .then(function (response) {
        return me.put(
          "/repos/{user}/{repo}/pulls/{number}/merge",
          {user: forkUser, repo: repo, number: response.body.number},
          {
            commit_message: "Merge from upstream"
          });
      });
  },

  createBranch: function (user, repo, baseBranch, newBranch) {
    var me = this;
    return this.get(
      "/repos/{user}/{repo}/git/refs/heads/{branch}",
      {user: user, repo: repo, branch: baseBranch})
      .then(function (response) {
        var sha = response.body.object.sha;
        return me.post(
          "/repos/{user}/{repo}/git/refs",
          {user: user, repo: repo},
          {
            ref: "refs/heads/" + newBranch,
            sha: sha
          });
      });
  },

  editFile: function (user, repo, branch, path, commitMessage, editCallback) {
    var me = this;
    var sha;

    if (path[0] === '/') {
      path = path.slice(1);
    }

    return this.get(
      "/repos/{user}/{repo}/contents/{+path}",
      {user: user, repo: repo, branch: branch, path: path})
      .then(function (response) {
        var oldContent = new Buffer(response.body.content, 'base64');
        sha = response.body.sha;
        return editCallback(oldContent);
      })
      .then(function (newContent) {
        return me.put(
          "/repos/{user}/{repo}/contents/{+path}",
          {user: user, repo: repo, branch: branch, path: path},
          {
            path: path,
            message: commitMessage || "no commit message",
            content: newContent.toString('base64'),
            sha: sha,
            branch: branch
          });
        // TODO: Handle the case where the file changed between
        // getting it and saving it and retry (see issue #21)
      });
  },

  createPullRequest: function (sourceUser, repo, sourceBranch, targetUser, targetBranch, title, body) {
    return this.post(
      "/repos/{user}/{repo}/pulls",
      {user: targetUser, repo: repo},
      {
        head: sourceUser + ":" + sourceBranch,
        base: targetBranch,
        title: title,
        body: body
      })
      .then(function (response) {
        return response.body;
      });
  },

  getPullRequest: function (user, repo, pullRequestNumber) {
    return this.get(
      "/repos/{user}/{repo}/pulls/{pr}",
      {user: user, repo: repo, pr: pullRequestNumber})
    .then(function (response) {
      if (response.statusCode !== 200) {
          throw new Error("Got unexpected status code when getting pull request data: " + response.statusCode);
      }
      return response.body;
    });
  },

  getRepo: function (user, repo) {
    return this.get(
      "/repos/{user}/{repo}",
      {user: user, repo: repo})
    .then(function (response) {
      if (response.statusCode !== 200) {
          throw new Error("Got unexpected status code when getting repository: " + response.statusCode);
      }
      return response.body;
    });
  }
};
<commit_msg>Retrieve base copy of post file from the correct branch instead of always from master<commit_after>var request = require('request');
var template = require('url-template');
var RSVP = require('rsvp');

module.exports = GithubClient;

// Responsible for interacting with Github. This isn't a complete
// Github client right now, it just does a set of things needed for
// the Hubbub project.
function GithubClient (user, auth) {
  this.user = user;
  this.auth = auth;
}

function getBody(ressponse) {
  return response.body;
}

GithubClient.prototype = {

  // The request library's main function promisified, easy to overide
  // for tests
  _request: function (options) {
    var me = this;
    return new RSVP.Promise(function (resolve, reject) {
      request(options, function (err, response, body) {
        if (err) {
          reject(err);
        } else {
          response.body = body;
          resolve(response);
        }
      });
    });
  },

  request: function (method, url, params, body) {
    var me = this;
    url = template.parse("https://api.github.com" + url).expand(params);
    // console.log('------------');
    // console.log(body);
    // console.log('requests', url);
    var options = {
      method: method,
      url: url,
      json: true,
      body: body,
      auth: me.auth,
      headers: {
        'User-Agent': 'hubbub'
      }
    };

    return this._request(options)
      .then(function (response) {
        // Turn all responses with status codes 400 and above into
        // errors on the promise
        if (response.statusCode >= 400) {
          throw (response);
        } else {
          return response;
        }
      });
  },

  get: function (url, params) {
    return this.request('GET', url, params, null);
  },

  post: function (url, params, body) {
    return this.request('POST', url, params, body);
  },

  put: function (url, params, body) {
    return this.request('PUT', url, params, body);
  },

  "delete": function (url, params) {
    return this.request('DELETE', url, params, null);
  },

  // Create a new fork of a repo (on the authenticated user's
  // account). Forks are created asynchronously.
  createFork: function (user, repo) {
    return this.post('/repos/{user}/{repo}/forks', {user: user, repo: repo})
      .then(function (response) {
        if (response.statusCode !== 202) {
          throw new Error("Got unexpected status code when creating fork: " + response.statusCode);
        }
        return response;
      });
  },

  // Update origin-fork

  // Massive hack but the only way I could find to update a fork
  // through the API was to create a Pull Request then merge it. Fails
  // if there's already a pull request.
  updateFork: function (originUser, forkUser, repo, branch) {
    var me = this;
    return this.post(
      "/repos/{user}/{repo}/pulls",
      {user: forkUser, repo: repo},
      {
        title: "Update from origin",
        head: originUser + ":" + branch,
        base: branch,
        body: "Update from origin"
      })
      .then(function (response) {
        return me.put(
          "/repos/{user}/{repo}/pulls/{number}/merge",
          {user: forkUser, repo: repo, number: response.body.number},
          {
            commit_message: "Merge from upstream"
          });
      });
  },

  createBranch: function (user, repo, baseBranch, newBranch) {
    var me = this;
    return this.get(
      "/repos/{user}/{repo}/git/refs/heads/{branch}",
      {user: user, repo: repo, branch: baseBranch})
      .then(function (response) {
        var sha = response.body.object.sha;
        return me.post(
          "/repos/{user}/{repo}/git/refs",
          {user: user, repo: repo},
          {
            ref: "refs/heads/" + newBranch,
            sha: sha
          });
      });
  },

  editFile: function (user, repo, branch, path, commitMessage, editCallback) {
    var me = this;
    var sha;

    if (path[0] === '/') {
      path = path.slice(1);
    }

    return this.get(
      "/repos/{user}/{repo}/contents/{+path}?ref={branch}",
      {user: user, repo: repo, branch: branch, path: path})
      .then(function (response) {
        var oldContent = new Buffer(response.body.content, 'base64');
        sha = response.body.sha;
        return editCallback(oldContent);
      })
      .then(function (newContent) {
        return me.put(
          "/repos/{user}/{repo}/contents/{+path}",
          {user: user, repo: repo, branch: branch, path: path},
          {
            path: path,
            message: commitMessage || "no commit message",
            content: newContent.toString('base64'),
            sha: sha,
            branch: branch
          });
        // TODO: Handle the case where the file changed between
        // getting it and saving it and retry (see issue #21)
      });
  },

  createPullRequest: function (sourceUser, repo, sourceBranch, targetUser, targetBranch, title, body) {
    return this.post(
      "/repos/{user}/{repo}/pulls",
      {user: targetUser, repo: repo},
      {
        head: sourceUser + ":" + sourceBranch,
        base: targetBranch,
        title: title,
        body: body
      })
      .then(function (response) {
        return response.body;
      });
  },

  getPullRequest: function (user, repo, pullRequestNumber) {
    return this.get(
      "/repos/{user}/{repo}/pulls/{pr}",
      {user: user, repo: repo, pr: pullRequestNumber})
    .then(function (response) {
      if (response.statusCode !== 200) {
          throw new Error("Got unexpected status code when getting pull request data: " + response.statusCode);
      }
      return response.body;
    });
  },

  getRepo: function (user, repo) {
    return this.get(
      "/repos/{user}/{repo}",
      {user: user, repo: repo})
    .then(function (response) {
      if (response.statusCode !== 200) {
          throw new Error("Got unexpected status code when getting repository: " + response.statusCode);
      }
      return response.body;
    });
  }
};
<|endoftext|>


<commit_before>const crypto = require('crypto')
const debug = require('debug')('github')

const secret = process.env.GITHUB_WEBHOOK_SECRET || 'hush-hush'

const sign = (secret, data) => {
  const buffer = new Buffer(data, 'utf8')
  return 'sha1=' + crypto.createHmac('sha1', secret).update(buffer).digest('hex')
}

module.exports = (app) => {
  app.post('/hooks/github', (req, res) => {
    const event = req.headers['x-github-event']
    if (!event) {
      res.writeHead(400, 'Event Header Missing')
      return res.end()
    }

    const signature = req.headers['x-hub-signature']
    if (!signature || signature !== sign(secret, req.raw)) {
      res.writeHead(401, 'Invalid Signature')
      return res.end()
    }

    res.end()

    const data = req.body
    data.action = data.action ? event + '.' + data.action : event

    var source = data.repository ? data.repository.full_name : data.organization.login
    console.log('event@%s: %s', source, data.action)

    if (debug.enabled) {
      debug(JSON.stringify(data, null, 2))
    }

    app.emit(data.action, data)
  })
}
<commit_msg>Log when we've got requests with invalid secrets<commit_after>const crypto = require('crypto')
const debug = require('debug')('github')

const secret = process.env.GITHUB_WEBHOOK_SECRET || 'hush-hush'

const sign = (secret, data) => {
  const buffer = new Buffer(data, 'utf8')
  return 'sha1=' + crypto.createHmac('sha1', secret).update(buffer).digest('hex')
}

module.exports = (app) => {
  app.post('/hooks/github', (req, res) => {
    const event = req.headers['x-github-event']
    if (!event) {
      res.writeHead(400, 'Event Header Missing')
      return res.end()
    }

    const signature = req.headers['x-hub-signature']
    if (!signature || signature !== sign(secret, req.raw)) {
      res.writeHead(401, 'Invalid Signature')
      console.error('! event@%s: %s - invalid signature, returning 401', source, data.action)
      return res.end()
    }

    res.end()

    const data = req.body
    data.action = data.action ? event + '.' + data.action : event

    var source = data.repository ? data.repository.full_name : data.organization.login
    console.log('event@%s: %s', source, data.action)

    if (debug.enabled) {
      debug(JSON.stringify(data, null, 2))
    }

    app.emit(data.action, data)
  })
}
<|endoftext|>


<commit_before>var path = require('path');
var fs = require('fs');
var machine = require('./machine').machine;
var settings = require('./settings');
var db = require('./db');
var File=db.File; // link to the files database collection
var PLATFORM = require('process').platform;

ALLOWED_EXTENSIONS = ['.nc','.g','.sbp','.gc','.gcode'];

function allowed_file(filename){
	if (ALLOWED_EXTENSIONS.indexOf(path.extname(filename).toLowerCase()) !== -1)
	{
		return true;
	}
	else {
		return false;
	}
};

exports.get_files = function(req, res, next) {
	File.list_all(function(result){
		res.json({'files':result});
});
};

exports.upload_file = function(req, res, next) {
	var file = req.files.file;
    if(file && allowed_file(file.name))
    {
    	var filename=file.name;
    	console.log("Saving: " + filename);
       	var full_path = path.join(settings.upload_dir, filename);
       	console.log(full_path);
       	fs.rename(file.path, full_path, function(err) {
       		if (err){
       			throw err;
       		}
        	// delete the temporary file, so that the explicitly set temporary upload dir does not get filled with unwanted files
        	fs.unlink(file.path, function() {
        		if (err) {throw err;}
        		new File(filename, full_path).save(function(file){
				res.send(302,file); // file saved
			}); //save in db

        	});
        });
    }
    else if (file){
	res.send(415); // wrong format
    }
    else{
	res.send(400);// problem reciving the file (bad request)
    }
};

exports.delete_file = function(req, res, next) {
	console.log('Deleting file');
	File.get_by_id(req.params.id,function(file){
		if(file)
		{
			fs.unlink(file.path, function(){ //delete file on hdd
				file.delete(function(){res.send(204);}); // delete file in db

			});
		}
		else
		{
			console.log("file not found ! cannot delete");
			res.send(404);
		}
	});

};

exports.download_file = function(req, res, next) {
	File.get_by_id(req.params.id,function(file){
		if(!file){res.send(404);return;}
		console.log('Downloading file');
		fs.readFile((file.path),function (err, data){
			if (err) throw err;
			res.header('Content-Description','File Transfer');
			res.header('Content-Type','application/octet-stream');
			res.header('Content-Disposition','attachment; filename='+file.filename);
			res.header('Content-Transfer-Encoding','binary');
			res.header('Expires', 0);
			res.header('Cache-Control','must-revalidate, post-check=0, pre-check=0');
			res.header('Pragma','public');
			res.header('Content-Length', file.size);
			res.header('Location', req.headers['referer']);
			res.send(data.toString());
		});
	});

};

<commit_msg>Update files_module_handlers.js<commit_after>var path = require('path');
var fs = require('fs');
var machine = require('./machine').machine;
var settings = require('./settings');
var db = require('./db');
var File=db.File; // link to the files database collection

ALLOWED_EXTENSIONS = ['.nc','.g','.sbp','.gc','.gcode'];

function allowed_file(filename){
	if (ALLOWED_EXTENSIONS.indexOf(path.extname(filename).toLowerCase()) !== -1)
	{
		return true;
	}
	else {
		return false;
	}
};

exports.get_files = function(req, res, next) {
	File.list_all(function(result){
		res.json({'files':result});
});
};

exports.upload_file = function(req, res, next) {
	var file = req.files.file;
    if(file && allowed_file(file.name))
    {
    	var filename=file.name;
    	console.log("Saving: " + filename);
       	var full_path = path.join(settings.upload_dir, filename);
       	console.log(full_path);
       	fs.rename(file.path, full_path, function(err) {
       		if (err){
       			throw err;
       		}
        	// delete the temporary file, so that the explicitly set temporary upload dir does not get filled with unwanted files
        	fs.unlink(file.path, function() {
        		if (err) {throw err;}
        		new File(filename, full_path).save(function(file){
				res.send(302,file); // file saved
			}); //save in db

        	});
        });
    }
    else if (file){
	res.send(415); // wrong format
    }
    else{
	res.send(400);// problem reciving the file (bad request)
    }
};

exports.delete_file = function(req, res, next) {
	console.log('Deleting file');
	File.get_by_id(req.params.id,function(file){
		if(file)
		{
			fs.unlink(file.path, function(){ //delete file on hdd
				file.delete(function(){res.send(204);}); // delete file in db

			});
		}
		else
		{
			console.log("file not found ! cannot delete");
			res.send(404);
		}
	});

};

exports.download_file = function(req, res, next) {
	File.get_by_id(req.params.id,function(file){
		if(!file){res.send(404);return;}
		console.log('Downloading file');
		fs.readFile((file.path),function (err, data){
			if (err) throw err;
			res.header('Content-Description','File Transfer');
			res.header('Content-Type','application/octet-stream');
			res.header('Content-Disposition','attachment; filename='+file.filename);
			res.header('Content-Transfer-Encoding','binary');
			res.header('Expires', 0);
			res.header('Cache-Control','must-revalidate, post-check=0, pre-check=0');
			res.header('Pragma','public');
			res.header('Content-Length', file.size);
			res.header('Location', req.headers['referer']);
			res.send(data.toString());
		});
	});

};

<|endoftext|>


<commit_before>$(function () {
  $.getJSON('https://represent.opennorth.ca/boundary-sets/?limit=0', function (data) {
    var boundary_sets = {}
      , provinces_key = gettext('Provincial legislatures')
      , iterations = {
          'elections': 'Candidates'
        , 'representative-sets': 'Representatives'
      }, key_map = {
          'NL': gettext('Newfoundland and Labrador councils')
        , 'PE': gettext('Prince Edward Island councils')
        , 'NS': gettext('Nova Scotia councils')
        , 'NB': gettext('New Brunswick councils')
        , 'QC': gettext('Quebec councils')
        , 'ON': gettext('Ontario councils')
        , 'MB': gettext('Manitoba councils')
        , 'SK': gettext('Saskatchewan councils')
        , 'AB': gettext('Alberta councils')
        , 'BC': gettext('British Columbia councils')
        , 'YT': gettext('Yukon councils')
        , 'NT': gettext('Northwest Territories councils')
        , 'NU': gettext('Nunavut councils')
      }, uncategorized_map = {
          '/elections/house-of-commons/': 'Canada'
        , '/representative-sets/house-of-commons/': 'Canada'
        , '/representative-sets/new-brunswick-municipal-councils/': 'NB'
        , '/representative-sets/conseil-municipal-de-montreal/': 'QC'
        , '/representative-sets/grande-prairie-city-council/': 'AB'
        , '/representative-sets/lethbridge-city-council/': 'AB'
        // Ontario
        , '/representative-sets/georgina-town-council/': 'ON'
        , '/representative-sets/lambton-county-council/': 'ON'
        , '/representative-sets/lasalle-town-council/': 'ON'
        , '/representative-sets/niagara-regional-council/': 'ON'
        , '/representative-sets/oshawa-city-council/': 'ON'
        , '/representative-sets/peel-regional-council/': 'ON'
        , '/representative-sets/waterloo-regional-council/': 'ON'
        , '/representative-sets/whitchurch-stouffville-town-council/': 'ON'
        , '/representative-sets/uxbridge-township-council/': 'ON'
        // British Columbia
        , '/representative-sets/abbotsford-city-council/': 'BC'
        , '/representative-sets/burnaby-city-council/': 'BC'
        , '/representative-sets/coquitlam-city-council/': 'BC'
        , '/representative-sets/kelowna-city-council/': 'BC'
        , '/representative-sets/langley-township-council/': 'BC'
        , '/representative-sets/langley-city-council/': 'BC'
        , '/representative-sets/richmond-city-council/': 'BC'
        , '/representative-sets/saanich-district-council/': 'BC'
        , '/representative-sets/surrey-city-council/': 'BC'
        , '/representative-sets/vancouver-city-council/': 'BC'
        , '/representative-sets/victoria-city-council/': 'BC'
      };

    $.each(data.objects, function (i, boundary_set) {
      boundary_sets[boundary_set.url] = boundary_set.domain.split(', ')[1];
    });

    $.each(iterations, function (endpoint, label) {
      var path = label.toLowerCase()
        , field = path + '_url';

      $.getJSON('https://represent.opennorth.ca/' + endpoint + '/?limit=0', function (data) {
        var sets = {}
          , keys = []
          , key
          , i
          , l
          , j
          , m
          , list
          , $ul;

        if (label === 'Representatives') {
          sets['Canada'] = ['
' + gettext('All elected officials') + '
'];
        }

        $.each(data.objects, function (i, set) {
          var basename;

          if (set.url.indexOf('/campaign-set-') === -1) {
            key = boundary_sets[set.related.boundary_set_url];
            if (!key) {
              if (/Assembl/.test(set.name)) {
                key = provinces_key;
              }
              else {
                key = uncategorized_map[set.url] || gettext('Uncategorized');
              }
            }
            if (!sets[key]) {
              sets[key] = [];
            }
            basename = set.related[field].split('/')[2];
            // Exception.
            if (field == 'candidates_url' && basename == 'legislative-assembly-of-british-columbia') {
              basename = 'bc-legislature';
            }
            sets[key].push('
' + set.name + '
');
          }
        });

        for (key in sets) {
          if (sets.hasOwnProperty(key)) {
            keys.push(key);
          }
        }

        keys.sort();
        $.each([provinces_key, 'Canada'], function (i, key) {
          var index = $.inArray(key, keys);
          if (index > 0) {
            keys.splice(index, 1);
            keys.unshift(key);
          }
        });

        $('#downloads').append('
' + gettext(label) + '
');
        for (i = 0, l = keys.length; i < l; i++) {
          key = keys[i];
          console.log(key);
          console.log(sets);
          list = sets[key];
          list.sort();

          if (key != 'Canada') {
            $('#downloads').append('
' + (key_map[key] || key) + '
');
          }
          $ul = $('

');
          for (j = 0, m = list.length; j < m; j++) {
            $ul.append($(list[j]));
          }
          $('#downloads').append($ul);
        }
      });
    });

    $('#loading').remove();
  });
});
<commit_msg>Exclude province-wide collections of municipal councils from downloads, as scrapers_ca_app doesn't prepare CSVs for those, closes #110<commit_after>$(function () {
  $.getJSON('https://represent.opennorth.ca/boundary-sets/?limit=0', function (data) {
    var boundary_sets = {}
      , provinces_key = gettext('Provincial legislatures')
      , iterations = {
          'elections': 'Candidates'
        , 'representative-sets': 'Representatives'
      }, key_map = {
          'NL': gettext('Newfoundland and Labrador councils')
        , 'PE': gettext('Prince Edward Island councils')
        , 'NS': gettext('Nova Scotia councils')
        , 'NB': gettext('New Brunswick councils')
        , 'QC': gettext('Quebec councils')
        , 'ON': gettext('Ontario councils')
        , 'MB': gettext('Manitoba councils')
        , 'SK': gettext('Saskatchewan councils')
        , 'AB': gettext('Alberta councils')
        , 'BC': gettext('British Columbia councils')
        , 'YT': gettext('Yukon councils')
        , 'NT': gettext('Northwest Territories councils')
        , 'NU': gettext('Nunavut councils')
      }, uncategorized_map = {
          '/elections/house-of-commons/': 'Canada'
        , '/representative-sets/house-of-commons/': 'Canada'
        , '/representative-sets/conseil-municipal-de-montreal/': 'QC'
        , '/representative-sets/grande-prairie-city-council/': 'AB'
        , '/representative-sets/lethbridge-city-council/': 'AB'
        // Ontario
        , '/representative-sets/georgina-town-council/': 'ON'
        , '/representative-sets/lambton-county-council/': 'ON'
        , '/representative-sets/lasalle-town-council/': 'ON'
        , '/representative-sets/niagara-regional-council/': 'ON'
        , '/representative-sets/oshawa-city-council/': 'ON'
        , '/representative-sets/peel-regional-council/': 'ON'
        , '/representative-sets/waterloo-regional-council/': 'ON'
        , '/representative-sets/whitchurch-stouffville-town-council/': 'ON'
        , '/representative-sets/uxbridge-township-council/': 'ON'
        // British Columbia
        , '/representative-sets/abbotsford-city-council/': 'BC'
        , '/representative-sets/burnaby-city-council/': 'BC'
        , '/representative-sets/coquitlam-city-council/': 'BC'
        , '/representative-sets/kelowna-city-council/': 'BC'
        , '/representative-sets/langley-township-council/': 'BC'
        , '/representative-sets/langley-city-council/': 'BC'
        , '/representative-sets/richmond-city-council/': 'BC'
        , '/representative-sets/saanich-district-council/': 'BC'
        , '/representative-sets/surrey-city-council/': 'BC'
        , '/representative-sets/vancouver-city-council/': 'BC'
        , '/representative-sets/victoria-city-council/': 'BC'
      };

    $.each(data.objects, function (i, boundary_set) {
      boundary_sets[boundary_set.url] = boundary_set.domain.split(', ')[1];
    });

    $.each(iterations, function (endpoint, label) {
      var path = label.toLowerCase()
        , field = path + '_url';

      $.getJSON('https://represent.opennorth.ca/' + endpoint + '/?limit=0', function (data) {
        var sets = {}
          , keys = []
          , key
          , i
          , l
          , j
          , m
          , list
          , $ul;

        if (label === 'Representatives') {
          sets['Canada'] = ['
' + gettext('All elected officials') + '
'];
        }

        $.each(data.objects, function (i, set) {
          var basename;

          if (set.url.indexOf('/campaign-set-') === -1 && set.url.indexOf('-municipal-councils') === -1) {
            key = boundary_sets[set.related.boundary_set_url];
            if (!key) {
              if (/Assembl/.test(set.name)) {
                key = provinces_key;
              }
              else {
                key = uncategorized_map[set.url] || gettext('Uncategorized');
              }
            }
            if (!sets[key]) {
              sets[key] = [];
            }
            basename = set.related[field].split('/')[2];
            // Exception.
            if (field == 'candidates_url' && basename == 'legislative-assembly-of-british-columbia') {
              basename = 'bc-legislature';
            }
            sets[key].push('
' + set.name + '
');
          }
        });

        for (key in sets) {
          if (sets.hasOwnProperty(key)) {
            keys.push(key);
          }
        }

        keys.sort();
        $.each([provinces_key, 'Canada'], function (i, key) {
          var index = $.inArray(key, keys);
          if (index > 0) {
            keys.splice(index, 1);
            keys.unshift(key);
          }
        });

        $('#downloads').append('
' + gettext(label) + '
');
        for (i = 0, l = keys.length; i < l; i++) {
          key = keys[i];
          console.log(key);
          console.log(sets);
          list = sets[key];
          list.sort();

          if (key != 'Canada') {
            $('#downloads').append('
' + (key_map[key] || key) + '
');
          }
          $ul = $('

');
          for (j = 0, m = list.length; j < m; j++) {
            $ul.append($(list[j]));
          }
          $('#downloads').append($ul);
        }
      });
    });

    $('#loading').remove();
  });
});
<|endoftext|>


<commit_before>"use strict";
var inherits = require('util').inherits;
var ValidatingHandler = require('./core/validating_handler');

var Data = function (dataSpec) {
	ValidatingHandler.call(this, dataSpec);
};
inherits(Data, ValidatingHandler);

Data.prototype.name = 'Data';

Data.prototype.handleRequest = function (ctx) {
	var data;
	if (ctx.mechanicsCtx.hasBody) {
		if (ctx.mechanicsCtx.isBodyParsed) {
			data = ctx.mechanicsCtx.body;
		}
		else if (ctx.mechanicsCtx.body) {
			data = JSON.parse(ctx.mechanicsCtx.body);
		}
	}
	else if (ctx.mechanicsCtx.req != null) {
		var req = ctx.mechanicsCtx.req;
		var json = req.query._json;
		if (json) {
			data = JSON.parse(json);
		}
		else {
			data = req.body;
		}
	}

	var error = this.validate(ctx, data);
	if (error) {
		ctx.error(error);
	}
	else {
		ctx.data = data;
		ctx.next();
	}
};

Data.data = function (dataSpec) {
	return new Data(dataSpec);
};

module.exports = Data;
<commit_msg>_json query arg renamed to 'data'<commit_after>"use strict";
var inherits = require('util').inherits;
var ValidatingHandler = require('./core/validating_handler');

var Data = function (dataSpec) {
	ValidatingHandler.call(this, dataSpec);
};
inherits(Data, ValidatingHandler);

Data.prototype.name = 'Data';

Data.prototype.handleRequest = function (ctx) {
	var data;
	if (ctx.mechanicsCtx.hasBody) {
		if (ctx.mechanicsCtx.isBodyParsed) {
			data = ctx.mechanicsCtx.body;
		}
		else if (ctx.mechanicsCtx.body) {
			data = JSON.parse(ctx.mechanicsCtx.body);
		}
	}
	else if (ctx.mechanicsCtx.req != null) {
		var req = ctx.mechanicsCtx.req;
		var queryData = req.query.data;
		if (queryData) {
			data = JSON.parse(queryData);
		}
		else {
			data = req.body;
		}
	}

	var error = this.validate(ctx, data);
	if (error) {
		ctx.error(error);
	}
	else {
		ctx.data = data;
		ctx.next();
	}
};

Data.data = function (dataSpec) {
	return new Data(dataSpec);
};

module.exports = Data;
<|endoftext|>


<commit_before>var geolocate_supported = true; // until prove false

var geocoder = new google.maps.Geocoder();
var southwest_limit = new L.LatLng(32.1342, -95.6219);
var northeast_limit = new L.LatLng(32.6871, -94.9844);
var bounding_box = new L.LatLngBounds(southwest_limit, northeast_limit);
var outside = false; // until prove true

var map = null;

var user_marker = null;
var displayed_slug = null;
var displayed_polygon = null;
var smith_county_polygon = null;

var boundaries = new Array();

function init_map(lat, lng) {
    if (map == null) {
        var ll = new L.LatLng(lat, lng);

        map = new L.Map('map_canvas', {
            zoom: 14,
            center: ll,
        });

        tiles = new L.TileLayer("http://mt1.google.com/vt/lyrs=m@155000000&hl=en&x={x}&y={y}&z={z}&s={s}", {
            maxZoom: 17,
            attribution: "Map data is Copyright Google, 2011"
        });

        map.addLayer(tiles);
    }

    var center = new L.LatLng(lat, lng);
    map.panTo(center);

    check_for_locale(center);
    resize_listener(center);

    display_smith_county();
}

function show_user_marker(lat, lng) {
    var ll = new L.LatLng(lat, lng);

    if (user_marker != null) {
        map.removeLayer(user_marker);
        user_marker = null;
    }

    user_marker = new L.Marker(ll, { draggable: true });
    map.addLayer(user_marker);

    user_marker.on('dragend', function() {
        ll = user_marker.getLatLng();
        geocode(L.LatLng(ll.lat, ll.lng))
    });
}

function geocode(query) {
    if (typeof(query) == 'string') {
        pattr = /\stx\s|\stexas\s/gi;
        match = query.match(pattr);
        if (!match) {
            query = query + ' TX';
        }
        gr = { 'address': query };
    } else {
        gr = { 'location': new google.maps.LatLng(ll.lat, ll.lng) };
    }
    geocoder.geocode(gr, handle_geocode);
}

function handle_geocode(results, status) {
    alt_addresses(results);

    lat = results[0].geometry.location.lat();
    lng = results[0].geometry.location.lng();

    last_location = [lat, lng];

    normalized_address = results[0].formatted_address;
    $('#location-form #address').val(normalized_address);

    process_location(lat, lng);
    save_last_location(last_location);
}

function geolocate() {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(geolocation_success, geolocation_error);
    } else {
        use_default_location();

        $('#resultinfo').html('Your browser does not support automatically determining your location so we\'re showing you Tyler Public Library.');

        geolocate_supported = false;
    }
}

function geolocation_success(position) {
    process_location(position.coords.latitude, position.coords.longitude)
    ll = new L.LatLng(position.coords.latitude, position.coords.longitude);

    geocode(ll);
    check_for_locale(ll);
    hide_search()
}

function geolocation_error() {
    use_default_location();

    $('#resultinfo').html('Your browser does not support automatically determining your location so we\'re showing you Tyler Public Library.');
}

function process_location(lat, lng) {
    $('#resultinfo').html(
        'Latitude: ' + lat + '
' +
        'Longitude: ' + lng + '
'
    );

    init_map(lat, lng);
    show_user_marker(lat, lng);
    get_boundaries(lat, lng);
}

function save_last_location(location) {
    store.set('last_location', location);
}

function get_last_location() {
    last_location = store.get('last_location');
    return last_location;
}

function clear_last_location() {
    store.remove('last_location');
}

function check_saved_location() {
    last_location = get_last_location();
    if (last_location) {
        return true;
    } else {
        return false;
    }
}

function check_for_locale(center) {
    var temp = new L.LatLngBounds(center, center);

    if (!bounding_box.contains(temp) && window.location.hash == "#demo") {
        show_outside();
        outside = true;
    } else {
        hide_outside();
        outside = false;
    }
}

function alt_addresses(results) {
    $('#alt-addresses').html('');

    keep = new Array();

    $.each(results, function(i,val) {
        if (i==0) return; // skip the first result

        for (var t in val.types) {
            if (val.types[t] == 'street_address' || val.types[t] == 'intersection') {
                keep.push(val.formatted_address);
                break;
            }
        }
    });

    if (keep.length <= 1) {
        $('#did-you-mean')
            .addClass('disabled-link')
            .unbind();
    } else {
        $('#did-you-mean')
            .removeClass('disabled-link')
            .click(function(e) {
                    e.stopPropagation();
                    toggle_alt_addresses();
                    });

        for (var i in keep) {
            $('#alt-addresses').append('' + keep[i] + '
');
        }
    }
}

// Use boundary service to lookup what areas the location falls within
function get_boundaries(lat, lng) {
    var table_html = '
This location is within:

';
    var query_url = 'http://{{ settings.API_DOMAIN }}/1.0/boundary/?format=jsonp&limit=100&contains='+lat+','+lng+'&callback=?';

    displayed_kind = null;
    for_display = null;

    if (displayed_polygon != null) {
        // Hide old polygon
        displayed_kind = boundaries[displayed_slug].kind;
        displayed_polygon.setMap(null);
        displayed_polygon = null;
        displayed_slug = null;
    }

    // Clear old boundaries
    boundaries.length = 0;

    $.getJSON(query_url, function(data) {
        $.each(data.objects, function(i, obj) {
            boundaries[obj.slug] = obj;
            table_html += '
' + obj.kind + '	' + obj.name + '		';

            // Try to display a new polygon of the same kind as the last shown
            if (displayed_kind != null && obj.kind == displayed_kind) {
                for_display = obj;
            }
        });
        table_html += '
';
        $('#area-lookup').html(table_html);

        if (for_display != null) {
            display_boundary(for_display.slug, true);
        }
    });
}

function display_boundary(slug, no_fit) {
    // Clear old polygons
    if (displayed_polygon != null) {
        displayed_polygon.setMap(null);
        displayed_polygon = null;
        displayed_slug = null;

        $("#boundaries .selected").removeClass("selected");
    }

    // Construct new polygons
    var coords = boundaries[slug]["simple_shape"].coordinates;
    var paths = [];
    var bounds = new L.LatLngBounds();

    $.each(coords, function(i, n){
        $.each(n, function(j, o){
            var path = [];

            $.each(o, function(k,p){
                var ll = new L.LatLng(p[1], p[0]);
                path.push(ll);
                bounds.extend(ll);
            });

            paths.push(path);
        });
    });

    displayed_polygon = new L.Polygon(paths, {
        color: "#244f79",
        opacity: 0.8,
        weight: 3,
        fill: true,
        fillColor: "#244f79",
        fillOpacity: 0.2
    });

    displayed_slug = slug;
    displayed_polygon.setMap(map);

    $("#boundaries #" + slug).addClass("selected");

    if (!no_fit) {
        map.fitBounds(bounds);
    }
}

function display_smith_county() {
    // Construct new polygons
    var paths = [];

    $.each(SMITH_COUNTY['features'][0]['geometry']['coordinates'], function(i, n){
        var path = [];

        $.each(n, function(k, p){
            var ll = new L.LatLng(p[1], p[0]);
            path.push(ll);
        });

        paths.push(path);
    });

    smith_county_polygon = new L.Polygon(paths, {
        color: "#000000",
        opacity: 1.0,
        weight: 2,
        fill: false
    });

    map.addLayer(smith_county_polygon);
}

function show_search() {
    $('#not-where-i-am').hide();
    if (geolocate_supported) { $('#use-current-location').fadeIn(); }
    $('#did-you-mean').fadeIn();
    $('#location-form').slideDown();
}

function hide_search() {
    $('#not-where-i-am').show();
    $('#use-current-location').hide()
    $('#location-form').slideUp();
}

function switch_page(page_id) {
    $(".page-content").hide()
    $("#" + page_id + "-page").show()
    window.location.hash = page_id

    if (window.location.hash == "#demo") {
        if (outside) {
            show_outside();
        }

        resize_end_trigger();

        if (!map) {
            if (check_saved_location()) {
                last_location = store.get('last_location');
                geocode(new L.LatLng(last_location[0], last_location[1]));
            } else {
                geolocate();
            }
        }
    } else {
        hide_outside();
    }
}

function show_outside() {
    $('#outside').fadeIn(500);
}

function hide_outside() {
    $('#outside').fadeOut(250);
}

/* DOM EVENT HANDLERS */
function resize_listener(center) {
    $(this).bind('resize_end', function(){
        if (map) {
            map.panTo(center);
        }
    });
}

function resize_end_trigger() {
    $(window).resize(function() {
        if (this.resizeto) {
            clearTimeout(this.resizeto)
            };

        this.resizeto = setTimeout(function() {
            $(this).trigger('resize_end');
            }, 500);
    });
}

function not_where_i_am() {
    show_search();
}

function use_current_location() {
    geolocate();
}

function use_default_location() {
    process_location(32.349549, -95.301829);
}

function toggle_alt_addresses() {
    alt_adds_div = $('#alt-addresses');
    if (alt_adds_div.is(':hidden')) {
        show_alt_addresses();
    } else if (alt_adds_div.is(':visible')) {
        hide_alt_addresses();
    }
}

function show_alt_addresses() {
    $('#alt-addresses').slideDown(250);
    $('#did-you-mean').addClass('highlight');
}

function hide_alt_addresses() {
    $('#alt-addresses').hide();
    $('#did-you-mean.highlight').removeClass('highlight');
}

function search_focused() {
    if(this.value == '{{ default_search_text }}') {
        $(this).val("");
    }
}

function address_search() {
    geocode($("#location-form #address").val());

    return false;
}

$(document).ready(function() {
    // Setup handlers
    $('body').click(hide_alt_addresses);
    $('#not-where-i-am').click(not_where_i_am);
    $('#use-current-location').click(use_current_location);
    $('#use-default-location').click(use_default_location);
    $('#did-you-mean').click(function(e) { e.stopPropagation(); toggle_alt_addresses(); });
    $('#location-form input[type=text]').focus(search_focused);
    $('#location-form').submit(address_search)

    if (window.location.hash != "") {
        switch_page(window.location.hash.substring(1));
    } else {
        switch_page("demo");
    }
});

<commit_msg>Removed jsonp from boundary calls.<commit_after>var geolocate_supported = true; // until prove false

var geocoder = new google.maps.Geocoder();
var southwest_limit = new L.LatLng(32.1342, -95.6219);
var northeast_limit = new L.LatLng(32.6871, -94.9844);
var bounding_box = new L.LatLngBounds(southwest_limit, northeast_limit);
var outside = false; // until prove true

var map = null;

var user_marker = null;
var displayed_slug = null;
var displayed_polygon = null;
var smith_county_polygon = null;

var boundaries = new Array();

function init_map(lat, lng) {
    if (map == null) {
        var ll = new L.LatLng(lat, lng);

        map = new L.Map('map_canvas', {
            zoom: 14,
            center: ll,
        });

        tiles = new L.TileLayer("http://mt1.google.com/vt/lyrs=m@155000000&hl=en&x={x}&y={y}&z={z}&s={s}", {
            maxZoom: 17,
            attribution: "Map data is Copyright Google, 2011"
        });

        map.addLayer(tiles);
    }

    var center = new L.LatLng(lat, lng);
    map.panTo(center);

    check_for_locale(center);
    resize_listener(center);

    display_smith_county();
}

function show_user_marker(lat, lng) {
    var ll = new L.LatLng(lat, lng);

    if (user_marker != null) {
        map.removeLayer(user_marker);
        user_marker = null;
    }

    user_marker = new L.Marker(ll, { draggable: true });
    map.addLayer(user_marker);

    user_marker.on('dragend', function() {
        ll = user_marker.getLatLng();
        geocode(L.LatLng(ll.lat, ll.lng))
    });
}

function geocode(query) {
    if (typeof(query) == 'string') {
        pattr = /\stx\s|\stexas\s/gi;
        match = query.match(pattr);
        if (!match) {
            query = query + ' TX';
        }
        gr = { 'address': query };
    } else {
        gr = { 'location': new google.maps.LatLng(query.lat, query.lng) };
    }
    geocoder.geocode(gr, handle_geocode);
}

function handle_geocode(results, status) {
    alt_addresses(results);

    lat = results[0].geometry.location.lat();
    lng = results[0].geometry.location.lng();

    last_location = [lat, lng];

    normalized_address = results[0].formatted_address;
    $('#location-form #address').val(normalized_address);

    process_location(lat, lng);
    save_last_location(last_location);
}

function geolocate() {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(geolocation_success, geolocation_error);
    } else {
        use_default_location();

        $('#resultinfo').html('Your browser does not support automatically determining your location so we\'re showing you Tyler Public Library.');

        geolocate_supported = false;
    }
}

function geolocation_success(position) {
    process_location(position.coords.latitude, position.coords.longitude)
    ll = new L.LatLng(position.coords.latitude, position.coords.longitude);

    geocode(ll);
    check_for_locale(ll);
    hide_search()
}

function geolocation_error() {
    use_default_location();

    $('#resultinfo').html('Your browser does not support automatically determining your location so we\'re showing you Tyler Public Library.');
}

function process_location(lat, lng) {
    $('#resultinfo').html(
        'Latitude: ' + lat + '
' +
        'Longitude: ' + lng + '
'
    );

    init_map(lat, lng);
    show_user_marker(lat, lng);
    get_boundaries(lat, lng);
}

function save_last_location(location) {
    store.set('last_location', location);
}

function get_last_location() {
    last_location = store.get('last_location');
    return last_location;
}

function clear_last_location() {
    store.remove('last_location');
}

function check_saved_location() {
    last_location = get_last_location();
    if (last_location) {
        return true;
    } else {
        return false;
    }
}

function check_for_locale(center) {
    var temp = new L.LatLngBounds(center, center);

    if (!bounding_box.contains(temp) && window.location.hash == "#demo") {
        show_outside();
        outside = true;
    } else {
        hide_outside();
        outside = false;
    }
}

function alt_addresses(results) {
    $('#alt-addresses').html('');

    keep = new Array();

    $.each(results, function(i,val) {
        if (i==0) return; // skip the first result

        for (var t in val.types) {
            if (val.types[t] == 'street_address' || val.types[t] == 'intersection') {
                keep.push(val.formatted_address);
                break;
            }
        }
    });

    if (keep.length <= 1) {
        $('#did-you-mean')
            .addClass('disabled-link')
            .unbind();
    } else {
        $('#did-you-mean')
            .removeClass('disabled-link')
            .click(function(e) {
                    e.stopPropagation();
                    toggle_alt_addresses();
                    });

        for (var i in keep) {
            $('#alt-addresses').append('' + keep[i] + '
');
        }
    }
}

// Use boundary service to lookup what areas the location falls within
function get_boundaries(lat, lng) {
    var table_html = '
This location is within:

';
    var query_url = 'http://{{ settings.API_DOMAIN }}/1.0/boundary/?limit=100&contains=' + lat + ',' + lng + '';

    displayed_kind = null;
    for_display = null;

    if (displayed_polygon != null) {
        // Hide old polygon
        displayed_kind = boundaries[displayed_slug].kind;
        displayed_polygon.setMap(null);
        displayed_polygon = null;
        displayed_slug = null;
    }

    // Clear old boundaries
    boundaries.length = 0;

    $.getJSON(query_url, function(data) {
        $.each(data.objects, function(i, obj) {
            boundaries[obj.slug] = obj;
            table_html += '
' + obj.kind + '	' + obj.name + '		';

            // Try to display a new polygon of the same kind as the last shown
            if (displayed_kind != null && obj.kind == displayed_kind) {
                for_display = obj;
            }
        });
        table_html += '
';
        $('#area-lookup').html(table_html);

        if (for_display != null) {
            display_boundary(for_display.slug, true);
        }
    });
}

function display_boundary(slug, no_fit) {
    // Clear old polygons
    if (displayed_polygon != null) {
        displayed_polygon.setMap(null);
        displayed_polygon = null;
        displayed_slug = null;

        $("#boundaries .selected").removeClass("selected");
    }

    // Construct new polygons
    var coords = boundaries[slug]["simple_shape"].coordinates;
    var paths = [];
    var bounds = new L.LatLngBounds();

    $.each(coords, function(i, n){
        $.each(n, function(j, o){
            var path = [];

            $.each(o, function(k,p){
                var ll = new L.LatLng(p[1], p[0]);
                path.push(ll);
                bounds.extend(ll);
            });

            paths.push(path);
        });
    });

    displayed_polygon = new L.Polygon(paths, {
        color: "#244f79",
        opacity: 0.8,
        weight: 3,
        fill: true,
        fillColor: "#244f79",
        fillOpacity: 0.2
    });

    displayed_slug = slug;
    displayed_polygon.setMap(map);

    $("#boundaries #" + slug).addClass("selected");

    if (!no_fit) {
        map.fitBounds(bounds);
    }
}

function display_smith_county() {
    // Construct new polygons
    var paths = [];

    $.each(SMITH_COUNTY['features'][0]['geometry']['coordinates'], function(i, n){
        var path = [];

        $.each(n, function(k, p){
            var ll = new L.LatLng(p[1], p[0]);
            path.push(ll);
        });

        paths.push(path);
    });

    smith_county_polygon = new L.Polygon(paths, {
        color: "#000000",
        opacity: 1.0,
        weight: 2,
        fill: false
    });

    map.addLayer(smith_county_polygon);
}

function show_search() {
    $('#not-where-i-am').hide();
    if (geolocate_supported) { $('#use-current-location').fadeIn(); }
    $('#did-you-mean').fadeIn();
    $('#location-form').slideDown();
}

function hide_search() {
    $('#not-where-i-am').show();
    $('#use-current-location').hide()
    $('#location-form').slideUp();
}

function switch_page(page_id) {
    $(".page-content").hide()
    $("#" + page_id + "-page").show()
    window.location.hash = page_id

    if (window.location.hash == "#demo") {
        if (outside) {
            show_outside();
        }

        resize_end_trigger();

        if (!map) {
            if (check_saved_location()) {
                last_location = store.get('last_location');
                geocode(new L.LatLng(last_location[0], last_location[1]));
            } else {
                geolocate();
            }
        }
    } else {
        hide_outside();
    }
}

function show_outside() {
    $('#outside').fadeIn(500);
}

function hide_outside() {
    $('#outside').fadeOut(250);
}

/* DOM EVENT HANDLERS */
function resize_listener(center) {
    $(this).bind('resize_end', function(){
        if (map) {
            map.panTo(center);
        }
    });
}

function resize_end_trigger() {
    $(window).resize(function() {
        if (this.resizeto) {
            clearTimeout(this.resizeto)
            };

        this.resizeto = setTimeout(function() {
            $(this).trigger('resize_end');
            }, 500);
    });
}

function not_where_i_am() {
    show_search();
}

function use_current_location() {
    geolocate();
}

function use_default_location() {
    process_location(32.349549, -95.301829);
}

function toggle_alt_addresses() {
    alt_adds_div = $('#alt-addresses');
    if (alt_adds_div.is(':hidden')) {
        show_alt_addresses();
    } else if (alt_adds_div.is(':visible')) {
        hide_alt_addresses();
    }
}

function show_alt_addresses() {
    $('#alt-addresses').slideDown(250);
    $('#did-you-mean').addClass('highlight');
}

function hide_alt_addresses() {
    $('#alt-addresses').hide();
    $('#did-you-mean.highlight').removeClass('highlight');
}

function search_focused() {
    if(this.value == '{{ default_search_text }}') {
        $(this).val("");
    }
}

function address_search() {
    geocode($("#location-form #address").val());

    return false;
}

$(document).ready(function() {
    // Setup handlers
    $('body').click(hide_alt_addresses);
    $('#not-where-i-am').click(not_where_i_am);
    $('#use-current-location').click(use_current_location);
    $('#use-default-location').click(use_default_location);
    $('#did-you-mean').click(function(e) { e.stopPropagation(); toggle_alt_addresses(); });
    $('#location-form input[type=text]').focus(search_focused);
    $('#location-form').submit(address_search)

    if (window.location.hash != "") {
        switch_page(window.location.hash.substring(1));
    } else {
        switch_page("demo");
    }
});

<|endoftext|>


<commit_before>var MemCache = require("./memcache"),
    LocalCache = require("./localcache");

function initialize(setting) {
    if (setting.client === "memcache") {
        return new MemCache();
    }
    else {
        return new LocalCache();
    }
}

module.exports = {
    initialize: initialize
};<commit_msg>mongo change 1<commit_after>var MemCache = require("./memcache"),
    LocalCache = require("./localcache"),
    MongoDbCache = require("./mongodb");

function initialize(setting) {
    if (setting.client === "memcache") {
        return new MemCache();
    }
    else if(setting.client === "mongodb"){
        return new MongoDbCache();
    }
    else {
        return new LocalCache();
    }
}

module.exports = {
    initialize: initialize
};<|endoftext|>


<commit_before>(function($) {
  $(document).ready(function() {
    $('.handle').closest('tbody').activeAdminSortableTable();
  });

  $.fn.activeAdminSortableTable = function() {
    this.sortable({
      handle: ".handle",
      update: function(event, ui) {
        var item = ui.item.find('[data-sort-url]');
        var url = item.data('sort-url');
        var actionOnSuccess = item.data('sort-success-action');
        var customParams = {};
        if (typeof item.data('sort-custom-params') === 'object') {
          customParams = item.data('sort-custom-params');
        }

        $.ajax({
          url: url,
          type: 'post',
          data: $.extend(customParams, { position: ui.item.find('[data-position]').data('position') - 1 }),
          error: function () { console.error('Saving sortable error'); },
          success: function () {
            location.href = location.href;
          },
          async: false
        });
      }
    });

    this.disableSelection();
  }
})(jQuery);
<commit_msg>Fix #10 reordering<commit_after>(function($) {
  $(document).ready(function() {
    $('.handle').closest('tbody').activeAdminSortableTable();
  });

  $.fn.activeAdminSortableTable = function() {
    this.sortable({
      handle: ".handle",
      update: function(event, ui) {
        var item = ui.item.find('[data-sort-url]');
        var url = item.data('sort-url');
        var customParams = {};
        if (typeof item.data('sort-custom-params') === 'object') {
          customParams = item.data('sort-custom-params');
        }

        var nextElement = ui.item[0].nextElementSibling;

        var nextPosition = $(nextElement).find('[data-position]').data('position');
        var currentPosition = ui.item.find('[data-position]').data('position');

        if(nextPosition === undefined || nextPosition > currentPosition) {
          // moved down
          var previousElement = ui.item[0].previousElementSibling;
          var previousPosition = $(previousElement).find('[data-position]').data('position');
          var newPosition = previousPosition;
        } else {
          // moved up
          var newPosition = nextPosition;
        }

        $.ajax({
          url: url,
          type: 'post',
          data: $.extend(customParams, { position: newPosition }),
          error: function () { console.error('Saving sortable error'); },
          success: function () {
            location.href = location.href;
          },
          async: false
        });
      }
    });

    this.disableSelection();
  }
})(jQuery);
<|endoftext|>


<commit_before>#!/usr/bin/env node

const stencila = require('.')
const colors = require('colors') // eslint-disable-line no-unused-vars

// Banner
console.log(('Stencila CLI for Node.js ' + stencila.version + '\n').green)

// Start up the host and notify user
stencila.host.startup().then(function () {
  console.log(stencila.host.title + ' is being served at ' + stencila.host.url)
})
<commit_msg>Use address instead of title<commit_after>#!/usr/bin/env node

const stencila = require('.')
const colors = require('colors') // eslint-disable-line no-unused-vars

// Banner
console.log(('Stencila CLI for Node.js ' + stencila.version + '\n').green)

// Start up the host and notify user
stencila.host.startup().then(function () {
  console.log(stencila.host.address + ' is being served at ' + stencila.host.url)
})
<|endoftext|>


<commit_before>//= require can.jquery-all
//= require sections/section
//= require controls/control
//= require controls/controls_controller

(function(namespace, $) {
function mapunmap(unmap) {
  return function(section, rcontrol, ccontrol) {
      var params = {
        ccontrol : (ccontrol ? ccontrol.id : "")
      };
      if(unmap)
        params.u = "1";
      if(rcontrol) params.rcontrol = rcontrol.id;
      if(section) params.section = section.id;

      var dfd = section ?
        section.map_rcontrol(params)
        : rcontrol.map_ccontrol(params);
      dfd.then(can.proxy(this.updateButtons, this));
      return dfd;
  }
}

can.Control("CMS.Controllers.Mapping", {
  //static
  cache : {}
}, {
  init : function() {
    this.link_lists();
    this.updateButtons();
  }

  , link_lists : function() {
      $.when(
        this.options.company_list_controller.find_all_deferred
        , this.options.reg_list_controller.find_all_deferred
        , this.options.section_list_controller.find_all_deferred
      ).done(function() {

        can.each(CMS.Models.RegControl.cache, function(rcontrol, id) {
          rcontrol.attr("implementing_controls", new can.Model.List(
            can.$(rcontrol.implementing_controls).map(function(index, ictl){
              return CMS.Models.Control.findInCacheById(ictl.id);
          })));
        });

        can.each(CMS.Models.SectionSlug.cache, function(section, id) {
          section.update_linked_controls();
        });

      });

  }

  , "#rmap:not([disabled]), #cmap:not([disabled]) click" : function(el, ev) {
    var that = this;
    var section = $("#selected_sections").control(namespace.CMS.Controllers.Sections).options.instance;
    var rcontrol = $("#selected_rcontrol").control(namespace.CMS.Controllers.Controls).options.instance;
    var ccontrol = $("#selected_ccontrol").control(namespace.CMS.Controllers.Controls).options.instance;

    if(el.is("#cmap")) {
      section = null;
    }
    var dfd = this[el.is(".unmapbtn") ? "unmap" : "map"](section, rcontrol, ccontrol);
    this.bindXHRToButton(dfd, el);
    var that = this;
    dfd.then(function() {
      that.options.section_list_controller.draw_list(); //manual update because section model doesn't contain "real" rcontrol model
    });

    if(!rcontrol && el.is("#rmap")) {
      var notice, reg_slug;
      dfd.then(function(resp, status, xhr) {
        notice = /.*Created regulation control (.+)\. Mapped regulation control\. */.exec(xhr.getResponseHeader("X-Flash-Notice"));
        if(notice)
          reg_slug = notice[1];
      })
      dfd.then($.proxy(this.options.reg_list_controller, "fetch_list"))
      .then(function() {
        that.options.reg_list_controller.find_all_deferred.then(function(list) {
          var ccontrol = section.linked_controls[section.linked_controls.length - 1];
          section.removeElementFromChildList("linked_controls", ccontrol);
          section.addElementToChildList("linked_controls", can.filter(can.makeArray(list), function(item) { return item.slug === reg_slug })[0]);
          section.addElementToChildList("linked_controls", ccontrol); //adding the reg control in before the ccontrol is necessary because we
                                                                      // are assuming order when updating linkages
        });
      });
    }
  }

  , unmap : function() { return mapunmap(true).apply(this, arguments); }
  , map : function() { return mapunmap(false).apply(this, arguments); }

  , "#rcontrol_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Controls.Instances.SelectedRegControl.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , "#ccontrol_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Controls.Instances.SelectedCompanyControl.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , "#section_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Sections.Instances.SelectedSection.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , updateButtons : function(ev, oldVal, newVal) {
    var section = $("#selected_sections").control(namespace.CMS.Controllers.Sections).options.instance;
    var rcontrol = $("#selected_rcontrol").control(namespace.CMS.Controllers.Controls).options.instance;
    var ccontrol = $("#selected_ccontrol").control(namespace.CMS.Controllers.Controls).options.instance;

    var rmap = $('#rmap');
    var cmap = $('#cmap');

    rmap.attr('disabled', !(section && (rcontrol || ccontrol)));
    if (!(section && (rcontrol || ccontrol))) {
      rmap.children(':first').text('Map section to control');
    }
    cmap.attr('disabled', !(rcontrol && ccontrol));
    if (!(rcontrol && ccontrol)) {
      cmap.children(':first').text('Map control to control');
    }

    if ((section && (rcontrol || ccontrol)) || (rcontrol && ccontrol)) {
          var rmap_text = $(rmap.children()[0]);
          var cmap_text = $(cmap.children()[0]);
          var runmap = section && rcontrol ? $(section.linked_controls).filter(function() { return this.id  === rcontrol.id}).length : false;
              runmap || (runmap = section && !rcontrol && ccontrol ? $(section.linked_controls).filter(function() { return this.id === ccontrol.id}).length : false);
          var cunmap = rcontrol && ccontrol ? $(rcontrol.implementing_controls).filter(function() { return this.id === ccontrol.id}).length : false;

          // We don't know how we'd unmap a ccontrol directly from a section, because there's an auto-generated
          //  rcontrol associated with it.  So don't allow it.
          if(section && !rcontrol && runmap) {
            rmap.attr("disabled", true);
          }

          rmap_text.text(runmap ? 'Unmap' : 'Map section to control')
          rmap[runmap ? 'addClass' : "removeClass"]("unmapbtn");
          cmap_text.text(cunmap ? 'Unmap' : 'Map control to control')
          cmap[cunmap ? 'addClass' : "removeClass"]("unmapbtn");
    }
  }
  , ".clearselection click" : function(el, ev) {
    this.updateButtons();
  }

  // Post-submit handler for new control dialog
  , "#new_control ajax:json" : function(el, ev, data) {
    if(data.program_id.toString() === this.options.id) {
      // add this control to the reg controls.
      // This isn't the best way to go about it, but CanJS/Mustache is currently ornery about accepting new observable list elements
      //  added with "push" --BM 12/11/2012
      var rctl = this.options.reg_list_controller;
      can.Model.Cacheable.prototype.addElementToChildList.call(rctl.options.observer, "list", new namespace.CMS.Models.RegControl(data));
    }
    var cctl = this.options.company_list_controller;
    can.Model.Cacheable.prototype.addElementToChildList.call(cctl.options.observer, "list", new namespace.CMS.Models.Control(data));
  }

  , "a.controllist, a.controllistRM click" : function(el, ev) {
    var $dialog = $("#mapping_dialog");
    if(!$dialog.length) {
      $dialog = $('

')
        .appendTo(this.element)
        .draggable({ handle: '.modal-header' });
    }

    ev.preventDefault();
    // Not putting in the real model because live binding is having a problem with how we do things.
    $dialog.html(can.view("/assets/sections/controls_mapping.mustache", el.closest("[data-model]").data("model").serialize()));
    $dialog.modal_form({ backdrop: true }).modal_form('show');
  }

  , "#mapping_dialog .closebtn click" : function(el) {
    el.closest("#mapping_dialog").modal_form('hide');
  }

  , "#mapping_dialog .unmapbtn click" : function(el, ev) {
    var thiscontrol = el.data("id")
    , _section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"))
    , that = this
    , $rc, rcontrol, ccontrol, section;
    if(($rc = el.closest("[data-rcontrol-id]")).length > 0) {
      rcontrol = namespace.CMS.Models.RegControl.findInCacheById($rc.data("rcontrol-id"));
      ccontrol = namespace.CMS.Models.Control.findInCacheById(thiscontrol);
    } else {
      rcontrol = namespace.CMS.Models.RegControl.findInCacheById(thiscontrol);
      section = _section;
    }
    this.bindXHRToButton(
      this.unmap(section, rcontrol, ccontrol)
        .then(function() {
          _section.update_linked_controls();
          var $dialog = $("#mapping_dialog");
          $dialog.html(can.view("/assets/sections/controls_mapping.mustache", _section.serialize()));
          that.options.section_list_controller.draw_list();
        }),
      el);
  }

  , "#section_na click" : function(el, ev) {
    var section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"));
    section.attr("na", el.attr("checked") ? 1 : 0);
    this.bindXHRToButton(section.save(), el);
  }

  , "#section_notes change" : function(el, ev) {
    var section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"));
    section.attr("notes", el.val());
    this.bindXHRToButton(section.save(), el);
  }

});

can.Control("CMS.Controllers.MappingWidgets", {}, {

  ".clearselection click" : function(el, ev) {
    var controllers = this.element.find(".cms_controllers_controls, .cms_controllers_sections").controls(namespace.CMS.Controllers.Controls);
    $(controllers).each(function() {
      if(this.options.arity === 1) {
        this.update({instance : null});
      } else {
        this.setSelected(null);
      }
    });
  }

  , ".widgetsearch-tocontent keydown" : function(el, ev) {
    var controllers = this.element.find(".cms_controllers_controls, .cms_controllers_sections").controls(namespace.CMS.Controllers.Controls);
    $(controllers).each(function() {
      var that = this;
      if(that.search_timeout) clearTimeout(that.search_timeout);
      that.search_timeout = setTimeout(function() {
        if(that.options.arity > 1) {
          that.filter(el.val());
        }
      }, 300);
    });
    ev.stopPropagation();
  }

});

})(this, can.$);
<commit_msg>Story 44854563: re-calculating button disabled states after mapping AJAX to ensure that unmap button for section-ccontrol is always disabled<commit_after>//= require can.jquery-all
//= require sections/section
//= require controls/control
//= require controls/controls_controller

(function(namespace, $) {
function mapunmap(unmap) {
  return function(section, rcontrol, ccontrol) {
      var params = {
        ccontrol : (ccontrol ? ccontrol.id : "")
      };
      if(unmap)
        params.u = "1";
      if(rcontrol) params.rcontrol = rcontrol.id;
      if(section) params.section = section.id;

      var dfd = section ?
        section.map_rcontrol(params)
        : rcontrol.map_ccontrol(params);
      dfd.then(can.proxy(this.updateButtons, this));
      return dfd;
  }
}

can.Control("CMS.Controllers.Mapping", {
  //static
  cache : {}
}, {
  init : function() {
    this.link_lists();
    this.updateButtons();
  }

  , link_lists : function() {
      $.when(
        this.options.company_list_controller.find_all_deferred
        , this.options.reg_list_controller.find_all_deferred
        , this.options.section_list_controller.find_all_deferred
      ).done(function() {

        can.each(CMS.Models.RegControl.cache, function(rcontrol, id) {
          rcontrol.attr("implementing_controls", new can.Model.List(
            can.$(rcontrol.implementing_controls).map(function(index, ictl){
              return CMS.Models.Control.findInCacheById(ictl.id);
          })));
        });

        can.each(CMS.Models.SectionSlug.cache, function(section, id) {
          section.update_linked_controls();
        });

      });

  }

  , "#rmap:not([disabled]), #cmap:not([disabled]) click" : function(el, ev) {
    var that = this;
    var section = $("#selected_sections").control(namespace.CMS.Controllers.Sections).options.instance;
    var rcontrol = $("#selected_rcontrol").control(namespace.CMS.Controllers.Controls).options.instance;
    var ccontrol = $("#selected_ccontrol").control(namespace.CMS.Controllers.Controls).options.instance;

    if(el.is("#cmap")) {
      section = null;
    }
    var dfd = this[el.is(".unmapbtn") ? "unmap" : "map"](section, rcontrol, ccontrol);
    this.bindXHRToButton(dfd, el);
    dfd.always(this.proxy("updateButtons")); //bindXHR will remove the disabled attr, so re-check afterwards.
    var that = this;
    dfd.then(function() {
      that.options.section_list_controller.draw_list(); //manual update because section model doesn't contain "real" rcontrol model
    });

    if(!rcontrol && el.is("#rmap")) {
      var notice, reg_slug;
      dfd.then(function(resp, status, xhr) {
        notice = /.*Created regulation control (.+)\. Mapped regulation control\. */.exec(xhr.getResponseHeader("X-Flash-Notice"));
        if(notice)
          reg_slug = notice[1];
      })
      dfd.then($.proxy(this.options.reg_list_controller, "fetch_list"))
      .then(function() {
        that.options.reg_list_controller.find_all_deferred.then(function(list) {
          var ccontrol = section.linked_controls[section.linked_controls.length - 1];
          section.removeElementFromChildList("linked_controls", ccontrol);
          section.addElementToChildList("linked_controls", can.filter(can.makeArray(list), function(item) { return item.slug === reg_slug })[0]);
          section.addElementToChildList("linked_controls", ccontrol); //adding the reg control in before the ccontrol is necessary because we
                                                                      // are assuming order when updating linkages
        });
      });
    }
  }

  , unmap : function() { return mapunmap(true).apply(this, arguments); }
  , map : function() { return mapunmap(false).apply(this, arguments); }

  , "#rcontrol_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Controls.Instances.SelectedRegControl.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , "#ccontrol_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Controls.Instances.SelectedCompanyControl.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , "#section_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Sections.Instances.SelectedSection.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , updateButtons : function(ev, oldVal, newVal) {
    var section = $("#selected_sections").control(namespace.CMS.Controllers.Sections).options.instance;
    var rcontrol = $("#selected_rcontrol").control(namespace.CMS.Controllers.Controls).options.instance;
    var ccontrol = $("#selected_ccontrol").control(namespace.CMS.Controllers.Controls).options.instance;

    var rmap = $('#rmap');
    var cmap = $('#cmap');

    rmap.attr('disabled', !(section && (rcontrol || ccontrol)));
    if (!(section && (rcontrol || ccontrol))) {
      rmap.children(':first').text('Map section to control');
    }
    cmap.attr('disabled', !(rcontrol && ccontrol));
    if (!(rcontrol && ccontrol)) {
      cmap.children(':first').text('Map control to control');
    }

    if ((section && (rcontrol || ccontrol)) || (rcontrol && ccontrol)) {
          var rmap_text = $(rmap.children()[0]);
          var cmap_text = $(cmap.children()[0]);
          var runmap = section && rcontrol ? $(section.linked_controls).filter(function() { return this.id  === rcontrol.id}).length : false;
              runmap || (runmap = section && !rcontrol && ccontrol ? $(section.linked_controls).filter(function() { return this.id === ccontrol.id}).length : false);
          var cunmap = rcontrol && ccontrol ? $(rcontrol.implementing_controls).filter(function() { return this.id === ccontrol.id}).length : false;

          // We don't know how we'd unmap a ccontrol directly from a section, because there's an auto-generated
          //  rcontrol associated with it.  So don't allow it.
          if(section && !rcontrol && runmap) {
            rmap.attr("disabled", true);
          }

          rmap_text.text(runmap ? 'Unmap' : 'Map section to control')
          rmap[runmap ? 'addClass' : "removeClass"]("unmapbtn");
          cmap_text.text(cunmap ? 'Unmap' : 'Map control to control')
          cmap[cunmap ? 'addClass' : "removeClass"]("unmapbtn");
    }
  }
  , ".clearselection click" : function(el, ev) {
    this.updateButtons();
  }

  // Post-submit handler for new control dialog
  , "#new_control ajax:json" : function(el, ev, data) {
    if(data.program_id.toString() === this.options.id) {
      // add this control to the reg controls.
      // This isn't the best way to go about it, but CanJS/Mustache is currently ornery about accepting new observable list elements
      //  added with "push" --BM 12/11/2012
      var rctl = this.options.reg_list_controller;
      can.Model.Cacheable.prototype.addElementToChildList.call(rctl.options.observer, "list", new namespace.CMS.Models.RegControl(data));
    }
    var cctl = this.options.company_list_controller;
    can.Model.Cacheable.prototype.addElementToChildList.call(cctl.options.observer, "list", new namespace.CMS.Models.Control(data));
  }

  , "a.controllist, a.controllistRM click" : function(el, ev) {
    var $dialog = $("#mapping_dialog");
    if(!$dialog.length) {
      $dialog = $('

')
        .appendTo(this.element)
        .draggable({ handle: '.modal-header' });
    }

    ev.preventDefault();
    // Not putting in the real model because live binding is having a problem with how we do things.
    $dialog.html(can.view("/assets/sections/controls_mapping.mustache", el.closest("[data-model]").data("model").serialize()));
    $dialog.modal_form({ backdrop: true }).modal_form('show');
  }

  , "#mapping_dialog .closebtn click" : function(el) {
    el.closest("#mapping_dialog").modal_form('hide');
  }

  , "#mapping_dialog .unmapbtn click" : function(el, ev) {
    var thiscontrol = el.data("id")
    , _section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"))
    , that = this
    , $rc, rcontrol, ccontrol, section;
    if(($rc = el.closest("[data-rcontrol-id]")).length > 0) {
      rcontrol = namespace.CMS.Models.RegControl.findInCacheById($rc.data("rcontrol-id"));
      ccontrol = namespace.CMS.Models.Control.findInCacheById(thiscontrol);
    } else {
      rcontrol = namespace.CMS.Models.RegControl.findInCacheById(thiscontrol);
      section = _section;
    }
    this.bindXHRToButton(
      this.unmap(section, rcontrol, ccontrol)
        .then(function() {
          _section.update_linked_controls();
          var $dialog = $("#mapping_dialog");
          $dialog.html(can.view("/assets/sections/controls_mapping.mustache", _section.serialize()));
          that.options.section_list_controller.draw_list();
        }),
      el);
  }

  , "#section_na click" : function(el, ev) {
    var section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"));
    section.attr("na", el.attr("checked") ? 1 : 0);
    this.bindXHRToButton(section.save(), el);
  }

  , "#section_notes change" : function(el, ev) {
    var section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"));
    section.attr("notes", el.val());
    this.bindXHRToButton(section.save(), el);
  }

});

can.Control("CMS.Controllers.MappingWidgets", {}, {

  ".clearselection click" : function(el, ev) {
    var controllers = this.element.find(".cms_controllers_controls, .cms_controllers_sections").controls(namespace.CMS.Controllers.Controls);
    $(controllers).each(function() {
      if(this.options.arity === 1) {
        this.update({instance : null});
      } else {
        this.setSelected(null);
      }
    });
  }

  , ".widgetsearch-tocontent keydown" : function(el, ev) {
    var controllers = this.element.find(".cms_controllers_controls, .cms_controllers_sections").controls(namespace.CMS.Controllers.Controls);
    $(controllers).each(function() {
      var that = this;
      if(that.search_timeout) clearTimeout(that.search_timeout);
      that.search_timeout = setTimeout(function() {
        if(that.options.arity > 1) {
          that.filter(el.val());
        }
      }, 300);
    });
    ev.stopPropagation();
  }

});

})(this, can.$);
<|endoftext|>


<commit_before>//= require can.jquery-all
//= require sections/section
//= require controls/control
//= require controls/controls_controller

(function(namespace, $) {
function mapunmap(unmap) {
  return function(section, rcontrol, ccontrol) {
      var params = {
        ccontrol : (ccontrol ? ccontrol.id : "")
      };
      if(unmap)
        params.u = "1";
      if(rcontrol) params.rcontrol = rcontrol.id;
      if(section) params.section = section.id;

      var dfd = section ?
        section.map_rcontrol(params)
        : rcontrol.map_ccontrol(params);
      dfd.then(can.proxy(this.updateButtons, this));
      return dfd;
  }
}

can.Control("CMS.Controllers.Mapping", {
  //static
  cache : {}
}, {
  init : function() {
    this.link_lists();
    this.updateButtons();
  }

  , link_lists : function() {
      $.when(
        this.options.company_list_controller.find_all_deferred
        , this.options.reg_list_controller.find_all_deferred
        , this.options.section_list_controller.find_all_deferred
      ).done(function() {

        can.each(CMS.Models.RegControl.cache, function(rcontrol, id) {
          rcontrol.attr("implementing_controls", new can.Model.List(
            can.$(rcontrol.implementing_controls).map(function(index, ictl){
              return CMS.Models.Control.findInCacheById(ictl.id);
          })));
        });

        can.each(CMS.Models.SectionSlug.cache, function(section, id) {
          section.update_linked_controls();
        });

      });

  }

  , "#rmap, #cmap click" : function(el, ev) {
    var that = this;
    var section = $("#selected_sections").control(namespace.CMS.Controllers.Sections).options.instance;
    var rcontrol = $("#selected_rcontrol").control(namespace.CMS.Controllers.Controls).options.instance;
    var ccontrol = $("#selected_ccontrol").control(namespace.CMS.Controllers.Controls).options.instance;

    if(el.is("#cmap")) {
      section = null;
    }
    var dfd = this[el.is(".unmapbtn") ? "unmap" : "map"](section, rcontrol, ccontrol);
    var that = this;
    dfd.then(function() {
      that.options.section_list_controller.draw_list(); //manual update because section model doesn't contain "real" rcontrol model
    });

    if(!rcontrol && el.is("#rmap")) {
      var notice, reg_slug;
      dfd.then(function(resp, status, xhr) {
        notice = /.*Created regulation control (.+)\. Mapped regulation control\. */.exec(xhr.getResponseHeader("X-Flash-Notice"));
        if(notice)
          reg_slug = notice[1];
      })
      dfd.then($.proxy(this.options.reg_list_controller, "fetch_list"))
      .then(function() {
        that.options.reg_list_controller.find_all_deferred.then(function(list) {
          var ccontrol = section.linked_controls[section.linked_controls.length - 1];
          section.removeElementFromChildList("linked_controls", ccontrol);
          section.addElementToChildList("linked_controls", can.filter(can.makeArray(list), function(item) { return item.slug === reg_slug })[0]);
          section.addElementToChildList("linked_controls", ccontrol); //adding the reg control in before the ccontrol is necessary because we
                                                                      // are assuming order when updating linkages
        });
      });
    }
  }

  , unmap : function() { return mapunmap(true).apply(this, arguments); }
  , map : function() { return mapunmap(false).apply(this, arguments); }

  , "#rcontrol_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Controls.Instances.SelectedRegControl.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , "#ccontrol_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Controls.Instances.SelectedCompanyControl.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , "#section_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Sections.Instances.SelectedSection.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , updateButtons : function(ev, oldVal, newVal) {
    var section = $("#selected_sections").control(namespace.CMS.Controllers.Sections).options.instance;
    var rcontrol = $("#selected_rcontrol").control(namespace.CMS.Controllers.Controls).options.instance;
    var ccontrol = $("#selected_ccontrol").control(namespace.CMS.Controllers.Controls).options.instance;

    var rmap = $('#rmap');
    var cmap = $('#cmap');

    rmap.attr('disabled', !(section && (rcontrol || ccontrol)));
    if (!(section && (rcontrol || ccontrol))) {
      rmap.children(':first').text('Map section to control');
    }
    cmap.attr('disabled', !(rcontrol && ccontrol));
    if (!(rcontrol && ccontrol)) {
      cmap.children(':first').text('Map control to control');
    }

    if ((section && (rcontrol || ccontrol)) || (rcontrol && ccontrol)) {
          var rmap_text = $(rmap.children()[0]);
          var cmap_text = $(cmap.children()[0]);
          var runmap = section && rcontrol ? $(section.linked_controls).filter(function() { return this.id  === rcontrol.id}).length : false;
              runmap || (runmap = section && !rcontrol && ccontrol ? $(section.linked_controls).filter(function() { return this.id === ccontrol.id}).length : false);
          var cunmap = rcontrol && ccontrol ? $(rcontrol.implementing_controls).filter(function() { return this.id === ccontrol.id}).length : false;

          // We don't know how we'd unmap a ccontrol directly from a section, because there's an auto-generated
          //  rcontrol associated with it.  So don't allow it.
          if(section && !rcontrol && runmap) {
            rmap.attr("disabled", true);
          }

          rmap_text.text(runmap ? 'Unmap' : 'Map section to control')
          rmap[runmap ? 'addClass' : "removeClass"]("unmapbtn");
          cmap_text.text(cunmap ? 'Unmap' : 'Map control to control')
          cmap[cunmap ? 'addClass' : "removeClass"]("unmapbtn");
    }
  }
  , ".clearselection click" : function(el, ev) {
    this.updateButtons();
  }

  // Post-submit handler for new control dialog
  , "#new_control ajax:json" : function(el, ev, data) {
    if(data.program_id.toString() === this.options.id) {
      // add this control to the reg controls.
      // This isn't the best way to go about it, but CanJS/Mustache is currently ornery about accepting new observable list elements
      //  added with "push" --BM 12/11/2012
      var rctl = this.options.reg_list_controller;
      can.Model.Cacheable.prototype.addElementToChildList.call(rctl.options.observer, "list", new namespace.CMS.Models.RegControl(data));
    }
    var cctl = this.options.company_list_controller;
    can.Model.Cacheable.prototype.addElementToChildList.call(cctl.options.observer, "list", new namespace.CMS.Models.Control(data));
  }

  , "a.controllist, a.controllistRM click" : function(el, ev) {
    var $dialog = $("#mapping_dialog");
    if(!$dialog.length) {
      $dialog = $('

')
        .appendTo(this.element)
        .draggable({ handle: '.modal-header' });
    }

    ev.preventDefault();
    // Not putting in the real model because live binding is having a problem with how we do things.
    $dialog.html(can.view("/sections/controls_mapping.mustache", el.closest("[data-model]").data("model").serialize()));
    $dialog.modal_form({ backdrop: false }).modal_form('show');
  }

  , "#mapping_dialog .closebtn click" : function(el) {
    el.closest("#mapping_dialog").modal_form('hide');
  }

  , "#mapping_dialog .unmapbtn click" : function(el) {
    var thiscontrol = el.data("id")
    , _section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"))
    , that = this
    , $rc, rcontrol, ccontrol, section;
    if(($rc = el.closest("[data-rcontrol-id]")).length > 0) {
      rcontrol = namespace.CMS.Models.RegControl.findInCacheById($rc.data("rcontrol-id"));
      ccontrol = namespace.CMS.Models.Control.findInCacheById(thiscontrol);
    } else {
      rcontrol = namespace.CMS.Models.RegControl.findInCacheById(thiscontrol);
      section = _section;
    }
    this.unmap(section, rcontrol, ccontrol)
    .then(function() {
      _section.update_linked_controls();
      var $dialog = $("#mapping_dialog");
      $dialog.html(can.view("/sections/controls_mapping.mustache", _section.serialize()));
      that.options.section_list_controller.draw_list();

    });
  }

  , "#section_na click" : function(el, ev) {
    var section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"));
    section.attr("na", el.attr("checked") ? 1 : 0);
    section.save();
  }

  , "#section_notes change" : function(el, ev) {
    var section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"));
    section.attr("notes", el.val());
    section.save();
  }

});

can.Control("CMS.Controllers.MappingWidgets", {}, {

  ".clearselection click" : function(el, ev) {
    var controllers = this.element.find(".cms_controllers_controls, .cms_controllers_sections").controls(namespace.CMS.Controllers.Controls);
    $(controllers).each(function() {
      if(this.options.arity === 1) {
        this.update({instance : null});
      } else {
        this.setSelected(null);
      }
    });
  }

  , ".widgetsearch-tocontent keydown" : function(el, ev) {
    var controllers = this.element.find(".cms_controllers_controls, .cms_controllers_sections").controls(namespace.CMS.Controllers.Controls);
    $(controllers).each(function() {
      var that = this;
      setTimeout(function() {
        if(that.options.arity > 1) {
          that.filter(el.val());
        }
      }, 1);
    });
    ev.stopPropagation();
  }

});

})(this, can.$);
<commit_msg>Story 41622431: Ensuring that disabled map/unmap buttons do not fire map/unmap when clicked<commit_after>//= require can.jquery-all
//= require sections/section
//= require controls/control
//= require controls/controls_controller

(function(namespace, $) {
function mapunmap(unmap) {
  return function(section, rcontrol, ccontrol) {
      var params = {
        ccontrol : (ccontrol ? ccontrol.id : "")
      };
      if(unmap)
        params.u = "1";
      if(rcontrol) params.rcontrol = rcontrol.id;
      if(section) params.section = section.id;

      var dfd = section ?
        section.map_rcontrol(params)
        : rcontrol.map_ccontrol(params);
      dfd.then(can.proxy(this.updateButtons, this));
      return dfd;
  }
}

can.Control("CMS.Controllers.Mapping", {
  //static
  cache : {}
}, {
  init : function() {
    this.link_lists();
    this.updateButtons();
  }

  , link_lists : function() {
      $.when(
        this.options.company_list_controller.find_all_deferred
        , this.options.reg_list_controller.find_all_deferred
        , this.options.section_list_controller.find_all_deferred
      ).done(function() {

        can.each(CMS.Models.RegControl.cache, function(rcontrol, id) {
          rcontrol.attr("implementing_controls", new can.Model.List(
            can.$(rcontrol.implementing_controls).map(function(index, ictl){
              return CMS.Models.Control.findInCacheById(ictl.id);
          })));
        });

        can.each(CMS.Models.SectionSlug.cache, function(section, id) {
          section.update_linked_controls();
        });

      });

  }

  , "#rmap:not([disabled]), #cmap:not([disabled]) click" : function(el, ev) {
    var that = this;
    var section = $("#selected_sections").control(namespace.CMS.Controllers.Sections).options.instance;
    var rcontrol = $("#selected_rcontrol").control(namespace.CMS.Controllers.Controls).options.instance;
    var ccontrol = $("#selected_ccontrol").control(namespace.CMS.Controllers.Controls).options.instance;

    if(el.is("#cmap")) {
      section = null;
    }
    var dfd = this[el.is(".unmapbtn") ? "unmap" : "map"](section, rcontrol, ccontrol);
    var that = this;
    dfd.then(function() {
      that.options.section_list_controller.draw_list(); //manual update because section model doesn't contain "real" rcontrol model
    });

    if(!rcontrol && el.is("#rmap")) {
      var notice, reg_slug;
      dfd.then(function(resp, status, xhr) {
        notice = /.*Created regulation control (.+)\. Mapped regulation control\. */.exec(xhr.getResponseHeader("X-Flash-Notice"));
        if(notice)
          reg_slug = notice[1];
      })
      dfd.then($.proxy(this.options.reg_list_controller, "fetch_list"))
      .then(function() {
        that.options.reg_list_controller.find_all_deferred.then(function(list) {
          var ccontrol = section.linked_controls[section.linked_controls.length - 1];
          section.removeElementFromChildList("linked_controls", ccontrol);
          section.addElementToChildList("linked_controls", can.filter(can.makeArray(list), function(item) { return item.slug === reg_slug })[0]);
          section.addElementToChildList("linked_controls", ccontrol); //adding the reg control in before the ccontrol is necessary because we
                                                                      // are assuming order when updating linkages
        });
      });
    }
  }

  , unmap : function() { return mapunmap(true).apply(this, arguments); }
  , map : function() { return mapunmap(false).apply(this, arguments); }

  , "#rcontrol_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Controls.Instances.SelectedRegControl.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , "#ccontrol_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Controls.Instances.SelectedCompanyControl.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , "#section_list .regulationslot click" : function(el, ev) {
    CMS.Controllers.Sections.Instances.SelectedSection.update({ instance : el.closest("[data-model]").data("model") });
    this.updateButtons();
    ev.preventDefault();
  }

  , updateButtons : function(ev, oldVal, newVal) {
    var section = $("#selected_sections").control(namespace.CMS.Controllers.Sections).options.instance;
    var rcontrol = $("#selected_rcontrol").control(namespace.CMS.Controllers.Controls).options.instance;
    var ccontrol = $("#selected_ccontrol").control(namespace.CMS.Controllers.Controls).options.instance;

    var rmap = $('#rmap');
    var cmap = $('#cmap');

    rmap.attr('disabled', !(section && (rcontrol || ccontrol)));
    if (!(section && (rcontrol || ccontrol))) {
      rmap.children(':first').text('Map section to control');
    }
    cmap.attr('disabled', !(rcontrol && ccontrol));
    if (!(rcontrol && ccontrol)) {
      cmap.children(':first').text('Map control to control');
    }

    if ((section && (rcontrol || ccontrol)) || (rcontrol && ccontrol)) {
          var rmap_text = $(rmap.children()[0]);
          var cmap_text = $(cmap.children()[0]);
          var runmap = section && rcontrol ? $(section.linked_controls).filter(function() { return this.id  === rcontrol.id}).length : false;
              runmap || (runmap = section && !rcontrol && ccontrol ? $(section.linked_controls).filter(function() { return this.id === ccontrol.id}).length : false);
          var cunmap = rcontrol && ccontrol ? $(rcontrol.implementing_controls).filter(function() { return this.id === ccontrol.id}).length : false;

          // We don't know how we'd unmap a ccontrol directly from a section, because there's an auto-generated
          //  rcontrol associated with it.  So don't allow it.
          if(section && !rcontrol && runmap) {
            rmap.attr("disabled", true);
          }

          rmap_text.text(runmap ? 'Unmap' : 'Map section to control')
          rmap[runmap ? 'addClass' : "removeClass"]("unmapbtn");
          cmap_text.text(cunmap ? 'Unmap' : 'Map control to control')
          cmap[cunmap ? 'addClass' : "removeClass"]("unmapbtn");
    }
  }
  , ".clearselection click" : function(el, ev) {
    this.updateButtons();
  }

  // Post-submit handler for new control dialog
  , "#new_control ajax:json" : function(el, ev, data) {
    if(data.program_id.toString() === this.options.id) {
      // add this control to the reg controls.
      // This isn't the best way to go about it, but CanJS/Mustache is currently ornery about accepting new observable list elements
      //  added with "push" --BM 12/11/2012
      var rctl = this.options.reg_list_controller;
      can.Model.Cacheable.prototype.addElementToChildList.call(rctl.options.observer, "list", new namespace.CMS.Models.RegControl(data));
    }
    var cctl = this.options.company_list_controller;
    can.Model.Cacheable.prototype.addElementToChildList.call(cctl.options.observer, "list", new namespace.CMS.Models.Control(data));
  }

  , "a.controllist, a.controllistRM click" : function(el, ev) {
    var $dialog = $("#mapping_dialog");
    if(!$dialog.length) {
      $dialog = $('

')
        .appendTo(this.element)
        .draggable({ handle: '.modal-header' });
    }

    ev.preventDefault();
    // Not putting in the real model because live binding is having a problem with how we do things.
    $dialog.html(can.view("/sections/controls_mapping.mustache", el.closest("[data-model]").data("model").serialize()));
    $dialog.modal_form({ backdrop: false }).modal_form('show');
  }

  , "#mapping_dialog .closebtn click" : function(el) {
    el.closest("#mapping_dialog").modal_form('hide');
  }

  , "#mapping_dialog .unmapbtn click" : function(el) {
    var thiscontrol = el.data("id")
    , _section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"))
    , that = this
    , $rc, rcontrol, ccontrol, section;
    if(($rc = el.closest("[data-rcontrol-id]")).length > 0) {
      rcontrol = namespace.CMS.Models.RegControl.findInCacheById($rc.data("rcontrol-id"));
      ccontrol = namespace.CMS.Models.Control.findInCacheById(thiscontrol);
    } else {
      rcontrol = namespace.CMS.Models.RegControl.findInCacheById(thiscontrol);
      section = _section;
    }
    this.unmap(section, rcontrol, ccontrol)
    .then(function() {
      _section.update_linked_controls();
      var $dialog = $("#mapping_dialog");
      $dialog.html(can.view("/sections/controls_mapping.mustache", _section.serialize()));
      that.options.section_list_controller.draw_list();

    });
  }

  , "#section_na click" : function(el, ev) {
    var section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"));
    section.attr("na", el.attr("checked") ? 1 : 0);
    section.save();
  }

  , "#section_notes change" : function(el, ev) {
    var section = namespace.CMS.Models.SectionSlug.findInCacheById(el.closest("[data-section-id]").data("section-id"));
    section.attr("notes", el.val());
    section.save();
  }

});

can.Control("CMS.Controllers.MappingWidgets", {}, {

  ".clearselection click" : function(el, ev) {
    var controllers = this.element.find(".cms_controllers_controls, .cms_controllers_sections").controls(namespace.CMS.Controllers.Controls);
    $(controllers).each(function() {
      if(this.options.arity === 1) {
        this.update({instance : null});
      } else {
        this.setSelected(null);
      }
    });
  }

  , ".widgetsearch-tocontent keydown" : function(el, ev) {
    var controllers = this.element.find(".cms_controllers_controls, .cms_controllers_sections").controls(namespace.CMS.Controllers.Controls);
    $(controllers).each(function() {
      var that = this;
      setTimeout(function() {
        if(that.options.arity > 1) {
          that.filter(el.val());
        }
      }, 1);
    });
    ev.stopPropagation();
  }

});

})(this, can.$);
<|endoftext|>