<commit_before>const FileService = require('../lib/FileService');
const GDriveService = require('../lib/GDriveService');
const assert = require('assert');
const fs = require('fs');
const sinon = require('sinon');

describe('FileService', function() {
  beforeEach(function() {
    this.service = new FileService();
  });

  describe('createLoggerSpreadsheet()', function() {
    it('should return newly created file resource', function() {
      const stub = sinon.stub(GDriveService, 'copyFile');
      const mockCopy = fs
        .readFileSync('test/mocks/copy_file_response_200.json')
        .toString();
      stub.returns(mockCopy);
      const expected = {
        today: new Date().getDate(),
        destID: '1234'
      };
      const copy = FileService.createLoggerSpreadsheet(
        expected.today,
        expected.destID
      );
      assert.equal(copy, mockCopy, 'returns wrong value');
      // TODO: this id shouldn't be hardcoded like this
      assert.equal(
        stub.getCall(0).args[1],
        '17xHN9N5KxVie9nuFFzCur7WkcMP7aLG4xsPis8Ctxjg',
        'GDriveService.copyFile called with wrong id'
      );
      const requestBody = {
        title: 'Copy Folder Log ' + expected.today,
        parents: [
          {
            kind: 'drive#fileLink',
            id: expected.destID
          }
        ]
      };
      assert.deepEqual(
        stub.getCall(0).args[0],
        requestBody,
        'GDriveService.copyFile called with wrong body'
      );

      stub.restore();
    });

    it('should return error message if GDriveService.copyFile fails', function() {
      const stub = sinon.stub(GDriveService, 'copyFile');
      const errMsg = 'Error copying selected folder';
      stub.throws(new Error(errMsg));
      const copy = FileService.createLoggerSpreadsheet(1, 2);
      assert.equal(copy, errMsg, 'does not return error message');
    });
  });
});
<commit_msg>add tests<commit_after>const FileService = require('../lib/FileService');
const GDriveService = require('../lib/GDriveService');
const assert = require('assert');
const fs = require('fs');
const sinon = require('sinon');

describe('FileService', function() {
  beforeEach(function() {
    this.service = new FileService();
  });

  describe('createLoggerSpreadsheet()', function() {
    it('should return newly created file resource', function() {
      const stub = sinon.stub(GDriveService, 'copyFile');
      const mockCopy = fs
        .readFileSync('test/mocks/copy_file_response_200.json')
        .toString();
      stub.returns(mockCopy);
      const expected = {
        today: new Date().getTime(),
        destID: '1234'
      };
      const copy = FileService.createLoggerSpreadsheet(
        expected.today,
        expected.destID
      );
      assert.equal(copy, mockCopy, 'returns wrong value');
      // TODO: this id shouldn't be hardcoded like this
      assert.equal(
        stub.getCall(0).args[1],
        '17xHN9N5KxVie9nuFFzCur7WkcMP7aLG4xsPis8Ctxjg',
        'GDriveService.copyFile called with wrong id'
      );
      const requestBody = {
        title: 'Copy Folder Log ' + expected.today,
        parents: [
          {
            kind: 'drive#fileLink',
            id: expected.destID
          }
        ]
      };
      assert.deepEqual(
        stub.getCall(0).args[0],
        requestBody,
        'GDriveService.copyFile called with wrong body'
      );

      stub.restore();
    });

    it('should return error message if GDriveService.copyFile fails', function() {
      const stub = sinon.stub(GDriveService, 'copyFile');
      const errMsg = 'Error copying selected folder';
      stub.throws(new Error(errMsg));
      const copy = FileService.createLoggerSpreadsheet(1, 2);
      assert.equal(copy, errMsg, 'does not return error message');

      stub.restore();
    });
  });

  describe('initializeDestinationFolder()', function() {
    it('should copy to options.srcFolderID when copyTo == same', function() {
      const stub = sinon.stub(GDriveService, 'insertFolder');
      const spy = sinon.spy(FileService, 'copyPermissions');
      const mockFolder = fs
        .readFileSync('test/mocks/insert_folder_response_200.json')
        .toString();
      stub.returns(mockFolder);
      const options = {
        srcFolderID: '123',
        copyTo: 'same',
        copyPermissions: false,
        srcFolderName: '234',
        destFolderName: '345',
        srcParentID: '456'
      };
      const today = new Date().getTime();
      const requestBody = {
        description: 'Copy of ' + options.srcFolderName + ', created ' + today,
        title: options.destFolderName,
        parents: [
          {
            kind: 'drive#fileLink',
            id: options.srcParentID
          }
        ],
        mimeType: 'application/vnd.google-apps.folder'
      };
      const destFolder = FileService.initializeDestinationFolder(options, today);
      assert.deepEqual(
        stub.getCall(0).args[0],
        requestBody,
        'GDriveService.insertFolder called with wrong args'
      );

      assert(
        spy.notCalled,
        'copyPermissions called when it was not supposed to be called'
      );
      stub.restore();
    });

    it('should copy to root when copyTo == root', function() {
      assert(false, "write test");
    })
    it('should copy to custom when copyTo == custom', function() {
      assert(false, "write test");
    })
  });
});
<|endoftext|>


<commit_before>/**
 * Author: Vova Zaytsev <zaytsev@usc.edu>
 */

app.controller("NlcdClientController", ["$scope", "$location", "$sce", "NcldApiFactory",
    function ($scope, $location, $sce, NcldApiFactory) {

        /**
          *
          **/

        var graphId = $location.search().g;

        $scope.central              = null;
        $scope.related              = [];
        $scope.meta                 = null;
        $scope.selection            = [];
        $scope.textSelection        = null;
        $scope.dateDistr            = null;
        $scope.selectedDateEntry    = null;

        $scope.display = {

            // Tab 'ALL'
            relatedTabAllReversed:        false,
            relatedTabAllPredicate:       "inSelection",

            // Tab 'SOURCES'
            relatedTabSourcesReversed:    false,
            relatedTabSourcesPredicate:   "referenceCount",

            // Tab 'AUTHORS'
            relatedTabAuthorsReversed:    false,
            relatedTabAuthorsPredicate:   "referenceCount",

            // Tab 'DATES'
            relatedTabDatesReversed:      false,
            relatedTabDatesPredicate:     "documentsCount"

        };

        // Init bootstrap javascript
        $("#relatedTabs a").click(function (e) {
            e.preventDefault();
            $(this).tab("show");
        });
        $("#relatedTabs a:first").tab("show");

        // Init tooltipe
        $(".tip-tooltip").tooltip({
            "animation": true,
            "placement": "top",
        });

        $("body").popover({
              "container": "body",
              "trigger": "hover",
              "delay": 1,
              "html": true,
              "placement": "right",
              "selector": ".tip-popover"
        });

        NcldApiFactory.getTestGraph(graphId).success(function(data){

            $scope.sg = new StoryGraph(data);
            $scope.central = $scope.sg.getCentralNode();
            $scope.related = $scope.sg.getNodes();
            $scope.meta = data.meta;

            var distrPlaceId = "storyDistribution";
            var nwPlaceId = "storyNetwork";

            var distrWidth = document.getElementById(distrPlaceId).offsetWidth;
            var nwWidth = document.getElementById(nwPlaceId).offsetWidth;

            var height = 300;

            $scope.sg.drawDistribution(distrPlaceId, distrWidth, height);
            $scope.sg.drawNetwork(nwPlaceId, nwWidth, height);
            $scope.dateDistr = $scope.sg.distr.dateDistr;

        });

        //
        $scope.RelatedAllTabOrderBy = function(predicate) {
            if ($scope.display.relatedTabAllPredicate == predicate) {
                $scope.display.relatedTabAllReversed = !$scope.display.relatedTabAllReversed;
            }
            $scope.display.relatedTabAllPredicate = predicate;
        }

        //
        $scope.RelatedDatesTabOrderBy = function(predicate) {
            if ($scope.display.relatedTabDatesPredicate == predicate) {
                $scope.display.relatedTabDatesReversed = !$scope.display.relatedTabDatesReversed;
            }
            $scope.display.relatedTabDatesPredicate = predicate;
        }

        //
        $scope.SetSelection = function(referencesList) {

            for (var i in $scope.selection) {
                $scope.selection[i].inSelection = null;
            };
            $scope.selection = [];
            for (var i in referencesList) {
                var refId = referencesList[i];
                var item = $scope.sg.getNode(refId);
                item.inSelection = true;
                $scope.selection.push(item);
            };

            $scope.sg.gfx.SetDistributionSelection(referencesList);
            $scope.sg.gfx.SetNetworkSelection(referencesList);
        };

        //
        $scope.TextSelection = function(chunk, referencesList) {

            $scope.SetSelection([]);

            if ($scope.selectedDateEntry) {
                $scope.SelectDate($scope.selectedDateEntry);
            }

            if ($scope.textSelection) {
                $scope.textSelection.isSelected = false;
                if ($scope.textSelection.tagId == chunk.tagId) {
                    $scope.textSelection = null;
                    return;
                }
            }
            $scope.textSelection = chunk;
            $scope.textSelection.isSelected = true;
            $scope.SetSelection(referencesList);

        };

        //
        $scope.SelectDate = function(dateEntry) {

            if ($scope.textSelection) {
                $scope.TextSelection($scope.textSelection, []);
            }

            $scope.SetSelection([]);

            if ($scope.selectedDateEntry == dateEntry) {

                $scope.selectedDateEntry.selected = false;
                $scope.selectedDateEntry = null;

            } else {

                $scope.SetSelection(dateEntry.selection);

                if ($scope.selectedDateEntry)
                    $scope.selectedDateEntry.selected = false;

                $scope.selectedDateEntry = dateEntry;
                $scope.selectedDateEntry.selected = true;

            }

        };

        //
        $scope.toolPopoverContent = function(node) {

            var authors = node.authors.join(", ").toTitleCase();
            var source = "";
            var len = 10000;
            for (var i in node.sources) {
                if (node.sources[i].length < len) {
                    source = node.sources[i];
                    len = node.sources[i].length;
                }
            }

            return "

authror: "
                   + authors
                   + "

source: "
                   + source
                   + "

"
                   + String.prototype.CutStr(node.body, true, 256, "...")
                   + "
";
        }

}]);<commit_msg>update contrib data<commit_after>/**
 * Author: Vova Zaytsev <zaytsev@usc.edu>
 */

