<commit_before>/**
 * Implementation of some of Drupal's database layer in Node.js.
 *
 * Ie. stuff that lives in database.inc in Drupal.
 */
"use strict";

var activeDb,
    mysql = require('mysql'),
    pg = require('pg'),
    activeBackend;

/**
 * db_connect() as in Drupal 6.
 *
 * This is much more complex with PDO in Drupal 7, which we won't try to
 * emulate here.
 */
function connect(options, backend) {
  activeBackend = backend;
  // Custom override. See https://github.com/felixge/node-mysql/issues/82 .
  mysql.Client.prototype.escape = function(val) {
    var object = false;
    if (val === undefined || val === null) {
      return 'NULL';
    }

    switch (typeof val) {
      case 'boolean': return (val) ? 'true' : 'false';
      case 'number': return val+'';
    }

    if (typeof val === 'object') {
      val = val.toString();
      object = true;
    }

    val = val.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
      switch(s) {
        case "\0": return "\\0";
        case "\n": return "\\n";
        case "\r": return "\\r";
        case "\b": return "\\b";
        case "\t": return "\\t";
        case "\x1a": return "\\Z";
        default: return "\\"+s;
      }
    });

    if (object) {
      return val;
    }

    return "'"+val+"'";
  };

  if (backend === 'pgsql') {
    pg.connect(options, function (err, client) {
      activeDb = client;

      if (activeDb !== null) {
        activeDb.on('error', function (err) {
          console.log(err);
        });
      }
    });
  }
  else {
    activeDb = mysql.createClient(options);

    if (activeDb !== null) {
      activeDb.on('error', function (err) {
        console.log(err);
      });
    }
  }

  return activeDb;
}

/**
 * db_query() as in Drupal (though callback-based).
 *
 * This function assumes that db_connect() has done its work, so be sure
 * to call it and wait for its callback first.
 */
function query(queryString, args, callback) {
  if (!activeDb) {
    callback('No active database connection for query.');
  }

  if (activeBackend == 'mysql') {
    queryString = queryString.replace(/\$\d+/, '?');
  }

  activeDb.query(queryString, args, function (err, result) {
    if (err) {
      callback(err, null);
      return;
    }
    if (activeBackend == 'mysql') {
      callback(err, result);
    }
    else if (activeBackend == 'pgsql') {
      var rows = [];
      if (result.rows) {
        rows = result.rows;
      }
      callback(err, rows);
    }
  });
}

module.exports = {
  activeDb: activeDb,
  connect: connect,
  query: query
};

<commit_msg>Properly use PostgreSQL connection pooling.<commit_after>/**
 * Implementation of some of Drupal's database layer in Node.js.
 *
 * Ie. stuff that lives in database.inc in Drupal.
 */
"use strict";

var activeDb,
    mysql = require('mysql'),
    pg = require('pg'),
    activeBackend,
    connectionOptions;

/**
 * Initialize and setup the connection to Drupal for futher
 */
function init(options, backend) {
  activeBackend = backend;
  connectionOptions = options;
  connect(connectionOptions);
}

function getClient(callback) {
  if (activeBackend === 'mysql') {
    if (activeDb) {
      callback(null, activeDb);
    }
    else {
      connect(connectionOptions);
      callback(null, activeDb);
    }
  }
  if (activeBackend === 'pgsql') {
    connect(connectionOptions, callback);
  }
}

/**
 * db_connect() as in Drupal 6.
 *
 * This is much more complex with PDO in Drupal 7, which we won't try to
 * emulate here.
 */
function connect(options, callback) {
  // Custom override. See https://github.com/felixge/node-mysql/issues/82 .
  mysql.Client.prototype.escape = function(val) {
    var object = false;
    if (val === undefined || val === null) {
      return 'NULL';
    }

    switch (typeof val) {
      case 'boolean': return (val) ? 'true' : 'false';
      case 'number': return val+'';
    }

    if (typeof val === 'object') {
      val = val.toString();
      object = true;
    }

    val = val.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
      switch(s) {
        case "\0": return "\\0";
        case "\n": return "\\n";
        case "\r": return "\\r";
        case "\b": return "\\b";
        case "\t": return "\\t";
        case "\x1a": return "\\Z";
        default: return "\\"+s;
      }
    });

    if (object) {
      return val;
    }

    return "'"+val+"'";
  };

  if (activeBackend === 'pgsql' && callback) {
    pg.connect(options, callback);
  }
  else if (activeBackend === 'mysql') {
    activeDb = mysql.createClient(options);

    if (activeDb !== null) {
      activeDb.on('error', function (err) {
        console.log(err);
      });
    }
  }

  return activeDb;
}

/**
 * db_query() as in Drupal (though callback-based).
 */
function query(queryString, args, callback) {
  getClient(function (err, client) {
    if (err) {throw err;}
    if (!client) {
      callback('Could not connect to the database', null);
    }
    else {
      runQuery(client, queryString, args, callback);
    }
  });
}

/**
 * Do the actual work of running the query.
 */
function runQuery(client, queryString, args, callback) {
  if (activeBackend === 'mysql') {
    queryString = queryString.replace(/\$\d+/, '?');
  }

  client.query(queryString, args, function (err, result) {
    if (err) {
      callback(err, null);
      return;
    }
    if (activeBackend === 'mysql') {
      callback(err, result);
    }
    else if (activeBackend === 'pgsql') {
      var rows = [];
      if (result.rows) {
        rows = result.rows;
      }
      callback(err, rows);
    }
  });
}

module.exports = {
  connect: connect,
  getClient: getClient,
  init: init,
  query: query,
  runQuery: runQuery
};

<|endoftext|>


<commit_before>import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { currentURL, visit, fillIn } from '@ember/test-helpers';
import { authenticateSession } from 'ember-simple-auth/test-support';

module('Acceptance | client_admin | client', function(hooks) {
  setupApplicationTest(hooks);

  test('visiting client AWI', async function(assert) {
    await authenticateSession({
      uid: 'tib.awi',
      name: 'Alfred Wegener Institute',
      role_id: 'client_admin',
      provider_id: 'tib',
      client_id: 'tib.awi'
    });
    await visit('/clients/tib.awi');

    assert.equal(currentURL(), '/clients/tib.awi');
    assert.dom('h2.work').hasText('Alfred Wegener Institute');
    assert.dom('a.nav-link.active').hasText('Info');
  });

  test('visiting client AWI settings', async function(assert) {
    await authenticateSession({
      uid: 'tib.awi',
      name: 'Alfred Wegener Institute',
      role_id: 'client_admin',
      provider_id: 'tib',
      client_id: 'tib.awi'
    });
    await visit('/clients/tib.awi/settings');

    assert.equal(currentURL(), '/clients/tib.awi/settings');
    assert.dom('h2.work').hasText('Alfred Wegener Institute');
    assert.dom('a.nav-link.active').hasText('Settings');
    assert.dom('button#edit-client').includesText('Update Account');
    assert.dom('button#delete-client').doesNotExist();
  });

  test('visiting client AWI prefixes', async function(assert) {
    await authenticateSession({
      uid: 'tib.awi',
      name: 'Alfred Wegener Institute',
      role_id: 'client_admin',
      provider_id: 'tib',
      client_id: 'tib.awi'
    });
    await visit('/clients/tib.awi/prefixes');

    assert.equal(currentURL(), '/clients/tib.awi/prefixes');
    assert.dom('h2.work').hasText('Alfred Wegener Institute');
    assert.dom('a.nav-link.active').hasText('Prefixes');
  });

  test('visiting client AWI dois', async function(assert) {
    await authenticateSession({
      uid: 'tib.awi',
      name: 'Alfred Wegener Institute',
      role_id: 'client_admin',
      provider_id: 'tib',
      client_id: 'tib.awi'
    });
    await visit('/clients/tib.awi/dois');

    assert.equal(currentURL(), '/clients/tib.awi/dois');
    assert.dom('h2.work').hasText('Alfred Wegener Institute');
    assert.dom('a.nav-link.active').hasText('DOIs');
    assert.dom('a#new-doi').includesText('Create DOI (Form)');
    assert.dom('a#upload-doi').includesText('Create DOI (File Upload)');
    assert.dom('a#transfer-dois').doesNotExist();
  });

  // test('creating a new DOI for client AWI renders', async function(assert) {
  //   await authenticateSession({
  //     uid: 'tib.awi',
  //     name: 'Alfred Wegener Institute',
  //     role_id: 'client_admin',
  //     provider_id: 'tib',
  //     client_id: 'tib.awi'
  //   });
  //   await visit('/clients/tib.awi/dois/new');
  //   //on landing
  //   assert.equal(currentURL(), '/clients/tib.awi/dois/new');
  //   assert.dom('h3').hasText('Create DOI (Form)');
  //   assert.dom('input#url-field').hasNoValue();
  //   assert.dom('input#publisher-field').hasNoValue();
  //   assert.dom('input#publication-year-field').hasNoValue();
  //   assert.dom('input#draft-radio').isChecked();
  //   assert.dom('input#registered-radio').isNotChecked();
  //   assert.dom('input#findable-radio').isNotChecked();
  //   assert.dom('input#suffix-field').hasAnyValue();
  // });

  // test('creating a new DOI for client AWI', async function(assert) {
  //   assert.expect(5);
  //   await authenticateSession({
  //     uid: 'tib.awi',
  //     name: 'Alfred Wegener Institute',
  //     role_id: 'client_admin',
  //     provider_id: 'tib',
  //     client_id: 'tib.awi'
  //   });
  //   await visit('/clients/tib.awi/dois/new');
  //   await fillIn('input#url-field', 'http://bbc.co.uk');
  //   await fillIn('input#publisher-field', 'the BBC');
  //   await fillIn('input#publication-year-field', 1928);

  //   assert.dom('input#url-field').hasValue('http://bbc.co.uk');
  //   assert.dom('input#publisher-field').hasValue('the BBC');
  //   assert.dom('input#publication-year-field').hasValue("1928");
  //   assert.dom('input#url-field').hasStyle({color:'rgb(46, 204, 113)'});
  //   assert.dom('input#publisher-field').hasStyle({color:'rgb(46, 204, 113)'});
  // });
});
<commit_msg>fix test. #160<commit_after>import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { currentURL, visit } from '@ember/test-helpers';
import { authenticateSession } from 'ember-simple-auth/test-support';

