<commit_before>// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

couchTests.rewrite = function(debug) {
  if (debug) debugger;
  var dbNames = ["test_suite_db", "test_suite_db/with_slashes"];
  for (var i=0; i < dbNames.length; i++) {
    var db = new CouchDB(dbNames[i]);
    var dbName = encodeURIComponent(dbNames[i]);
    db.deleteDb();
    db.createDb();

    var designDoc = {
      _id:"_design/test",
      language: "javascript",
      _attachments:{
        "foo.txt": {
          content_type:"text/plain",
          data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
        }
      },
      rewrites: stringFun(function(req) {
        prefix = req.path[4];
        if (prefix === 'foo') {
            return 'foo.txt';
        }
        if (prefix === 'foo2') {
            return {path: 'foo.txt', method: 'GET'};
        }
        if (prefix === 'hello') {
            if (req.method != 'PUT') {
                return
            }
            id = req.path[5];
            return {path: '_update/hello/' + id};
        }
        if (prefix === 'welcome') {
            if (req.path.length == 6){
                name = req.path[5];
                return {path: '_show/welcome', query: {'name': name}};
            }
            return '_show/welcome';
        }
        if (prefix === 'welcome2') {
            return {path: '_show/welcome', query: {'name': 'user'}};
        }
        if (prefix === 'welcome3') {
            name = req.path[5];
            if (req.method == 'PUT') {
                path = '_update/welcome2/' + name;
            } else if (req.method == 'GET') {
                path = '_show/welcome2/' + name;
            } else {
                return;
            }
            return path;
        }
        if (prefix === 'welcome4') {
            return {path: '_show/welcome3',  query: {name: req.path[5]}};
        }
        if (prefix === 'welcome5') {
            rest = req.path.slice(5).join('/');
            return {path: '_show/' + rest,  query: {name: rest}};
        }
        if (prefix === 'basicView') {
            rest = req.path.slice(5).join('/');
            return {path: '_view/basicView'};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/basicView') {
            return {path: '_list/simpleForm/basicView'};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/basicViewFixed') {
            return {path: '_list/simpleForm/basicView',
                    query: {startkey: '"3"', endkey: '"8"'}};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/complexView') {
            return {path: '_list/simpleForm/complexView',
                    query: {key: JSON.stringify([1,2])}};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/complexView2') {
            return {path: '_list/simpleForm/complexView',
                    query: {key: JSON.stringify(['test', {}])}};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/complexView3') {
            return {path: '_list/simpleForm/complexView',
                    query: {key: JSON.stringify(['test', ['test', 'essai']])}};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/complexView4') {
            return {path: '_list/simpleForm/complexView2',
                    query: {key: JSON.stringify({"c": 1})}};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/complexView4') {
            return {path: '_list/simpleForm/complexView2',
                    query: {key: JSON.stringify({"c": 1})}};
        }
        if (req.path.slice(4).join('/') === '/') {
            return {path: '_view/basicView'};
        }
        if (prefix === 'db') {
            return {path: '../../' + req.path.slice(5).join('/')};
        }
      }),
      lists: {
        simpleForm: stringFun(function(head, req) {
          log("simpleForm");
          send('
');
          var row, row_number = 0, prevKey, firstKey = null;
          while (row = getRow()) {
            row_number += 1;
            if (!firstKey) firstKey = row.key;
            prevKey = row.key;
            send('\n
Key: '+row.key
                 +' Value: '+row.value
                 +' LineNo: '+row_number+'
');
          }
          return '

FirstKey: '+ firstKey + ' LastKey: '+ prevKey+'
';
        }),
      },
      shows: {
        "welcome": stringFun(function(doc,req) {
          return "Welcome " + req.query["name"];
        }),
        "welcome2": stringFun(function(doc, req) {
          return "Welcome " + doc.name;
        }),
        "welcome3": stringFun(function(doc,req) {
          return "Welcome " + req.query["name"];
        })
      },
      updates: {
        "hello" : stringFun(function(doc, req) {
          if (!doc) {
            if (req.id) {
              return [{
                _id : req.id
              }, "New World"]
            }
            return [null, "Empty World"];
          }
          doc.world = "hello";
          doc.edited_by = req.userCtx;
          return [doc, "hello doc"];
        }),
        "welcome2": stringFun(function(doc, req) {
          if (!doc) {
            if (req.id) {
              return [{
                _id: req.id,
                name: req.id
              }, "New World"]
            }
            return [null, "Empty World"];
          }
          return [doc, "hello doc"];
        })
      },
      views : {
        basicView : {
          map : stringFun(function(doc) {
            if (doc.integer) {
              emit(doc.integer, doc.string);
            }

          })
        },
        complexView: {
          map: stringFun(function(doc) {
            if (doc.type == "complex") {
              emit([doc.a, doc.b], doc.string);
            }
          })
        },
        complexView2: {
          map: stringFun(function(doc) {
            if (doc.type == "complex") {
              emit(doc.a, doc.string);
            }
          })
        },
        complexView3: {
          map: stringFun(function(doc) {
            if (doc.type == "complex") {
              emit(doc.b, doc.string);
            }
          })
        }
      }
    }

    db.save(designDoc);

    var docs = makeDocs(0, 10);
    db.bulkSave(docs);

    var docs2 = [
      {"a": 1, "b": 1, "string": "doc 1", "type": "complex"},
      {"a": 1, "b": 2, "string": "doc 2", "type": "complex"},
      {"a": "test", "b": {}, "string": "doc 3", "type": "complex"},
      {"a": "test", "b": ["test", "essai"], "string": "doc 4", "type": "complex"},
      {"a": {"c": 1}, "b": "", "string": "doc 5", "type": "complex"}
    ];

    db.bulkSave(docs2);

    // test simple rewriting

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo");
    T(req.responseText == "This is a base64 encoded text");
    T(req.getResponseHeader("Content-Type") == "text/plain");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo2");
    T(req.responseText == "This is a base64 encoded text");
    T(req.getResponseHeader("Content-Type") == "text/plain");

    // test POST
    // hello update world

    var doc = {"word":"plankton", "name":"Rusty"}
    var resp = db.save(doc);
    T(resp.ok);
    var docid = resp.id;

    xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/hello/"+docid);
    T(xhr.status == 201);
    T(xhr.responseText == "hello doc");
    T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")))

    doc = db.open(docid);
    T(doc.world == "hello");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome?name=user");
    T(req.responseText == "Welcome user");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome/user");
    T(req.responseText == "Welcome user");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome2");
    T(req.responseText == "Welcome user");

    xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
    T(xhr.status == 201);
    T(xhr.responseText == "New World");
    T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")));

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
    T(xhr.responseText == "Welcome test");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome4/user");
    T(req.responseText == "Welcome user");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome5/welcome3");
    T(req.responseText == "Welcome welcome3");

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/basicView");
    T(xhr.status == 200, "view call");
    T(/{"total_rows":9/.test(xhr.responseText));

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView");
    T(xhr.status == 200, "with query params");
    T(/FirstKey: [1, 2]/.test(xhr.responseText));

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView2");
    T(xhr.status == 200, "with query params");
    T(/Value: doc 3/.test(xhr.responseText));

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView3");
    T(xhr.status == 200, "with query params");
    T(/Value: doc 4/.test(xhr.responseText));

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView4");
    T(xhr.status == 200, "with query params");
    T(/Value: doc 5/.test(xhr.responseText));

    // COUCHDB-2031 - path normalization versus qs params
    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/db/_design/test?meta=true");
    T(xhr.status == 200, "path normalization works with qs params");
    var result = JSON.parse(xhr.responseText);
    T(result['_id'] == "_design/test");
    T(typeof(result['_revs_info']) === "object");

    // test early response
    var ddoc = {
      _id: "_design/response",
      rewrites: stringFun(function(req){
        status = parseInt(req.query.status);
        return {code: status,
                body: JSON.stringify({"status": status}),
                headers: {'x-foo': 'bar', 'Content-Type': 'application/json'}};
      })
    }
    T(db.save(ddoc).ok);
    var xhr = CouchDB.request("GET", "/"+dbName+"/_design/response/_rewrite?status=200");
    T(xhr.status == 200);
    T(xhr.headers['x-foo'] == 'bar');
    T(xhr.responseText == '{"status":200}');
    var xhr = CouchDB.request("GET", "/"+dbName+"/_design/response/_rewrite?status=451");
    T(xhr.status == 451);
    T(xhr.headers['Content-Type'] == 'application/json');
    var xhr = CouchDB.request("GET", "/"+dbName+"/_design/response/_rewrite?status=600");
    T(xhr.status == 500);

    // test path relative to server
    var ddoc = {
      _id: "_design/relative",
      rewrites: stringFun(function(req){
        return '../../../_uuids'
      })
    }
    T(db.save(ddoc).ok);
    var xhr = CouchDB.request("GET", "/"+dbName+"/_design/relative/_rewrite/uuids");
    T(xhr.status == 200);
    var result = JSON.parse(xhr.responseText);
    T(result.uuids.length == 1);

    // test loop
    var ddoc_loop = {
      _id: "_design/loop",
      rewrites: stringFun(function(req) {
        return '_rewrite/loop';
      })
    };
    db.save(ddoc_loop);
    var url = "/"+dbName+"/_design/loop/_rewrite/loop";
    var xhr = CouchDB.request("GET", url);
    TEquals(400, xhr.status);
  }
}
<commit_msg>Fix rewrite_js test: do not delete/create a DB in rapid succession<commit_after>// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

couchTests.rewrite = function(debug) {
  if (debug) debugger;
  var dbNames = [get_random_db_name(), get_random_db_name() + "test_suite_db/with_slashes"];
  for (var i=0; i < dbNames.length; i++) {
    var db = new CouchDB(dbNames[i]);
    var dbName = encodeURIComponent(dbNames[i]);
    db.deleteDb();
    db.createDb();

    var designDoc = {
      _id:"_design/test",
      language: "javascript",
      _attachments:{
        "foo.txt": {
          content_type:"text/plain",
          data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
        }
      },
      rewrites: stringFun(function(req) {
        prefix = req.path[4];
        if (prefix === 'foo') {
            return 'foo.txt';
        }
        if (prefix === 'foo2') {
            return {path: 'foo.txt', method: 'GET'};
        }
        if (prefix === 'hello') {
            if (req.method != 'PUT') {
                return
            }
            id = req.path[5];
            return {path: '_update/hello/' + id};
        }
        if (prefix === 'welcome') {
            if (req.path.length == 6){
                name = req.path[5];
                return {path: '_show/welcome', query: {'name': name}};
            }
            return '_show/welcome';
        }
        if (prefix === 'welcome2') {
            return {path: '_show/welcome', query: {'name': 'user'}};
        }
        if (prefix === 'welcome3') {
            name = req.path[5];
            if (req.method == 'PUT') {
                path = '_update/welcome2/' + name;
            } else if (req.method == 'GET') {
                path = '_show/welcome2/' + name;
            } else {
                return;
            }
            return path;
        }
        if (prefix === 'welcome4') {
            return {path: '_show/welcome3',  query: {name: req.path[5]}};
        }
        if (prefix === 'welcome5') {
            rest = req.path.slice(5).join('/');
            return {path: '_show/' + rest,  query: {name: rest}};
        }
        if (prefix === 'basicView') {
            rest = req.path.slice(5).join('/');
            return {path: '_view/basicView'};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/basicView') {
            return {path: '_list/simpleForm/basicView'};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/basicViewFixed') {
            return {path: '_list/simpleForm/basicView',
                    query: {startkey: '"3"', endkey: '"8"'}};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/complexView') {
            return {path: '_list/simpleForm/complexView',
                    query: {key: JSON.stringify([1,2])}};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/complexView2') {
            return {path: '_list/simpleForm/complexView',
                    query: {key: JSON.stringify(['test', {}])}};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/complexView3') {
            return {path: '_list/simpleForm/complexView',
                    query: {key: JSON.stringify(['test', ['test', 'essai']])}};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/complexView4') {
            return {path: '_list/simpleForm/complexView2',
                    query: {key: JSON.stringify({"c": 1})}};
        }
        if (req.path.slice(4).join('/') === 'simpleForm/complexView4') {
            return {path: '_list/simpleForm/complexView2',
                    query: {key: JSON.stringify({"c": 1})}};
        }
        if (req.path.slice(4).join('/') === '/') {
            return {path: '_view/basicView'};
        }
        if (prefix === 'db') {
            return {path: '../../' + req.path.slice(5).join('/')};
        }
      }),
      lists: {
        simpleForm: stringFun(function(head, req) {
          log("simpleForm");
          send('
');
          var row, row_number = 0, prevKey, firstKey = null;
          while (row = getRow()) {
            row_number += 1;
            if (!firstKey) firstKey = row.key;
            prevKey = row.key;
            send('\n
Key: '+row.key
                 +' Value: '+row.value
                 +' LineNo: '+row_number+'
');
          }
          return '

FirstKey: '+ firstKey + ' LastKey: '+ prevKey+'
';
        }),
      },
      shows: {
        "welcome": stringFun(function(doc,req) {
          return "Welcome " + req.query["name"];
        }),
        "welcome2": stringFun(function(doc, req) {
          return "Welcome " + doc.name;
        }),
        "welcome3": stringFun(function(doc,req) {
          return "Welcome " + req.query["name"];
        })
      },
      updates: {
        "hello" : stringFun(function(doc, req) {
          if (!doc) {
            if (req.id) {
              return [{
                _id : req.id
              }, "New World"]
            }
            return [null, "Empty World"];
          }
          doc.world = "hello";
          doc.edited_by = req.userCtx;
          return [doc, "hello doc"];
        }),
        "welcome2": stringFun(function(doc, req) {
          if (!doc) {
            if (req.id) {
              return [{
                _id: req.id,
                name: req.id
              }, "New World"]
            }
            return [null, "Empty World"];
          }
          return [doc, "hello doc"];
        })
      },
      views : {
        basicView : {
          map : stringFun(function(doc) {
            if (doc.integer) {
              emit(doc.integer, doc.string);
            }

          })
        },
        complexView: {
          map: stringFun(function(doc) {
            if (doc.type == "complex") {
              emit([doc.a, doc.b], doc.string);
            }
          })
        },
        complexView2: {
          map: stringFun(function(doc) {
            if (doc.type == "complex") {
              emit(doc.a, doc.string);
            }
          })
        },
        complexView3: {
          map: stringFun(function(doc) {
            if (doc.type == "complex") {
              emit(doc.b, doc.string);
            }
          })
        }
      }
    }

    db.save(designDoc);

    var docs = makeDocs(0, 10);
    db.bulkSave(docs);

    var docs2 = [
      {"a": 1, "b": 1, "string": "doc 1", "type": "complex"},
      {"a": 1, "b": 2, "string": "doc 2", "type": "complex"},
      {"a": "test", "b": {}, "string": "doc 3", "type": "complex"},
      {"a": "test", "b": ["test", "essai"], "string": "doc 4", "type": "complex"},
      {"a": {"c": 1}, "b": "", "string": "doc 5", "type": "complex"}
    ];

    db.bulkSave(docs2);

    // test simple rewriting

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo");
    T(req.responseText == "This is a base64 encoded text");
    T(req.getResponseHeader("Content-Type") == "text/plain");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo2");
    T(req.responseText == "This is a base64 encoded text");
    T(req.getResponseHeader("Content-Type") == "text/plain");

    // test POST
    // hello update world

    var doc = {"word":"plankton", "name":"Rusty"}
    var resp = db.save(doc);
    T(resp.ok);
    var docid = resp.id;

    xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/hello/"+docid);
    T(xhr.status == 201);
    T(xhr.responseText == "hello doc");
    T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")))

    doc = db.open(docid);
    T(doc.world == "hello");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome?name=user");
    T(req.responseText == "Welcome user");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome/user");
    T(req.responseText == "Welcome user");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome2");
    T(req.responseText == "Welcome user");

    xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
    T(xhr.status == 201);
    T(xhr.responseText == "New World");
    T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")));

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
    T(xhr.responseText == "Welcome test");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome4/user");
    T(req.responseText == "Welcome user");

    req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome5/welcome3");
    T(req.responseText == "Welcome welcome3");

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/basicView");
    T(xhr.status == 200, "view call");
    T(/{"total_rows":9/.test(xhr.responseText));

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView");
    T(xhr.status == 200, "with query params");
    T(/FirstKey: [1, 2]/.test(xhr.responseText));

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView2");
    T(xhr.status == 200, "with query params");
    T(/Value: doc 3/.test(xhr.responseText));

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView3");
    T(xhr.status == 200, "with query params");
    T(/Value: doc 4/.test(xhr.responseText));

    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView4");
    T(xhr.status == 200, "with query params");
    T(/Value: doc 5/.test(xhr.responseText));

    // COUCHDB-2031 - path normalization versus qs params
    xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/db/_design/test?meta=true");
    T(xhr.status == 200, "path normalization works with qs params");
    var result = JSON.parse(xhr.responseText);
    T(result['_id'] == "_design/test");
    T(typeof(result['_revs_info']) === "object");

    // test early response
    var ddoc = {
      _id: "_design/response",
      rewrites: stringFun(function(req){
        status = parseInt(req.query.status);
        return {code: status,
                body: JSON.stringify({"status": status}),
                headers: {'x-foo': 'bar', 'Content-Type': 'application/json'}};
      })
    }
    T(db.save(ddoc).ok);
    var xhr = CouchDB.request("GET", "/"+dbName+"/_design/response/_rewrite?status=200");
    T(xhr.status == 200);
    T(xhr.headers['x-foo'] == 'bar');
    T(xhr.responseText == '{"status":200}');
    var xhr = CouchDB.request("GET", "/"+dbName+"/_design/response/_rewrite?status=451");
    T(xhr.status == 451);
    T(xhr.headers['Content-Type'] == 'application/json');
    var xhr = CouchDB.request("GET", "/"+dbName+"/_design/response/_rewrite?status=600");
    T(xhr.status == 500);

    // test path relative to server
    var ddoc = {
      _id: "_design/relative",
      rewrites: stringFun(function(req){
        return '../../../_uuids'
      })
    }
    T(db.save(ddoc).ok);
    var xhr = CouchDB.request("GET", "/"+dbName+"/_design/relative/_rewrite/uuids");
    T(xhr.status == 200);
    var result = JSON.parse(xhr.responseText);
    T(result.uuids.length == 1);

    // test loop
    var ddoc_loop = {
      _id: "_design/loop",
      rewrites: stringFun(function(req) {
        return '_rewrite/loop';
      })
    };
    db.save(ddoc_loop);
    var url = "/"+dbName+"/_design/loop/_rewrite/loop";
    var xhr = CouchDB.request("GET", url);
    TEquals(400, xhr.status);
  }
}
<|endoftext|>


<commit_before>/**
 * @author qiao / https://github.com/qiao
 * @author mrdoob / http://mrdoob.com
 * @author alteredq / http://alteredqualia.com/
 * @author WestLangley / http://github.com/WestLangley
 */

THREE.OrbitControls = function ( object, domElement, upVector ) {

    this.object = object;
    this.domElement = ( domElement !== undefined ) ? domElement : document;
    this.upVector = upVector || new THREE.Vector3(0,1,0);

    // API
    this.enabled = true;

    this.center = new THREE.Vector3();

    this.userZoom = true;
    this.userZoomSpeed = 1.0;

    this.userRotate = true;
    this.userRotateSpeed = 1.0;

    this.userPan = true;
    this.userPanSpeed = 2.0;

    this.autoRotate = false;
    this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60

    this.minPolarAngle = 0; // radians
    this.maxPolarAngle = Math.PI; // radians

    this.minDistance = 0.2;
    this.maxDistance = 600;

    // 65 /*A*/, 83 /*S*/, 68 /*D*/
    this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40, ROTATE: 65, ZOOM: 83, PAN: 68 };

    // internals

    var scope = this;

    var EPS = 0.000001;
    var PIXELS_PER_ROUND = 1800;

    var rotateStart = new THREE.Vector2();
    var rotateEnd = new THREE.Vector2();
    var rotateDelta = new THREE.Vector2();

    var zoomStart = new THREE.Vector2();
    var zoomEnd = new THREE.Vector2();
    var zoomDelta = new THREE.Vector2();

    var phiDelta = 0;
    var thetaDelta = 0;
    var scale = 1;

    var origPhiDelta = phiDelta;
    var origThetaDelta = thetaDelta;
    var origScale = scale;

    var lastPosition = new THREE.Vector3();

    var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 };
    var state = STATE.NONE;

    // events

    var changeEvent = { type: 'change' };

    this.rotateLeft = function ( angle ) {

        if ( angle === undefined ) {
          angle = 2 * Math.PI /180  * scope.userRotateSpeed;
        }

        thetaDelta += angle;

    };

    this.rotateRight = function ( angle ) {

        if ( angle === undefined ) {
          angle = 2 * Math.PI /180  * scope.userRotateSpeed;
        }

        thetaDelta -= angle;

    };

    this.rotateUp = function ( angle ) {

        if ( angle === undefined ) {
          angle = 2 * Math.PI /180  * scope.userRotateSpeed;
        }

        phiDelta -= angle;

    };

    this.rotateDown = function ( angle ) {

        if ( angle === undefined ) {
          angle = 2 * Math.PI /180  * scope.userRotateSpeed;
        }

        phiDelta += angle;

    };

    this.zoomIn = function ( zoomScale ) {

        if ( zoomScale === undefined ) {

            zoomScale = getZoomScale();
        }
        scale /= zoomScale;
        this.scale = scale;
    };

    this.zoomOut = function ( zoomScale ) {

        if ( zoomScale === undefined ) {

            zoomScale = getZoomScale();
        }
        scale *= zoomScale;
        this.scale = scale;
    };

    this.pan = function ( distance ) {
        distance.transformDirection( this.object.matrix );
        distance.multiplyScalar( scope.userPanSpeed );

        this.object.position.add( distance );
        this.center.add( distance );

    };

    this.update = function (dt) {
        //this is a modified version, with inverted Y and Z (since we use camera.z => up)
        var position = this.object.position;
        var offset = position.clone().sub( this.center );

        if(this.upVector.z == 1)
        {
          // angle from z-axis around y-axis, upVector : z
          var theta = Math.atan2( offset.x, offset.y );
          // angle from y-axis
          var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.y * offset.y ), offset.z );
        }
        else
        {
          //in case of y up
          var theta = Math.atan2( offset.x, offset.z );
          var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
          thetaDelta = -(thetaDelta);
        }

        if ( this.autoRotate ) {
            this.rotateLeft( getAutoRotationAngle() );
        }

        theta += thetaDelta;
        phi += phiDelta;

        // restrict phi to be between desired limits
        phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
        // restrict phi to be betwee EPS and PI-EPS
        phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
        //multiply by scaling effect
        var radius = offset.length() * scale;
        // restrict radius to be between desired limits
        radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );

        if(this.upVector.z == 1)
        {
          offset.x = radius * Math.sin( phi ) * Math.sin( theta );
          offset.z = radius * Math.cos( phi );
          offset.y = radius * Math.sin( phi ) * Math.cos( theta );
        }
        else
        {
          offset.x = radius * Math.sin( phi ) * Math.sin( theta );
          offset.y = radius * Math.cos( phi );
          offset.z = radius * Math.sin( phi ) * Math.cos( theta );
        }

        position.copy( this.center ).add( offset );
        this.object.lookAt( this.center );

        thetaDelta = 0;
        phiDelta = 0;
        scale = 1;

        if ( lastPosition.distanceTo( this.object.position ) > 0 ) {

            this.dispatchEvent( changeEvent );

            lastPosition.copy( this.object.position );
        }

    };

    function getAutoRotationAngle() {

        return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;

    }

    function getZoomScale() {

        return Math.pow( 0.95, scope.userZoomSpeed );

    }

    function onMouseDown( event ) {
        if ( scope.enabled === false ) return;
        if ( scope.userRotate === false ) return;
        //event.preventDefault();

        //FIXME : make it configurable
        if ( state === STATE.NONE )
        {
            if ( event.button === 0 )
                state = STATE.ROTATE;
            if ( event.button === 1 )
                state = STATE.ZOOM;
            if ( event.button === 2 )
                state = STATE.PAN;
        }

        if ( state === STATE.ROTATE ) {
            rotateStart.set( event.clientX, event.clientY );

        } else if ( state === STATE.ZOOM ) {
            zoomStart.set( event.clientX, event.clientY );

        } else if ( state === STATE.PAN ) {
            //state = STATE.PAN;
        }
        document.addEventListener( 'mousemove', onMouseMove, false );
        document.addEventListener( 'up', onMouseUp, false );
    }

    function onMouseMove( event ) {

        if ( scope.enabled === false ) return;

        //event.preventDefault();

        if ( state === STATE.ROTATE ) {

            rotateEnd.set( event.clientX, event.clientY );
            rotateDelta.subVectors( rotateEnd, rotateStart );

            scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed );
            scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed );

            rotateStart.copy( rotateEnd );

        } else if ( state === STATE.ZOOM ) {

            zoomEnd.set( event.clientX, event.clientY );
            zoomDelta.subVectors( zoomEnd, zoomStart );

            if ( zoomDelta.y > 0 ) {

                scope.zoomIn();

            } else {

                scope.zoomOut();

            }

            zoomStart.copy( zoomEnd );

        } else if ( state === STATE.PAN ) {
            var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
            var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
            scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) );

        }

    }

    function onMouseUp( event ) {
        if ( scope.enabled === false ) return;
        if ( scope.userRotate === false ) return;
        scope.domElement.removeEventListener( 'mousemove', onMouseMove, false );
        scope.domElement.removeEventListener( 'up', onMouseUp, false );
        state = STATE.NONE;
    }

    function onMouseWheel( event ) {
        if ( scope.enabled === false ) return;
        if ( scope.userZoom === false ) return;

        var delta = 0;

        if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9

            delta = event.wheelDelta;

        } else if ( event.detail ) { // Firefox older

            delta = - event.detail;

        }else if( event.deltaY ) { // Firefox

            delta = -event.deltaY;

        }

        if ( delta > 0 ) {

            scope.zoomOut();

        } else {

            scope.zoomIn();

        }

    }

    function onKeyDown( event ) {

        if ( scope.enabled === false ) return;
        if ( scope.userPan === false ) return;

        switch ( event.keyCode ) {

            /*case scope.keys.UP:
                scope.pan( new THREE.Vector3( 0, 1, 0 ) );
                break;
            case scope.keys.BOTTOM:
                scope.pan( new THREE.Vector3( 0, - 1, 0 ) );
                break;
            case scope.keys.LEFT:
                scope.pan( new THREE.Vector3( - 1, 0, 0 ) );
                break;
            case scope.keys.RIGHT:
                scope.pan( new THREE.Vector3( 1, 0, 0 ) );
                break;
            */
            case scope.keys.ROTATE:
                state = STATE.ROTATE;
                break;
            case scope.keys.ZOOM:
                state = STATE.ZOOM;
                break;
            case scope.keys.PAN:
                state = STATE.PAN;
                break;

        }

    }

    function onKeyUp( event ) {

        switch ( event.keyCode ) {

            case scope.keys.ROTATE:
            case scope.keys.ZOOM:
            case scope.keys.PAN:
                state = STATE.NONE;
                break;
        }
    }

    this.enable= function (){
    	scope.enabled = true;
    	this.enabled = true;
    	state = STATE.NONE;
    }

    this.disable = function(){
    	scope.enabled = false;
    	this.enabled = false;
    	state = STATE.NONE;
    }

    function onPinch( event ) {
        if ( scope.enabled === false ) return;
        if ( scope.userZoom === false ) return;
        scope.domElement.removeEventListener( 'mousemove', onPointerMove, false );
        scope.domElement.removeEventListener( 'up', onPointerUp, false );
        var delta = 0;
        delta = event.scale;
        //scope.userZoomSpeed = 0.4;
        //console.log("pinching",delta);
        if ( delta > 1 ) {
            //console.log("zooming out");
            scope.zoomOut();
        } else {
            //console.log("zooming in");
            scope.zoomIn();
        }
        scope.pointers = {};
    }

    function onPointerDown( event )
    {
      //console.log("pointer down", event);
      //scope.pointers[event.pointerId] = {x: event.pageX, y: event.pageY};

      if(Object.keys(scope.pointers).length >1 && event.pointerType !== 'mouse'){
        //console.log("more than one pointer, pinch zoom etc enabled",Object.keys(scope.pointers).length);
        state = STATE.NONE;
        return;
      }

      if ( scope.enabled === false ) return;
      if ( scope.userRotate === false ) return;
        //event.preventDefault();
        if ( state === STATE.NONE )
        {
            if ( event.button === 0 )
                state = STATE.ROTATE;
            if ( event.button === 1 )
                state = STATE.ZOOM;
            if ( event.button === 2 )
                state = STATE.PAN;
        }
        if ( state === STATE.ROTATE ) {
            rotateStart.set( event.clientX, event.clientY );

        } else if ( state === STATE.ZOOM ) {
            zoomStart.set( event.clientX, event.clientY );

        } else if ( state === STATE.PAN ) {
            //state = STATE.PAN;
        }
        scope.domElement.addEventListener( 'mousemove', onPointerMove, false );
        scope.domElement.addEventListener( 'up', onPointerUp, false );
    }

    function onPointerUp( event )
    {
      //console.log("pointer up");
      //delete scope.pointers[event.pointerId];
      state = STATE.NONE;

      scope.domElement.removeEventListener( 'mousemove', onPointerMove, false );
      scope.domElement.removeEventListener( 'up', onPointerUp, false );
    }

    function onPointerMove( event )
    {
      //if(event.button ==2 ) console.log("pointer move", event);
      //is primary
        if ( scope.enabled === false ) return;
        //event.preventDefault();

        if ( state === STATE.ROTATE ) {

            rotateEnd.set( event.clientX, event.clientY );
            rotateDelta.subVectors( rotateEnd, rotateStart );

            scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed );
            scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed );

            rotateStart.copy( rotateEnd );

        } else if ( state === STATE.ZOOM ) {
            zoomEnd.set( event.clientX, event.clientY );
            zoomDelta.subVectors( zoomEnd, zoomStart );
            scope.userZoomSpeed = 0.6;
            if ( zoomDelta.y > 0 ) {
                scope.zoomIn();
            } else {
                scope.zoomOut();
            }
            //zoomStart.copy( zoomEnd );

        } else if ( state === STATE.PAN ) {
            //console.log(event);
            var pointerId = 2;//event.pointerId
            //FIXME: polymer pointer events is broken
            var pointerData = scope.pointers[pointerId];
            if(pointerId && pointerData)
            {
              var newPointerData = {x: event.pageX, y: event.pageY};
              var movementX = (newPointerData.x - pointerData.x);
              var movementY = (newPointerData.y - pointerData.y);
              scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) );
              scope.userPanSpeed = 4.0;

              scope.pointers[pointerId] = newPointerData;
            }
            else{
              var newPointerData = {x: event.pageX, y: event.pageY};
              scope.pointers[pointerId] = newPointerData;
            }

        }
    }

    this.reset = function(){
      this.center = new THREE.Vector3();
      this.phiDelta= origPhiDelta;
      this.thetaDelta= origThetaDelta ;
      this.scale = origScale = scale;
      this.update();
    }

    this.setDomElement=function(domElement)
    {
      this.domElement = domElement;
      this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
      //window.addEventListener( 'keydown', onKeyDown, false );
      //window.addEventListener( 'keyup', onKeyUp, false );
      this.domElement.addEventListener( 'pinch', onPinch, false);
      this.domElement.addEventListener( 'down', onPointerDown, false );
      this.domElement.addEventListener( 'up', onPointerUp, false );
      this.domElement.addEventListener( 'mousemove', onPointerMove, false );

      //from MDN
      var wheelSupport = "onwheel" in document.createElement("div") ? "wheel" : // Modern browsers support "wheel"
              document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least "mousewheel"
              "DOMMouseScroll"; // let's assume that remaining browsers are older Firefox

      this.domElement.addEventListener( 'wheel', onMouseWheel, false );
      //this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
    }

    scope.pointers= {};

};

THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
<commit_msg>- temporary hack to switch controls' rotation to right mouse  * needs rework to make it configurable (possibly with added keyboard shortcuts)<commit_after>/**
 * @author qiao / https://github.com/qiao
 * @author mrdoob / http://mrdoob.com
 * @author alteredq / http://alteredqualia.com/
 * @author WestLangley / http://github.com/WestLangley
 */

THREE.OrbitControls = function ( object, domElement, upVector ) {

    this.object = object;
    this.domElement = ( domElement !== undefined ) ? domElement : document;
    this.upVector = upVector || new THREE.Vector3(0,1,0);

    // API
    this.rotateButton = 2;
    this.panButton = 4;

    this.enabled = true;

    this.center = new THREE.Vector3();

    this.userZoom = true;
    this.userZoomSpeed = 1.0;

    this.userRotate = true;
    this.userRotateSpeed = 1.0;

    this.userPan = true;
    this.userPanSpeed = 2.0;

    this.autoRotate = false;
    this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60

    this.minPolarAngle = 0; // radians
    this.maxPolarAngle = Math.PI; // radians

    this.minDistance = 0.2;
    this.maxDistance = 600;

    // 65 /*A*/, 83 /*S*/, 68 /*D*/
    this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40, ROTATE: 65, ZOOM: 83, PAN: 68 };

    // internals

    var scope = this;

    var EPS = 0.000001;
    var PIXELS_PER_ROUND = 1800;

    var rotateStart = new THREE.Vector2();
    var rotateEnd = new THREE.Vector2();
    var rotateDelta = new THREE.Vector2();

    var zoomStart = new THREE.Vector2();
    var zoomEnd = new THREE.Vector2();
    var zoomDelta = new THREE.Vector2();

    var phiDelta = 0;
    var thetaDelta = 0;
    var scale = 1;

    var origPhiDelta = phiDelta;
    var origThetaDelta = thetaDelta;
    var origScale = scale;

    var lastPosition = new THREE.Vector3();

    var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 };
    var state = STATE.NONE;

    // events

    var changeEvent = { type: 'change' };

    this.rotateLeft = function ( angle ) {

        if ( angle === undefined ) {
          angle = 2 * Math.PI /180  * scope.userRotateSpeed;
        }

        thetaDelta += angle;

    };

    this.rotateRight = function ( angle ) {

        if ( angle === undefined ) {
          angle = 2 * Math.PI /180  * scope.userRotateSpeed;
        }

        thetaDelta -= angle;

    };

    this.rotateUp = function ( angle ) {

        if ( angle === undefined ) {
          angle = 2 * Math.PI /180  * scope.userRotateSpeed;
        }

        phiDelta -= angle;

    };

    this.rotateDown = function ( angle ) {

        if ( angle === undefined ) {
          angle = 2 * Math.PI /180  * scope.userRotateSpeed;
        }

        phiDelta += angle;

    };

    this.zoomIn = function ( zoomScale ) {

        if ( zoomScale === undefined ) {

            zoomScale = getZoomScale();
        }
        scale /= zoomScale;
        this.scale = scale;
    };

    this.zoomOut = function ( zoomScale ) {

        if ( zoomScale === undefined ) {

            zoomScale = getZoomScale();
        }
        scale *= zoomScale;
        this.scale = scale;
    };

    this.pan = function ( distance ) {
        distance.transformDirection( this.object.matrix );
        distance.multiplyScalar( scope.userPanSpeed );

        this.object.position.add( distance );
        this.center.add( distance );

    };

    this.update = function (dt) {
        //this is a modified version, with inverted Y and Z (since we use camera.z => up)
        var position = this.object.position;
        var offset = position.clone().sub( this.center );

        if(this.upVector.z == 1)
        {
          // angle from z-axis around y-axis, upVector : z
          var theta = Math.atan2( offset.x, offset.y );
          // angle from y-axis
          var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.y * offset.y ), offset.z );
        }
        else
        {
          //in case of y up
          var theta = Math.atan2( offset.x, offset.z );
          var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
          thetaDelta = -(thetaDelta);
        }

        if ( this.autoRotate ) {
            this.rotateLeft( getAutoRotationAngle() );
        }

        theta += thetaDelta;
        phi += phiDelta;

        // restrict phi to be between desired limits
        phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
        // restrict phi to be betwee EPS and PI-EPS
        phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
        //multiply by scaling effect
        var radius = offset.length() * scale;
        // restrict radius to be between desired limits
        radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );

        if(this.upVector.z == 1)
        {
          offset.x = radius * Math.sin( phi ) * Math.sin( theta );
          offset.z = radius * Math.cos( phi );
          offset.y = radius * Math.sin( phi ) * Math.cos( theta );
        }
        else
        {
          offset.x = radius * Math.sin( phi ) * Math.sin( theta );
          offset.y = radius * Math.cos( phi );
          offset.z = radius * Math.sin( phi ) * Math.cos( theta );
        }

        position.copy( this.center ).add( offset );
        this.object.lookAt( this.center );

        thetaDelta = 0;
        phiDelta = 0;
        scale = 1;

        if ( lastPosition.distanceTo( this.object.position ) > 0 ) {

            this.dispatchEvent( changeEvent );

            lastPosition.copy( this.object.position );
        }

    };

    function getAutoRotationAngle() {

        return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;

    }

    function getZoomScale() {

        return Math.pow( 0.95, scope.userZoomSpeed );

    }

    function onMouseDown( event ) {
        if ( scope.enabled === false ) return;
        if ( scope.userRotate === false ) return;
        //event.preventDefault();

        //FIXME : make it configurable
        if ( state === STATE.NONE )
        {
            if ( event.button === scope.rotateButton )
                state = STATE.ROTATE;
            if ( event.button === 1 )
                state = STATE.ZOOM;
            if ( event.button === scope.panButton )
                state = STATE.PAN;
        }

        if ( state === STATE.ROTATE ) {
            rotateStart.set( event.clientX, event.clientY );

        } else if ( state === STATE.ZOOM ) {
            zoomStart.set( event.clientX, event.clientY );

        } else if ( state === STATE.PAN ) {
            //state = STATE.PAN;
        }
        document.addEventListener( 'mousemove', onMouseMove, false );
        document.addEventListener( 'up', onMouseUp, false );
    }

    function onMouseMove( event ) {

        if ( scope.enabled === false ) return;

        //event.preventDefault();

        if ( state === STATE.ROTATE ) {

            rotateEnd.set( event.clientX, event.clientY );
            rotateDelta.subVectors( rotateEnd, rotateStart );

            scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed );
            scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed );

            rotateStart.copy( rotateEnd );

        } else if ( state === STATE.ZOOM ) {

            zoomEnd.set( event.clientX, event.clientY );
            zoomDelta.subVectors( zoomEnd, zoomStart );

            if ( zoomDelta.y > 0 ) {

                scope.zoomIn();

            } else {

                scope.zoomOut();

            }

            zoomStart.copy( zoomEnd );

        } else if ( state === STATE.PAN ) {
            var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
            var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
            scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) );

        }

    }

    function onMouseUp( event ) {
        if ( scope.enabled === false ) return;
        if ( scope.userRotate === false ) return;
        scope.domElement.removeEventListener( 'mousemove', onMouseMove, false );
        scope.domElement.removeEventListener( 'up', onMouseUp, false );
        state = STATE.NONE;
    }

    function onMouseWheel( event ) {
        if ( scope.enabled === false ) return;
        if ( scope.userZoom === false ) return;

        var delta = 0;

        if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9

            delta = event.wheelDelta;

        } else if ( event.detail ) { // Firefox older

            delta = - event.detail;

        }else if( event.deltaY ) { // Firefox

            delta = -event.deltaY;

        }

        if ( delta > 0 ) {

            scope.zoomOut();

        } else {

            scope.zoomIn();

        }

    }

    function onKeyDown( event ) {

        if ( scope.enabled === false ) return;
        if ( scope.userPan === false ) return;

        switch ( event.keyCode ) {

            /*case scope.keys.UP:
                scope.pan( new THREE.Vector3( 0, 1, 0 ) );
                break;
            case scope.keys.BOTTOM:
                scope.pan( new THREE.Vector3( 0, - 1, 0 ) );
                break;
            case scope.keys.LEFT:
                scope.pan( new THREE.Vector3( - 1, 0, 0 ) );
                break;
            case scope.keys.RIGHT:
                scope.pan( new THREE.Vector3( 1, 0, 0 ) );
                break;
            */
            case scope.keys.ROTATE:
                state = STATE.ROTATE;
                break;
            case scope.keys.ZOOM:
                state = STATE.ZOOM;
                break;
            case scope.keys.PAN:
                state = STATE.PAN;
                break;

        }

    }

    function onKeyUp( event ) {

        switch ( event.keyCode ) {

            case scope.keys.ROTATE:
            case scope.keys.ZOOM:
            case scope.keys.PAN:
                state = STATE.NONE;
                break;
        }
    }

    this.enable= function (){
    	scope.enabled = true;
    	this.enabled = true;
    	state = STATE.NONE;
    }

    this.disable = function(){
    	scope.enabled = false;
    	this.enabled = false;
    	state = STATE.NONE;
    }

    function onPinch( event ) {
        if ( scope.enabled === false ) return;
        if ( scope.userZoom === false ) return;
        scope.domElement.removeEventListener( 'mousemove', onPointerMove, false );
        scope.domElement.removeEventListener( 'up', onPointerUp, false );
        var delta = 0;
        delta = event.scale;
        //scope.userZoomSpeed = 0.4;
        //console.log("pinching",delta);
        if ( delta > 1 ) {
            //console.log("zooming out");
            scope.zoomOut();
        } else {
            //console.log("zooming in");
            scope.zoomIn();
        }
        scope.pointers = {};
    }

    function onPointerDown( event )
    {
      //console.log("pointer down", event);
      //scope.pointers[event.pointerId] = {x: event.pageX, y: event.pageY};

      if(Object.keys(scope.pointers).length >1 && event.pointerType !== 'mouse'){
        //console.log("more than one pointer, pinch zoom etc enabled",Object.keys(scope.pointers).length);
        state = STATE.NONE;
        return;
      }

      if ( scope.enabled === false ) return;
      if ( scope.userRotate === false ) return;
        //event.preventDefault();
        if ( state === STATE.NONE )
        {
            if ( event.button === scope.rotateButton )
                state = STATE.ROTATE;
            if ( event.button === 1 )
                state = STATE.ZOOM;
            if ( event.button === scope.panButton )
                state = STATE.PAN;
        }
        if ( state === STATE.ROTATE ) {
            rotateStart.set( event.clientX, event.clientY );

        } else if ( state === STATE.ZOOM ) {
            zoomStart.set( event.clientX, event.clientY );

        } else if ( state === STATE.PAN ) {
            //state = STATE.PAN;
        }
        scope.domElement.addEventListener( 'mousemove', onPointerMove, false );
        scope.domElement.addEventListener( 'up', onPointerUp, false );
    }

    function onPointerUp( event )
    {
      //console.log("pointer up");
      //delete scope.pointers[event.pointerId];
      state = STATE.NONE;

      scope.domElement.removeEventListener( 'mousemove', onPointerMove, false );
      scope.domElement.removeEventListener( 'up', onPointerUp, false );
    }

    function onPointerMove( event )
    {
      //if(event.button ==2 ) console.log("pointer move", event);
      //is primary
        if ( scope.enabled === false ) return;
        //event.preventDefault();

        if ( state === STATE.ROTATE ) {

            rotateEnd.set( event.clientX, event.clientY );
            rotateDelta.subVectors( rotateEnd, rotateStart );

            scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed );
            scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed );

            rotateStart.copy( rotateEnd );

        } else if ( state === STATE.ZOOM ) {
            zoomEnd.set( event.clientX, event.clientY );
            zoomDelta.subVectors( zoomEnd, zoomStart );
            scope.userZoomSpeed = 0.6;
            if ( zoomDelta.y > 0 ) {
                scope.zoomIn();
            } else {
                scope.zoomOut();
            }
            //zoomStart.copy( zoomEnd );

        } else if ( state === STATE.PAN ) {
            //console.log(event);
            var pointerId = 2;//event.pointerId
            //FIXME: polymer pointer events is broken
            var pointerData = scope.pointers[pointerId];
            if(pointerId && pointerData)
            {
              var newPointerData = {x: event.pageX, y: event.pageY};
              var movementX = (newPointerData.x - pointerData.x);
              var movementY = (newPointerData.y - pointerData.y);
              scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) );
              scope.userPanSpeed = 4.0;

              scope.pointers[pointerId] = newPointerData;
            }
            else{
              var newPointerData = {x: event.pageX, y: event.pageY};
              scope.pointers[pointerId] = newPointerData;
            }

        }
    }

    this.reset = function(){
      this.center = new THREE.Vector3();
      this.phiDelta= origPhiDelta;
      this.thetaDelta= origThetaDelta ;
      this.scale = origScale = scale;
      this.update();
    }

    this.setDomElement=function(domElement)
    {
      console.log("attaching orbit controls to", domElement);
      this.domElement = domElement;
      this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
      //window.addEventListener( 'keydown', onKeyDown, false );
      //window.addEventListener( 'keyup', onKeyUp, false );
      this.domElement.addEventListener( 'pinch', onPinch, false);
      this.domElement.addEventListener( 'down', onPointerDown, false );
      this.domElement.addEventListener( 'up', onPointerUp, false );
      this.domElement.addEventListener( 'mousemove', onPointerMove, false );

      //from MDN
      var wheelSupport = "onwheel" in document.createElement("div") ? "wheel" : // Modern browsers support "wheel"
              document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least "mousewheel"
              "DOMMouseScroll"; // let's assume that remaining browsers are older Firefox

      this.domElement.addEventListener( 'wheel', onMouseWheel, false );
      //this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
    }

    scope.pointers= {};

};

THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
<|endoftext|>


<commit_before>/// <reference types="cypress" />

context('People', () => {
    beforeEach(() => {
        cy.loginStandard();
    })

    it('Open the People Dashboard', () => {
        cy.visit("PeopleDashboard.php");
        cy.contains('People Dashboard');
        cy.contains('People Functions');
        cy.contains('Reports');
        cy.contains('Family Roles');
        cy.contains('People Classification');
        cy.contains('Gender Demographics');
    });

    it('Listing all persons', () => {
        cy.visit("v2/people");
        cy.contains('Admin');
        cy.contains('Church');
        cy.contains('Joel');
        cy.contains('Emma');
    });

    it('Listing all persons with gender filter', () => {
        cy.visit("v2/people?Gender=0");
        cy.contains('Admin');
        cy.contains('Church');
        cy.contains('Kennedy');
        cy.contains('Judith');
        cy.contains('Emma').should('not.exist');
    });

    it('Person Not Found', () => {
        cy.visit("PersonView.php?PersonID=9999");
        cy.contains('Oops! PERSON 9999 Not Found');
    });

});

<commit_msg>skipping dashbaord page<commit_after>/// <reference types="cypress" />

context('Standard People', () => {

    it('Open the People Dashboard', () => {
        cy.loginStandard("PeopleDashboard.php");
        cy.contains('People Dashboard');
        cy.contains('People Functions');
        cy.contains('Reports');
        cy.contains('Family Roles');
        cy.contains('People Classification');
        cy.contains('Gender Demographics');
    });

    it('Listing all persons', () => {
        cy.loginStandard("v2/people");
        cy.contains('Admin');
        cy.contains('Church');
        cy.contains('Joel');
        cy.contains('Emma');
    });

    it('Listing all persons with gender filter', () => {
        cy.loginStandard("v2/people?Gender=0", false);
        cy.contains('Admin');
        cy.contains('Church');
        cy.contains('Kennedy');
        cy.contains('Judith');
        cy.contains('Emma').should('not.exist');
    });

    it('Person Not Found', () => {
        cy.loginStandard("PersonView.php?PersonID=9999", false);
        cy.location('pathname').should('include', "person/not-found");
        cy.contains('Oops! PERSON 9999 Not Found');
    });

});