app.controller("NlcdClientController", ["$scope", "$location", "$sce", "NcldApiFactory",
    function ($scope, $location, $sce, NcldApiFactory) {

        /**
          *
          **/

        var graphId = $location.search().g;

        $scope.central              = null;
        $scope.related              = [];
        $scope.meta                 = null;
        $scope.selection            = [];
        $scope.textSelection        = null;
        $scope.dateDistr            = null;
        $scope.selectedDateEntry    = null;

        $scope.display = {

            // Tab 'ALL'
            relatedTabAllReversed:        false,
            relatedTabAllPredicate:       "inSelection",

            // Tab 'SOURCES'
            relatedTabSourcesReversed:    false,
            relatedTabSourcesPredicate:   "referenceCount",

            // Tab 'AUTHORS'
            relatedTabAuthorsReversed:    false,
            relatedTabAuthorsPredicate:   "referenceCount",

            // Tab 'DATES'
            relatedTabDatesReversed:      false,
            relatedTabDatesPredicate:     "date"

        };

        // Init bootstrap javascript
        $("#relatedTabs a").click(function (e) {
            e.preventDefault();
            $(this).tab("show");
        });
        $("#relatedTabs a:first").tab("show");

        // Init tooltipe
        $(".tip-tooltip").tooltip({
            "animation": true,
            "placement": "top",
        });

        $("body").popover({
              "container": "body",
              "trigger": "hover",
              "delay": 1,
              "html": true,
              "placement": "right",
              "selector": ".tip-popover"
        });

        NcldApiFactory.getTestGraph(graphId).success(function(data){

            $scope.sg = new StoryGraph(data);
            $scope.central = $scope.sg.getCentralNode();
            $scope.related = $scope.sg.getNodes();
            $scope.meta = data.meta;

            var distrPlaceId = "storyDistribution";
            var nwPlaceId = "storyNetwork";

            var distrWidth = document.getElementById(distrPlaceId).offsetWidth;
            var nwWidth = document.getElementById(nwPlaceId).offsetWidth;

            var height = 300;

            $scope.sg.drawDistribution(distrPlaceId, distrWidth, height);
            $scope.sg.drawNetwork(nwPlaceId, nwWidth, height);
            $scope.dateDistr = $scope.sg.distr.dateDistr;

        });

        //
        $scope.RelatedAllTabOrderBy = function(predicate) {
            if ($scope.display.relatedTabAllPredicate == predicate) {
                $scope.display.relatedTabAllReversed = !$scope.display.relatedTabAllReversed;
            }
            $scope.display.relatedTabAllPredicate = predicate;
        }

        //
        $scope.RelatedDatesTabOrderBy = function(predicate) {
            if ($scope.display.relatedTabDatesPredicate == predicate) {
                $scope.display.relatedTabDatesReversed = !$scope.display.relatedTabDatesReversed;
            }
            $scope.display.relatedTabDatesPredicate = predicate;
        }

        //
        $scope.SetSelection = function(referencesList) {

            for (var i in $scope.selection) {
                $scope.selection[i].inSelection = null;
            };
            $scope.selection = [];
            for (var i in referencesList) {
                var refId = referencesList[i];
                var item = $scope.sg.getNode(refId);
                item.inSelection = true;
                $scope.selection.push(item);
            };

            $scope.sg.gfx.SetDistributionSelection(referencesList);
            $scope.sg.gfx.SetNetworkSelection(referencesList);
        };

        //
        $scope.TextSelection = function(chunk, referencesList) {

            $scope.SetSelection([]);

            if ($scope.selectedDateEntry) {
                $scope.SelectDate($scope.selectedDateEntry);
            }

            if ($scope.textSelection) {
                $scope.textSelection.isSelected = false;
                if ($scope.textSelection.tagId == chunk.tagId) {
                    $scope.textSelection = null;
                    return;
                }
            }
            $scope.textSelection = chunk;
            $scope.textSelection.isSelected = true;
            $scope.SetSelection(referencesList);

        };

        //
        $scope.SelectDate = function(dateEntry) {

            if ($scope.textSelection) {
                $scope.TextSelection($scope.textSelection, []);
            }

            $scope.SetSelection([]);

            if ($scope.selectedDateEntry == dateEntry) {

                $scope.selectedDateEntry.selected = false;
                $scope.selectedDateEntry = null;

            } else {

                $scope.SetSelection(dateEntry.selection);

                if ($scope.selectedDateEntry)
                    $scope.selectedDateEntry.selected = false;

                $scope.selectedDateEntry = dateEntry;
                $scope.selectedDateEntry.selected = true;

            }

        };

        //
        $scope.toolPopoverContent = function(node) {

            var authors = node.authors.join(", ").toTitleCase();
            var source = "";
            var len = 10000;
            for (var i in node.sources) {
                if (node.sources[i].length < len) {
                    source = node.sources[i];
                    len = node.sources[i].length;
                }
            }

            return "

authror: "
                   + authors
                   + "

source: "
                   + source
                   + "

"
                   + String.prototype.CutStr(node.body, true, 256, "...")
                   + "
";
        }

}]);<|endoftext|>


<commit_before>JanusFireboxParser = function() {
}