module('Acceptance | client_admin | client', function(hooks) {
  setupApplicationTest(hooks);

  test('visiting client AWI', async function(assert) {
    await authenticateSession({
      uid: 'tib.awi',
      name: 'Alfred Wegener Institute',
      role_id: 'client_admin',
      provider_id: 'tib',
      client_id: 'tib.awi'
    });
    await visit('/clients/tib.awi');

    assert.equal(currentURL(), '/clients/tib.awi');
    assert.dom('h2.work').hasText('Alfred Wegener Institute');
    assert.dom('a.nav-link.active').hasText('Info');
  });

  test('visiting client AWI settings', async function(assert) {
    await authenticateSession({
      uid: 'tib.awi',
      name: 'Alfred Wegener Institute',
      role_id: 'client_admin',
      provider_id: 'tib',
      client_id: 'tib.awi'
    });
    await visit('/clients/tib.awi/settings');

    assert.equal(currentURL(), '/clients/tib.awi/settings');
    assert.dom('h2.work').hasText('Alfred Wegener Institute');
    assert.dom('a.nav-link.active').hasText('Settings');
    assert.dom('button#edit-client').includesText('Update Account');
    assert.dom('button#delete-client').doesNotExist();
  });

  test('visiting client AWI prefixes', async function(assert) {
    await authenticateSession({
      uid: 'tib.awi',
      name: 'Alfred Wegener Institute',
      role_id: 'client_admin',
      provider_id: 'tib',
      client_id: 'tib.awi'
    });
    await visit('/clients/tib.awi/prefixes');

    assert.equal(currentURL(), '/clients/tib.awi/prefixes');
    assert.dom('h2.work').hasText('Alfred Wegener Institute');
    assert.dom('a.nav-link.active').hasText('Prefixes');
  });

  test('visiting client AWI dois', async function(assert) {
    await authenticateSession({
      uid: 'tib.awi',
      name: 'Alfred Wegener Institute',
      role_id: 'client_admin',
      provider_id: 'tib',
      client_id: 'tib.awi'
    });
    await visit('/clients/tib.awi/dois');

    assert.equal(currentURL(), '/clients/tib.awi/dois');
    assert.dom('h2.work').hasText('Alfred Wegener Institute');
    assert.dom('a.nav-link.active').hasText('DOIs');
    assert.dom('a#new-doi').includesText('Create DOI (Form)');
    assert.dom('a#upload-doi').includesText('Create DOI (File Upload)');
    assert.dom('a#transfer-dois').doesNotExist();
  });

  // test('creating a new DOI for client AWI renders', async function(assert) {
  //   await authenticateSession({
  //     uid: 'tib.awi',
  //     name: 'Alfred Wegener Institute',
  //     role_id: 'client_admin',
  //     provider_id: 'tib',
  //     client_id: 'tib.awi'
  //   });
  //   await visit('/clients/tib.awi/dois/new');
  //   //on landing
  //   assert.equal(currentURL(), '/clients/tib.awi/dois/new');
  //   assert.dom('h3').hasText('Create DOI (Form)');
  //   assert.dom('input#url-field').hasNoValue();
  //   assert.dom('input#publisher-field').hasNoValue();
  //   assert.dom('input#publication-year-field').hasNoValue();
  //   assert.dom('input#draft-radio').isChecked();
  //   assert.dom('input#registered-radio').isNotChecked();
  //   assert.dom('input#findable-radio').isNotChecked();
  //   assert.dom('input#suffix-field').hasAnyValue();
  // });

  // test('creating a new DOI for client AWI', async function(assert) {
  //   assert.expect(5);
  //   await authenticateSession({
  //     uid: 'tib.awi',
  //     name: 'Alfred Wegener Institute',
  //     role_id: 'client_admin',
  //     provider_id: 'tib',
  //     client_id: 'tib.awi'
  //   });
  //   await visit('/clients/tib.awi/dois/new');
  //   await fillIn('input#url-field', 'http://bbc.co.uk');
  //   await fillIn('input#publisher-field', 'the BBC');
  //   await fillIn('input#publication-year-field', 1928);

  //   assert.dom('input#url-field').hasValue('http://bbc.co.uk');
  //   assert.dom('input#publisher-field').hasValue('the BBC');
  //   assert.dom('input#publication-year-field').hasValue("1928");
  //   assert.dom('input#url-field').hasStyle({color:'rgb(46, 204, 113)'});
  //   assert.dom('input#publisher-field').hasStyle({color:'rgb(46, 204, 113)'});
  // });
});
<|endoftext|>


<commit_before>(function() {
  angular.module("typeahead", []).directive("typeahead", [
    "$timeout", function($timeout) {
      return {
        template: "
<input ng-model=\"term\" type=\"text\" autocomplete=\"off\" />

",
        scope: true,
        transclude: true,
        restrict: "E",
        compile: function(element, attributes) {
          var $el, attr, value, _ref;
          $el = element.find("input");
          _ref = attributes.$attr;
          for (attr in _ref) {
            value = _ref[attr];
            $el.attr(value, attributes[attr]);
            element[0].removeAttribute(value);
          }
          return function(scope, element, attributes) {
            var $input, $lis, $ul, currentEl, hideList, select, setAsCurrent, setCurrent, setFirstAsCurrent, setLastAsCurrent;
            $lis = $ul = currentEl = null;
            $input = element.find("input");
            $input[0].addEventListener("blur", function() {
              return hideList();
            });
            $timeout(function() {
              $ul = element.find("ul");
              $ul.addClass("hide");
              return null;
            });
            hideList = function() {
              return $lis.removeClass("show").removeClass("active").addClass("hide");
            };
            setCurrent = function(direction) {
              var oldCurrentEl;
              if (!$ul[0].getElementsByClassName("show")[0]) {
                return;
              }
              if (currentEl) {
                currentEl.className = "show";
                oldCurrentEl = currentEl;
                currentEl = currentEl["" + direction + "Sibling"];
                if (currentEl) {
                  while (currentEl && (!currentEl.className || currentEl.className.indexOf("hide") >= 0)) {
                    currentEl = currentEl["" + direction + "Sibling"];
                  }
                  if (!currentEl) {
                    currentEl = oldCurrentEl;
                  }
                  currentEl.className += " active";
                } else {
                  setAsCurrent(direction);
                }
              } else {
                setAsCurrent(direction);
              }
              return null;
            };
            setAsCurrent = function(direction) {
              if (direction === "next") {
                setFirstAsCurrent();
              } else {
                setLastAsCurrent();
              }
              return null;
            };
            setFirstAsCurrent = function() {
              currentEl = $ul[0].getElementsByClassName("show")[0];
              if (currentEl) {
                currentEl.className += " active";
              }
              return null;
            };
            setLastAsCurrent = function() {
              var els;
              els = $ul[0].getElementsByClassName("show");
              currentEl = els[els.length - 1];
              if (currentEl) {
                currentEl.className += " active";
              }
              return null;
            };
            select = function(el) {
              $timeout(function() {
                $input.val(el.innerHTML).triggerHandler("input");
                return hideList();
              });
              return null;
            };
            scope.typeaheadKeydown = function(evt) {
              switch (evt.which) {
                case 38:
                  setCurrent("previous");
                  break;
                case 40:
                case 16:
                  setCurrent("next");
                  break;
                case 13:
                case 32:
                  if (currentEl != null) {
                    select(currentEl);
                  }
                  break;
                case 27:
                  hideList();
                  currentEl = null;
                  break;
                default:
                  if (currentEl) {
                    currentEl.className = "show";
                  }
                  currentEl = null;
              }
              return null;
            };
            scope.typeaheadSelect = function(evt) {
              return select(evt.target);
            };
            return scope.typeaheadKeyup = function(evt) {
              var liEl, term, _i, _len, _ref1;
              if ((_ref1 = evt.which) === 38 || _ref1 === 40 || _ref1 === 16 || _ref1 === 32 || _ref1 === 13 || _ref1 === 27) {
                return;
              }
              if (!$lis) {
                $lis = $ul.find("li");
                $lis.addClass("hide");
                $ul.removeClass("hide");
              }
              term = $input.val().toLowerCase();
              for (_i = 0, _len = $lis.length; _i < _len; _i++) {
                liEl = $lis[_i];
                liEl.className = term && liEl.innerHTML.toLowerCase().indexOf(term) >= 0 ? "show" : "hide";
              }
              return null;
            };
          };
        }
      };
    }
  ]);

}).call(this);
<commit_msg>make LIs more dynamic<commit_after>(function() {
  angular.module("typeahead", []).directive("typeahead", [
    "$timeout", function($timeout) {
      return {
        template: "
<input ng-model=\"term\" type=\"text\" autocomplete=\"off\" />

",
        scope: true,
        transclude: true,
        restrict: "E",
        compile: function(element, attributes) {
          var $el, attr, value, _ref;
          $el = element.find("input");
          _ref = attributes.$attr;
          for (attr in _ref) {
            value = _ref[attr];
            $el.attr(value, attributes[attr]);
            element[0].removeAttribute(value);
          }
          return function(scope, element, attributes) {
            var $input, $ul, currentEl, hideList, select, setAsCurrent, setCurrent, setFirstAsCurrent, setLastAsCurrent;
            $ul = currentEl = null;
            $input = element.find("input");
            $input[0].addEventListener("blur", function() {
              return hideList();
            });
            $timeout(function() {
              $ul = element.find("ul");
              $ul.find("li").addClass("hide");
              return null;
            });
            hideList = function() {
              return $ul.find("li").removeClass("show").removeClass("active").addClass("hide");
            };
            setCurrent = function(direction) {
              var oldCurrentEl;
              if (!$ul[0].getElementsByClassName("show")[0]) {
                return;
              }
              if (currentEl) {
                currentEl.className = "show";
                oldCurrentEl = currentEl;
                currentEl = currentEl["" + direction + "Sibling"];
                if (currentEl) {
                  while (currentEl && (!currentEl.className || currentEl.className.indexOf("hide") >= 0)) {
                    currentEl = currentEl["" + direction + "Sibling"];
                  }
                  if (!currentEl) {
                    currentEl = oldCurrentEl;
                  }
                  currentEl.className += " active";
                } else {
                  setAsCurrent(direction);
                }
              } else {
                setAsCurrent(direction);
              }
              return null;
            };
            setAsCurrent = function(direction) {
              if (direction === "next") {
                setFirstAsCurrent();
              } else {
                setLastAsCurrent();
              }
              return null;
            };
            setFirstAsCurrent = function() {
              currentEl = $ul[0].getElementsByClassName("show")[0];
              if (currentEl) {
                currentEl.className += " active";
              }
              return null;
            };
            setLastAsCurrent = function() {
              var els;
              els = $ul[0].getElementsByClassName("show");
              currentEl = els[els.length - 1];
              if (currentEl) {
                currentEl.className += " active";
              }
              return null;
            };
            select = function(el) {
              $timeout(function() {
                $input.val(el.innerHTML).triggerHandler("input");
                return hideList();
              });
              return null;
            };
            scope.typeaheadKeydown = function(evt) {
              switch (evt.which) {
                case 38:
                  setCurrent("previous");
                  break;
                case 40:
                case 16:
                  setCurrent("next");
                  break;
                case 13:
                case 32:
                  if (currentEl != null) {
                    select(currentEl);
                  }
                  break;
                case 27:
                  hideList();
                  currentEl = null;
                  break;
                default:
                  if (currentEl) {
                    currentEl.className = "show";
                  }
                  currentEl = null;
              }
              return null;
            };
            scope.typeaheadSelect = function(evt) {
              return select(evt.target);
            };
            return scope.typeaheadKeyup = function(evt) {
              var liEl, term, _i, _len, _ref1, _ref2;
              if ((_ref1 = evt.which) === 38 || _ref1 === 40 || _ref1 === 16 || _ref1 === 32 || _ref1 === 13 || _ref1 === 27) {
                return;
              }
              term = $input.val().toLowerCase();
              _ref2 = $ul.find("li");
              for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
                liEl = _ref2[_i];
                liEl.className = term && liEl.innerHTML.toLowerCase().indexOf(term) >= 0 ? "show" : "hide";
              }
              return null;
            };
          };
        }
      };
    }
  ]);

}).call(this);
<|endoftext|>