<|endoftext|>


<commit_before>/**
* Build config for electron 'Renderer Process' file
*/

import path from 'path';
import webpack from 'webpack';
import merge from 'webpack-merge';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import baseConfig from './webpack.config.base';
import RollbarSourceMapPlugin from 'rollbar-sourcemap-webpack-plugin';
import cp from 'child_process';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import TerserPlugin from 'terser-webpack-plugin';
import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';

const VERSION_SHA = process.env.CIRCLE_SHA1 ||
  process.env.APPVEYOR_REPO_COMMIT ||
  cp.execSync('git rev-parse HEAD', {cwd: __dirname, encoding: 'utf8' });

const ROLLBAR_POST_TOKEN = process.env.ROLLBAR_POST_TOKEN;

if (process.env.DEBUG_ERROR === 'true') {
  console.log('~ ~ ~ ~ ~ ~ ~ ~ ~ ~');
  console.log('### DEBUG MODE ###');
  console.log('~ ~ ~ ~ ~ ~ ~ ~ ~ ~');
  console.log();
}

if ((!process.env.API_URL && !process.env.UPLOAD_URL && !process.env.DATA_URL && !process.env.BLIP_URL)) {
  console.log('Using the default environment, which is now production.');
} else {
  console.log('***** NOT using the default environment *****');
  console.log('The default right-click server menu may be incorrect.');
  console.log('API_URL =', process.env.API_URL);
  console.log('UPLOAD_URL =', process.env.UPLOAD_URL);
  console.log('DATA_URL =', process.env.DATA_URL);
  console.log('BLIP_URL =', process.env.BLIP_URL);
}