JanusFireboxParser.prototype.parse = function(source, baseurl, datapath) {
  var xml = this.parseXML(source, false, true);
  var rooms = this.getAsArray(this.arrayget(xml, 'fireboxroom._children.room', {}));
  var room = {_children: {}};
  for (var i = 0; i < rooms.length; i++) {
    var attrs = Object.keys(rooms[i]).filter(function(k) { return (k[0] != '_'); });
    attrs.forEach(function(k) {
      room[k] = rooms[i][k];
    });
    if (rooms[i]._children) {
      Object.keys(rooms[i]._children).forEach(function(k) {
        room._children[k] = rooms[i]._children[k];
      });
    }
  }
  var roomdata = this.getRoomData(xml, room, baseurl, datapath);
  roomdata.source = source;
  return roomdata;
}
JanusFireboxParser.prototype.getRoomData = function(xml, room, baseurl, datapath) {
  var assets = this.parseAssets(xml, baseurl, datapath);

  var parseNode = this.parseNode.bind(this);

  var roomdata = {
    assets: assets,
    room: this.parseNode(room)
  };
  for (var k in room._children) {
    var objects = this.getAsArray(room._children[k]);
    roomdata[k] = objects.map(parseNode);
  }

  // TODO - some rooms have orphan objects, outside of the <Room> tag.
  // We should parse these too, but I don't have any examples to test with
/*
  var orphantypes = ['link', 'image', 'image3d', 'video', 'sound', 'text', 'paragraph', 'light', 'particle', 'ghost'];
  for (var i = 0; i < orphantypes.length; i++) {
    var type = orphantypes[i],
        orphans = this.getAsArray(this.arrayget(xml, 'fireboxroom._children.' + type));
    if (orphans && orphans.length > 0) {
      if (!roomdata[type]) roomdata[type] = [];
      roomdata[type].push.apply(roomdata[type], orphans);
    }
  };
*/
  return roomdata;
}
JanusFireboxParser.prototype.getAsArray = function(arr) {
  return (arr instanceof Array ? arr : [arr]);
}
JanusFireboxParser.prototype.parseAssets = function(xml, baseurl, datapath) {
  var assetxml = this.arrayget(xml, 'fireboxroom._children.assets.0', {});
  var objectassets = this.getAsArray(this.arrayget(assetxml, "_children.assetobject", []));
  var soundassets = this.getAsArray(this.arrayget(assetxml, "_children.assetsound", []));
  var imageassets = this.getAsArray(this.arrayget(assetxml, "_children.assetimage", []));
  var videoassets = this.getAsArray(this.arrayget(assetxml, "_children.assetvideo", []));
  var scriptassets = this.getAsArray(this.arrayget(assetxml, "_children.assetscript", []));
  var ghostassets = this.getAsArray(this.arrayget(assetxml, "_children.assetghost", []));
  var websurfaceassets = this.getAsArray(this.arrayget(assetxml, "_children.assetwebsurface", []));
  var shaderassets = this.getAsArray(this.arrayget(assetxml, "_children.assetshader", []));
  var fontassets = this.getAsArray(this.arrayget(assetxml, "_children.assetfont", []));
  var assetlist = [];
  if (!datapath) {
    datapath = 'http://web.janusvr.com/media';
  }
  var fixURLEncoding = this.fixURLEncoding.bind(this);
  imageassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype: 'image',
      name: n.id,
      src: src,
      baseurl: baseurl,
      hasalpha: ('hasalpha' in n ? n.hasalpha == "true" || n.hasalpha === true || n.hasalpha === 1 || n.hasalpha === '1' : null),
      proxy: n.proxy,
      vr180: n.vr180,
      sbs3d: n.sbs3d,
      ou3d: n.ou3d,
      flipy: n.flipy,
      reverse3d: n.reverse3d,
    });
  });
  videoassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'video',
      name:n.id,
      src: src,
      loop: (n.loop && n.loop != 'false' && n.loop != '0'),
      vr180: n.vr180,
      sbs3d: n.sbs3d == 'true',
      ou3d: n.ou3d == 'true',
      hasalpha: n.hasalpha == 'true',
      flipy: n.flipy,
      reverse3d: n.reverse3d,
      auto_play: n.auto_play == 'true',
      baseurl: baseurl,
      proxy: n.proxy && n.proxy != 'false'
    });
  });
  soundassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'sound',
      name:n.id,
      src: src,
      baseurl: baseurl
    });
  });
  var websurfaces = {};
  websurfaceassets.forEach(function(n) { websurfaces[n.id] = n; });
  scriptassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'script',
      name: src,
      src: src,
      baseurl: baseurl
    });
  });
  shaderassets.forEach(function(n) {
    n.uniforms = (n._children && n._children.uniform ? n._children.uniform : false);
    assetlist.push({
      assettype: 'shader',
      name: n.id,
      shadertype: n.shadertype || 'default',
      fragment_src: n.src || n.fragment_src,
      vertex_src: n.vertex_src,
      hasalpha: n.hasalpha,
      uniforms: n.uniforms,
      baseurl: baseurl,
    });
  });
  fontassets.forEach(function(n) {
    assetlist.push({
      assettype: 'font',
      name: n.id,
      src: n.src,
      baseurl: baseurl,
    });
  });

  var objlist = [];
  objectassets.forEach(function(n) {
    if (n.src) {
      var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
      var mtlsrc = (n.mtl && n.mtl.match(/^file:/) ? n.mtl.replace(/^file:/, datapath) : n.mtl);
      if (mtlsrc && !mtlsrc.match(/^(https?:)?\/\//)) mtlsrc = baseurl + mtlsrc;
      var srcparts = src.split(' ');
      src = srcparts[0];
      assetlist.push({assettype: 'model', name: n.id, src: src, mtl: mtlsrc, tex_linear: n.tex_linear, tex0: n.tex || n.tex0 || srcparts[1], tex1: n.tex1 || srcparts[2], tex2: n.tex2 || srcparts[3], tex3: n.tex3 || srcparts[4]});
    }
  });
  var assets = {
    object: objectassets,
    image: imageassets,
    sound: soundassets,
    video: videoassets,
    websurfaces: websurfaces,
    scripts: scriptassets,
    ghosts: ghostassets,
    shaders: shaderassets,
    assetlist: assetlist
  };
  return assets;
}

JanusFireboxParser.prototype.getVectorValue = function(vector, defaultvalue) {
  if (typeof defaultvalue == 'undefined') {
    defaultvalue = null;//[0,0,0];
  }
  if (typeof vector == 'string') {
    return vector.trim().split(' ').map(parseFloat);
  } else if (vector instanceof THREE.Vector3) {
    return vector.toArray();
  } else if (typeof vector == 'undefined') {
    return defaultvalue;
  }
  return vector;
}
JanusFireboxParser.prototype.parseNode = function(n) {
  var nodeinfo = {};
  var attrs = Object.keys(n);
  attrs.forEach(function(k) {
    nodeinfo[k] = (n[k] == 'false' ? false : n[k]);
  });

  nodeinfo.pos = this.getVectorValue(n.pos);
  nodeinfo.scale = this.getVectorValue(n.scale, [1,1,1]);
  nodeinfo.orientation = this.getOrientation(n.xdir, n.ydir || n.up, n.zdir || n.fwd);
  nodeinfo.col = (n.col ? (n.col[0] == '#' ? [parseInt(n.col.substr(1,2), 16)/255, parseInt(n.col.substr(3, 2), 16)/255, parseInt(n.col.substr(5, 2), 16)/255] : n.col) : null);

  var minscale = 1e-20;
/*
  nodeinfo.scale[0] = Math.max(minscale, nodeinfo.scale[0]);
  nodeinfo.scale[1] = Math.max(minscale, nodeinfo.scale[1]);
  nodeinfo.scale[2] = Math.max(minscale, nodeinfo.scale[2]);
*/
  if (nodeinfo.scale[0] < minscale && nodeinfo.scale[0] > -minscale) nodeinfo.scale[0] = minscale;
  if (nodeinfo.scale[1] < minscale && nodeinfo.scale[1] > -minscale) nodeinfo.scale[1] = minscale;
  if (nodeinfo.scale[2] < minscale && nodeinfo.scale[2] > -minscale) nodeinfo.scale[2] = minscale;

  return nodeinfo;
}

JanusFireboxParser.prototype.getOrientation = function(xdir, ydir, zdir) {
  if (xdir) {
    xdir = (xdir instanceof THREE.Vector3 ? xdir : new THREE.Vector3().fromArray(xdir.split(' '))).normalize();
  } else {
    xdir = new THREE.Vector3(1,0,0);
  }
  if (ydir) {
    ydir = (ydir instanceof THREE.Vector3 ? ydir : new THREE.Vector3().fromArray(ydir.split(' '))).normalize();
  } else {
    ydir = new THREE.Vector3(0,1,0);
  }
  if (zdir) {
    zdir = (zdir instanceof THREE.Vector3 ? zdir : new THREE.Vector3().fromArray(zdir.split(' '))).normalize();
  } else {
    zdir = new THREE.Vector3(0,0,1);
  }

  var newydir = ydir.clone().sub(zdir).multiplyScalar(ydir.dot(zdir)).normalize();
  xdir.crossVectors(ydir, zdir).normalize();

  var mat4 = new THREE.Matrix4().makeBasis(xdir, ydir, zdir);
  var quat = new THREE.Quaternion();
  var pos = new THREE.Vector3();
  var scale = new THREE.Vector3();
  //quat.setFromRotationMatrix(mat4);
  mat4.decompose(pos, quat, scale);
  quat.normalize();
  //quat.multiply(new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI, 0)));
  return quat;
}
JanusFireboxParser.prototype.parseXML = function(imgxml, leaf, forceLower) {
  var node, root, parent, xmldoc;
  if (imgxml.nodeName) {
    xmldoc = node = imgxml;
  } else {
    try {
      if (window.DOMParser) {
        var parser = new DOMParser();
        xmldoc = parser.parseFromString(imgxml,"application/xml");
        node = xmldoc.children[0];
      } else {
        node = new ActiveXObject("Microsoft.XMLDOM");
        node.async = "false";
        node.loadXML(imgxml).firstChild;
      }

      // Chrome doesn't throw an exception for malformed XML, so we look for a <parsererror> xml tag
      // Firefox now appears to follow the same behavior, but puts the <parsererror> as the top-level element instead of as a child of the last DOM element which parsed successfully
      var parsererrors = (node.tagName == 'parsererror' ? [node] : node.getElementsByTagName("parsererror"));
      if (parsererrors.length > 0) {
        // Extract the message from the first div child of the <parsererror> element
        var errorel = parsererrors[0].getElementsByTagName('div')[0] || parsererrors[0];
        throw new JanusFireboxParserException(errorel.innerHTML);
      }
    } catch (e) {
      throw new JanusFireboxParserException(e.message);
    }
  }
  root = {};
  if (!leaf) {
    var rootname = node.tagName;
    if (forceLower) rootname = rootname.toLowerCase();
    if (!root[rootname]) root[rootname] = {};
    parent = root[rootname];
    //node = parent[node.tagName];
  } else {
    parent = root;
  }
  if (node.attributes) {
    for (var i = 0; i < node.attributes.length; i++) {
      var name = node.attributes[i].nodeName;
      if (forceLower) name = name.toLowerCase();
      var value = node.attributes[i].nodeValue;
      parent[name] = value;
    }
  }
  if (node.childNodes) {
    for (var j = 0; j < node.childNodes.length; j++) {
      var child = node.childNodes[j];
      var nodename = child.nodeName;
      if (forceLower) nodename = nodename.toLowerCase();
      if (!parent._children) parent._children = {};
      if (!parent._children[nodename]) {
        parent._children[nodename] = [];
      } else if (parent._children[nodename].constructor !== Array) {
        parent._children[nodename] = [parent._children[nodename]];
      }
      if (node.getElementsByTagName(child.tagName).length > 0) {
        parent._children[nodename].push(this.parseXML(child, true, forceLower));
      } else if (child.nodeName) {
        if (child.nodeName == "#text" || child.nodeName == "#cdata-section") {
          // this gets confused if you have multiple text/cdata nodes...
          if (!child.nodeValue.match(/^[\s\n]*$/m)) {
            parent._content = child.nodeValue;
          }
        } else {
          parent._children[nodename] = parent._children[nodename].concat(this.parseXML(child, true, forceLower));
        }
      }
    }
  }
  return root;
};

/**
 * Retrieves specified dot-separated value from a multilevel object element
 *
 * @function JanusFireboxParser.arrayget
 * @param {object} obj
 * @param {string} name
 * @param {object|number|string} [defval] default value if none found
*/
JanusFireboxParser.prototype.arrayget = function(obj, name, defval) {
  var ptr = obj;
  var x = name.split(".");
  for (var i = 0; i < x.length; i++) {
    if (ptr==null || (!(ptr[x[i]] instanceof Array) && !(ptr[x[i]] instanceof Object) && i != x.length-1)) {
      ptr = null;
      break;
    }
    ptr = ptr[x[i]];
  }
  if (typeof ptr == "undefined" || ptr === null) {
    return (typeof defval == "undefined" ? null : defval);
  }
  return ptr;
};

/**
 * Fixes encoding of URL strings if they weren't properly encoded
 *
 * @function JanusFireboxParser.fixURLEncoding
 * @param {string} url
 * @returns {string} encoded URL
*/
JanusFireboxParser.prototype.fixURLEncoding = function(url) {
  var fixed = url;
  if (url.indexOf(' ') != -1) {
    fixed = encodeURI(url);
  }
  return fixed;
};

/**
 * Exception class for XML parse errors
 */
function JanusFireboxParserException(msg) {
  this.message = msg;
}
<commit_msg>Add websurfaces to list of assets (fixes missing websurfaces in rooms with no other assets)<commit_after>JanusFireboxParser = function() {
}

JanusFireboxParser.prototype.parse = function(source, baseurl, datapath) {
  var xml = this.parseXML(source, false, true);
  var rooms = this.getAsArray(this.arrayget(xml, 'fireboxroom._children.room', {}));
  var room = {_children: {}};
  for (var i = 0; i < rooms.length; i++) {
    var attrs = Object.keys(rooms[i]).filter(function(k) { return (k[0] != '_'); });
    attrs.forEach(function(k) {
      room[k] = rooms[i][k];
    });
    if (rooms[i]._children) {
      Object.keys(rooms[i]._children).forEach(function(k) {
        room._children[k] = rooms[i]._children[k];
      });
    }
  }
  var roomdata = this.getRoomData(xml, room, baseurl, datapath);
  roomdata.source = source;
  return roomdata;
}
JanusFireboxParser.prototype.getRoomData = function(xml, room, baseurl, datapath) {
  var assets = this.parseAssets(xml, baseurl, datapath);

  var parseNode = this.parseNode.bind(this);

  var roomdata = {
    assets: assets,
    room: this.parseNode(room)
  };
  for (var k in room._children) {
    var objects = this.getAsArray(room._children[k]);
    roomdata[k] = objects.map(parseNode);
  }

  // TODO - some rooms have orphan objects, outside of the <Room> tag.
  // We should parse these too, but I don't have any examples to test with
/*
  var orphantypes = ['link', 'image', 'image3d', 'video', 'sound', 'text', 'paragraph', 'light', 'particle', 'ghost'];
  for (var i = 0; i < orphantypes.length; i++) {
    var type = orphantypes[i],
        orphans = this.getAsArray(this.arrayget(xml, 'fireboxroom._children.' + type));
    if (orphans && orphans.length > 0) {
      if (!roomdata[type]) roomdata[type] = [];
      roomdata[type].push.apply(roomdata[type], orphans);
    }
  };
*/
  return roomdata;
}
JanusFireboxParser.prototype.getAsArray = function(arr) {
  return (arr instanceof Array ? arr : [arr]);
}
JanusFireboxParser.prototype.parseAssets = function(xml, baseurl, datapath) {
  var assetxml = this.arrayget(xml, 'fireboxroom._children.assets.0', {});
  var objectassets = this.getAsArray(this.arrayget(assetxml, "_children.assetobject", []));
  var soundassets = this.getAsArray(this.arrayget(assetxml, "_children.assetsound", []));
  var imageassets = this.getAsArray(this.arrayget(assetxml, "_children.assetimage", []));
  var videoassets = this.getAsArray(this.arrayget(assetxml, "_children.assetvideo", []));
  var scriptassets = this.getAsArray(this.arrayget(assetxml, "_children.assetscript", []));
  var ghostassets = this.getAsArray(this.arrayget(assetxml, "_children.assetghost", []));
  var websurfaceassets = this.getAsArray(this.arrayget(assetxml, "_children.assetwebsurface", []));
  var shaderassets = this.getAsArray(this.arrayget(assetxml, "_children.assetshader", []));
  var fontassets = this.getAsArray(this.arrayget(assetxml, "_children.assetfont", []));
  var assetlist = [];
  if (!datapath) {
    datapath = 'http://web.janusvr.com/media';
  }
  var fixURLEncoding = this.fixURLEncoding.bind(this);
  imageassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype: 'image',
      name: n.id,
      src: src,
      baseurl: baseurl,
      hasalpha: ('hasalpha' in n ? n.hasalpha == "true" || n.hasalpha === true || n.hasalpha === 1 || n.hasalpha === '1' : null),
      proxy: n.proxy,
      vr180: n.vr180,
      sbs3d: n.sbs3d,
      ou3d: n.ou3d,
      flipy: n.flipy,
      reverse3d: n.reverse3d,
    });
  });
  videoassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'video',
      name:n.id,
      src: src,
      loop: (n.loop && n.loop != 'false' && n.loop != '0'),
      vr180: n.vr180,
      sbs3d: n.sbs3d == 'true',
      ou3d: n.ou3d == 'true',
      hasalpha: n.hasalpha == 'true',
      flipy: n.flipy,
      reverse3d: n.reverse3d,
      auto_play: n.auto_play == 'true',
      baseurl: baseurl,
      proxy: n.proxy && n.proxy != 'false'
    });
  });
  soundassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'sound',
      name:n.id,
      src: src,
      baseurl: baseurl
    });
  });
  var websurfaces = {};
  websurfaceassets.forEach(function(n) {
    websurfaces[n.id] = n;
    assetlist.push(n);
  });
  scriptassets.forEach(function(n) {
    var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
    assetlist.push({
      assettype:'script',
      name: src,
      src: src,
      baseurl: baseurl
    });
  });
  shaderassets.forEach(function(n) {
    n.uniforms = (n._children && n._children.uniform ? n._children.uniform : false);
    assetlist.push({
      assettype: 'shader',
      name: n.id,
      shadertype: n.shadertype || 'default',
      fragment_src: n.src || n.fragment_src,
      vertex_src: n.vertex_src,
      hasalpha: n.hasalpha,
      uniforms: n.uniforms,
      baseurl: baseurl,
    });
  });
  fontassets.forEach(function(n) {
    assetlist.push({
      assettype: 'font',
      name: n.id,
      src: n.src,
      baseurl: baseurl,
    });
  });

  var objlist = [];
  objectassets.forEach(function(n) {
    if (n.src) {
      var src = fixURLEncoding(n.src.match(/^file:/) ? n.src.replace(/^file:/, datapath) : n.src);
      var mtlsrc = (n.mtl && n.mtl.match(/^file:/) ? n.mtl.replace(/^file:/, datapath) : n.mtl);
      if (mtlsrc && !mtlsrc.match(/^(https?:)?\/\//)) mtlsrc = baseurl + mtlsrc;
      var srcparts = src.split(' ');
      src = srcparts[0];
      assetlist.push({assettype: 'model', name: n.id, src: src, mtl: mtlsrc, tex_linear: n.tex_linear, tex0: n.tex || n.tex0 || srcparts[1], tex1: n.tex1 || srcparts[2], tex2: n.tex2 || srcparts[3], tex3: n.tex3 || srcparts[4]});
    }
  });
  var assets = {
    object: objectassets,
    image: imageassets,
    sound: soundassets,
    video: videoassets,
    websurfaces: websurfaces,
    scripts: scriptassets,
    ghosts: ghostassets,
    shaders: shaderassets,
    assetlist: assetlist
  };
  return assets;
}

JanusFireboxParser.prototype.getVectorValue = function(vector, defaultvalue) {
  if (typeof defaultvalue == 'undefined') {
    defaultvalue = null;//[0,0,0];
  }
  if (typeof vector == 'string') {
    return vector.trim().split(' ').map(parseFloat);
  } else if (vector instanceof THREE.Vector3) {
    return vector.toArray();
  } else if (typeof vector == 'undefined') {
    return defaultvalue;
  }
  return vector;
}
JanusFireboxParser.prototype.parseNode = function(n) {
  var nodeinfo = {};
  var attrs = Object.keys(n);
  attrs.forEach(function(k) {
    nodeinfo[k] = (n[k] == 'false' ? false : n[k]);
  });

  nodeinfo.pos = this.getVectorValue(n.pos);
  nodeinfo.scale = this.getVectorValue(n.scale, [1,1,1]);
  nodeinfo.orientation = this.getOrientation(n.xdir, n.ydir || n.up, n.zdir || n.fwd);
  nodeinfo.col = (n.col ? (n.col[0] == '#' ? [parseInt(n.col.substr(1,2), 16)/255, parseInt(n.col.substr(3, 2), 16)/255, parseInt(n.col.substr(5, 2), 16)/255] : n.col) : null);

  var minscale = 1e-20;
/*
  nodeinfo.scale[0] = Math.max(minscale, nodeinfo.scale[0]);
  nodeinfo.scale[1] = Math.max(minscale, nodeinfo.scale[1]);
  nodeinfo.scale[2] = Math.max(minscale, nodeinfo.scale[2]);
*/
  if (nodeinfo.scale[0] < minscale && nodeinfo.scale[0] > -minscale) nodeinfo.scale[0] = minscale;
  if (nodeinfo.scale[1] < minscale && nodeinfo.scale[1] > -minscale) nodeinfo.scale[1] = minscale;
  if (nodeinfo.scale[2] < minscale && nodeinfo.scale[2] > -minscale) nodeinfo.scale[2] = minscale;

  return nodeinfo;
}

JanusFireboxParser.prototype.getOrientation = function(xdir, ydir, zdir) {
  if (xdir) {
    xdir = (xdir instanceof THREE.Vector3 ? xdir : new THREE.Vector3().fromArray(xdir.split(' '))).normalize();
  } else {
    xdir = new THREE.Vector3(1,0,0);
  }
  if (ydir) {
    ydir = (ydir instanceof THREE.Vector3 ? ydir : new THREE.Vector3().fromArray(ydir.split(' '))).normalize();
  } else {
    ydir = new THREE.Vector3(0,1,0);
  }
  if (zdir) {
    zdir = (zdir instanceof THREE.Vector3 ? zdir : new THREE.Vector3().fromArray(zdir.split(' '))).normalize();
  } else {
    zdir = new THREE.Vector3(0,0,1);
  }

  var newydir = ydir.clone().sub(zdir).multiplyScalar(ydir.dot(zdir)).normalize();
  xdir.crossVectors(ydir, zdir).normalize();

  var mat4 = new THREE.Matrix4().makeBasis(xdir, ydir, zdir);
  var quat = new THREE.Quaternion();
  var pos = new THREE.Vector3();
  var scale = new THREE.Vector3();
  //quat.setFromRotationMatrix(mat4);
  mat4.decompose(pos, quat, scale);
  quat.normalize();
  //quat.multiply(new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI, 0)));
  return quat;
}
JanusFireboxParser.prototype.parseXML = function(imgxml, leaf, forceLower) {
  var node, root, parent, xmldoc;
  if (imgxml.nodeName) {
    xmldoc = node = imgxml;
  } else {
    try {
      if (window.DOMParser) {
        var parser = new DOMParser();
        xmldoc = parser.parseFromString(imgxml,"application/xml");
        node = xmldoc.children[0];
      } else {
        node = new ActiveXObject("Microsoft.XMLDOM");
        node.async = "false";
        node.loadXML(imgxml).firstChild;
      }

      // Chrome doesn't throw an exception for malformed XML, so we look for a <parsererror> xml tag
      // Firefox now appears to follow the same behavior, but puts the <parsererror> as the top-level element instead of as a child of the last DOM element which parsed successfully
      var parsererrors = (node.tagName == 'parsererror' ? [node] : node.getElementsByTagName("parsererror"));
      if (parsererrors.length > 0) {
        // Extract the message from the first div child of the <parsererror> element
        var errorel = parsererrors[0].getElementsByTagName('div')[0] || parsererrors[0];
        throw new JanusFireboxParserException(errorel.innerHTML);
      }
    } catch (e) {
      throw new JanusFireboxParserException(e.message);
    }
  }
  root = {};
  if (!leaf) {
    var rootname = node.tagName;
    if (forceLower) rootname = rootname.toLowerCase();
    if (!root[rootname]) root[rootname] = {};
    parent = root[rootname];
    //node = parent[node.tagName];
  } else {
    parent = root;
  }
  if (node.attributes) {
    for (var i = 0; i < node.attributes.length; i++) {
      var name = node.attributes[i].nodeName;
      if (forceLower) name = name.toLowerCase();
      var value = node.attributes[i].nodeValue;
      parent[name] = value;
    }
  }
  if (node.childNodes) {
    for (var j = 0; j < node.childNodes.length; j++) {
      var child = node.childNodes[j];
      var nodename = child.nodeName;
      if (forceLower) nodename = nodename.toLowerCase();
      if (!parent._children) parent._children = {};
      if (!parent._children[nodename]) {
        parent._children[nodename] = [];
      } else if (parent._children[nodename].constructor !== Array) {
        parent._children[nodename] = [parent._children[nodename]];
      }
      if (node.getElementsByTagName(child.tagName).length > 0) {
        parent._children[nodename].push(this.parseXML(child, true, forceLower));
      } else if (child.nodeName) {
        if (child.nodeName == "#text" || child.nodeName == "#cdata-section") {
          // this gets confused if you have multiple text/cdata nodes...
          if (!child.nodeValue.match(/^[\s\n]*$/m)) {
            parent._content = child.nodeValue;
          }
        } else {
          parent._children[nodename] = parent._children[nodename].concat(this.parseXML(child, true, forceLower));
        }
      }
    }
  }
  return root;
};

/**
 * Retrieves specified dot-separated value from a multilevel object element
 *
 * @function JanusFireboxParser.arrayget
 * @param {object} obj
 * @param {string} name
 * @param {object|number|string} [defval] default value if none found
*/
JanusFireboxParser.prototype.arrayget = function(obj, name, defval) {
  var ptr = obj;
  var x = name.split(".");
  for (var i = 0; i < x.length; i++) {
    if (ptr==null || (!(ptr[x[i]] instanceof Array) && !(ptr[x[i]] instanceof Object) && i != x.length-1)) {
      ptr = null;
      break;
    }
    ptr = ptr[x[i]];
  }
  if (typeof ptr == "undefined" || ptr === null) {
    return (typeof defval == "undefined" ? null : defval);
  }
  return ptr;
};

/**
 * Fixes encoding of URL strings if they weren't properly encoded
 *
 * @function JanusFireboxParser.fixURLEncoding
 * @param {string} url
 * @returns {string} encoded URL
*/
JanusFireboxParser.prototype.fixURLEncoding = function(url) {
  var fixed = url;
  if (url.indexOf(' ') != -1) {
    fixed = encodeURI(url);
  }
  return fixed;
};

/**
 * Exception class for XML parse errors
 */
function JanusFireboxParserException(msg) {
  this.message = msg;
}
<|endoftext|>


<commit_before>// Globals
var describe = describe;
var beforeEach = beforeEach;
var it = it;
var expect = expect;
var module = module;
var inject = inject;
describe('N-Org', function() {
  var $scope;
  var NOrgNodeCtrl;
  var json;

  beforeEach(module('nOrg'));

  beforeEach(inject(function($rootScope, $controller, $log) {
    $scope = $rootScope.$new();
    NOrgNodeCtrl = $controller("NOrgCtrl", {$scope: $scope});
  }));

  it('should exist', inject(function () {
    expect(NOrgNodeCtrl).toBeTruthy();
  }));

  describe('cursor:', function () {

  });
});
<commit_msg>Remove unused test grouping<commit_after>// Globals
var describe = describe;
var beforeEach = beforeEach;
var it = it;
var expect = expect;
var module = module;
var inject = inject;
describe('N-Org', function() {
  var $scope;
  var NOrgNodeCtrl;
  var json;

  beforeEach(module('nOrg'));

  beforeEach(inject(function($rootScope, $controller, $log) {
    $scope = $rootScope.$new();
    NOrgNodeCtrl = $controller("NOrgCtrl", {$scope: $scope});
  }));

  it('should exist', inject(function () {
    expect(NOrgNodeCtrl).toBeTruthy();
  }));
});
<|endoftext|>


<commit_before>var Cheerio = require('cheerio');

var $make = Cheerio.prototype.make;

Cheerio.prototype.make = function(dom, context) {
  var ret = $make.call(this, dom, context);

  ret.__defineSetter__('innerHTML', function(html) {
    this.html(html || '');
  });

  return ret;
};

Cheerio.prototype.bind = Cheerio.prototype.unbind =
Cheerio.prototype.on = Cheerio.prototype.off =
Cheerio.prototype.delegate = function() {
  return this;
};

Cheerio.prototype.get = Cheerio.prototype.eq;
Cheerio.prototype.forEach = function(callback, scope) {
  var elements = this;
  elements.each(function(index) {
    callback.call(scope || elements, this, index);
  });
};

Cheerio.prototype.getAttribute = function(name) {
  return this.attr(name);
};

Cheerio.prototype.val = function(value) {
  // TODO : Special case for non-text inputs
  return this.attr('value', value);
};

Cheerio.prototype.css = function(name, value) {
  // TODO : Implement
};
Cheerio.prototype.toggle = function(toggle) {
  if (toggle === undefined) {
    toggle = this.css('display') !== 'none';
  }

  this[toggle ? 'show' : 'hide']();
  return this;
};
Cheerio.prototype.show = function() {
  this.css('display', 'none');
  return this;
};
Cheerio.prototype.hide = function() {
  this.css('display', '');
  return this;
};
Cheerio.prototype.toggleClass = function(className, toggle) {
  if (toggle === undefined) {
    toggle = !this.hasClass(className);
  }
  if (toggle) {
    this.addClass(className);
  } else {
    this.removeClass(className);
  }
  return this;
};

Cheerio.prototype.ready = function(callback) {
  callback();
};
<commit_msg>CSS shim implementation<commit_after>var _ = require('underscore'),
    Cheerio = require('cheerio');

var $make = Cheerio.prototype.make;

Cheerio.prototype.make = function(dom, context) {
  var ret = $make.call(this, dom, context);

  ret.__defineSetter__('innerHTML', function(html) {
    this.html(html || '');
  });

  return ret;
};

Cheerio.prototype.bind = Cheerio.prototype.unbind =
Cheerio.prototype.on = Cheerio.prototype.off =
Cheerio.prototype.delegate = function() {
  return this;
};

Cheerio.prototype.get = Cheerio.prototype.eq;
Cheerio.prototype.forEach = function(callback, scope) {
  var elements = this;
  elements.each(function(index) {
    callback.call(scope || elements, this, index);
  });
};

Cheerio.prototype.getAttribute = function(name) {
  return this.attr(name);
};

Cheerio.prototype.val = function(value) {
  // TODO : Special case for non-text inputs
  return this.attr('value', value);
};

Cheerio.prototype.css = function(name, value) {
  /*jshint eqnull: true */
  var styles = {};
  (this.attr('style') || '').split(/\s*;\s*/g).forEach(function(style) {
    var components = style.split(':');
    if (!components[0]) {
      return;
    }

    styles[components[0]] = (components[1] || '').replace(/;\s*$/, '');
  });

  if (value != null) {
    styles[name] = value;

    this.attr('style', _.map(styles, function(value, key) { return value ? (key + ':' + value + ';') : ''; }).join(''));
  } else {
    return styles[name];
  }
};
Cheerio.prototype.toggle = function(toggle) {
  if (toggle === undefined) {
    toggle = this.css('display') !== 'none';
  }

  this[toggle ? 'show' : 'hide']();
  return this;
};
Cheerio.prototype.show = function() {
  this.css('display', 'none');
  return this;
};
Cheerio.prototype.hide = function() {
  this.css('display', '');
  return this;
};
Cheerio.prototype.toggleClass = function(className, toggle) {
  if (toggle === undefined) {
    toggle = !this.hasClass(className);
  }
  if (toggle) {
    this.addClass(className);
  } else {
    this.removeClass(className);
  }
  return this;
};

Cheerio.prototype.ready = function(callback) {
  callback();
};
<|endoftext|>


<commit_before>var babel = require('babel');

module.exports = function (wallaby) {

	return {

		files: ['src/*.js', 'testHelpers/*.js'],

		tests: ['test/*-test.js' ],

		env: {
			type: 'node'
		},

		preprocessors: {
			'**/*.js': file => babel.transform(file.content, {sourceMap: true})
		}
	};
};
<commit_msg>Adding explanation for wallaby.js<commit_after>/*
  This is the config file for the [Wallabyjs](http://wallabyjs.com) test runner
*/

var babel = require('babel');

module.exports = function (wallaby) {
	return {
		files: ['src/*.js', 'testHelpers/*.js'],
		tests: ['test/*-test.js' ],
		env: {
			type: 'node'
		},
		preprocessors: {
			'**/*.js': file => babel.transform(file.content, {sourceMap: true})
		}
	};
};
<|endoftext|>


<commit_before>if (typeof define !== 'function') {
  var define = require('amdefine')(module);
}

var promising = require('./lib/promising');

define(['requirejs', 'fs'], function(requirejs, fs, undefined) {
  var suites = [];

  suites.push({
    name: "caching",
    desc: "Caching stores settings about which paths to cache locally",
    setup: function(env, test) {
      global.RemoteStorage = function() {};
      RemoteStorage.log = function() {};
      require('./src/caching');
      env.Caching = RemoteStorage.Caching;

      test.result(true);
    },

    beforeEach: function(env, test) {
      env.caching = new env.Caching();
      test.result(true);
    },

    tests: [
      {
        desc: "#get() returns undefined for paths that haven't been configured",
        run: function(env, test) {
          test.assertType(env.caching.get('/foo/'), 'undefined');
        }
      },

      {
        desc: "#get() with no path given throws an error",
        run: function(env, test) {
          try {
            env.caching.get();
            test.result(false, "get() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#remove() with no path given throws an error",
        run: function(env, test) {
          try {
            env.caching.remove();
            test.result(false, "remove() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#set() with no path given throws an error",
        run: function(env, test) {
          try {
            env.caching.set();
            test.result(false, "set() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#set() with undefined settings given throws an error",
        run: function(env, test) {
          try {
            env.caching.set('/foo/');
            test.result(false, "set() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#set() sets caching settings for given path",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          test.assert(env.caching.get('/foo/'), { data: true });
        }
      },

      {
        desc: "#remove() removes caching settings from given path",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          test.assertTypeAnd(env.caching.get('/foo/'), 'object');
          env.caching.remove('/foo/');
          test.assertType(env.caching.get('/foo/'), 'undefined');
        }
      },

      {
        desc: "#descendIntoPath() with no path given throws an error",
        run: function(env, test) {
          try {
            env.caching.descendIntoPath();
            test.result(false, "descendIntoPath() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#cachePath() with no path given throws an error",
        run: function(env, test) {
          try {
            env.caching.cachePath();
            test.result(false, "syncDataIn() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#descendIntoPath() with a file path given throws an error",
        run: function(env, test) {
          try {
            env.caching.descendIntoPath('/foo/bar');
            test.result(false, "descendIntoPath() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#descendIntoPath() works for configured paths",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          test.assertAnd(env.caching.descendIntoPath('/foo/'), true);
          test.assert(env.caching.descendIntoPath('/bar/'), false);
        }
      },

      {
        desc: "#descendIntoPath() works for subfolders",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          test.assertAnd(env.caching.descendIntoPath('/foo/bar/'), true);
          test.assert(env.caching.descendIntoPath('/foo/bar/baz/'), true);
        }
      },

      {
        desc: "#rootPaths contains configured paths",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          test.assert(env.caching.rootPaths, ['/foo/']);
        }
      },

      {
        desc: "#rootPaths doesn't contain paths that overlap entirely, but only the shortest one",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          env.caching.set('/bar/', { data: true });
          env.caching.set('/foo/bar/baz/', { data: true });
          test.assert(env.caching.rootPaths, ['/foo/', '/bar/']);
        }
      },

      {
        desc: "#rootPaths doesn't contain paths that have been removed",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          env.caching.set('/bar/', { data: true });
          env.caching.set('/foo/bar/baz/', { data: true });
          env.caching.remove('/foo/');
          test.assert(env.caching.rootPaths, ['/foo/bar/baz/', '/bar/']);
        }
      },

      {
        desc: "#reset resets the state",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          env.caching.set('/bar/', { data: false });
          env.caching.reset();
          test.assertTypeAnd(env.caching.get('/foo/'), 'undefined');
          test.assertTypeAnd(env.caching.get('/bar/'), 'undefined');
          test.assert(env.caching.rootPaths, []);
        }
      },

      {
        desc: "waitForPath queues a promise if rootPath not ready and waitForRemote is true",
        run: function(env, test) {
          env.caching.enable('/foo/', true);
          var promise = env.caching.waitForPath('/foo/bar');
          test.assertAnd(env.caching.queuedPromises, {
            '/foo/bar': [promise]
          });
          env.caching.set('/foo/', {data: true, ready: true});
          test.assertAnd(env.caching.queuedPromises, {});
          promise.then(function() {
            test.done();
          });
        }
      },

      {
        desc: "waitForPath doesn't queue a promise if rootPath not ready and waitForRemote is false",
        run: function(env, test) {
          env.caching.enable('/foo/', false);
          var promise = env.caching.waitForPath('/foo/bar');
          test.assertAnd(typeof(env.caching.queuedPromises), 'undefined');
          promise.then(function() {
            test.done();
          });
        }
      },

      {
        desc: "waitForPath also fulfills the promise if rootPath ready beforehand",
        run: function(env, test) {
          env.caching.enable('/foo/');
          env.caching.set('/foo/', {data: true, ready: true});
          var promise = env.caching.waitForPath('/foo/bar');
          test.assertAnd(env.caching.queuedPromises, undefined);
          promise.then(function() {
            test.done();
          });
        }
      },

      {
        desc: "when setting waitForRemote to true, cachePathReady returns true if and only if ready is set",
        run: function(env, test) {
          env.caching.enable('/foo/', true);
          env.caching.enable('/bar/', true);
          test.assertAnd(env.caching.cachePathReady('/foo/'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/baz.txt'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/baz.txt'), false);
          test.assertAnd(env.caching.cachePathReady('/bar/'), false);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/'), false);
          test.assertAnd(env.caching.cachePathReady('/bar/baz.txt'), false);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/baz.txt'), false);
          env.caching.set('/bar/', { data: true, ready: true });
          test.assertAnd(env.caching.cachePathReady('/foo/'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/baz.txt'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/baz.txt'), false);
          test.assertAnd(env.caching.cachePathReady('/bar/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/baz.txt'), true);
          test.assert(env.caching.cachePathReady('/bar/foo/baz.txt'), true);
        }
      },

      {
        desc: "when setting waitForRemote to false, cachePathReady always returns true",
        run: function(env, test) {
          env.caching.enable('/foo/', false);
          env.caching.enable('/bar/', false);
          test.assertAnd(env.caching.cachePathReady('/foo/'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/baz.txt'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/baz.txt'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/baz.txt'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/baz.txt'), true);
          env.caching.set('/bar/', { data: true, ready: true });
          test.assertAnd(env.caching.cachePathReady('/foo/'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/baz.txt'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/baz.txt'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/baz.txt'), true);
          test.assert(env.caching.cachePathReady('/bar/foo/baz.txt'), true);
        }
      }
    ]
  });

  return suites;
});
<commit_msg>when comparing arrays, jaribu now considers element order important as well.<commit_after>if (typeof define !== 'function') {
  var define = require('amdefine')(module);
}

var promising = require('./lib/promising');

define(['requirejs', 'fs'], function(requirejs, fs, undefined) {
  var suites = [];

  suites.push({
    name: "caching",
    desc: "Caching stores settings about which paths to cache locally",
    setup: function(env, test) {
      global.RemoteStorage = function() {};
      RemoteStorage.log = function() {};
      require('./src/caching');
      env.Caching = RemoteStorage.Caching;

      test.result(true);
    },

    beforeEach: function(env, test) {
      env.caching = new env.Caching();
      test.result(true);
    },

    tests: [
      {
        desc: "#get() returns undefined for paths that haven't been configured",
        run: function(env, test) {
          test.assertType(env.caching.get('/foo/'), 'undefined');
        }
      },

      {
        desc: "#get() with no path given throws an error",
        run: function(env, test) {
          try {
            env.caching.get();
            test.result(false, "get() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#remove() with no path given throws an error",
        run: function(env, test) {
          try {
            env.caching.remove();
            test.result(false, "remove() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#set() with no path given throws an error",
        run: function(env, test) {
          try {
            env.caching.set();
            test.result(false, "set() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#set() with undefined settings given throws an error",
        run: function(env, test) {
          try {
            env.caching.set('/foo/');
            test.result(false, "set() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#set() sets caching settings for given path",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          test.assert(env.caching.get('/foo/'), { data: true });
        }
      },

      {
        desc: "#remove() removes caching settings from given path",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          test.assertTypeAnd(env.caching.get('/foo/'), 'object');
          env.caching.remove('/foo/');
          test.assertType(env.caching.get('/foo/'), 'undefined');
        }
      },

      {
        desc: "#descendIntoPath() with no path given throws an error",
        run: function(env, test) {
          try {
            env.caching.descendIntoPath();
            test.result(false, "descendIntoPath() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#cachePath() with no path given throws an error",
        run: function(env, test) {
          try {
            env.caching.cachePath();
            test.result(false, "syncDataIn() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#descendIntoPath() with a file path given throws an error",
        run: function(env, test) {
          try {
            env.caching.descendIntoPath('/foo/bar');
            test.result(false, "descendIntoPath() didn't fail");
          } catch(e) {
            test.result(true);
          }
        }
      },

      {
        desc: "#descendIntoPath() works for configured paths",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          test.assertAnd(env.caching.descendIntoPath('/foo/'), true);
          test.assert(env.caching.descendIntoPath('/bar/'), false);
        }
      },

      {
        desc: "#descendIntoPath() works for subfolders",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          test.assertAnd(env.caching.descendIntoPath('/foo/bar/'), true);
          test.assert(env.caching.descendIntoPath('/foo/bar/baz/'), true);
        }
      },

      {
        desc: "#rootPaths contains configured paths",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          test.assert(env.caching.rootPaths, ['/foo/']);
        }
      },

      {
        desc: "#rootPaths doesn't contain paths that overlap entirely, but only the shortest one",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          env.caching.set('/bar/', { data: true });
          env.caching.set('/foo/bar/baz/', { data: true });
          test.assert(env.caching.rootPaths, ['/foo/', '/bar/']);
        }
      },

      {
        desc: "#rootPaths doesn't contain paths that have been removed",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          env.caching.set('/bar/', { data: true });
          env.caching.set('/foo/bar/baz/', { data: true });
          env.caching.remove('/foo/');
          test.assert(env.caching.rootPaths.sort(), ['/foo/bar/baz/', '/bar/'].sort());
        }
      },

      {
        desc: "#reset resets the state",
        run: function(env, test) {
          env.caching.set('/foo/', { data: true });
          env.caching.set('/bar/', { data: false });
          env.caching.reset();
          test.assertTypeAnd(env.caching.get('/foo/'), 'undefined');
          test.assertTypeAnd(env.caching.get('/bar/'), 'undefined');
          test.assert(env.caching.rootPaths, []);
        }
      },

      {
        desc: "waitForPath queues a promise if rootPath not ready and waitForRemote is true",
        run: function(env, test) {
          env.caching.enable('/foo/', true);
          var promise = env.caching.waitForPath('/foo/bar');
          test.assertAnd(env.caching.queuedPromises, {
            '/foo/bar': [promise]
          });
          env.caching.set('/foo/', {data: true, ready: true});
          test.assertAnd(env.caching.queuedPromises, {});
          promise.then(function() {
            test.done();
          });
        }
      },

      {
        desc: "waitForPath doesn't queue a promise if rootPath not ready and waitForRemote is false",
        run: function(env, test) {
          env.caching.enable('/foo/', false);
          var promise = env.caching.waitForPath('/foo/bar');
          test.assertAnd(typeof(env.caching.queuedPromises), 'undefined');
          promise.then(function() {
            test.done();
          });
        }
      },

      {
        desc: "waitForPath also fulfills the promise if rootPath ready beforehand",
        run: function(env, test) {
          env.caching.enable('/foo/');
          env.caching.set('/foo/', {data: true, ready: true});
          var promise = env.caching.waitForPath('/foo/bar');
          test.assertAnd(env.caching.queuedPromises, undefined);
          promise.then(function() {
            test.done();
          });
        }
      },

      {
        desc: "when setting waitForRemote to true, cachePathReady returns true if and only if ready is set",
        run: function(env, test) {
          env.caching.enable('/foo/', true);
          env.caching.enable('/bar/', true);
          test.assertAnd(env.caching.cachePathReady('/foo/'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/baz.txt'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/baz.txt'), false);
          test.assertAnd(env.caching.cachePathReady('/bar/'), false);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/'), false);
          test.assertAnd(env.caching.cachePathReady('/bar/baz.txt'), false);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/baz.txt'), false);
          env.caching.set('/bar/', { data: true, ready: true });
          test.assertAnd(env.caching.cachePathReady('/foo/'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/baz.txt'), false);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/baz.txt'), false);
          test.assertAnd(env.caching.cachePathReady('/bar/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/baz.txt'), true);
          test.assert(env.caching.cachePathReady('/bar/foo/baz.txt'), true);
        }
      },

      {
        desc: "when setting waitForRemote to false, cachePathReady always returns true",
        run: function(env, test) {
          env.caching.enable('/foo/', false);
          env.caching.enable('/bar/', false);
          test.assertAnd(env.caching.cachePathReady('/foo/'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/baz.txt'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/baz.txt'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/baz.txt'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/baz.txt'), true);
          env.caching.set('/bar/', { data: true, ready: true });
          test.assertAnd(env.caching.cachePathReady('/foo/'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/baz.txt'), true);
          test.assertAnd(env.caching.cachePathReady('/foo/bar/baz.txt'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/foo/'), true);
          test.assertAnd(env.caching.cachePathReady('/bar/baz.txt'), true);
          test.assert(env.caching.cachePathReady('/bar/foo/baz.txt'), true);
        }
      }
    ]
  });

  return suites;
});
<|endoftext|>


<commit_before>//Anytime loader, simulates load events for ajax requests
function getSubClass(sub_class_name,parent_class){
  if((typeof(sub_class_name) == 'string') && (sub_class_name != '') && (sub_class_name != 'true')){
    var this_class = sub_class_name;
  } else {
    var this_class = parent_class;
  }
  return this_class;
};

String.prototype.toCapCamel = function(){
  camel = this.replace(/[-_]([a-z])/g, function (g) { return g.replace(/[-_]/,'').charAt(0).toUpperCase(); });
  return camel.charAt(0).toUpperCase() + camel.slice(1);
};

var AnyTimeManager = Class.extend({
  init: function(){
    this.loader_array = []
  },
  register: function(data_attribute,load_method,base_class){
    this.loader_array.push({data_attribute: data_attribute, base_class: base_class, load_method: load_method});
  },
  registerList: function(list){
    var anytime_manager = this;
    $.each(list,function(){
      anytime_manager.register(this + '','instantiate',null)
    })
  },
  registerListWithClasses: function(list){
    var anytime_manager = this;
    $.each(list,function(attr,klass){
      anytime_manager.register(attr,'instantiate',klass)
    })
  },
  registerRunList: function(list){
    var anytime_manager = this;
    $.each(list,function(attr,method){
      anytime_manager.register(attr,method,null)
    })
  },
  instantiate: function(jq_obj, class_name){
    if(!jq_obj.data('anytime_loaded')){
      jq_obj.data('anytime_loaded',true);
      var this_class = eval(class_name);
      new this_class(jq_obj);
    }
  },
  run: function (jq_obj, resource, method_name){
    if(!jq_obj.data('anytime_run')){
      jq_obj.data('anytime_run',true);
      resource[method_name](jq_obj);
    }
  },
  load: function(){
    var any_time_manager = this;
    $.each(any_time_manager.loader_array,function(){
      var data_attribute = this['data_attribute'];
      var base_class = this['base_class'];
      if(!base_class){
        base_class = data_attribute.toCapCamel();
      }
      var this_method = this['load_method'];
      $('[data-' + data_attribute + ']').each(function(){
        if('instantiate' == this_method){
          var declared_class = $(this).data('sub-type');
          var this_class = getSubClass(declared_class,base_class);
          any_time_manager.instantiate($(this),this_class);
        }else{
          any_time_manager.run($(this),base_class,this_method);
        }

      });
    });
  }
});
any_time_manager = new AnyTimeManager();
$(document).ajaxComplete(function(){
  any_time_manager.load();
});
$(document).ready(function(){
  any_time_manager.load();
});

// End AnyTime library
<commit_msg>first try at adding namespaces<commit_after>//Anytime loader, simulates load events for ajax requests
function getSubClass(sub_class_name,parent_class){
  if((typeof(sub_class_name) == 'string') && (sub_class_name != '') && (sub_class_name != 'true')){
    var this_class = sub_class_name;
  } else {
    var this_class = parent_class;
  }
  return this_class;
};

String.prototype.toCapCamel = function(){
  camel = this.replace(/[-_]([a-z])/g, function (g) { return g.replace(/[-_]/,'').charAt(0).toUpperCase(); });
  return camel.charAt(0).toUpperCase() + camel.slice(1);
};

var AnyTimeManager = Class.extend({
  init: function(){
    this.loader_array = []
  },
  register: function(data_attribute,load_method,base_class,namespace){
    if(!namespace){namespace = ''}else{namespace= namespace + '.'}
    this.loader_array.push({data_attribute: data_attribute, base_class: base_class, load_method: load_method, namespace: namespace});
  },
  registerList: function(list,namespace){
    var anytime_manager = this;
    $.each(list,function(){
      anytime_manager.register(this + '','instantiate',null,namespace)
    })
  },
  registerListWithClasses: function(list,namespace){
    var anytime_manager = this;
    $.each(list,function(attr,klass){
      anytime_manager.register(attr,'instantiate',klass,namespace)
    })
  },
  registerRunList: function(list){
    var anytime_manager = this;
    $.each(list,function(attr,method){
      anytime_manager.register(attr,method,null)
    })
  },
  instantiate: function(jq_obj, class_name){
    if(!jq_obj.data('anytime_loaded')){
      jq_obj.data('anytime_loaded',true);
      var this_class = eval(class_name);
      new this_class(jq_obj);
    }
  },
  run: function (jq_obj, resource, method_name){
    if(!jq_obj.data('anytime_run')){
      jq_obj.data('anytime_run',true);
      resource[method_name](jq_obj);
    }
  },
  load: function(){
    var any_time_manager = this;
    $.each(any_time_manager.loader_array,function(){
      var data_attribute = this['data_attribute'];
      var base_class = this['base_class'];
      if(!base_class){
        base_class = data_attribute.toCapCamel();
      }
      var this_method = this['load_method'];
      var namespace = this['namespace'];
      $('[data-' + data_attribute + ']').each(function(){
        if('instantiate' == this_method){
          var declared_class = $(this).data('sub-type');
          var this_class = getSubClass(declared_class,base_class);
          this_class = namespace + this_class;
          any_time_manager.instantiate($(this),this_class);
        }else{
          any_time_manager.run($(this),base_class,this_method);
        }

      });
    });
  }
});
any_time_manager = new AnyTimeManager();
$(document).ajaxComplete(function(){
  any_time_manager.load();
});
$(document).ready(function(){
  any_time_manager.load();
});

// End AnyTime library
<|endoftext|>


<commit_before>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Children, Component } from 'react';
import classnames from 'classnames';
import { schema, PropTypes } from 'react-desc';
import LinkNextIcon from './icons/base/LinkNext';

import CSSClassnames from '../utils/CSSClassnames';

const CLASS_ROOT = CSSClassnames.ANCHOR;

export default class Anchor extends Component {

  constructor () {
    super();
    this._onClick = this._onClick.bind(this);
  }

  _onClick (event) {
    const { method, onClick, path} = this.props;
    const { router } = this.context;

    event.preventDefault();

    if ('push' === method) {
      router.push(path);
    } else if ('replace' === method) {
      router.replace(path);
    }

    if (onClick) {
      onClick();
    }
  }

  render () {
    const {
      a11yTitle, align, animateIcon, children, className, disabled, href, icon,
      label, onClick, path, primary, reverse, tag, ...props
    } = this.props;
    delete props.method;
    const { router } = this.context;

    let anchorIcon;
    if (icon) {
      anchorIcon = icon;
    } else if (primary) {
      anchorIcon = (
        <LinkNextIcon a11yTitle='link next' />
      );
    }

    if (anchorIcon && !primary && !label) {
      anchorIcon = <span className={`${CLASS_ROOT}__icon`}>{anchorIcon};
    }

    let hasIcon = anchorIcon !== undefined;
    let anchorChildren = Children.map(children, child => {
      if (child && child.type && child.type.icon) {
        hasIcon = true;
        child = <span className={`${CLASS_ROOT}__icon`}>{child};
      }
      return child;
    });

    let adjustedHref = (path && router) ? router.createPath(path) : href;

    let classes = classnames(
      CLASS_ROOT,
      {
        [`${CLASS_ROOT}--animate-icon`]: hasIcon && animateIcon !== false,
        [`${CLASS_ROOT}--disabled`]: disabled,
        [`${CLASS_ROOT}--icon`]: anchorIcon || hasIcon,
        [`${CLASS_ROOT}--icon-label`]: hasIcon && label,
        [`${CLASS_ROOT}--align-${align}`]: align,
        [`${CLASS_ROOT}--primary`]: primary,
        [`${CLASS_ROOT}--reverse`]: reverse,
        [`${CLASS_ROOT}--active`]: (router && path && router.isActive(path))
      },
      className
    );

    let adjustedOnClick = (path && router ? this._onClick : onClick);

    if (!anchorChildren) {
      anchorChildren = label;
    }

    const first = reverse ? anchorChildren : anchorIcon;
    const second = reverse ? anchorIcon : anchorChildren;

    const Component = tag;
    return (
      <Component {...props} href={adjustedHref} className={classes}
        aria-label={a11yTitle} onClick={adjustedOnClick}>
        {first}
        {second}
      </Component>
    );
  }
};

schema(Anchor, {
  description: `A text link. We have a separate component from the browser
  base so we can style it. You can either set the icon and/or label properties
  or just use children.`,
  usage: `import Anchor from 'grommet/components/Anchor';
  <Anchor href={location} label="Label" />`,
  props: {
    a11yTitle: [PropTypes.string, 'Accessibility title.'],
    align: [PropTypes.oneOf(['start', 'center', 'end']), 'Text alignment.'],
    animateIcon: [PropTypes.bool, 'Whether to animate the icon on hover.'],
    disabled: [PropTypes.bool, 'Whether to disable the anchor.'],
    href: [PropTypes.string, 'Hyperlink reference to place in the anchor.'],
    icon: [PropTypes.element, 'Icon element to place in the anchor.'],
    id: [PropTypes.string, 'Anchor identifier.'],
    label: [PropTypes.node, 'Label text to place in the anchor.'],
    method: [PropTypes.oneOf(['push', 'replace']),
      'Valid only when used with path. Indicates whether the browser history' +
      ' should be appended to or replaced.', {
        defaultProp: 'push'
      }
    ],
    onClick: [PropTypes.func, 'Click handler.'],
    path: [PropTypes.string, 'React-router path to navigate to when clicked.'],
    primary: [PropTypes.bool, 'Whether this is a primary anchor.'],
    reverse: [
      PropTypes.bool,
      'Whether an icon and label should be reversed so that the icon is at ' +
      'the end of the anchor.'
    ],
    tag: [PropTypes.string,
      'The DOM tag to use for the element. The default is . This should be' +
      ' used in conjunction with components like Link from React Router. In' +
      ' this case, Link controls the navigation while Anchor controls the' +
      ' styling.', {
        defaultProp: 'a'
      }
    ],
    target: [PropTypes.string, 'Target of the link.']
  }
});

Anchor.contextTypes = {
  router: React.PropTypes.object
};
<commit_msg>Anchor: Fix onClick to only work if the anchor is not disabled #1072 (#1087)<commit_after>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Children, Component } from 'react';
import classnames from 'classnames';
import { schema, PropTypes } from 'react-desc';
import LinkNextIcon from './icons/base/LinkNext';

import CSSClassnames from '../utils/CSSClassnames';

const CLASS_ROOT = CSSClassnames.ANCHOR;

export default class Anchor extends Component {

  constructor () {
    super();
    this._onClick = this._onClick.bind(this);
  }

  _onClick (event) {
    const { method, onClick, path, disabled } = this.props;
    const { router } = this.context;

    event.preventDefault();

    if (!disabled) {
      if ('push' === method) {
        router.push(path);
      } else if ('replace' === method) {
        router.replace(path);
      }

      if (onClick) {
        onClick();
      }
    }
  }

  render () {
    const {
      a11yTitle, align, animateIcon, children, className, disabled, href, icon,
      label, onClick, path, primary, reverse, tag, ...props
    } = this.props;
    delete props.method;
    const { router } = this.context;

    let anchorIcon;
    if (icon) {
      anchorIcon = icon;
    } else if (primary) {
      anchorIcon = (
        <LinkNextIcon a11yTitle='link next' />
      );
    }

    if (anchorIcon && !primary && !label) {
      anchorIcon = <span className={`${CLASS_ROOT}__icon`}>{anchorIcon};
    }

    let hasIcon = anchorIcon !== undefined;
    let anchorChildren = Children.map(children, child => {
      if (child && child.type && child.type.icon) {
        hasIcon = true;
        child = <span className={`${CLASS_ROOT}__icon`}>{child};
      }
      return child;
    });

    let adjustedHref = (path && router) ? router.createPath(path) : href;

    let classes = classnames(
      CLASS_ROOT,
      {
        [`${CLASS_ROOT}--animate-icon`]: hasIcon && animateIcon !== false,
        [`${CLASS_ROOT}--disabled`]: disabled,
        [`${CLASS_ROOT}--icon`]: anchorIcon || hasIcon,
        [`${CLASS_ROOT}--icon-label`]: hasIcon && label,
        [`${CLASS_ROOT}--align-${align}`]: align,
        [`${CLASS_ROOT}--primary`]: primary,
        [`${CLASS_ROOT}--reverse`]: reverse,
        [`${CLASS_ROOT}--active`]: (router && path && router.isActive(path))
      },
      className
    );

    let adjustedOnClick = (path && router ? this._onClick : onClick);

    if (!anchorChildren) {
      anchorChildren = label;
    }

    const first = reverse ? anchorChildren : anchorIcon;
    const second = reverse ? anchorIcon : anchorChildren;

    const Component = tag;
    return (
      <Component {...props} href={adjustedHref} className={classes}
        aria-label={a11yTitle} onClick={adjustedOnClick}>
        {first}
        {second}
      </Component>
    );
  }
};

schema(Anchor, {
  description: `A text link. We have a separate component from the browser
  base so we can style it. You can either set the icon and/or label properties
  or just use children.`,
  usage: `import Anchor from 'grommet/components/Anchor';
  <Anchor href={location} label="Label" />`,
  props: {
    a11yTitle: [PropTypes.string, 'Accessibility title.'],
    align: [PropTypes.oneOf(['start', 'center', 'end']), 'Text alignment.'],
    animateIcon: [PropTypes.bool, 'Whether to animate the icon on hover.'],
    disabled: [PropTypes.bool, 'Whether to disable the anchor.'],
    href: [PropTypes.string, 'Hyperlink reference to place in the anchor.'],
    icon: [PropTypes.element, 'Icon element to place in the anchor.'],
    id: [PropTypes.string, 'Anchor identifier.'],
    label: [PropTypes.node, 'Label text to place in the anchor.'],
    method: [PropTypes.oneOf(['push', 'replace']),
      'Valid only when used with path. Indicates whether the browser history' +
      ' should be appended to or replaced.', {
        defaultProp: 'push'
      }
    ],
    onClick: [PropTypes.func, 'Click handler.'],
    path: [PropTypes.string, 'React-router path to navigate to when clicked.'],
    primary: [PropTypes.bool, 'Whether this is a primary anchor.'],
    reverse: [
      PropTypes.bool,
      'Whether an icon and label should be reversed so that the icon is at ' +
      'the end of the anchor.'
    ],
    tag: [PropTypes.string,
      'The DOM tag to use for the element. The default is . This should be' +
      ' used in conjunction with components like Link from React Router. In' +
      ' this case, Link controls the navigation while Anchor controls the' +
      ' styling.', {
        defaultProp: 'a'
      }
    ],
    target: [PropTypes.string, 'Target of the link.']
  }
});

Anchor.contextTypes = {
  router: React.PropTypes.object
};
<|endoftext|>