<commit_before>// ------------------------------------------------------
// Object Tools
//
// (c) 2014 PonyCode Corporation
// License to distribute freely
//
// Simple native object merge
//
// { a : { b : "value", c : "value" }} MERGE { a : { b : "replace", e : "new" }}
//   - YIELDS -
// { a : { b : "replace", c : "value", e: "new" }}
//
// Primitive properties will be replace object properties
// Object properties will be merged with object properties at the same key
//
// ------------------------------------------------------

( function() {

    function Config( options ){
        this._trace = {};
        this._data = {};
	    this._options = options || {
            maxListValueLength : 60,
            maxListDepth : 8
        };
    }

    Config.prototype.set = function( keyPath, value, traceSource ){
        if( !keyPath || keyPath.length == 0 ) return;

        traceSource = traceSource || "?";
        if( keyPath === '.' ){
            this._data = this._merge( this._data, value, traceSource, "" );
        } else if( keyPath.indexOf('.') > 0 ){
            this._setValueForDottedKeyPath( this._data, value, keyPath.split('.'), traceSource, keyPath );
        }else{
            this._data[ keyPath ] = this._merge( this._data[ keyPath ], value, traceSource, keyPath );
        }
    };

    Config.prototype.get = function( keyPath, defaultValue ){
        if( !keyPath || keyPath.length == 0 ) return undefined;

        var value;

        if( keyPath === '.' ){
            value = this._data;
        } else if( keyPath.indexOf('.') != -1 ){
            value = this._getValueForDottedKeyPath( this._data, keyPath.split('.') );
        }else{
            value = this._data[ keyPath ];
        }
        return ( value === undefined ) ? defaultValue : value ;
    };

    Config.prototype.list = function(){
        var self = this;
		var chalk = require('chalk');

        var dStr = '├───';
        var depthString = '';
        for( var i=0; i < self._options.maxListDepth; i++) depthString += dStr;

	    function _isPrintableObject( object ){
		    if (object instanceof Function)  return true;
		    if (object instanceof String)    return true;
		    if (object instanceof Number)    return true;
		    if (object instanceof Date)      return true;
		    if (object instanceof RegExp)    return true;
		    if (object instanceof Buffer)    return true;
		    return false;
	    }

	    function _recursiveListObject( object, path, depth ){
            path = path || "";
            depth = depth || 0;

		    var depthIndicator = depthString.substring(0,dStr.length*(depth+1));
            for( var key in object ){
                if( object.hasOwnProperty( key ) ){

                    var line = chalk.white( depthIndicator );

	                line += chalk.white.bold( key ) + chalk.white(' : ');

	                var value = object[key];
	                var stringValue = false;
                    var shouldRecurse = false;
                    var source = self.trace( path + "." + key );

	                if( value instanceof Object ){
		                if( _isPrintableObject( value ) ){
                            stringValue = value.toString();;
		                } else {
                            if( depth < self._options.maxListDepth-1 ) shouldRecurse = true;
                            else stringValue = '...';
		                }
	                } else {
                        stringValue = value.toString();
	                }

                    if( stringValue ) line += chalk.cyan( stringValue.substring( 0, self._options.maxValueLength ) ) + ' ';
	                if( source ) line += ' [' + chalk.yellow( source ) + ']';

                    console.log( line );

                    if( shouldRecurse ){
                        _recursiveListObject( value, path + "." + key, depth+1);
                    }
                }
            }
        }

        _recursiveListObject( self._data );
    };

    Config.prototype.trace = function( key ){
        if( key === undefined ) return this._trace;
        return this._trace[ this._normalizedKey( key ) ];
    };

    Config.prototype._normalizedKey  = function( key ){
        return (key.charAt(0) !== '.' ) ? "." + key : key;
    };

    // ----------------------------
    // Helper to merge two values (objects or primitives)
    // ----------------------------
    Config.prototype._merge = function( backObject, frontObject, sourceName, currentPath ){
        if( frontObject === undefined ) {
            return backObject;
        }

        currentPath = currentPath || "";
        sourceName = sourceName || "?";
        this._trace[ this._normalizedKey(currentPath) ] = sourceName;

        if( backObject === undefined ) {
            return frontObject;
        }

        if( Array.isArray( frontObject ) || frontObject instanceof Buffer || !(frontObject instanceof Object) ){       // primitive value returned as-is, array used without merging
            return frontObject;
        }

        if( !(backObject instanceof Object) ){       // object value returned as-is
            return frontObject;
        }

        var outObject = {};
        var propertyName;

        // Clone one level of backObject
        for( propertyName in backObject ) {
            if (backObject.hasOwnProperty(propertyName)) {
                outObject[propertyName] = backObject[propertyName];
            }
        }

        // Merge in each property of front object
        for( propertyName in frontObject ) {
            if (frontObject.hasOwnProperty(propertyName)) {
                outObject[ propertyName ] = this._merge( backObject[ propertyName], frontObject[ propertyName ], sourceName, currentPath + "." + propertyName);
            }
        }

        return outObject;
    };

    // ----------------------------
    // Helper to set config with a dot-path key
    // ----------------------------
    Config.prototype._setValueForDottedKeyPath = function( targetData, configValue, configKeyPathComponents, sourceName, keyPath ){
        if( configKeyPathComponents.length === 1){
            targetData[ configKeyPathComponents ] = this._merge( targetData[ configKeyPathComponents ], configValue, sourceName, keyPath );
        } else {
            var nextComponent = configKeyPathComponents.shift();
            if( typeof targetData[nextComponent] === 'undefined' ){
                targetData[nextComponent] = {};
            } else if( typeof targetData[nextComponent] !== 'object' ){
                throw new Error("Attempt to set value with path through non object at path: " + configKeyPathComponents );
            }

            this._setValueForDottedKeyPath( targetData[nextComponent], configValue, configKeyPathComponents, sourceName, keyPath );
        }
    };

    // ----------------------------
    // Helper to get config with a dot-path key
    // ----------------------------
    Config.prototype._getValueForDottedKeyPath = function( sourceData, configKeyPathComponents ){
        if( configKeyPathComponents.length === 1 ){
            return sourceData[configKeyPathComponents[0]];
        }else{
            var nextComponent = configKeyPathComponents.shift();

            if( typeof sourceData[nextComponent] === 'undefined' ) return undefined;

            if( typeof sourceData[nextComponent] !== 'object' ){
                throw new Error("Attempt to get value with path through non object at sub-path: " + configKeyPathComponents );
            }
            return this._getValueForDottedKeyPath( sourceData[nextComponent], configKeyPathComponents );
        }
    };

    // ----------------------------
    // Expose merge objects, as a utility and for testing
    // ----------------------------
    Config.prototype.mergeObjects = function( backObject, frontObject ){
        return this._merge( backObject, frontObject );
    };

    module.exports = Config;

})();<commit_msg>list handles objects of type undefined<commit_after>// ------------------------------------------------------
// Object Tools
//
// (c) 2014 PonyCode Corporation
// License to distribute freely
//
// Simple native object merge
//
// { a : { b : "value", c : "value" }} MERGE { a : { b : "replace", e : "new" }}
//   - YIELDS -
// { a : { b : "replace", c : "value", e: "new" }}
//
// Primitive properties will be replace object properties
// Object properties will be merged with object properties at the same key
//
// ------------------------------------------------------