export default merge.smart(baseConfig, {
  devtool: 'source-map',

  mode: 'production',

  target: 'electron-renderer',

  entry: ['./app/index'],

  output: {
    path: path.join(__dirname, 'app/dist'),
    publicPath: '../dist/',
    filename: 'renderer.prod.js'
  },

  module: {
    rules: [
      // Extract all .global.css to style.css as is
      {
        test: /\.global\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            loader: 'css-loader',
            options: {
              sourceMap: true
            }
          }
        ]
      },

      // Pipe other styles through css modules and append to style.css
      {
        test: /^((?!\.global).)*\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
              modules: {
                localIdentName: '[local]___[hash:base64:5]',
              },
              importLoaders: 1
            }
          }
        ]
      },

      {
        test: /\.module\.less$/,
        use: [{
          loader: MiniCssExtractPlugin.loader
        }, {
          loader: 'css-loader',
          options: {
            modules: {
              localIdentName: '[name]__[local]___[hash:base64:5]'
            },
            importLoaders: 1,
            sourceMap: true,
          }
        }, {
          loader: 'less-loader',
          options: {
            sourceMap: true
          }
        }]
      },

      {
        test: /^((?!module).)*\.less$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              sourceMap: true
            }
          },
          {
            loader: 'less-loader',
            options: {
              sourceMap: true
            }
          }
        ]
      },

      // Fonts
      { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, use: [{
        loader: 'url-loader',

        options: {
          limit: 10000,
          mimetype: 'application/font-woff'
        }
      }] },
      { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, use: [{
        loader: 'url-loader',

        options: {
          limit: 10000,
          mimetype: 'application/font-woff'
        }
      }] },
      { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, use: [{
        loader: 'url-loader',

        options: {
          limit: 10000,
          mimetype: 'application/octet-stream'
        }
      }] },
      { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, use: [{
        loader: 'file-loader'
      }] },
      { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, use: [{
        loader: 'url-loader',

        options: {
          limit: 10000,
          mimetype: 'image/svg+xml'
        }
      }] },

      // Images
      {
        test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/,
        use: [{
          loader: 'url-loader'
        }]
      }
    ]
  },

  optimization: {
    minimizer: process.env.E2E_BUILD
      ? []
      : [
          new TerserPlugin({
            parallel: true,
            sourceMap: true,
            cache: true,
            terserOptions: {
              keep_classnames: true, // we check against some classnames
              keep_fnames: true
            },
            extractComments: false
          }),
          new OptimizeCSSAssetsPlugin({
            cssProcessorOptions: {
              map: {
                inline: false,
                annotation: true
              }
            }
          })
        ]
  },

  plugins: [
    /**
    * Create global constants which can be configured at compile time.
    *
    * Useful for allowing different behaviour between development builds and
    * release builds
    *
    * NODE_ENV should be production so that modules do not perform certain
    * development checks
    */
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) || '"production"',
      'process.env.BUILD': JSON.stringify(process.env.BUILD) || '"prod"',
      __DEBUG__: JSON.stringify(JSON.parse(process.env.DEBUG_ERROR || 'false')),
      __VERSION_SHA__: JSON.stringify(VERSION_SHA),
      __ROLLBAR_POST_TOKEN__: JSON.stringify(ROLLBAR_POST_TOKEN),
      'global.GENTLY': false, // http://github.com/visionmedia/superagent/wiki/SuperAgent-for-Webpack for platform-client
    }),

    /**
    * Dynamically generate index.html page
    */
    new HtmlWebpackPlugin({
      filename: '../app.html',
      template: 'app/app.html',
      inject: false
    }),

    new MiniCssExtractPlugin({
      filename: 'style.css'
    }),

    /** Upload sourcemap to Rollbar */
    ...(ROLLBAR_POST_TOKEN ? [new RollbarSourceMapPlugin({
      accessToken: ROLLBAR_POST_TOKEN,
      version: VERSION_SHA,
      publicPath: 'http://dynamichost/dist'
    })] : []),

    new BundleAnalyzerPlugin({
      analyzerMode:
        process.env.OPEN_ANALYZER === 'true' ? 'server' : 'disabled',
      openAnalyzer: process.env.OPEN_ANALYZER === 'true'
    })
  ],

  node: {
    __dirname: true, // https://github.com/visionmedia/superagent/wiki/SuperAgent-for-Webpack for platform-client
  }
});
<commit_msg>setting mangle to false<commit_after>/**
* Build config for electron 'Renderer Process' file
*/