( function() {

    function Config( options ){
        this._trace = {};
        this._data = {};
	    this._options = options || {
            maxListValueLength : 60,
            maxListDepth : 8
        };
    }

    Config.prototype.set = function( keyPath, value, traceSource ){
        if( !keyPath || keyPath.length == 0 ) return;

        traceSource = traceSource || "?";
        if( keyPath === '.' ){
            this._data = this._merge( this._data, value, traceSource, "" );
        } else if( keyPath.indexOf('.') > 0 ){
            this._setValueForDottedKeyPath( this._data, value, keyPath.split('.'), traceSource, keyPath );
        }else{
            this._data[ keyPath ] = this._merge( this._data[ keyPath ], value, traceSource, keyPath );
        }
    };

    Config.prototype.get = function( keyPath, defaultValue ){
        if( !keyPath || keyPath.length == 0 ) return undefined;

        var value;

        if( keyPath === '.' ){
            value = this._data;
        } else if( keyPath.indexOf('.') != -1 ){
            value = this._getValueForDottedKeyPath( this._data, keyPath.split('.') );
        }else{
            value = this._data[ keyPath ];
        }
        return ( value === undefined ) ? defaultValue : value ;
    };

    Config.prototype.list = function(){
        var self = this;
		var chalk = require('chalk');

        var dStr = '├───';
        var depthString = '';
        for( var i=0; i < self._options.maxListDepth; i++) depthString += dStr;

	    function _isPrintableObject( object ){
		    if (object instanceof Function)  return true;
		    if (object instanceof String)    return true;
		    if (object instanceof Number)    return true;
		    if (object instanceof Date)      return true;
		    if (object instanceof RegExp)    return true;
		    if (object instanceof Buffer)    return true;
		    return false;
	    }

	    function _recursiveListObject( object, path, depth ){
            path = path || "";
            depth = depth || 0;

		    var depthIndicator = depthString.substring(0,dStr.length*(depth+1));
            for( var key in object ){
                if( object.hasOwnProperty( key ) ){

                    var line = chalk.white( depthIndicator );

	                line += chalk.white.bold( key ) + chalk.white(' : ');

	                var value = object[key];
	                var stringValue = false;
                    var shouldRecurse = false;
                    var source = self.trace( path + "." + key );

                    if( value === undefined ){
                        stringValue = 'undefined';
                    } else {
                        if (value instanceof Object) {
                            if (_isPrintableObject(value)) {
                                stringValue = value.toString();
                                ;
                            } else {
                                if (depth < self._options.maxListDepth - 1) shouldRecurse = true;
                                else stringValue = '...';
                            }
                        } else {
                            stringValue = value.toString();
                        }
                    }

                    if( stringValue ) line += chalk.cyan( stringValue.substring( 0, self._options.maxValueLength ) ) + ' ';
	                if( source ) line += ' [' + chalk.yellow( source ) + ']';

                    console.log( line );

                    if( shouldRecurse ){
                        _recursiveListObject( value, path + "." + key, depth+1);
                    }
                }
            }
        }

        _recursiveListObject( self._data );
    };

    Config.prototype.trace = function( key ){
        if( key === undefined ) return this._trace;
        return this._trace[ this._normalizedKey( key ) ];
    };

    Config.prototype._normalizedKey  = function( key ){
        return (key.charAt(0) !== '.' ) ? "." + key : key;
    };

    // ----------------------------
    // Helper to merge two values (objects or primitives)
    // ----------------------------
    Config.prototype._merge = function( backObject, frontObject, sourceName, currentPath ){
        if( frontObject === undefined ) {
            return backObject;
        }

        currentPath = currentPath || "";
        sourceName = sourceName || "?";
        this._trace[ this._normalizedKey(currentPath) ] = sourceName;

        if( backObject === undefined ) {
            return frontObject;
        }

        if( Array.isArray( frontObject ) || frontObject instanceof Buffer || !(frontObject instanceof Object) ){       // primitive value returned as-is, array used without merging
            return frontObject;
        }

        if( !(backObject instanceof Object) ){       // object value returned as-is
            return frontObject;
        }

        var outObject = {};
        var propertyName;

        // Clone one level of backObject
        for( propertyName in backObject ) {
            if (backObject.hasOwnProperty(propertyName)) {
                outObject[propertyName] = backObject[propertyName];
            }
        }

        // Merge in each property of front object
        for( propertyName in frontObject ) {
            if (frontObject.hasOwnProperty(propertyName)) {
                outObject[ propertyName ] = this._merge( backObject[ propertyName], frontObject[ propertyName ], sourceName, currentPath + "." + propertyName);
            }
        }

        return outObject;
    };

    // ----------------------------
    // Helper to set config with a dot-path key
    // ----------------------------
    Config.prototype._setValueForDottedKeyPath = function( targetData, configValue, configKeyPathComponents, sourceName, keyPath ){
        if( configKeyPathComponents.length === 1){
            targetData[ configKeyPathComponents ] = this._merge( targetData[ configKeyPathComponents ], configValue, sourceName, keyPath );
        } else {
            var nextComponent = configKeyPathComponents.shift();
            if( typeof targetData[nextComponent] === 'undefined' ){
                targetData[nextComponent] = {};
            } else if( typeof targetData[nextComponent] !== 'object' ){
                throw new Error("Attempt to set value with path through non object at path: " + configKeyPathComponents );
            }

            this._setValueForDottedKeyPath( targetData[nextComponent], configValue, configKeyPathComponents, sourceName, keyPath );
        }
    };

    // ----------------------------
    // Helper to get config with a dot-path key
    // ----------------------------
    Config.prototype._getValueForDottedKeyPath = function( sourceData, configKeyPathComponents ){
        if( configKeyPathComponents.length === 1 ){
            return sourceData[configKeyPathComponents[0]];
        }else{
            var nextComponent = configKeyPathComponents.shift();

            if( typeof sourceData[nextComponent] === 'undefined' ) return undefined;

            if( typeof sourceData[nextComponent] !== 'object' ){
                throw new Error("Attempt to get value with path through non object at sub-path: " + configKeyPathComponents );
            }
            return this._getValueForDottedKeyPath( sourceData[nextComponent], configKeyPathComponents );
        }
    };

    // ----------------------------
    // Expose merge objects, as a utility and for testing
    // ----------------------------
    Config.prototype.mergeObjects = function( backObject, frontObject ){
        return this._merge( backObject, frontObject );
    };

    module.exports = Config;

})();<|endoftext|>


<commit_before>/**
 * @description A element cropper plugin.
 *
 * @name selection
 * @version 1.0
 * @author mbaijs
 */
define(
[
    // App core modules
    //
    "config"
,   "cache"
,   "util.math"
,   "util.detect"
],
function( config, cache, utilMath, utilDetect )
{
    var module =
        {
            options : config.options.ui.selection
        }

    ,   $imageCreatorViewport
    ,   $imageCreatorCanvas
    ,   $imageCreatorSelection
    ,   $imageCreatorSelectionTextEdit

    ,   shiftKeyEnabled = false
    ,   editing         = false
    ;

    module.initialize = function()
    {
        // Get basic app DOM elements.
        //
        $imageCreatorViewport          = $( ".imageCreatorViewport" );
        $imageCreatorCanvas            = $( ".imageCreatorCanvas" );
        $imageCreatorSelection         = $( ".imageCreatorSelection" );
        $imageCreatorSelectionTextEdit = $( ".imageCreatorSelectionTextEdit" );

        // Listen for global app events.
        //
        $.subscribe( "layerUpdate", selectionUpdate );
        $.subscribe( "layerSelect", selectionUpdate );
        $.subscribe( "layerVisibility", selectionVisibility );

        // Set selection viewport events
        //
        $( document ).hammer({
            scale_treshold    : 0
        ,   drag_min_distance : 0
        });

        $imageCreatorViewport.bind( "dragstart", selectionPosition );
        $imageCreatorViewport.bind( "transformstart", selectionPinch );
        $imageCreatorViewport.bind( "tap", selectionTap );
        $imageCreatorViewport.bind( "mousedown mousemove", function( event )
        {
            if( ! editing ) event.preventDefault();
        });

        $( document ).bind( "keydown", selectionKeyDown );
        $( document ).bind( "keyup", selectionKeyUp );

        // Set selection grip events.
        //
        $imageCreatorSelection.delegate( ".gripScale", "mousedown", selectionScale );
        $imageCreatorSelection.delegate( ".gripRotate", "mousedown", selectionRotate );

        $imageCreatorSelectionTextEdit.bind( "change, keyup", selectionSetText );

        // Only create grips if we have mouse events.
        //
        if( ! utilDetect.NO_MOUSEEVENTS ) selectionCreate();
    };

    function selectionCreate()
    {
        var _self = this
        ,   $grip = $( "

")
        ;

        $.each( module.options.grips, function( gripIndex, grip )
        {
            var $gripClone = $grip.clone();

            $gripClone.addClass( "grip" + grip );
            $gripClone.data( "grip", grip );

            $gripClone.find( ".gripScale" ).css( "cursor", grip.toLowerCase() + "-resize" );

            $imageCreatorSelection.append( $gripClone );
        });
    }

    function selectionUpdate( event, layer )
    {
        if( event.type === "layerSelect" )
        {
            selectionDisableEditing( event );
        }

        if( layer )
        {
            $imageCreatorSelection.css({
                "left"    : layer.positionRotated.x  - module.options.offset
            ,   "top"     : layer.positionRotated.y  - module.options.offset
            ,   "width"   : layer.sizeRotated.width  + module.options.offset
            ,   "height"  : layer.sizeRotated.height + module.options.offset
            });

            if( editing )
            {
                $imageCreatorSelectionTextEdit.css({
                    "width"      : layer.sizeCurrent.width
                ,   "height"     : layer.sizeCurrent.height
                ,   "left"       : layer.position.x
                ,   "top"        : layer.position.y
                ,   "display"    : "block"
                ,   "lineHeight" : Math.floor( layer.fontSize * layer.lineHeight ) + "px"
                ,   "fontSize"   : layer.fontSize
                ,   "fontFamily" : layer.font
                ,   "transform"  : "rotate(" + layer.rotation.degrees + "deg )"
                });
            }
        }

        $imageCreatorSelection.toggle( layer && layer.visible && ! layer.locked );
    }

    function selectionKeyDown( event )
    {
        if( event.shiftKey )
        {
            shiftKeyEnabled = true;
        }
    }

    function selectionKeyUp( event )
    {
        shiftKeyEnabled = false;
    }

    function selectionVisibility( event, layer )
    {
        if( layer.selected && ! layer.locked )
        {
            $imageCreatorSelection.toggle( layer.visible );
            $imageCreatorSelectionTextEdit.toggle( editing && layer.visible );
        }
    }

    function selectionScale( event )
    {
        var layerCurrent    = cache.getLayerActive()
        ,   layerScaleStart = layerCurrent.fontSize || layerCurrent.scale
        ,   gripName        = $( event.target ).parent().data( "grip" )
        ,   scaleSliceY     = 2 / ( layerCurrent.sizeRotated.height / layerScaleStart )
        ,   scaleSliceX     = 2 / ( layerCurrent.sizeRotated.width  / layerScaleStart )
        ,   mouse =
            {
                x : event.pageX
            ,   y : event.pageY
            }
        ,   deltaScale = 0
        ;

        $( "body" ).addClass( "noSelect" );

        $( document ).bind( "mousemove.selection", function( event )
        {
            var quantifierY = scaleSliceY * Math.abs( event.pageY - mouse.y )
            ,   quantifierX = scaleSliceX * Math.abs( event.pageX - mouse.x )
            ;

            if( gripName === "N" )
            {
                deltaScale = event.pageY > mouse.y ? ( deltaScale - quantifierY ) : ( deltaScale + quantifierY );
            }

            if( gripName === "NE" )
            {
            }

            if( gripName === "E" )
            {
                deltaScale = event.pageX > mouse.x ? ( deltaScale + quantifierX ) : ( deltaScale - quantifierX );
            }

            if( gripName === "SE" )
            {

            }

            if( gripName === "S" )
            {
                deltaScale = event.pageY > mouse.y ? ( deltaScale + quantifierY ) : ( deltaScale - quantifierY );
            }

            if( gripName === "SW" )
            {

            }

            if( gripName === "W" )
            {
                deltaScale = event.pageX > mouse.x ? ( deltaScale - quantifierX ) : ( deltaScale + quantifierX );
            }

            if( gripName === "NW" )
            {

            }

            if( layerCurrent.setFontSize )
            {
                layerCurrent.setFontSize( layerScaleStart + deltaScale );
            }
            else
            {
                layerCurrent.setScale( layerScaleStart + deltaScale );
            }

            mouse.x = event.pageX;
            mouse.y = event.pageY;

            $.publish( "layerUpdate", [ layerCurrent ] );
            $.publish( "selectionScale", [ layerCurrent.fontSize || layerCurrent.scale, true ] );
        });

        $( document ).bind( "mouseup.selection", function( event )
        {
            $( document ).unbind( ".selection" );
            $( "body" ).removeClass( "noSelect" );

            return false;
        });

        return false;
    }

    function selectionRotate( event )
    {
        event.preventDefault();

        var layerCurrent            = cache.getLayerActive()
        ,   layerRotationStart      = layerCurrent.rotation.radians
        ,   selectionOffset         = $imageCreatorSelection.offset()
        ,   gripPositionCenterStart =
            {
                x : event.pageX - selectionOffset.left - ( layerCurrent.sizeRotated.width  / 2 )
            ,   y : event.pageY - selectionOffset.top  - ( layerCurrent.sizeRotated.height / 2 )
            }
        ,   gripOffsetRadians = utilMath.sanitizeRadians( Math.atan2( gripPositionCenterStart.x, -gripPositionCenterStart.y ) )
        ,   slice             = Math.PI * 2 / module.options.grips.length;
        ;

        $( "html" ).addClass( "noSelect cursorRotate" );

        $( document ).bind( "mousemove.selection", function( event )
        {
            event.preventDefault();

            var gripPositionCenter =
            {
                x : event.pageX - $imageCreatorSelection.offset().left - ( layerCurrent.sizeRotated.width  / 2 )
            ,   y : event.pageY - $imageCreatorSelection.offset().top  - ( layerCurrent.sizeRotated.height / 2 )
            }
            ,   radians = utilMath.sanitizeRadians( layerRotationStart + utilMath.sanitizeRadians( Math.atan2( gripPositionCenter.x, -gripPositionCenter.y ) ) - gripOffsetRadians )
            ;

            if( shiftKeyEnabled )
            {
                radians = Math.round( radians * 1000 / ( slice * 1000 ) ) * slice;
            }

            layerCurrent.setRotate(
            {
                radians : radians
            ,   degrees : utilMath.toDegrees( radians )
            ,   sin     : Math.sin( radians )
            ,   cos     : Math.cos( radians )
            } );

            $.publish( "layerUpdate", [ layerCurrent, true ] );
            $.publish( "selectionRotate", [ layerCurrent.rotation, true ] );
        });

        $( document ).bind( "mouseup.selection", function( event )
        {
            $( document ).unbind( ".selection" );
            $( "html" ).removeClass( "noSelect cursorRotate" );

            return false;
        });

        return false;
    }

    function selectionPosition( event )
    {
        event.gesture.preventDefault();

        var layerCurrent = cache.getLayerActive()
        ,   mouse =
            {
                x : event.gesture.deltaX
            ,   y : event.gesture.deltaY
            }
        ;

        $( "html" ).addClass( "noSelect cursorGrabbing" );

        $( document ).bind( "drag.selection", function( event )
        {
            if( ! editing && layerCurrent && layerCurrent.visible )
            {
                layerCurrent.setPosition({
                    x : event.gesture.deltaX - mouse.x
                ,   y : event.gesture.deltaY - mouse.y
                });

                $.publish( "layerUpdate", [ layerCurrent, true ] );
            }

            mouse.x = event.gesture.deltaX;
            mouse.y = event.gesture.deltaY;
        });

        $( document ).bind( "dragend.selection", function( event )
        {
            $( document ).unbind( ".selection" );
            $( "html" ).removeClass( "noSelect cursorGrabbing" );

            return false;
        });
    }

    function selectionPinch( event )
    {
        event.gesture.preventDefault();

        var layerCurrent      = cache.getLayerActive()
        ,   layerRadiansStart = layerCurrent.rotation.radians
        ,   layerScaleStart   = layerCurrent.fontSize || layerCurrent.scale
        ,   deltaScale        = event.gesture.scale
        ,   multiplierScale   = layerCurrent.fontSize ? 20 : 0.75
        ;

        $( document ).bind( "transform.selection", function( event )
        {
            var radians  = utilMath.sanitizeRadians( layerRadiansStart + utilMath.toRadians( event.gesture.rotation ) )
            ,   rotation =
                {
                    radians : radians
                ,   degrees : utilMath.toDegrees( radians )
                ,   sin     : Math.sin( radians )
                ,   cos     : Math.cos( radians )
                }
            ,   scale = layerScaleStart + ( ( event.gesture.scale - deltaScale ) * multiplierScale );
            ;

            if( ! editing && layerCurrent && layerCurrent.visible )
            {
                layerCurrent.setRotate( rotation );

                if( layerCurrent.setFontSize )
                {
                    layerCurrent.setFontSize( scale);
                }
                else
                {
                    layerCurrent.setScale(scale);
                }

                $.publish( "layerUpdate", [ layerCurrent ] );
                $.publish( "selectionRotate", [ layerCurrent.rotation, true ] );
                $.publish( "selectionScale", [ layerCurrent.fontSize || layerCurrent.scale, true ] );
            }

            return false;
        });

        $( document ).bind( "transformend.selection", function( event )
        {
            $( document ).unbind( ".selection" );

            return false;
        });
    }

    function selectionTap( event )
    {
        var layerActive = cache.getLayerActive()
        ,   offset      = $imageCreatorViewport.offset()
        ,   mouse       =
            {
                x : event.gesture.center.pageX - offset.left
            ,   y : event.gesture.center.pageY - offset.top
            }
        ,   layerFound  = false
        ;

        $.each( cache.getLayers(), function( index, layer )
        {
            if( layer.plane === "baseline" )
            {
                if( utilMath.isPointInPath( mouse, layer.sizeCurrent, layer.position, layer.rotation.radians ) )
                {
                    if( layerActive.id === layer.id && layerActive.editable )
                    {
                        selectionEnableEditing( event, layerActive );
                    }
                    else
                    {
                        cache.setLayerActiveByID( layer.id );
                    }

                    layerFound = true;
                }
            }
        });

        if( ! layerFound && editing )
        {
            selectionDisableEditing();
        }
    }

    function selectionDisableEditing( event )
    {
        if( editing )
        {
            editing = false;

            $imageCreatorSelection.removeClass( "editing" );
            $imageCreatorSelectionTextEdit.hide();
        }
    }

    function selectionEnableEditing( event, layerActive )
    {
        if( ! editing )
        {
            editing = true;

            $imageCreatorSelectionTextEdit.val( layerActive.text );

            $imageCreatorSelection.addClass( "editing" );

            selectionUpdate( event, layerActive );

            $imageCreatorSelectionTextEdit.focus();
        }
    }

    function selectionSetText()
    {
        var layerCurrent = cache.getLayerActive();

        layerCurrent.setText( this.value );

        $.publish( "layerUpdate", [ layerCurrent ] );
    }

    return module;
});<commit_msg>UI Selection: Fixed a bug in the selectionTap method. Sometimes when layers were overlapping strange behavior occured.<commit_after>/**
 * @description A element cropper plugin.
 *
 * @name selection
 * @version 1.0
 * @author mbaijs
 */
define(
[
    // App core modules
    //
    "config"
,   "cache"
,   "util.math"
,   "util.detect"
],
function( config, cache, utilMath, utilDetect )
{
    var module =
        {
            options : config.options.ui.selection
        }

    ,   $imageCreatorViewport
    ,   $imageCreatorCanvas
    ,   $imageCreatorSelection
    ,   $imageCreatorSelectionTextEdit

    ,   shiftKeyEnabled = false
    ,   editing         = false
    ;

    module.initialize = function()
    {
        // Get basic app DOM elements.
        //
        $imageCreatorViewport          = $( ".imageCreatorViewport" );
        $imageCreatorCanvas            = $( ".imageCreatorCanvas" );
        $imageCreatorSelection         = $( ".imageCreatorSelection" );
        $imageCreatorSelectionTextEdit = $( ".imageCreatorSelectionTextEdit" );

        // Listen for global app events.
        //
        $.subscribe( "layerUpdate", selectionUpdate );
        $.subscribe( "layerSelect", selectionUpdate );
        $.subscribe( "layerVisibility", selectionVisibility );

        // Set selection viewport events
        //
        $( document ).hammer({
            scale_treshold    : 0
        ,   drag_min_distance : 0
        });

        $imageCreatorViewport.bind( "dragstart", selectionPosition );
        $imageCreatorViewport.bind( "transformstart", selectionPinch );
        $imageCreatorCanvas.bind( "tap", selectionTap );
        $imageCreatorViewport.bind( "mousedown mousemove", function( event )
        {
            if( ! editing ) event.preventDefault();
        });

        $( document ).bind( "keydown", selectionKeyDown );
        $( document ).bind( "keyup", selectionKeyUp );

        // Set selection grip events.
        //
        $imageCreatorSelection.delegate( ".gripScale", "mousedown", selectionScale );
        $imageCreatorSelection.delegate( ".gripRotate", "mousedown", selectionRotate );

        $imageCreatorSelectionTextEdit.bind( "change, keyup", selectionSetText );

        // Only create grips if we have mouse events.
        //
        if( ! utilDetect.NO_MOUSEEVENTS ) selectionCreate();
    };

    function selectionCreate()
    {
        var _self = this
        ,   $grip = $( "

")
        ;

        $.each( module.options.grips, function( gripIndex, grip )
        {
            var $gripClone = $grip.clone();

            $gripClone.addClass( "grip" + grip );
            $gripClone.data( "grip", grip );

            $gripClone.find( ".gripScale" ).css( "cursor", grip.toLowerCase() + "-resize" );

            $imageCreatorSelection.append( $gripClone );
        });
    }

    function selectionUpdate( event, layer )
    {
        if( event.type === "layerSelect" )
        {
            selectionDisableEditing( event );
        }

        if( layer )
        {
            $imageCreatorSelection.css({
                "left"    : layer.positionRotated.x  - module.options.offset
            ,   "top"     : layer.positionRotated.y  - module.options.offset
            ,   "width"   : layer.sizeRotated.width  + module.options.offset
            ,   "height"  : layer.sizeRotated.height + module.options.offset
            });

            if( editing )
            {
                $imageCreatorSelectionTextEdit.css({
                    "width"      : layer.sizeCurrent.width
                ,   "height"     : layer.sizeCurrent.height
                ,   "left"       : layer.position.x
                ,   "top"        : layer.position.y
                ,   "display"    : "block"
                ,   "lineHeight" : Math.floor( layer.fontSize * layer.lineHeight ) + "px"
                ,   "fontSize"   : layer.fontSize
                ,   "fontFamily" : layer.font
                ,   "transform"  : "rotate(" + layer.rotation.degrees + "deg )"
                });
            }
        }

        $imageCreatorSelection.toggle( layer && layer.visible && ! layer.locked );
    }

    function selectionKeyDown( event )
    {
        if( event.shiftKey )
        {
            shiftKeyEnabled = true;
        }
    }

    function selectionKeyUp( event )
    {
        shiftKeyEnabled = false;
    }

    function selectionVisibility( event, layer )
    {
        if( layer.selected && ! layer.locked )
        {
            $imageCreatorSelection.toggle( layer.visible );
            $imageCreatorSelectionTextEdit.toggle( editing && layer.visible );
        }
    }

    function selectionScale( event )
    {
        var layerCurrent    = cache.getLayerActive()
        ,   layerScaleStart = layerCurrent.fontSize || layerCurrent.scale
        ,   gripName        = $( event.target ).parent().data( "grip" )
        ,   scaleSliceY     = 2 / ( layerCurrent.sizeRotated.height / layerScaleStart )
        ,   scaleSliceX     = 2 / ( layerCurrent.sizeRotated.width  / layerScaleStart )
        ,   mouse =
            {
                x : event.pageX
            ,   y : event.pageY
            }
        ,   deltaScale = 0
        ;

        $( "body" ).addClass( "noSelect" );

        $( document ).bind( "mousemove.selection", function( event )
        {
            var quantifierY = scaleSliceY * Math.abs( event.pageY - mouse.y )
            ,   quantifierX = scaleSliceX * Math.abs( event.pageX - mouse.x )
            ;

            if( gripName === "N" )
            {
                deltaScale = event.pageY > mouse.y ? ( deltaScale - quantifierY ) : ( deltaScale + quantifierY );
            }

            if( gripName === "NE" )
            {
            }

            if( gripName === "E" )
            {
                deltaScale = event.pageX > mouse.x ? ( deltaScale + quantifierX ) : ( deltaScale - quantifierX );
            }

            if( gripName === "SE" )
            {

            }

            if( gripName === "S" )
            {
                deltaScale = event.pageY > mouse.y ? ( deltaScale + quantifierY ) : ( deltaScale - quantifierY );
            }

            if( gripName === "SW" )
            {

            }

            if( gripName === "W" )
            {
                deltaScale = event.pageX > mouse.x ? ( deltaScale - quantifierX ) : ( deltaScale + quantifierX );
            }

            if( gripName === "NW" )
            {

            }

            if( layerCurrent.setFontSize )
            {
                layerCurrent.setFontSize( layerScaleStart + deltaScale );
            }
            else
            {
                layerCurrent.setScale( layerScaleStart + deltaScale );
            }

            mouse.x = event.pageX;
            mouse.y = event.pageY;

            $.publish( "layerUpdate", [ layerCurrent ] );
            $.publish( "selectionScale", [ layerCurrent.fontSize || layerCurrent.scale, true ] );
        });

        $( document ).bind( "mouseup.selection", function( event )
        {
            $( document ).unbind( ".selection" );
            $( "body" ).removeClass( "noSelect" );

            return false;
        });

        return false;
    }

    function selectionRotate( event )
    {
        event.preventDefault();

        var layerCurrent            = cache.getLayerActive()
        ,   layerRotationStart      = layerCurrent.rotation.radians
        ,   selectionOffset         = $imageCreatorSelection.offset()
        ,   gripPositionCenterStart =
            {
                x : event.pageX - selectionOffset.left - ( layerCurrent.sizeRotated.width  / 2 )
            ,   y : event.pageY - selectionOffset.top  - ( layerCurrent.sizeRotated.height / 2 )
            }
        ,   gripOffsetRadians = utilMath.sanitizeRadians( Math.atan2( gripPositionCenterStart.x, -gripPositionCenterStart.y ) )
        ,   slice             = Math.PI * 2 / module.options.grips.length;
        ;

        $( "html" ).addClass( "noSelect cursorRotate" );

        $( document ).bind( "mousemove.selection", function( event )
        {
            event.preventDefault();

            var gripPositionCenter =
            {
                x : event.pageX - $imageCreatorSelection.offset().left - ( layerCurrent.sizeRotated.width  / 2 )
            ,   y : event.pageY - $imageCreatorSelection.offset().top  - ( layerCurrent.sizeRotated.height / 2 )
            }
            ,   radians = utilMath.sanitizeRadians( layerRotationStart + utilMath.sanitizeRadians( Math.atan2( gripPositionCenter.x, -gripPositionCenter.y ) ) - gripOffsetRadians )
            ;

            if( shiftKeyEnabled )
            {
                radians = Math.round( radians * 1000 / ( slice * 1000 ) ) * slice;
            }

            layerCurrent.setRotate(
            {
                radians : radians
            ,   degrees : utilMath.toDegrees( radians )
            ,   sin     : Math.sin( radians )
            ,   cos     : Math.cos( radians )
            } );

            $.publish( "layerUpdate", [ layerCurrent, true ] );
            $.publish( "selectionRotate", [ layerCurrent.rotation, true ] );
        });

        $( document ).bind( "mouseup.selection", function( event )
        {
            $( document ).unbind( ".selection" );
            $( "html" ).removeClass( "noSelect cursorRotate" );

            return false;
        });

        return false;
    }

    function selectionPosition( event )
    {
        event.gesture.preventDefault();

        var layerCurrent = cache.getLayerActive()
        ,   mouse =
            {
                x : event.gesture.deltaX
            ,   y : event.gesture.deltaY
            }
        ;

        $( "html" ).addClass( "noSelect cursorGrabbing" );

        $( document ).bind( "drag.selection", function( event )
        {
            if( ! editing && layerCurrent && layerCurrent.visible )
            {
                layerCurrent.setPosition({
                    x : event.gesture.deltaX - mouse.x
                ,   y : event.gesture.deltaY - mouse.y
                });

                $.publish( "layerUpdate", [ layerCurrent, true ] );
            }

            mouse.x = event.gesture.deltaX;
            mouse.y = event.gesture.deltaY;
        });

        $( document ).bind( "dragend.selection", function( event )
        {
            $( document ).unbind( ".selection" );
            $( "html" ).removeClass( "noSelect cursorGrabbing" );

            return false;
        });
    }

    function selectionPinch( event )
    {
        event.gesture.preventDefault();

        var layerCurrent      = cache.getLayerActive()
        ,   layerRadiansStart = layerCurrent.rotation.radians
        ,   layerScaleStart   = layerCurrent.fontSize || layerCurrent.scale
        ,   deltaScale        = event.gesture.scale
        ,   multiplierScale   = layerCurrent.fontSize ? 20 : 0.75
        ;

        $( document ).bind( "transform.selection", function( event )
        {
            var radians  = utilMath.sanitizeRadians( layerRadiansStart + utilMath.toRadians( event.gesture.rotation ) )
            ,   rotation =
                {
                    radians : radians
                ,   degrees : utilMath.toDegrees( radians )
                ,   sin     : Math.sin( radians )
                ,   cos     : Math.cos( radians )
                }
            ,   scale = layerScaleStart + ( ( event.gesture.scale - deltaScale ) * multiplierScale );
            ;

            if( ! editing && layerCurrent && layerCurrent.visible )
            {
                layerCurrent.setRotate( rotation );

                if( layerCurrent.setFontSize )
                {
                    layerCurrent.setFontSize( scale);
                }
                else
                {
                    layerCurrent.setScale(scale);
                }

                $.publish( "layerUpdate", [ layerCurrent ] );
                $.publish( "selectionRotate", [ layerCurrent.rotation, true ] );
                $.publish( "selectionScale", [ layerCurrent.fontSize || layerCurrent.scale, true ] );
            }

            return false;
        });

        $( document ).bind( "transformend.selection", function( event )
        {
            $( document ).unbind( ".selection" );

            return false;
        });
    }

    function selectionTap( event )
    {
        var layerActive = cache.getLayerActive()
        ,   offset      = $imageCreatorViewport.offset()
        ,   mouse       =
            {
                x : event.gesture.center.pageX - offset.left
            ,   y : event.gesture.center.pageY - offset.top
            }
        ,   layerFound  = false
        ;

        $.each( cache.getLayers(), function( index, layer )
        {
            if( layer.plane === "baseline" )
            {
                if( utilMath.isPointInPath( mouse, layer.sizeCurrent, layer.position, layer.rotation.radians ) )
                {
                    if( layerActive.id === layer.id && layerActive.editable )
                    {
                        selectionEnableEditing( event, layerActive );
                    }
                    else
                    {
                        cache.setLayerActiveByID( layer.id );
                    }

                    layerFound = true;

                    return false;
                }
            }
        });

        if( ! layerFound && editing )
        {
            selectionDisableEditing();
        }
    }

    function selectionDisableEditing( event )
    {
        if( editing )
        {
            editing = false;

            $imageCreatorSelection.removeClass( "editing" );
            $imageCreatorSelectionTextEdit.hide();
        }
    }

    function selectionEnableEditing( event, layerActive )
    {
        if( ! editing )
        {
            editing = true;

            $imageCreatorSelectionTextEdit.val( layerActive.text );

            $imageCreatorSelection.addClass( "editing" );

            selectionUpdate( event, layerActive );

            $imageCreatorSelectionTextEdit.focus();
        }
    }

    function selectionSetText()
    {
        var layerCurrent = cache.getLayerActive();

        layerCurrent.setText( this.value );

        $.publish( "layerUpdate", [ layerCurrent ] );
    }

    return module;
});<|endoftext|>


<commit_before>var nconf = require('nconf');
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var mongoose = require('mongoose');
var uuid = require('uuid');
var request = require('request');
//import logger from './logger';

var empty_config = {
  permissions: [],
  roles: []
};

var Permission = mongoose.model('Permission', {
  "name" : String,
  "description" : String,
  "application" : String,
  "id" : String
});

var Role = mongoose.model('Role', {
  "name" : String,
  "description" : String,
  "id" : String,
  "application" : String,
  "permissions" : [String]
});

class SettingsDBService {

  constructor(options) {
    options = options || {};

    mongoose.connect(nconf.get('MONGODB_CONNECTION_STRING'));
    this.db = mongoose.connection;
    this.db.on('error', function (err) {
      console.log('MongoDB connection error', err);
    });
  }

  getPermissions() {
    return new Promise((resolve, reject) => {
      Permission.find(function(err, permissions) {
        if (err) {
          console.log(err);
          reject(err);
        } else {
          console.log(permissions);
          resolve(permissions);
        }
      });
    }).then((permissions) => {
      return permissions;
    });
  }

  savePermission(permission) {
    return new Promise((resolve, reject) => {
      Permission.findOne({ id : permission.id }, function(err, result) {
        if (err) {
          console.log(err);
        }

        var id = uuid.v4();
        if (result != null)
          id = result.id;

        var permissionDocument = new Permission({
          "name" : permission.name,
          "description" : permission.description,
          "application" : permission.application,
          "id" : id
        });
        permissionDocument.save((err) => {
          if (err)
            console.log(err);
          else
            resolve(permissionDocument);
        });
      });
    }).then((permissionDocument) => {
      return permissionDocument;
    });
  }

  deletePermission(permission_id) {
    return new Promise((resolve, reject) => {
      Permission.remove({ id : permission_id }, function(err, result) {
        if (err) { console.log(err); reject(err); }
        resolve(result);
      });
    }).then((permissions) => {
      return permissions;
    });
  }

  getRoles() {
    return new Promise((resolve, reject) => {
      Role.find(function(err, roles) {
        if (err) {
          console.log(err);
          reject(err);
        } else {
          resolve(roles);
        }
      });
    }).then((roles) => {
      return roles;
    });
  }

  getFlatPermissions(roles) {
    return this.getPermissions()
      .then((permissions) => {
        let permissions_flat = [];

        // Process the user's roles.
        _.forEach(roles, (role) => {
          _.forEach(permissions, (permission) => {
            if (permissions_flat.indexOf(permission.id) === -1) {
              if (role.permissions && role.permissions.indexOf(permission.id) > -1) {
                permissions_flat.push(permission.id);
              }
            }
          });
        });

        // Return a list of role objects.
        return _.chain(permissions_flat)
          .map((permission_id) => {
            return _.find(permissions, { 'id': permission_id });
          })
          .filter((permission) => {
            return permission != null;
          })
          .value();
      });
  }

  getFlatRoles(id_list) {
    return this.getRoles()
      .then((roles) => {

        // This contains a flat list of all roles and sub roles that apply to the id_list
        let roles_flat = [];

        // Recursive method to find roles.
        let findRoles = (role_id) => {
          logger.log('Finding roles for: ' + role_id);

          // Only process each role once.
          if (roles_flat.indexOf(role_id) === -1) {
            roles_flat.push(role_id);

            // Load the role and add sub roles.
            let role = _.find(roles, { 'id': role_id });
            if (role && role.sub_roles) {
              _.forEach(role.sub_roles, (sub_role_id) => {
                findRoles(sub_role_id);
              });
            }
          }
        };
            logger.info(roles_flat);
            logger.info(roles);

        // Process the user's roles.
        _.forEach(id_list, (role_id) => {
          findRoles(role_id);
        });

        // Return a list of role objects.
        return _.chain(roles_flat)
          .map((role_id) => {
            return _.find(roles, { 'id': role_id });
          })
          .filter((role) => {
            return role != null && role !== false;
          })
          .value();
      });
  }

  saveRole(role) {
    return new Promise((resolve, reject) => {
      Role.findOne({ id : role.id }, function(err, result) {
        if (err) {
          console.log(err);
        }

        var id = uuid.v4();
        if (result != null)
          id = result.id;

        var roleDocument = new Role({
          "name" : role.name,
          "description" : role.description,
          "id" : id
        });
        roleDocument.save((err) => {
          if (err)
            console.log(err);
          else
            resolve(roleDocument);
        });
      });
    }).then((roleDocument) => {
      return roleDocument;
    });
  }

  addRolePermissions(roleId, permissions) {
    return new Promise((resolve, reject) => {
      Role.findOne({ id : roleId }, function(err, role) {
        if (err) {
          console.log(err); reject(err);
        }
        if (!role.permissions)
          role.permissions = [];

        var new_permissions = _.filter(permissions, function(permission) {
          return _.indexOf(role.permissions, permission) === -1;
        });

        _.forEach(new_permissions, function(permission) {
          role.permissions.push(permission);
        });

        role.save();
        resolve(role);
      });
    }).then((role) => {
      return role;
    });
  }

  deleteRolePermission(roleId, permissionId) {
    return new Promise((resolve, reject) => {
      Role.findOne({ id : roleId }, function(err, role) {
        if (err) {
          console.log(err); reject(err);
        }
        if (!role.permissions)
          role.permissions = [];

        var permission_index = role.permissions.indexOf(permissionId);
        if (permission_index > -1) {
          role.permissions.splice(permission_index, 1);
        }

        role.save();
        resolve(role);
      });
    }).then((role) => {
      return role;
    });
  }

  addRoleSubRoles(role_id, sub_roles) {
    var role;
    return this._ensureLoaded()
    .then(() => {
      var i = _.findIndex(this.config.roles, { 'id': role_id });
      role = this.config.roles[i];

      if (!role.sub_roles) {
        role.sub_roles = [];
      }

      var new_roles = _.filter(sub_roles, function(r) {
        return _.indexOf(role.sub_roles, r) === -1;
      });

      _.forEach(new_roles, function(r) {
        role.sub_roles.push(r);
      })
    }).then(() => {
      return this._writeConfig();
    }).then(() => {
      return role;
    })
  }

  deleteRoleSubRole(role_id, sub_role_id) {
    var role;
    return this._ensureLoaded()
    .then(() => {
      var i = _.findIndex(this.config.roles, { 'id': role_id });
      role = this.config.roles[i];

      if (!role.sub_roles) {
        role.sub_roles = [];
      }

      var sub_role_index = role.sub_roles.indexOf(sub_role_id);
      if (sub_role_index > -1) {
        role.sub_roles.splice(sub_role_index, 1);
      }

    }).then(() => {
      return this._writeConfig();
    }).then(() => {
      return role;
    })
  }

  deleteRole(role_id) {
    return new Promise((resolve, reject) => {
      Role.remove({ id : role_id }, function(err, result) {
        if (err) { console.log(err); reject(err); }
        resolve(result);
      });
    }).then((roles) => {
      return roles;
    });
  }
}

module.exports = new SettingsDBService();<commit_msg>Sub roles implemented<commit_after>var nconf = require('nconf');
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var mongoose = require('mongoose');
var uuid = require('uuid');
var request = require('request');
//import logger from './logger';

var empty_config = {
  permissions: [],
  roles: []
};

var Permission = mongoose.model('Permission', {
  "name" : String,
  "description" : String,
  "application" : String,
  "id" : String
});

var Role = mongoose.model('Role', {
  "name" : String,
  "description" : String,
  "id" : String,
  "application" : String,
  "permissions" : [String],
  "sub_roles" : [String]
});

class SettingsDBService {

  constructor(options) {
    options = options || {};

    mongoose.connect(nconf.get('MONGODB_CONNECTION_STRING'));
    this.db = mongoose.connection;
    this.db.on('error', function (err) {
      console.log('MongoDB connection error', err);
    });
  }

  getPermissions() {
    return new Promise((resolve, reject) => {
      Permission.find(function(err, permissions) {
        if (err) {
          console.log(err);
          reject(err);
        } else {
          console.log(permissions);
          resolve(permissions);
        }
      });
    }).then((permissions) => {
      return permissions;
    });
  }

  savePermission(permission) {
    return new Promise((resolve, reject) => {
      Permission.findOne({ id : permission.id }, function(err, result) {
        if (err) {
          console.log(err);
        }

        var id = uuid.v4();
        if (result != null)
          id = result.id;

        var permissionDocument = new Permission({
          "name" : permission.name,
          "description" : permission.description,
          "application" : permission.application,
          "id" : id
        });
        permissionDocument.save((err) => {
          if (err)
            console.log(err);
          else
            resolve(permissionDocument);
        });
      });
    }).then((permissionDocument) => {
      return permissionDocument;
    });
  }

  deletePermission(permission_id) {
    return new Promise((resolve, reject) => {
      Permission.remove({ id : permission_id }, function(err, result) {
        if (err) { console.log(err); reject(err); }
        resolve(result);
      });
    }).then((permissions) => {
      return permissions;
    });
  }

  getRoles() {
    return new Promise((resolve, reject) => {
      Role.find(function(err, roles) {
        if (err) {
          console.log(err);
          reject(err);
        } else {
          resolve(roles);
        }
      });
    }).then((roles) => {
      return roles;
    });
  }

  getFlatPermissions(roles) {
    return this.getPermissions()
      .then((permissions) => {
        let permissions_flat = [];

        // Process the user's roles.
        _.forEach(roles, (role) => {
          _.forEach(permissions, (permission) => {
            if (permissions_flat.indexOf(permission.id) === -1) {
              if (role.permissions && role.permissions.indexOf(permission.id) > -1) {
                permissions_flat.push(permission.id);
              }
            }
          });
        });

        // Return a list of role objects.
        return _.chain(permissions_flat)
          .map((permission_id) => {
            return _.find(permissions, { 'id': permission_id });
          })
          .filter((permission) => {
            return permission != null;
          })
          .value();
      });
  }

  getFlatRoles(id_list) {
    return this.getRoles()
      .then((roles) => {

        // This contains a flat list of all roles and sub roles that apply to the id_list
        let roles_flat = [];

        // Recursive method to find roles.
        let findRoles = (role_id) => {
          logger.log('Finding roles for: ' + role_id);

          // Only process each role once.
          if (roles_flat.indexOf(role_id) === -1) {
            roles_flat.push(role_id);

            // Load the role and add sub roles.
            let role = _.find(roles, { 'id': role_id });
            if (role && role.sub_roles) {
              _.forEach(role.sub_roles, (sub_role_id) => {
                findRoles(sub_role_id);
              });
            }
          }
        };
            logger.info(roles_flat);
            logger.info(roles);

        // Process the user's roles.
        _.forEach(id_list, (role_id) => {
          findRoles(role_id);
        });

        // Return a list of role objects.
        return _.chain(roles_flat)
          .map((role_id) => {
            return _.find(roles, { 'id': role_id });
          })
          .filter((role) => {
            return role != null && role !== false;
          })
          .value();
      });
  }

  saveRole(role) {
    return new Promise((resolve, reject) => {
      Role.findOne({ id : role.id }, function(err, result) {
        if (err) {
          console.log(err);
        }

        var id = uuid.v4();
        if (result != null)
          id = result.id;

        var roleDocument = new Role({
          "name" : role.name,
          "description" : role.description,
          "id" : id
        });
        roleDocument.save((err) => {
          if (err)
            console.log(err);
          else
            resolve(roleDocument);
        });
      });
    }).then((roleDocument) => {
      return roleDocument;
    });
  }

  addRolePermissions(roleId, permissions) {
    return new Promise((resolve, reject) => {
      Role.findOne({ id : roleId }, function(err, role) {
        if (err) {
          console.log(err); reject(err);
        }
        if (!role.permissions)
          role.permissions = [];

        var new_permissions = _.filter(permissions, function(permission) {
          return _.indexOf(role.permissions, permission) === -1;
        });

        _.forEach(new_permissions, function(permission) {
          role.permissions.push(permission);
        });

        role.save();
        resolve(role);
      });
    }).then((role) => {
      return role;
    });
  }

  deleteRolePermission(roleId, permissionId) {
    return new Promise((resolve, reject) => {
      Role.findOne({ id : roleId }, function(err, role) {
        if (err) {
          console.log(err); reject(err);
        }
        if (!role.permissions)
          role.permissions = [];

        var permission_index = role.permissions.indexOf(permissionId);
        if (permission_index > -1) {
          role.permissions.splice(permission_index, 1);
        }

        role.save();
        resolve(role);
      });
    }).then((role) => {
      return role;
    });
  }

  addRoleSubRoles(roleId, sub_roles) {
    return new Promise((resolve, reject) => {
      Role.findOne({ id : roleId }, function(err, role) {
        if (err) {
          console.log(err); reject(err);
        }
        if (!role.sub_roles)
          role.sub_roles = [];

        var new_sub_roles = _.filter(sub_roles, function(sub_role) {
          return _.indexOf(role.sub_roles, sub_role) === -1;
        });

        _.forEach(new_sub_roles, function(sub_role) {
          role.sub_roles.push(sub_role);
        });

        role.save();
        resolve(role);
      });
    }).then((role) => {
      return role;
    });
  }

  deleteRoleSubRole(roleId, sub_role_id) {
    return new Promise((resolve, reject) => {
      Role.findOne({ id : roleId }, function(err, role) {
        if (err) {
          console.log(err); reject(err);
        }
        if (!role.sub_roles)
          role.sub_roles = [];

        var role_index = role.sub_roles.indexOf(sub_role_id);
        if (role_index > -1) {
          role.sub_roles.splice(role_index, 1);
        }

        role.save();
        resolve(role);
      });
    }).then((role) => {
      return role;
    });
  }

  deleteRole(role_id) {
    return new Promise((resolve, reject) => {
      Role.remove({ id : role_id }, function(err, result) {
        if (err) { console.log(err); reject(err); }
        resolve(result);
      });
    }).then((roles) => {
      return roles;
    });
  }
}

module.exports = new SettingsDBService();<|endoftext|>


<commit_before>import BaseImageResource from './BaseImageResource';
import { settings } from '@pixi/settings';

/**
 * Resource type for HTMLImageElement.
 * @class
 * @extends PIXI.resources.BaseImageResource
 * @memberof PIXI.resources
 */
export default class ImageResource extends BaseImageResource
{
    /**
     * @param {HTMLImageElement|string} source - image source or URL
     * @param {boolean} [options.autoLoad=true] start loading process
     * @param {boolean} [options.createBitmap=true] whether its required to create
     *        a bitmap before upload defaults true
     * @param {boolean} [options.crossorigin=true] - Load image using cross origin
     */
    constructor(source, options)
    {
        options = options || {};

        if (!(source instanceof HTMLImageElement))
        {
            const imageElement = new Image();

            BaseImageResource.crossOrigin(imageElement, source, options.crossorigin);

            imageElement.src = source;
            source = imageElement;
        }

        super(source);

        /**
         * URL of the image source
         * @member {string}
         */
        this.url = source.src;

        /**
         * When process is completed
         * @member {Promise}
         * @private
         */
        this._process = null;

        /**
         * If the image should be disposed after upload
         * @member {boolean}
         * @default false
         */
        this.preserveBitmap = false;

        /**
         * If capable, convert the image using createImageBitmap API
         * @member {boolean}
         * @default PIXI.settings.CREATE_IMAGE_BITMAP
         */
        this.createBitmap = options.createBitmap !== false && settings.CREATE_IMAGE_BITMAP && !!window.createImageBitmap;

        /**
         * The ImageBitmap element created for HTMLImageElement
         * @member {ImageBitmap}
         * @default null
         */
        this.bitmap = null;

        /**
         * Promise when loading
         * @member {Promise}
         * @private
         * @default null
         */
        this._load = null;

        if (options.autoLoad !== false)
        {
            this.load();
        }
    }

    /**
     * returns a promise when image will be loaded and processed
     *
     * @param {boolean} [createBitmap=true] whether process image into bitmap
     * @returns {Promise}
     */
    load(createBitmap)
    {
        if (createBitmap !== undefined)
        {
            this.createBitmap = createBitmap;
        }

        if (this._load)
        {
            return this._load;
        }

        this._load = new Promise((resolve) =>
        {
            this.url = this.source.src;
            const { source } = this;

            const completed = () =>
            {
                if (this.destroyed)
                {
                    return;
                }
                source.onload = null;
                source.onerror = null;

                this.resize(source.width, source.height);
                this._load = null;

                if (this.createBitmap)
                {
                    resolve(this.process());
                }
                else
                {
                    resolve(this);
                }
            };

            if (source.complete && source.src)
            {
                completed();
            }
            else
            {
                source.onload = completed;
            }
        });

        return this._load;
    }

    /**
     * Called when we need to convert image into BitmapImage.
     * Can be called multiple times, real promise is cached inside.
     *
     * @returns {Promise} cached promise to fill that bitmap
     */
    process()
    {
        if (this._process !== null)
        {
            return this._process;
        }
        if (this.bitmap !== null || !window.createImageBitmap)
        {
            return Promise.resolve(this);
        }

        this._process = window.createImageBitmap(this.source)
            .then((bitmap) =>
            {
                if (this.destroyed)
                {
                    return Promise.reject();
                }
                this.bitmap = bitmap;
                this.update();
                this._process = null;

                return Promise.resolve(this);
            });

        return this._process;
    }

    /**
     * Upload the image resource to GPU.
     *
     * @param {PIXI.Renderer} renderer - Renderer to upload to
     * @param {PIXI.BaseTexture} baseTexture - BaseTexture for this resource
     * @param {PIXI.glCore.Texture} glTexture - GLTexture to use
     */
    upload(renderer, baseTexture, glTexture)
    {
        if (this.createBitmap)
        {
            if (!this.bitmap)
            {
                // yeah, ignore the output
                this.process();
                if (!this.bitmap)
                {
                    return false;
                }
            }

            super.upload(renderer, baseTexture, glTexture, this.bitmap);

            if (!this.preserveBitmap)
            {
                if (this.bitmap.close)
                {
                    this.bitmap.close();
                }

                this.bitmap = null;
            }
        }
        else
        {
            super.upload(renderer, baseTexture, glTexture);
        }

        return true;
    }

    /**
     * Destroys this texture
     * @override
     */
    dispose()
    {
        super.dispose();

        if (this.bitmap)
        {
            this.bitmap.close();
            this.bitmap = null;
        }
        this._process = null;
        this._load = null;
    }
}
<commit_msg>Adds premultiplyAlpha option to ImageResource (#4729)<commit_after>import BaseImageResource from './BaseImageResource';
import { settings } from '@pixi/settings';

/**
 * Resource type for HTMLImageElement.
 * @class
 * @extends PIXI.resources.BaseImageResource
 * @memberof PIXI.resources
 */
export default class ImageResource extends BaseImageResource
{
    /**
     * @param {HTMLImageElement|string} source - image source or URL
     * @param {boolean} [options.autoLoad=true] start loading process
     * @param {boolean} [options.createBitmap=true] whether its required to create
     *        a bitmap before upload defaults true
     * @param {boolean} [options.crossorigin=true] - Load image using cross origin
     * @param {boolean} [options.premultiplyAlpha=true] - Premultiply image alpha in bitmap
     */
    constructor(source, options)
    {
        options = options || {};

        if (!(source instanceof HTMLImageElement))
        {
            const imageElement = new Image();

            BaseImageResource.crossOrigin(imageElement, source, options.crossorigin);

            imageElement.src = source;
            source = imageElement;
        }

        super(source);

        /**
         * URL of the image source
         * @member {string}
         */
        this.url = source.src;

        /**
         * When process is completed
         * @member {Promise}
         * @private
         */
        this._process = null;

        /**
         * If the image should be disposed after upload
         * @member {boolean}
         * @default false
         */
        this.preserveBitmap = false;

        /**
         * If capable, convert the image using createImageBitmap API
         * @member {boolean}
         * @default PIXI.settings.CREATE_IMAGE_BITMAP
         */
        this.createBitmap = options.createBitmap !== false && settings.CREATE_IMAGE_BITMAP && !!window.createImageBitmap;

        /**
         * Controls texture premultiplyAlpha field
         * Copies from options
         * @member {boolean|null}
         * @readonly
         */
        this.premultiplyAlpha = options.premultiplyAlpha !== false;

        /**
         * The ImageBitmap element created for HTMLImageElement
         * @member {ImageBitmap}
         * @default null
         */
        this.bitmap = null;

        /**
         * Promise when loading
         * @member {Promise}
         * @private
         * @default null
         */
        this._load = null;

        if (options.autoLoad !== false)
        {
            this.load();
        }
    }

    /**
     * returns a promise when image will be loaded and processed
     *
     * @param {boolean} [createBitmap=true] whether process image into bitmap
     * @returns {Promise}
     */
    load(createBitmap)
    {
        if (createBitmap !== undefined)
        {
            this.createBitmap = createBitmap;
        }

        if (this._load)
        {
            return this._load;
        }

        this._load = new Promise((resolve) =>
        {
            this.url = this.source.src;
            const { source } = this;

            const completed = () =>
            {
                if (this.destroyed)
                {
                    return;
                }
                source.onload = null;
                source.onerror = null;

                this.resize(source.width, source.height);
                this._load = null;

                if (this.createBitmap)
                {
                    resolve(this.process());
                }
                else
                {
                    resolve(this);
                }
            };

            if (source.complete && source.src)
            {
                completed();
            }
            else
            {
                source.onload = completed;
            }
        });

        return this._load;
    }

    /**
     * Called when we need to convert image into BitmapImage.
     * Can be called multiple times, real promise is cached inside.
     *
     * @returns {Promise} cached promise to fill that bitmap
     */
    process()
    {
        if (this._process !== null)
        {
            return this._process;
        }
        if (this.bitmap !== null || !window.createImageBitmap)
        {
            return Promise.resolve(this);
        }

        this._process = window.createImageBitmap(this.source,
            0, 0, this.source.width, this.source.height,
            {
                premultiplyAlpha: this.premultiplyAlpha ? 'premultiply' : 'none',
            })
            .then((bitmap) =>
            {
                if (this.destroyed)
                {
                    return Promise.reject();
                }
                this.bitmap = bitmap;
                this.update();
                this._process = null;

                return Promise.resolve(this);
            });

        return this._process;
    }

    /**
     * Upload the image resource to GPU.
     *
     * @param {PIXI.Renderer} renderer - Renderer to upload to
     * @param {PIXI.BaseTexture} baseTexture - BaseTexture for this resource
     * @param {PIXI.glCore.Texture} glTexture - GLTexture to use
     */
    upload(renderer, baseTexture, glTexture)
    {
        baseTexture.premultiplyAlpha = this.premultiplyAlpha;

        if (this.createBitmap)
        {
            if (!this.bitmap)
            {
                // yeah, ignore the output
                this.process();
                if (!this.bitmap)
                {
                    return false;
                }
            }

            super.upload(renderer, baseTexture, glTexture, this.bitmap);

            if (!this.preserveBitmap)
            {
                if (this.bitmap.close)
                {
                    this.bitmap.close();
                }

                this.bitmap = null;
            }
        }
        else
        {
            super.upload(renderer, baseTexture, glTexture);
        }

        return true;
    }

    /**
     * Destroys this texture
     * @override
     */
    dispose()
    {
        super.dispose();

        if (this.bitmap)
        {
            this.bitmap.close();
            this.bitmap = null;
        }
        this._process = null;
        this._load = null;
    }
}
<|endoftext|>