import path from 'path';
import webpack from 'webpack';
import merge from 'webpack-merge';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import baseConfig from './webpack.config.base';
import RollbarSourceMapPlugin from 'rollbar-sourcemap-webpack-plugin';
import cp from 'child_process';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import TerserPlugin from 'terser-webpack-plugin';
import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';

const VERSION_SHA = process.env.CIRCLE_SHA1 ||
  process.env.APPVEYOR_REPO_COMMIT ||
  cp.execSync('git rev-parse HEAD', {cwd: __dirname, encoding: 'utf8' });

const ROLLBAR_POST_TOKEN = process.env.ROLLBAR_POST_TOKEN;

if (process.env.DEBUG_ERROR === 'true') {
  console.log('~ ~ ~ ~ ~ ~ ~ ~ ~ ~');
  console.log('### DEBUG MODE ###');
  console.log('~ ~ ~ ~ ~ ~ ~ ~ ~ ~');
  console.log();
}

if ((!process.env.API_URL && !process.env.UPLOAD_URL && !process.env.DATA_URL && !process.env.BLIP_URL)) {
  console.log('Using the default environment, which is now production.');
} else {
  console.log('***** NOT using the default environment *****');
  console.log('The default right-click server menu may be incorrect.');
  console.log('API_URL =', process.env.API_URL);
  console.log('UPLOAD_URL =', process.env.UPLOAD_URL);
  console.log('DATA_URL =', process.env.DATA_URL);
  console.log('BLIP_URL =', process.env.BLIP_URL);
}

export default merge.smart(baseConfig, {
  devtool: 'source-map',

  mode: 'production',

  target: 'electron-renderer',

  entry: ['./app/index'],

  output: {
    path: path.join(__dirname, 'app/dist'),
    publicPath: '../dist/',
    filename: 'renderer.prod.js'
  },

  module: {
    rules: [
      // Extract all .global.css to style.css as is
      {
        test: /\.global\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            loader: 'css-loader',
            options: {
              sourceMap: true
            }
          }
        ]
      },

      // Pipe other styles through css modules and append to style.css
      {
        test: /^((?!\.global).)*\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
              modules: {
                localIdentName: '[local]___[hash:base64:5]',
              },
              importLoaders: 1
            }
          }
        ]
      },

      {
        test: /\.module\.less$/,
        use: [{
          loader: MiniCssExtractPlugin.loader
        }, {
          loader: 'css-loader',
          options: {
            modules: {
              localIdentName: '[name]__[local]___[hash:base64:5]'
            },
            importLoaders: 1,
            sourceMap: true,
          }
        }, {
          loader: 'less-loader',
          options: {
            sourceMap: true
          }
        }]
      },

      {
        test: /^((?!module).)*\.less$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
              sourceMap: true
            }
          },
          {
            loader: 'less-loader',
            options: {
              sourceMap: true
            }
          }
        ]
      },

      // Fonts
      { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, use: [{
        loader: 'url-loader',

        options: {
          limit: 10000,
          mimetype: 'application/font-woff'
        }
      }] },
      { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, use: [{
        loader: 'url-loader',

        options: {
          limit: 10000,
          mimetype: 'application/font-woff'
        }
      }] },
      { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, use: [{
        loader: 'url-loader',

        options: {
          limit: 10000,
          mimetype: 'application/octet-stream'
        }
      }] },
      { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, use: [{
        loader: 'file-loader'
      }] },
      { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, use: [{
        loader: 'url-loader',

        options: {
          limit: 10000,
          mimetype: 'image/svg+xml'
        }
      }] },

      // Images
      {
        test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/,
        use: [{
          loader: 'url-loader'
        }]
      }
    ]
  },

  optimization: {
    minimizer: process.env.E2E_BUILD
      ? []
      : [
          new TerserPlugin({
            parallel: true,
            sourceMap: true,
            cache: true,
            terserOptions: {
              mangle: false
            },
            extractComments: false
          }),
          new OptimizeCSSAssetsPlugin({
            cssProcessorOptions: {
              map: {
                inline: false,
                annotation: true
              }
            }
          })
        ]
  },

  plugins: [
    /**
    * Create global constants which can be configured at compile time.
    *
    * Useful for allowing different behaviour between development builds and
    * release builds
    *
    * NODE_ENV should be production so that modules do not perform certain
    * development checks
    */
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) || '"production"',
      'process.env.BUILD': JSON.stringify(process.env.BUILD) || '"prod"',
      __DEBUG__: JSON.stringify(JSON.parse(process.env.DEBUG_ERROR || 'false')),
      __VERSION_SHA__: JSON.stringify(VERSION_SHA),
      __ROLLBAR_POST_TOKEN__: JSON.stringify(ROLLBAR_POST_TOKEN),
      'global.GENTLY': false, // http://github.com/visionmedia/superagent/wiki/SuperAgent-for-Webpack for platform-client
    }),

    /**
    * Dynamically generate index.html page
    */
    new HtmlWebpackPlugin({
      filename: '../app.html',
      template: 'app/app.html',
      inject: false
    }),

    new MiniCssExtractPlugin({
      filename: 'style.css'
    }),

    /** Upload sourcemap to Rollbar */
    ...(ROLLBAR_POST_TOKEN ? [new RollbarSourceMapPlugin({
      accessToken: ROLLBAR_POST_TOKEN,
      version: VERSION_SHA,
      publicPath: 'http://dynamichost/dist'
    })] : []),

    new BundleAnalyzerPlugin({
      analyzerMode:
        process.env.OPEN_ANALYZER === 'true' ? 'server' : 'disabled',
      openAnalyzer: process.env.OPEN_ANALYZER === 'true'
    })
  ],

  node: {
    __dirname: true, // https://github.com/visionmedia/superagent/wiki/SuperAgent-for-Webpack for platform-client
  }
});
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';

import CodedSetTableForm from './CodedSetTableForm';
import { responseSetProps } from '../prop-types/response_set_props';

export default class ResponseSetForm extends Component {
  constructor(props) {
    super(props);
    // TODO: Extract building of new response sets to
    // their own methods to clean things up.
    let version = 1;
    let versionIndependentId;
    let oid = this.props.responseSet.oid || '';
    if (props.action === 'extend') {
      oid = '';
    }
    if (props.action === 'revise') {
      version = this.props.responseSet.version + 1;
      versionIndependentId = this.props.responseSet.versionIndependentId;
    }
    let startingResponses;
    if (this.props.responseSet.responses) {
      startingResponses = filterResponses(this.props.responseSet.responses);
    } else {
      startingResponses = [{displayName: '', value: '', codeSystem: ''}];
    }
    this.state = {name: this.props.responseSet.name,
      oid,
      coded: this.props.responseSet.coded || false,
      description: this.props.responseSet.description || '',
      responsesAttributes: startingResponses,
      version: version,
      versionIndependentId: versionIndependentId
    };
  }

  render() {
    return (
      <form onSubmit={(e) => this.handleSubmit(e)}>

              Name
              <input type="text" value={this.state.name} name="name" id="name" onChange={this.handleChange('name')}/>

              OID
              <input type="text" value={this.state.oid} name="oid" id="oid" onChange={this.handleChange('oid')}/>

              Coded
              <input type="checkbox" value={this.state.coded} name="coded" id="coded" onChange={this.handleChange('coded')}/>

              Description
              <textarea value={this.state.description} name="description" id="description" onChange={this.handleChange('description')}/>

          <CodedSetTableForm itemWatcher={(r) => this.handleResponsesChange(r)}
                             initialItems={this.state.responsesAttributes}
                             parentName={'response_set'}
                             childName={'response'} />

            <input type="submit" value={`${this.props.action} Response Set`}/>

      </form>
    );
  }

  handleSubmit(event) {
    event.preventDefault();
    this.props.responseSetSubmitter(this.state, (response) => {
      // TODO: Handle when the saving response set fails.
      if (response.status === 201) {
        this.props.router.push(`/responseSets/${response.data.id}`);
      }
    });
  }

  handleResponsesChange(newResponses) {
    this.setState({responsesAttributes: newResponses});
  }

  handleChange(field) {
    return (event) => {
      let newState = {};
      newState[field] = event.target.value;
      this.setState(newState);
    };
  }
}

function filterResponses(responses) {
  return responses.map((nr) => {
    return {value: nr.value, codeSystem: nr.codeSystem, displayName: nr.displayName};
  });
}

ResponseSetForm.propTypes = {
  responseSet: responseSetProps.isRequired,
  responseSetSubmitter: PropTypes.func.isRequired,
  action: PropTypes.string.isRequired,
  router: PropTypes.object.isRequired
};
<commit_msg>Cleaned up the constructor<commit_after>import React, { Component, PropTypes } from 'react';

import CodedSetTableForm from './CodedSetTableForm';
import { responseSetProps } from '../prop-types/response_set_props';

export default class ResponseSetForm extends Component {
  constructor(props) {
    super(props);
    switch (this.props.action) {
      case 'revise':
        this.state = this.stateForRevise(this.props.responseSet);
        break;
      case 'extend':
        this.state = this.stateForExtend(this.props.responseSet);
        break;
      case 'new':
        this.state = this.stateForNew();
        break;
    }
  }

  stateForRevise(responseSet) {
    const name = responseSet.name || '';
    const oid = responseSet.oid || '';
    const coded = responseSet.coded || false;
    const description = responseSet.description || '';
    const responsesAttributes = filterResponses(responseSet.responses);
    const version = responseSet.version + 1;
    const versionIndependentId = responseSet.versionIndependentId;
    return {name, oid, description, coded, responsesAttributes,
      version, versionIndependentId};
  }

  stateForNew() {
    return {
      name: '', oid: '', coded: false, description: '',
      responsesAttributes: [{displayName: '', value: '', codeSystem: ''}],
      version: 1, versionIndependentId: null
    };
  }

  stateForExtend(responseSet) {
    const name = responseSet.name || '';
    const oid = '';
    const coded = responseSet.coded || false;
    const description = responseSet.description || '';
    const responsesAttributes = filterResponses(responseSet.responses);
    const version = 1;
    const versionIndependentId = null;
    return {name, oid, description, coded, responsesAttributes,
      version, versionIndependentId};
  }

  render() {
    return (
      <form onSubmit={(e) => this.handleSubmit(e)}>

              Name
              <input type="text" value={this.state.name} name="name" id="name" onChange={this.handleChange('name')}/>

              OID
              <input type="text" value={this.state.oid} name="oid" id="oid" onChange={this.handleChange('oid')}/>

              Coded
              <input type="checkbox" value={this.state.coded} name="coded" id="coded" onChange={this.handleChange('coded')}/>

              Description
              <textarea value={this.state.description} name="description" id="description" onChange={this.handleChange('description')}/>

          <CodedSetTableForm itemWatcher={(r) => this.handleResponsesChange(r)}
                             initialItems={this.state.responsesAttributes}
                             parentName={'response_set'}
                             childName={'response'} />

            <input type="submit" value={`${this.props.action} Response Set`}/>

      </form>
    );
  }

  handleSubmit(event) {
    event.preventDefault();
    this.props.responseSetSubmitter(this.state, (response) => {
      // TODO: Handle when the saving response set fails.
      if (response.status === 201) {
        this.props.router.push(`/responseSets/${response.data.id}`);
      }
    });
  }

  handleResponsesChange(newResponses) {
    this.setState({responsesAttributes: newResponses});
  }

  handleChange(field) {
    return (event) => {
      let newState = {};
      newState[field] = event.target.value;
      this.setState(newState);
    };
  }
}

function filterResponses(responses) {
  return responses.map((nr) => {
    return {value: nr.value, codeSystem: nr.codeSystem, displayName: nr.displayName};
  });
}

ResponseSetForm.propTypes = {
  responseSet: responseSetProps.isRequired,
  responseSetSubmitter: PropTypes.func.isRequired,
  action: PropTypes.string.isRequired,
  router: PropTypes.object.isRequired
};
<|endoftext|>


<commit_before>var $ = require('jquery');
var ko = require('knockout');
var bootbox = require('bootbox');
var moment = require('moment');

var $osf = require('js/osfHelpers');
var oop = require('js/oop');

/* global JSONEditor */
require('json-editor'); // TODO webpackify
require('js/json-editor-extensions');

var MetaSchema = function(params) {
    this.name = params.schema_name;
    this.version = params.schema_version;
    this.title = params.title || params.schema.title;
    this.schema = params.schema || {};
    this.id = [this.name, this.version].join('_');
};

var Draft = function(params) {
    this.pk = params.pk;
    var metaSchema = params.registration_schema;
    this.metaSchema = new MetaSchema(metaSchema);
    this.schema = metaSchema.schema;
    this.schemaName = metaSchema.schema_name;
    this.schemaVersion = metaSchema.schema_version;
    this.schemaData = params.registration_metadata;
};

var RegistrationEditor = function(urls, editorId) {
    var self = this;

    self.urls = urls;
    self.editorId = editorId;
    self.editor = null;

    self.draft = ko.observable(
        new Draft({
            pk: null,
            registration_schema: {
                schema: {
                    pages: []
                },
                schema_name: '',
                schema_version: ''
            },
            registration_metadata: {}
        })
    );
    self.disableSave = ko.pureComputed(function() {
        return !self.draft().schema;
    });

    self.currentSchema = ko.computed(function() {
        return self.draft().schema;
    });
};
RegistrationEditor.prototype.init = function(metaSchema, draft) {
    var self = this;

    if (draft){
        self.updateData(draft);
        self.updateEditor(self.draft().schema.pages[0]);
    }
    else {
        self.draft(new Draft({
            registration_schema: metaSchema
        }));

        self.updateEditor(metaSchema.schema.pages[0]);
    }
};
RegistrationEditor.prototype.selectSchema = function() {
    // TODO preview schema?
};
RegistrationEditor.prototype.updateData = function(draft) {
    var self = this;

    var newDraft = new Draft(draft);
    newDraft.schemaData = $.extend({}, newDraft.schemaData, self.draft().schemaData);
    self.draft(newDraft);
};
RegistrationEditor.prototype.fetchData = function() {
    var self = this;
    var ret = $.Deferred();
    if (!self.draft().pk) {
        ret.resolve();
    }
    $.getJSON(self.urls.get.replace('{draft_pk}', self.draft.pk)).then(ret.resolve);
    return ret;
};
RegistrationEditor.prototype.nextPage = function() {
    debugger;
};
RegistrationEditor.prototype.previousPage = function() {

};
RegistrationEditor.prototype.updateEditor = function(page, question) {
    var self = this;

    if (!question) {
        question = page.questions[0];
    }
    // load the data for the first schema and display
    if (self.editor) {
        self.editor.destroy();
    }
    self.editor = new JSONEditor(document.getElementById(self.editorId), {
        schema: question,
        startVal: self.draft().schemaData,
        theme: 'bootstrap3',
        disable_collapse: true,
        disable_edit_json: true,
        disable_properties: true,
        no_additional_properties: false
    });
    self.editor.on('change', function() {
        self.save();
    });
};
RegistrationEditor.prototype.selectPage = function(page, index) {
    var self = this;
    self.updateEditor(page);
};
RegistrationEditor.prototype.selectQuestion = function(page, question) {
    var self = this;
    self.updateEditor(page, question);
};
RegistrationEditor.prototype.create = function(schemaData) {
    var self = this;

    return $osf.postJSON(self.urls.create, {
        schema_name: self.draft().schemaName,
        schema_version: self.draft().schemaVersion,
        schema_data: schemaData
    }).then(self.updateData.bind(self));
};
RegistrationEditor.prototype.save = function() {
    var self = this;
    var schemaData = self.editor.getValue();
    if (!self.draft().pk) {
        return self.create(schemaData);
    }
    return $osf.putJSON(self.urls.update.replace('{draft_pk}', self.draft().pk), {
        schema_name: self.draft().schemaName,
        schema_version: self.draft().schemaVersion,
        schema_data: schemaData
    }).then(function(response) {
        console.log(response);
    });
};

var RegistrationManager = function(node, draftsSelector, editorSelector, controls) {
    var self = this;

    self.node = node;
    self.draftsSelector = draftsSelector;
    self.editorSelector = editorSelector;
    self.controls = controls;

    self.urls = {
        list: node.urls.api + 'draft/',
        get: node.urls.api + 'draft/{draft_pk}/',
        delete: node.urls.api + 'draft/{draft_pk}/',
        schemas: '/api/v1/project/schema/'
    };

    self.schemas = ko.observableArray();
    self.selectedSchema = ko.observable();

    // TODO: convert existing registration UI to frontend impl.
    // self.registrations = ko.observable([]);
    self.drafts = ko.observableArray();

    self.loading = ko.observable(true);

    // bound functions
    self.getDraftRegistrations = $.getJSON.bind(null, self.urls.list);
    self.getSchemas = $.getJSON.bind(null, self.urls.schemas);

    self.controls.showManager();
};
RegistrationManager.prototype.init = function() {
    var self = this;

    $osf.applyBindings(self, self.draftsSelector);

    var getSchemas = self.getSchemas();

    getSchemas.then(function(response) {
        self.schemas(response.meta_schemas);
    });

    var getDraftRegistrations = self.getDraftRegistrations();

    getDraftRegistrations.then(function(response) {
        self.drafts(response.drafts);
    });

    $.when(getSchemas, getDraftRegistrations).then(function() {
        self.loading(false);
    });
};
RegistrationManager.prototype.formatDate = function(dateString){
    return moment(dateString).toNow() + ' (' + '' + ')';
};
RegistrationManager.prototype.launchEditor = function(draft) {
    var self = this;
    var node = self.node;

    bootbox.hideAll();
    self.controls.showEditor();

    var regEditor = new RegistrationEditor({
        schemas: '/api/v1/project/schema/',
        create: node.urls.api + 'draft/',
        update: node.urls.api + 'draft/{draft_pk}/',
        get: node.urls.api + 'draft/{draft_pk}/'
    }, 'registrationEditor');
    var schema = self.selectedSchema();
    regEditor.init(schema, draft);
    $osf.applyBindings(regEditor, self.editorSelector);
    window.editor = regEditor;
};
RegistrationManager.prototype.editDraft = function(draft) {
    this.launchEditor(draft);
};
RegistrationManager.prototype.deleteDraft = function(draft) {
    var self = this;
    $.ajax({
        url: self.urls.delete.replace('{draft_pk}', draft.pk),
        method: 'DELETE'
    }).then(function() {
        self.drafts.remove(function(item) {
            return item.pk === draft.pk;
        });
    });
};
RegistrationManager.prototype.beforeRegister = function() {
    var self = this;

    var node = self.node;

    var context = {
        title: node.title,
        parentTitle: node.parentTitle,
        parentUrl: node.parentRegisterUrl,
        category: node.category === 'project' ? node.category : 'component',
        schemas: self.schemas,
        selectedSchema: self.selectedSchema,
        cancel: function() {
            bootbox.hideAll();
        },
        launchEditor: self.launchEditor.bind(self)
    };

    bootbox.dialog({
        title: 'Register ' + node.title,
        message: function() {
            var preRegisterMessage = ko.renderTemplate('preRegisterMessageTemplate', context, {}, this);
        }
    });
};

module.exports = {
    RegistrationEditor: RegistrationEditor,
    RegistrationManager: RegistrationManager
};
<commit_msg>changed theme to use extended bootstrap3<commit_after>var $ = require('jquery');
var ko = require('knockout');
var bootbox = require('bootbox');
var moment = require('moment');

var $osf = require('js/osfHelpers');
var oop = require('js/oop');

/* global JSONEditor */
require('json-editor'); // TODO webpackify
require('js/json-editor-extensions');

var MetaSchema = function(params) {
    this.name = params.schema_name;
    this.version = params.schema_version;
    this.title = params.title || params.schema.title;
    this.schema = params.schema || {};
    this.id = [this.name, this.version].join('_');
};

var Draft = function(params) {
    this.pk = params.pk;
    var metaSchema = params.registration_schema;
    this.metaSchema = new MetaSchema(metaSchema);
    this.schema = metaSchema.schema;
    this.schemaName = metaSchema.schema_name;
    this.schemaVersion = metaSchema.schema_version;
    this.schemaData = params.registration_metadata;
};

var RegistrationEditor = function(urls, editorId) {
    var self = this;

    self.urls = urls;
    self.editorId = editorId;
    self.editor = null;

    self.draft = ko.observable(
        new Draft({
            pk: null,
            registration_schema: {
                schema: {
                    pages: []
                },
                schema_name: '',
                schema_version: ''
            },
            registration_metadata: {}
        })
    );
    self.disableSave = ko.pureComputed(function() {
        return !self.draft().schema;
    });

    self.currentSchema = ko.computed(function() {
        return self.draft().schema;
    });
};
RegistrationEditor.prototype.init = function(metaSchema, draft) {
    var self = this;

    if (draft){
        self.updateData(draft);
        self.updateEditor(self.draft().schema.pages[0]);
    }
    else {
        self.draft(new Draft({
            registration_schema: metaSchema
        }));

        self.updateEditor(metaSchema.schema.pages[0]);
    }
};
RegistrationEditor.prototype.selectSchema = function() {
    // TODO preview schema?
};
RegistrationEditor.prototype.updateData = function(draft) {
    var self = this;

    var newDraft = new Draft(draft);
    newDraft.schemaData = $.extend({}, newDraft.schemaData, self.draft().schemaData);
    self.draft(newDraft);
};
RegistrationEditor.prototype.fetchData = function() {
    var self = this;
    var ret = $.Deferred();
    if (!self.draft().pk) {
        ret.resolve();
    }
    $.getJSON(self.urls.get.replace('{draft_pk}', self.draft.pk)).then(ret.resolve);
    return ret;
};
RegistrationEditor.prototype.nextPage = function() {
    debugger;
};
RegistrationEditor.prototype.previousPage = function() {

};
RegistrationEditor.prototype.updateEditor = function(page, question) {
    var self = this;

    if (!question) {
        question = page.questions[0];
    }
    // load the data for the first schema and display
    if (self.editor) {
        self.editor.destroy();
    }
    self.editor = new JSONEditor(document.getElementById(self.editorId), {
        schema: question,
        startVal: self.draft().schemaData,
        theme: 'bootstrap3_OSF',
        disable_collapse: true,
        disable_edit_json: true,
        disable_properties: true,
        no_additional_properties: false
    });
    self.editor.on('change', function() {
        self.save();
    });
};
RegistrationEditor.prototype.selectPage = function(page, index) {
    var self = this;
    self.updateEditor(page);
};
RegistrationEditor.prototype.selectQuestion = function(page, question) {
    var self = this;
    self.updateEditor(page, question);
};
RegistrationEditor.prototype.create = function(schemaData) {
    var self = this;

    return $osf.postJSON(self.urls.create, {
        schema_name: self.draft().schemaName,
        schema_version: self.draft().schemaVersion,
        schema_data: schemaData
    }).then(self.updateData.bind(self));
};
RegistrationEditor.prototype.save = function() {
    var self = this;
    var schemaData = self.editor.getValue();
    if (!self.draft().pk) {
        return self.create(schemaData);
    }
    return $osf.putJSON(self.urls.update.replace('{draft_pk}', self.draft().pk), {
        schema_name: self.draft().schemaName,
        schema_version: self.draft().schemaVersion,
        schema_data: schemaData
    }).then(function(response) {
        console.log(response);
    });
};

var RegistrationManager = function(node, draftsSelector, editorSelector, controls) {
    var self = this;

    self.node = node;
    self.draftsSelector = draftsSelector;
    self.editorSelector = editorSelector;
    self.controls = controls;

    self.urls = {
        list: node.urls.api + 'draft/',
        get: node.urls.api + 'draft/{draft_pk}/',
        delete: node.urls.api + 'draft/{draft_pk}/',
        schemas: '/api/v1/project/schema/'
    };

    self.schemas = ko.observableArray();
    self.selectedSchema = ko.observable();

    // TODO: convert existing registration UI to frontend impl.
    // self.registrations = ko.observable([]);
    self.drafts = ko.observableArray();

    self.loading = ko.observable(true);

    // bound functions
    self.getDraftRegistrations = $.getJSON.bind(null, self.urls.list);
    self.getSchemas = $.getJSON.bind(null, self.urls.schemas);

    self.controls.showManager();
};
RegistrationManager.prototype.init = function() {
    var self = this;

    $osf.applyBindings(self, self.draftsSelector);

    var getSchemas = self.getSchemas();

    getSchemas.then(function(response) {
        self.schemas(response.meta_schemas);
    });

    var getDraftRegistrations = self.getDraftRegistrations();

    getDraftRegistrations.then(function(response) {
        self.drafts(response.drafts);
    });

    $.when(getSchemas, getDraftRegistrations).then(function() {
        self.loading(false);
    });
};
RegistrationManager.prototype.formatDate = function(dateString){
    return moment(dateString).toNow() + ' (' + '' + ')';
};
RegistrationManager.prototype.launchEditor = function(draft) {
    var self = this;
    var node = self.node;

    bootbox.hideAll();
    self.controls.showEditor();

    var regEditor = new RegistrationEditor({
        schemas: '/api/v1/project/schema/',
        create: node.urls.api + 'draft/',
        update: node.urls.api + 'draft/{draft_pk}/',
        get: node.urls.api + 'draft/{draft_pk}/'
    }, 'registrationEditor');
    var schema = self.selectedSchema();
    regEditor.init(schema, draft);
    $osf.applyBindings(regEditor, self.editorSelector);
    window.editor = regEditor;
};
RegistrationManager.prototype.editDraft = function(draft) {
    this.launchEditor(draft);
};
RegistrationManager.prototype.deleteDraft = function(draft) {
    var self = this;
    $.ajax({
        url: self.urls.delete.replace('{draft_pk}', draft.pk),
        method: 'DELETE'
    }).then(function() {
        self.drafts.remove(function(item) {
            return item.pk === draft.pk;
        });
    });
};
RegistrationManager.prototype.beforeRegister = function() {
    var self = this;

    var node = self.node;

    var context = {
        title: node.title,
        parentTitle: node.parentTitle,
        parentUrl: node.parentRegisterUrl,
        category: node.category === 'project' ? node.category : 'component',
        schemas: self.schemas,
        selectedSchema: self.selectedSchema,
        cancel: function() {
            bootbox.hideAll();
        },
        launchEditor: self.launchEditor.bind(self)
    };

    bootbox.dialog({
        title: 'Register ' + node.title,
        message: function() {
            var preRegisterMessage = ko.renderTemplate('preRegisterMessageTemplate', context, {}, this);
        }
    });
};

module.exports = {
    RegistrationEditor: RegistrationEditor,
    RegistrationManager: RegistrationManager
};
<|endoftext|>


<commit_before>/* global document */
/* eslint-disable react/no-array-index-key */
/* eslint-disable jsx-a11y/accessible-emoji */

import React from 'react'
import ReactDom from 'react-dom'

import configuration from './configuration'

let lastError = []

const overlayStyle = {
  position: 'fixed',
  left: 0,
  top: 0,
  right: 0,

  backgroundColor: 'rgba(255,200,200,0.9)',

  color: '#000',
  fontFamily:
    '-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif',

  margin: 0,
  padding: '16px',
  maxHeight: '50%',
  overflow: 'auto',
}

const inlineErrorStyle = {
  backgroundColor: '#FEE',
}

const listStyle = {}

export const EmptyErrorPlaceholder = () => (

    ⚛🔥🤕

)

const mapError = ({ error, errorInfo }) => (

      {error.toString ? error.toString() : error.message || 'undefined error'}

    {errorInfo && errorInfo.componentStack ? (

Stack trace:

          {error.stack
            .split('\n')
            .slice(1, 2)
            .map((line, i) =>
{line}
)}
          {errorInfo.componentStack
            .split('\n')
            .filter(Boolean)
            .map((line, i) =>
{line}
)}

    ) : (
      error.stack && (

Stack trace:

            {error.stack
              .split('\n')
              .map((line, i) =>
{line}
)}

      )
    )}

)

class ErrorOverlay extends React.Component {
  state = {
    visible: true,
  }

  toggle = () => this.setState({ visible: !this.state.visible })

  render() {
    const { errors } = this.props
    if (!errors.length) {
      return null
    }
    const { visible } = this.state
    return (

          ⚛🔥😭: hot update was not successful{' '}
          <button onClick={this.toggle}>
            {visible ? 'collapse' : 'expand'}
          </button>

        {visible && (

            {errors.map((err, i) =>
{mapError(err)}
)}

        )}

    )
  }
}

const initErrorOverlay = () => {
  if (typeof document === 'undefined') {
    return
  }
  let div = document.querySelector('.react-hot-loader-error-overlay')
  if (!div) {
    div = document.createElement('div')
    div.className = 'react-hot-loader-error-overlay'
    document.body.appendChild(div)
  }
  if (lastError.length) {
    const Overlay = configuration.ErrorOverlay || ErrorOverlay
    ReactDom.render(<Overlay errors={lastError} />, div)
  } else {
    div.parentNode.removeChild(div)
  }
}

export const clearExceptions = () => {
  lastError = []
  initErrorOverlay()
}

export const logException = (error, errorInfo) => {
  lastError.push({ error, errorInfo })
  initErrorOverlay()
}
<commit_msg>fix: error overlay initialization prior body, fixes #1127<commit_after>/* global document */
/* eslint-disable react/no-array-index-key */
/* eslint-disable jsx-a11y/accessible-emoji */

import React from 'react'
import ReactDom from 'react-dom'

import configuration from './configuration'

let lastError = []

const overlayStyle = {
  position: 'fixed',
  left: 0,
  top: 0,
  right: 0,

  backgroundColor: 'rgba(255,200,200,0.9)',

  color: '#000',
  fontFamily:
    '-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif',

  margin: 0,
  padding: '16px',
  maxHeight: '50%',
  overflow: 'auto',
}

const inlineErrorStyle = {
  backgroundColor: '#FEE',
}

const listStyle = {}

export const EmptyErrorPlaceholder = () => (

    ⚛🔥🤕

)

const mapError = ({ error, errorInfo }) => (

      {error.toString ? error.toString() : error.message || 'undefined error'}

    {errorInfo && errorInfo.componentStack ? (

Stack trace:

          {error.stack
            .split('\n')
            .slice(1, 2)
            .map((line, i) =>
{line}
)}
          {errorInfo.componentStack
            .split('\n')
            .filter(Boolean)
            .map((line, i) =>
{line}
)}

    ) : (
      error.stack && (

Stack trace:

            {error.stack
              .split('\n')
              .map((line, i) =>
{line}
)}

      )
    )}

)

class ErrorOverlay extends React.Component {
  state = {
    visible: true,
  }

  toggle = () => this.setState({ visible: !this.state.visible })

  render() {
    const { errors } = this.props
    if (!errors.length) {
      return null
    }
    const { visible } = this.state
    return (

          ⚛🔥😭: hot update was not successful{' '}
          <button onClick={this.toggle}>
            {visible ? 'collapse' : 'expand'}
          </button>

        {visible && (

            {errors.map((err, i) =>
{mapError(err)}
)}

        )}

    )
  }
}

const initErrorOverlay = () => {
  if (typeof document === 'undefined' || !document.body) {
    return
  }
  let div = document.querySelector('.react-hot-loader-error-overlay')
  if (!div) {
    div = document.createElement('div')
    div.className = 'react-hot-loader-error-overlay'
    document.body.appendChild(div)
  }
  if (lastError.length) {
    const Overlay = configuration.ErrorOverlay || ErrorOverlay
    ReactDom.render(<Overlay errors={lastError} />, div)
  } else {
    div.parentNode.removeChild(div)
  }
}

export const clearExceptions = () => {
  if (lastError.length) {
    lastError = []
    initErrorOverlay()
  }
}

export const logException = (error, errorInfo) => {
  lastError.push({ error, errorInfo })
  initErrorOverlay()
}
<|endoftext|>