<commit_before>import { t } from '../util/locale';
import { modeDrawLine } from '../modes/draw_line';
import { actionReverse } from '../actions/reverse';
import { utilDisplayLabel } from '../util';
import { osmFlowingWaterwayTagValues, osmOneWayTags, osmRoutableHighwayTagValues } from '../osm/tags';
import { validationIssue, validationIssueFix } from '../core/validation';

export function validationImpossibleOneway() {
    var type = 'impossible_oneway';

    function typeForWay(way) {
        if (osmRoutableHighwayTagValues[way.tags.highway]) return 'highway';
        if (osmFlowingWaterwayTagValues[way.tags.waterway]) return 'waterway';
        return null;
    }

    function isOneway(way) {
        if (way.tags.oneway === 'yes') return true;
        if (way.tags.oneway) return false;

        for (var key in way.tags) {
            if (osmOneWayTags[key] && osmOneWayTags[key][way.tags[key]]) {
                return true;
            }
        }
        return false;
    }

    function continueDrawing(way, vertex, context) {
        // make sure the vertex is actually visible and editable
        var map = context.map();
        if (!map.editable() || !map.trimmedExtent().contains(vertex.loc)) {
            map.zoomToEase(vertex);
        }

        context.enter(
            modeDrawLine(context, way.id, context.graph(), context.graph(), 'line', way.affix(vertex.id), true)
        );
    }

    function nodeOccursMoreThanOnce(way, nodeID) {
        var occurences = 0;
        for (var index in way.nodes) {
            if (way.nodes[index] === nodeID) {
                occurences += 1;
                if (occurences > 1) return true;
            }
        }
        return false;
    }

    function issuesForNode(context, way, nodeID) {

        var isFirst = nodeID === way.first();

        var wayType = typeForWay(way);
        var isWaterway = wayType === 'waterway';

        // ignore if this way is self-connected at this node
        if (nodeOccursMoreThanOnce(way, nodeID)) return [];

        var osm = context.connection();
        if (!osm) return [];

        var node = context.hasEntity(nodeID);

        if (wayType === 'highway') {
            // entrances are considered connected
            if (node.tags.entrance && node.tags.entrance !== 'no') return [];
            if (node.tags.amenity === 'parking_entrance') return [];
        }

        // ignore if this node or its tile are unloaded
        if (!node || !osm.isDataLoaded(node.loc)) return [];

        var attachedWaysOfSameType = context.graph().parentWays(node).filter(function(parentWay) {
            if (parentWay.id === way.id) return false;
            return typeForWay(parentWay) === wayType;
        });

        // assume it's okay for waterways to start or end disconnected for now
        if (isWaterway && attachedWaysOfSameType.length === 0) return [];

        var attachedOneways = attachedWaysOfSameType.filter(function(attachedWay) {
            return isOneway(attachedWay);
        });

        // ignore if the way is connected to some non-oneway features
        if (attachedOneways.length < attachedWaysOfSameType.length) return [];

        if (attachedOneways.length) {
            var connectedEndpointsOkay = attachedOneways.some(function(attachedOneway) {
                if ((isFirst ? attachedOneway.first() : attachedOneway.last()) !== nodeID) return true;
                if (nodeOccursMoreThanOnce(attachedOneway, nodeID)) return true;
                return false;
            });
            if (connectedEndpointsOkay) return [];
        }

        var fixes = [];

        if (attachedOneways.length) {
            fixes.push(new validationIssueFix({
                icon: 'iD-operation-reverse',
                title: t('issues.fix.reverse_feature.title'),
                entityIds: [way.id],
                onClick: function() {
                    var id = this.issue.entityIds[0];
                    context.perform(actionReverse(id), t('operations.reverse.annotation'));
                }
            }));
        }
        if (node.tags.noexit !== 'yes') {
            fixes.push(new validationIssueFix({
                icon: 'iD-operation-continue' + (isFirst ? '-left' : ''),
                title: t('issues.fix.continue_from_' + (isFirst ? 'start' : 'end') + '.title'),
                onClick: function() {
                    var entityID = this.issue.entityIds[0];
                    var vertexID = this.issue.entityIds[1];
                    var way = context.entity(entityID);
                    var vertex = context.entity(vertexID);
                    continueDrawing(way, vertex, context);
                }
            }));
        }

        var placement = isFirst ? 'start' : 'end',
            messageID = wayType + '.',
            referenceID = wayType + '.';

        if (isWaterway) {
            messageID += 'connected.' + placement;
            referenceID += 'connected';
        } else {
            messageID += placement;
            referenceID += placement;
        }

        return [new validationIssue({
            type: type,
            subtype: wayType,
            severity: 'warning',
            message: function() {
                var entity = context.hasEntity(this.entityIds[0]);
                return entity ? t('issues.impossible_oneway.' + messageID + '.message', {
                    feature: utilDisplayLabel(entity, context)
                }) : '';
            },
            reference: getReference(referenceID),
            entityIds: [way.id, node.id],
            fixes: fixes
        })];

        function getReference(referenceID) {
            return function showReference(selection) {
                selection.selectAll('.issue-reference')
                    .data([0])
                    .enter()
                    .append('div')
                    .attr('class', 'issue-reference')
                    .text(t('issues.impossible_oneway.' + referenceID + '.reference'));
            };
        }
    }

    var validation = function checkDisconnectedWay(entity, context) {

        if (entity.type !== 'way' || entity.geometry(context.graph()) !== 'line') return [];

        if (entity.isClosed()) return [];

        if (!typeForWay(entity)) return [];

        if (!isOneway(entity)) return [];

        var firstIssues = issuesForNode(context, entity, entity.first());
        var lastIssues = issuesForNode(context, entity, entity.last());

        return firstIssues.concat(lastIssues);
    };

    validation.type = type;

    return validation;
}
<commit_msg>Don't flag oneway highways that connect to highway areas or ferry routes as impossible Don't flag oneway waterways that connect to springs, storm drains, water bodies, or coastlines as impossible<commit_after>import { t } from '../util/locale';
import { modeDrawLine } from '../modes/draw_line';
import { actionReverse } from '../actions/reverse';
import { utilDisplayLabel } from '../util';
import { osmFlowingWaterwayTagValues, osmOneWayTags, osmRoutableHighwayTagValues } from '../osm/tags';
import { validationIssue, validationIssueFix } from '../core/validation';

export function validationImpossibleOneway() {
    var type = 'impossible_oneway';

    function typeForWay(way, context) {
        if (way.geometry(context.graph()) !== 'line') return null;

        if (osmRoutableHighwayTagValues[way.tags.highway]) return 'highway';
        if (osmFlowingWaterwayTagValues[way.tags.waterway]) return 'waterway';
        return null;
    }

    function isOneway(way) {
        if (way.tags.oneway === 'yes') return true;
        if (way.tags.oneway) return false;

        for (var key in way.tags) {
            if (osmOneWayTags[key] && osmOneWayTags[key][way.tags[key]]) {
                return true;
            }
        }
        return false;
    }

    function continueDrawing(way, vertex, context) {
        // make sure the vertex is actually visible and editable
        var map = context.map();
        if (!map.editable() || !map.trimmedExtent().contains(vertex.loc)) {
            map.zoomToEase(vertex);
        }

        context.enter(
            modeDrawLine(context, way.id, context.graph(), context.graph(), 'line', way.affix(vertex.id), true)
        );
    }

    function nodeOccursMoreThanOnce(way, nodeID) {
        var occurences = 0;
        for (var index in way.nodes) {
            if (way.nodes[index] === nodeID) {
                occurences += 1;
                if (occurences > 1) return true;
            }
        }
        return false;
    }

    function isConnectedViaOtherTypes(context, way, node) {

        var wayType = typeForWay(way, context);

        if (wayType === 'highway') {
            // entrances are considered connected
            if (node.tags.entrance && node.tags.entrance !== 'no') return true;
            if (node.tags.amenity === 'parking_entrance') return true;
        } else if (wayType === 'waterway') {
            if (node.id === way.first()) {
                // multiple waterways may start at the same spring
                if (node.tags.natural === 'spring') return true;
            } else {
                // multiple waterways may end at the same drain
                if (node.tags.manhole === 'drain') return true;
            }
        }

        return context.graph().parentWays(node).some(function(parentWay) {
            if (parentWay.id === way.id) return false;

            if (wayType === 'highway') {

                // allow connections to highway areas
                if (parentWay.geometry(context.graph()) === 'area' &&
                    osmRoutableHighwayTagValues[parentWay.tags.highway]) return true;

                // count connections to ferry routes as connected
                if (parentWay.tags.route === 'ferry') return true;

                return context.graph().parentRelations(parentWay).some(function(parentRelation) {
                    if (parentRelation.tags.type === 'route' &&
                        parentRelation.tags.route === 'ferry') return true;

                    // allow connections to highway multipolygons
                    return parentRelation.isMultipolygon() && osmRoutableHighwayTagValues[parentRelation.tags.highway];
                });
            } else if (wayType === 'waterway') {
                // multiple waterways may start or end at a water body at the same node
                if (parentWay.tags.natural === 'water' ||
                    parentWay.tags.natural === 'coastline') return true;
            }
            return false;
        });
    }

    function issuesForNode(context, way, nodeID) {

        var isFirst = nodeID === way.first();

        var wayType = typeForWay(way, context);

        // ignore if this way is self-connected at this node
        if (nodeOccursMoreThanOnce(way, nodeID)) return [];

        var osm = context.connection();
        if (!osm) return [];

        var node = context.hasEntity(nodeID);

        // ignore if this node or its tile are unloaded
        if (!node || !osm.isDataLoaded(node.loc)) return [];

        if (isConnectedViaOtherTypes(context, way, node)) return [];

        var attachedWaysOfSameType = context.graph().parentWays(node).filter(function(parentWay) {
            if (parentWay.id === way.id) return false;
            return typeForWay(parentWay, context) === wayType;
        });

        // assume it's okay for waterways to start or end disconnected for now
        if (wayType === 'waterway' && attachedWaysOfSameType.length === 0) return [];

        var attachedOneways = attachedWaysOfSameType.filter(function(attachedWay) {
            return isOneway(attachedWay);
        });

        // ignore if the way is connected to some non-oneway features
        if (attachedOneways.length < attachedWaysOfSameType.length) return [];

        if (attachedOneways.length) {
            var connectedEndpointsOkay = attachedOneways.some(function(attachedOneway) {
                if ((isFirst ? attachedOneway.first() : attachedOneway.last()) !== nodeID) return true;
                if (nodeOccursMoreThanOnce(attachedOneway, nodeID)) return true;
                return false;
            });
            if (connectedEndpointsOkay) return [];
        }

        var fixes = [];

        if (attachedOneways.length) {
            fixes.push(new validationIssueFix({
                icon: 'iD-operation-reverse',
                title: t('issues.fix.reverse_feature.title'),
                entityIds: [way.id],
                onClick: function() {
                    var id = this.issue.entityIds[0];
                    context.perform(actionReverse(id), t('operations.reverse.annotation'));
                }
            }));
        }
        if (node.tags.noexit !== 'yes') {
            fixes.push(new validationIssueFix({
                icon: 'iD-operation-continue' + (isFirst ? '-left' : ''),
                title: t('issues.fix.continue_from_' + (isFirst ? 'start' : 'end') + '.title'),
                onClick: function() {
                    var entityID = this.issue.entityIds[0];
                    var vertexID = this.issue.entityIds[1];
                    var way = context.entity(entityID);
                    var vertex = context.entity(vertexID);
                    continueDrawing(way, vertex, context);
                }
            }));
        }

        var placement = isFirst ? 'start' : 'end',
            messageID = wayType + '.',
            referenceID = wayType + '.';

        if (wayType === 'waterway') {
            messageID += 'connected.' + placement;
            referenceID += 'connected';
        } else {
            messageID += placement;
            referenceID += placement;
        }

        return [new validationIssue({
            type: type,
            subtype: wayType,
            severity: 'warning',
            message: function() {
                var entity = context.hasEntity(this.entityIds[0]);
                return entity ? t('issues.impossible_oneway.' + messageID + '.message', {
                    feature: utilDisplayLabel(entity, context)
                }) : '';
            },
            reference: getReference(referenceID),
            entityIds: [way.id, node.id],
            fixes: fixes
        })];

        function getReference(referenceID) {
            return function showReference(selection) {
                selection.selectAll('.issue-reference')
                    .data([0])
                    .enter()
                    .append('div')
                    .attr('class', 'issue-reference')
                    .text(t('issues.impossible_oneway.' + referenceID + '.reference'));
            };
        }
    }

    var validation = function checkDisconnectedWay(entity, context) {

        if (entity.type !== 'way' || entity.geometry(context.graph()) !== 'line') return [];

        if (entity.isClosed()) return [];

        if (!typeForWay(entity, context)) return [];

        if (!isOneway(entity)) return [];

        var firstIssues = issuesForNode(context, entity, entity.first());
        var lastIssues = issuesForNode(context, entity, entity.last());

        return firstIssues.concat(lastIssues);
    };

    validation.type = type;

    return validation;
}
<|endoftext|>


<commit_before>window.onmouseup = function run(event1) {
  console.log("Mouse Up.... Line 1!");
  var echoForm = false

  if (window.getSelection() != "") {
    var keys = [];
    var selectedString = window.getSelection().toString();

    onkeydown = onkeyup = function(event2) {
      keys[event2.keyCode] = event2.type == 'keydown';

      if ( (keys[17] === true) && (keys[69] === true) ) {
        event2.preventDefault();
        (keys[17] = false);
        (keys[69] = false);

        if ( echoForm === false ) {
          // not protected variable!
          spawnedEcho = spawnEchoForm(event1.pageX, event1.pageY, this);
          echoForm = true;

          console.log("Before submit: " + selectedString);

          var userTextandSubmitForm = document.getElementById("userTextAndSubmit");
          userTextandSubmitForm.addEventListener("submit", function(event3){
            event3.preventDefault();

            console.log("Inside button submit: " + selectedString);

            var userText = document.getElementById("userText").value;

            closeEchoFormAfterSubmit(selectedString);
            echoForm = false;

            chrome.runtime.sendMessage({
              message: selectedString + " " + userText
            }, function(response) {
              // response from eventpage.js
            });
          });
        };

        document.onmouseup = function(event4) {
          console.log("Inside MouseDown/UP: " + selectedString);
          hideSpawnedEcho(event4, selectedString);
        };
      };
    };
  };
};

function closeEchoFormAfterSubmit(selectedString) {
  var echoFrame = document.getElementsByClassName("echo-frame")[0];
  body.removeChild(echoFrame);
  spawnedEcho = null;
  console.log("Greetings from Close Form: " + selectedString);
  removeHighlight(selectedString);
};

function spawnEchoForm(x, y, that) {
  that.echoForm = document.createElement("div");
  that.echoForm.setAttribute("class", "echo-frame");

  that.echoSubmit = document.createElement("div");
  that.echoSubmit.setAttribute("class", "echo-submit");
  that.echoForm.appendChild(that.echoSubmit);

  that.echoInputForm = document.createElement("form");
  that.echoInputForm.setAttribute("id", "userTextAndSubmit");
  that.echoSubmit.appendChild(that.echoInputForm);

  that.echoButton = document.createElement("button");
  that.echoButton.setAttribute("type", "submit");
  that.echoInputForm.appendChild(that.echoButton);

  that.echoText = document.createElement("input");
  that.echoText.setAttribute("type", "text");
  that.echoText.setAttribute("id", "userText");
  that.echoText.setAttribute("name", "userText");
  that.echoText.setAttribute("placeholder", "add to your Echo");
  that.echoInputForm.appendChild(that.echoText);

  that.echoTextCharCount = document.createElement("div");
  that.echoTextCharCount.setAttribute("id", "char-count");
  that.echoInputForm.appendChild(that.echoTextCharCount);

  var shortenedUrlLength = 25; //subject to change based on length of shortered URL
  var userSelectedString = window.getSelection().toString();
  var lengthOfUserText = that.echoText.value.length;
  var charCount = userSelectedString.length + shortenedUrlLength + lengthOfUserText;
  that.echoTextCharCount.innerHTML = charCount;

  that.echoText.addEventListener("keyup", function(event) {
    lengthOfUserText = that.echoText.value.length;
    charCount = userSelectedString.length + shortenedUrlLength + lengthOfUserText;
    that.echoTextCharCount.innerHTML = charCount;
  });

  that.echoText.addEventListener("keyup", function(event) {
    lengthOfUserText = that.echoText.value.length;
    charCount = userSelectedString.length + shortenedUrlLength + lengthOfUserText;
    that.echoTextCharCount.innerHTML = charCount;

    if (charCount > 119 && charCount < 140){
      document.getElementById("char-count").style.color="#e67e22";
    }
    else if (charCount > 139){
      document.getElementById("char-count").style.color="#c0392b";
    }
    else {
      document.getElementById("char-count").style.backgroundColor="transparent";
    }
  });

  that.fileRef = document.createElement("link");
  that.fileRef.setAttribute("rel", "stylesheet");
  that.fileRef.setAttribute("type", "text/css");
  that.fileRef.setAttribute("href", chrome.extension.getURL("echoform.css"));
  document.getElementsByTagName("head")[0].appendChild(that.fileRef);

  that.echoForm.style.visibility = "visible";

  if ( x > (document.body.clientWidth - 300) ) {
    x = document.body.clientWidth - 310;
    that.echoForm.style.left = x + "px";
  } else {
    that.echoForm.style.left = x + "px";
  };

  y = y + 15;
  that.echoForm.style.top = y + "px";

  body = document.getElementsByTagName("body")[0];
  body.appendChild(that.echoForm);
  textHighlight();
  document.getElementById("userText").focus();
  return true;
};

function hideSpawnedEcho(event4, selectedString) {
  var echoFrame = document.getElementsByClassName("echo-frame")[0];
  console.log("Hide Spawned: " + selectedString);
  console.log(spawnedEcho);

  if (spawnedEcho) {
    if (!checkClickEventWithinForm(event4, echoFrame)) {
      body.removeChild(echoFrame);
      spawnedEcho = null;
      console.log("almost to remove: " + selectedString);
      removeHighlight(selectedString);
    }
  }
};

function checkClickEventWithinForm(event, parent) {
  var current = event.target;

  while (current) {
    if (current === parent) return true;
    current = current.parentNode;
  }
  return false;
};

function textHighlight() {
  window.getSelection();

  document.designMode = "on";
  document.execCommand("BackColor", false, "#B6FCD5");
  document.designMode = "off";
}

function removeHighlight(selectedString) {
  console.log("greeting from remove: " + selectedString);
  window.find(selectedString);

  document.designMode = "on";
  document.execCommand("backcolor", false, "#FFFFFF");
  document.designMode = "off";
  window.getSelection().removeAllRanges();
}
<commit_msg>Content Script; Fixed bug for backspacing color change<commit_after>window.onmouseup = function run(event1) {
  console.log("Mouse Up.... Line 1!");
  var echoForm = false

  if (window.getSelection() != "") {
    var keys = [];
    var selectedString = window.getSelection().toString();

    onkeydown = onkeyup = function(event2) {
      keys[event2.keyCode] = event2.type == 'keydown';

      if ( (keys[17] === true) && (keys[69] === true) ) {
        event2.preventDefault();
        (keys[17] = false);
        (keys[69] = false);

        if ( echoForm === false ) {
          // not protected variable!
          spawnedEcho = spawnEchoForm(event1.pageX, event1.pageY, this);
          echoForm = true;

          console.log("Before submit: " + selectedString);

          var userTextandSubmitForm = document.getElementById("userTextAndSubmit");
          userTextandSubmitForm.addEventListener("submit", function(event3){
            event3.preventDefault();

            console.log("Inside button submit: " + selectedString);

            var userText = document.getElementById("userText").value;

            closeEchoFormAfterSubmit(selectedString);
            echoForm = false;

            chrome.runtime.sendMessage({
              message: selectedString + " " + userText
            }, function(response) {
              // response from eventpage.js
            });
          });
        };

        document.onmouseup = function(event4) {
          console.log("Inside MouseDown/UP: " + selectedString);
          hideSpawnedEcho(event4, selectedString);
        };
      };
    };
  };
};

function closeEchoFormAfterSubmit(selectedString) {
  var echoFrame = document.getElementsByClassName("echo-frame")[0];
  body.removeChild(echoFrame);
  spawnedEcho = null;
  console.log("Greetings from Close Form: " + selectedString);
  removeHighlight(selectedString);
};

function spawnEchoForm(x, y, that) {
  that.echoForm = document.createElement("div");
  that.echoForm.setAttribute("class", "echo-frame");

  that.echoSubmit = document.createElement("div");
  that.echoSubmit.setAttribute("class", "echo-submit");
  that.echoForm.appendChild(that.echoSubmit);

  that.echoInputForm = document.createElement("form");
  that.echoInputForm.setAttribute("id", "userTextAndSubmit");
  that.echoSubmit.appendChild(that.echoInputForm);

  that.echoButton = document.createElement("button");
  that.echoButton.setAttribute("type", "submit");
  that.echoInputForm.appendChild(that.echoButton);

  that.echoText = document.createElement("input");
  that.echoText.setAttribute("type", "text");
  that.echoText.setAttribute("id", "userText");
  that.echoText.setAttribute("name", "userText");
  that.echoText.setAttribute("placeholder", "add to your Echo");
  that.echoInputForm.appendChild(that.echoText);

  that.echoTextCharCount = document.createElement("div");
  that.echoTextCharCount.setAttribute("id", "char-count");
  that.echoInputForm.appendChild(that.echoTextCharCount);

  var shortenedUrlLength = 25; //subject to change based on length of shortered URL
  var userSelectedString = window.getSelection().toString();
  var lengthOfUserText = that.echoText.value.length;
  var charCount = userSelectedString.length + shortenedUrlLength + lengthOfUserText;
  that.echoTextCharCount.innerHTML = charCount;

  that.echoText.addEventListener("keyup", function(event) {
    lengthOfUserText = that.echoText.value.length;
    charCount = userSelectedString.length + shortenedUrlLength + lengthOfUserText;
    that.echoTextCharCount.innerHTML = charCount;
  });

  that.echoText.addEventListener("keyup", function(event) {
    lengthOfUserText = that.echoText.value.length;
    charCount = userSelectedString.length + shortenedUrlLength + lengthOfUserText;
    that.echoTextCharCount.innerHTML = charCount;

    if (charCount > 119 && charCount < 140){
      document.getElementById("char-count").style.color="#e67e22";
    }
    else if (charCount > 139){
      document.getElementById("char-count").style.color="#c0392b";
    }
    else {
      document.getElementById("char-count").style.color="#000000";
    }
  });

  that.fileRef = document.createElement("link");
  that.fileRef.setAttribute("rel", "stylesheet");
  that.fileRef.setAttribute("type", "text/css");
  that.fileRef.setAttribute("href", chrome.extension.getURL("echoform.css"));
  document.getElementsByTagName("head")[0].appendChild(that.fileRef);

  that.echoForm.style.visibility = "visible";

  if ( x > (document.body.clientWidth - 300) ) {
    x = document.body.clientWidth - 310;
    that.echoForm.style.left = x + "px";
  } else {
    that.echoForm.style.left = x + "px";
  };

  y = y + 15;
  that.echoForm.style.top = y + "px";

  body = document.getElementsByTagName("body")[0];
  body.appendChild(that.echoForm);
  textHighlight();
  document.getElementById("userText").focus();
  return true;
};

function hideSpawnedEcho(event4, selectedString) {
  var echoFrame = document.getElementsByClassName("echo-frame")[0];
  console.log("Hide Spawned: " + selectedString);
  console.log(spawnedEcho);

  if (spawnedEcho) {
    if (!checkClickEventWithinForm(event4, echoFrame)) {
      body.removeChild(echoFrame);
      spawnedEcho = null;
      console.log("almost to remove: " + selectedString);
      removeHighlight(selectedString);
    }
  }
};

function checkClickEventWithinForm(event, parent) {
  var current = event.target;

  while (current) {
    if (current === parent) return true;
    current = current.parentNode;
  }
  return false;
};

function textHighlight() {
  window.getSelection();

  document.designMode = "on";
  document.execCommand("BackColor", false, "#B6FCD5");
  document.designMode = "off";
}

function removeHighlight(selectedString) {
  console.log("greeting from remove: " + selectedString);
  window.find(selectedString);

  document.designMode = "on";
  document.execCommand("backcolor", false, "#FFFFFF");
  document.designMode = "off";
  window.getSelection().removeAllRanges();
}
<|endoftext|>


<commit_before>function peelBackRdf(data, format) {
  $('body').prepend('
<textarea id="code"></textarea>
');
  $('#code').text(data);
  var cm = CodeMirror.fromTextArea($('#code')[0], {
    mode: format,
    readOnly: "nocursor",
    viewportMargin: Infinity
  });
  $('#target').fold({
    directory: "chrome-extension://" + chrome.runtime.id,
    autoCurl: true
  });
  $('#turn_wrapper').click(
    function() {
      if ($('#turn_fold').is(':visible')) {
        $('#turn_fold').hide();
        $('#turn_wrapper').width('100%').height('100%').off();
        $('#turn_object').width('100%').height('100%').off();
        $('#turn_hideme').width('100%').height('100%').off();
      }/* else {
        $('#turn_fold').show();
        $('#turn_wrapper').width('80px').height('80px');
        $('#turn_object').width('80px').height('80px');
        $('#turn_hideme').width('85px').height('85px');
      } */
    }
  );
}

$.typedValue.types['http://www.w3.org/2001/XMLSchema#positiveInteger'] = {
    regex: /^[1-9][0-9]*$/,
    strip: true,
    /** @ignore */
    value: function (v) {
      return parseInt(v, 10);
    }
  };

function checkRdfXmlLicense(data, format) {
  var parser = new DOMParser();
  doc = parser.parseFromString(data, 'text/xml');
  try {
    var rdf = $.rdf().load(doc);
    var licenses = rdf
      .prefix('cc', 'http://creativecommons.org/ns#')
      .where('?doc cc:license ?license');
    licenses = licenses.add(
      rdf
        .prefix('dct', 'http://purl.org/dc/terms/')
        .where('?doc dct:license ?license')
    );
    if (licenses.select().length > 0) {
      return 'licensed';
    } else {
      return 'unlicensed';
    }
  } catch (e) {
    console.log(e);
    return 'error';
  }
}

function fetchRdf(rdfUrl, failfunc) {
  $.ajax(rdfUrl, {
    headers: {
      Accept: acceptFormats.join(', ')
    },
    cache: false,
    dataType: 'text',
    error: function(req, textStatus, errorThrown) {
      failfunc();
    },
    success: function(data, textStatus, res) {
      var ct = res.getResponseHeader('Content-Type');
      if (ct != null) {
        var format = null;
        for (var i = 0; i < acceptFormats.length; i++) {
          if (ct.slice(0, acceptFormats[i].length) == acceptFormats[i]) {
            format = acceptFormats[i];
            break;
          }
        }
        if (format != null) {
          peelBackRdf(data, format);
          chrome.runtime.sendMessage({
            method: 'setLicense',
            type: format,
	    check: checkRdfXmlLicense(data, format)
          }, function(response) {
	    console.log(response.text);
          });
        } else {
          failfunc();
        }
      } else {
        failfunc();
      }
    }
  });
}

var res = document.evaluate("//link[(@rel = 'alternate') or (@rel = 'meta')]", document.head, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)

var rdfUrl = null;
var rdfFormat = null;
var acceptFormats = ['application/rdf+xml', 'text/turtle'];

for (var i=0; i < res.snapshotLength; i++) {
  if (acceptFormats.indexOf(res.snapshotItem(i).type) > -1) {
    rdfFormat = res.snapshotItem(i).type;
    rdfUrl = res.snapshotItem(i).href; // relative
    break;
  }
}

if (rdfUrl == null) {
  // check to see whether we've been redirected here
  chrome.runtime.sendMessage({
    method: 'isRedirect',
    url: document.URL
  }, function(response) {
    if (response.redirect) {
      fetchRdf(response.fromUrl, function() {
        fetchRdf(document.URL); // if failed to fetch prior page as RDF
      });
    } else { // if no redirect, try fetching current page as RDF
      fetchRdf(document.URL, function() {});
    }
  });
} else {
  fetchRdf(rdfUrl, function() {});
}
<commit_msg>Avoid pesky cache buster additions.<commit_after>function peelBackRdf(data, format) {
  $('body').prepend('
<textarea id="code"></textarea>
');
  $('#code').text(data);
  var cm = CodeMirror.fromTextArea($('#code')[0], {
    mode: format,
    readOnly: "nocursor",
    viewportMargin: Infinity
  });
  $('#target').fold({
    directory: "chrome-extension://" + chrome.runtime.id,
    autoCurl: true
  });
  $('#turn_wrapper').click(
    function() {
      if ($('#turn_fold').is(':visible')) {
        $('#turn_fold').hide();
        $('#turn_wrapper').width('100%').height('100%').off();
        $('#turn_object').width('100%').height('100%').off();
        $('#turn_hideme').width('100%').height('100%').off();
      }/* else {
        $('#turn_fold').show();
        $('#turn_wrapper').width('80px').height('80px');
        $('#turn_object').width('80px').height('80px');
        $('#turn_hideme').width('85px').height('85px');
      } */
    }
  );
}

$.typedValue.types['http://www.w3.org/2001/XMLSchema#positiveInteger'] = {
    regex: /^[1-9][0-9]*$/,
    strip: true,
    /** @ignore */
    value: function (v) {
      return parseInt(v, 10);
    }
  };

function checkRdfXmlLicense(data, format) {
  var parser = new DOMParser();
  doc = parser.parseFromString(data, 'text/xml');
  try {
    var rdf = $.rdf().load(doc);
    var licenses = rdf
      .prefix('cc', 'http://creativecommons.org/ns#')
      .where('?doc cc:license ?license');
    licenses = licenses.add(
      rdf
        .prefix('dct', 'http://purl.org/dc/terms/')
        .where('?doc dct:license ?license')
    );
    if (licenses.select().length > 0) {
      return 'licensed';
    } else {
      return 'unlicensed';
    }
  } catch (e) {
    console.log(e);
    return 'error';
  }
}

function fetchRdf(rdfUrl, failfunc) {
  $.ajax(rdfUrl, {
    headers: {
      Accept: acceptFormats.join(', ')
    },
    cache: true,
    dataType: 'text',
    error: function(req, textStatus, errorThrown) {
      failfunc();
    },
    success: function(data, textStatus, res) {
      var ct = res.getResponseHeader('Content-Type');
      if (ct != null) {
        var format = null;
        for (var i = 0; i < acceptFormats.length; i++) {
          if (ct.slice(0, acceptFormats[i].length) == acceptFormats[i]) {
            format = acceptFormats[i];
            break;
          }
        }
        if (format != null) {
          peelBackRdf(data, format);
          chrome.runtime.sendMessage({
            method: 'setLicense',
            type: format,
	    check: checkRdfXmlLicense(data, format)
          }, function(response) {
	    console.log(response.text);
          });
        } else {
          failfunc();
        }
      } else {
        failfunc();
      }
    }
  });
}

var res = document.evaluate("//link[(@rel = 'alternate') or (@rel = 'meta')]", document.head, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)

var rdfUrl = null;
var rdfFormat = null;
var acceptFormats = ['application/rdf+xml', 'text/turtle'];

for (var i=0; i < res.snapshotLength; i++) {
  if (acceptFormats.indexOf(res.snapshotItem(i).type) > -1) {
    rdfFormat = res.snapshotItem(i).type;
    rdfUrl = res.snapshotItem(i).href; // relative
    break;
  }
}

if (rdfUrl == null) {
  // check to see whether we've been redirected here
  chrome.runtime.sendMessage({
    method: 'isRedirect',
    url: document.URL
  }, function(response) {
    if (response.redirect) {
      fetchRdf(response.fromUrl, function() {
        fetchRdf(document.URL); // if failed to fetch prior page as RDF
      });
    } else { // if no redirect, try fetching current page as RDF
      fetchRdf(document.URL, function() {});
    }
  });
} else {
  fetchRdf(rdfUrl, function() {});
}
<|endoftext|>


<commit_before>// Try to find diff file line numbers on the current page and link them their locations
function updateLineNumberButtons() {
	$('.linkable-line-number').each(function(i, el) {
    	el.onclick = function(mouseEvent) {
      		var line = $.trim(el.innerText);
      		if(parseInt(line)) {
        		// `line` seems to be a valid line number. Generate the URL to view the file at this line.
        		var baseURL = $(el).first().parentsUntil('.diff-view').last().find('.grouped-button')[0].href;
        		var lineParameter = '#L' + line + '-' + line;

        		// If the used presses the `alt` key we try to open the file for editing:
        		if(mouseEvent.altKey) {
          			var branch = getPullRequestHeadBranch();

          			if(branch) {
            			baseURL = baseURL.replace(/blob\/[a-z0-9]+/, 'edit/' + branch);
            			lineParameter = '?gotoLine=' + line;
          			} else {
            			alert('Sorry, you can\'t edit this file because you\'re not on a named branch');
          			}
        		}

        		window.open(baseURL + lineParameter, '_blank');
      		}
    	}
  	})
}

// Read a URL parameter from the current window URL
function getURLParameter(sParam) {
	var sPageURL = window.location.search.substring(1);
  	var sURLVariables = sPageURL.split('&');
    	for (var i = 0; i < sURLVariables.length; i++) {
        	var sParameterName = sURLVariables[i].split('=');
        	if (sParameterName[0] == sParam) {
            	return sParameterName[1];
        }
    }
}

// Check for a valid `gotoLine` URL parameter (generated by github magic) and try to find the github
// editor window in order to jump to the specified line.
function gotoLine() {
 	var line = parseInt(getURLParameter('gotoLine'));
 	if(line) {
		$(window).load(function() {
   			location.href = 'javascript:editor.ace.gotoLine(' + line + ', 0, false);' +
   			                ' editor.ace.scrollToRow(' + (line-1) + ');'
    	});
  	}
}

// Returns `true` if we are on a Github Pull Request page
function isPullRequestPage() {
  var pullRequestMatcher =/pull\/[0-9]+(\/files)?$/;
  return pullRequestMatcher.exec(window.location.pathname);
}

// Returns a Github URL
function getFileURL(command, fork, branch, file)
{
  return window.location.origin + '/' +
         fork +
         window.location.pathname.match(/\/[-A-Za-z0-9_]+/g)[1] + '/' +
         command + '/' + branch + '/' + file;
}

// Returns a Github blame URL
function getBlameURL(fork, branch, file)
{
  return getFileURL('blame', fork, branch, file);
}

// Returns the head branch of the current Pull Request
function getPullRequestHeadBranch() {
    return $('.pull-description .commit-ref .css-truncate-target')
      .last()
      .text();
}

// Returns the fork of the head branch of the current Pull Request
function getPullRequestHeadBranchFork() {
    var fork = $('.pull-description .commit-ref .css-truncate-target')
                .last()
                .prev()
                .text();

    // If the head and base branch is in the same fork, we need to read the fork name differently:
    if (!fork) {
      fork = window.location.pathname.match(/\/[-A-Za-z0-9_]+/g)[0];
      fork = fork.substring(1, fork.length);
    }
    return fork;
}

// Blame cache dictionary
//    Key: github blame URL
//    Value: Dictionary StartLine --> CommitInfo
var gitBlameCache = {};

// Read a commit info from the blame cache
function getCommitInfo(file, lineNumber) {

  // Go up in the file until we find the first line of a commit
  var i = lineNumber;
  while (  i >= 0 && !(i in gitBlameCache[file]) ) i--;

  if (i >= 0)
    return gitBlameCache[file][i];
  else
    return undefined;
}

// Performs git blame on a file in a branch and
// calls the callback with parameters `file`, `startLineNumber` and `commitMessage`
function blame(fork, branch, file, lineNumber, callback) {

  // Do request the blame if it was already requested
  if (file in gitBlameCache) {
    callback();
    return;
  }

  gitBlameCache[file] = {};

  var blameURL = getBlameURL(fork, branch, file);
  console.log(blameURL);
  $.ajax({
    url: blameURL,
    success: function(data, textStatus, jqXHR) {
      console.log('Received blame for ' + file);
      $(data).each(function(){
        if ($(this).is('div')) {
          var sections = $('.highlight .section-first', this);

          for (var i=0; i<sections.length; i++)
          {
            var author = $('.commitinfo', sections[i]).find('[rel="author"]').html();
            if (!author) {
              author = $('.commitinfo', sections[i]).find('a').last().html();
            }

            var commitDate = $('.commitinfo .date', sections[i]).html();
            var commitMessage = $('.commitinfo .message', sections[i]).attr('title');
            var startLineNumber = parseInt($('.line-number', sections[i]).html());

            if (i<sections.length-1) {
              var endLineNumber = parseInt($('.line-number', sections[i+1]).html()) - 1;
            } else {
              var endLineNumber = parseInt($('.line-number', this).last().html());
            }

            var commitInfo = {
              author: author,
              date: commitDate,
              message: commitMessage,
              startLineNumber: startLineNumber,
              endLineNumber: endLineNumber
            };

            gitBlameCache[file][startLineNumber] = commitInfo;
          }
        }
      });
      callback();
    },
    error: function(jqXHR, textStatus, errorThrown) {
      // In case of an timeout we want to reload the blame again. In all other cases not. E.g.
      // github returns an error if we perform a blame on an image.
      if (textStatus === "timeout") {
        delete gitBlameCache[file];
      }
    }
  });
}

// Returns a string containing the distance of time in words between `from` and now
// Source: https://github.com/drinks/jquery-relative-date/blob/master/jquery.relative-date.js
function distance_of_time_in_words(from) {
  var today = new Date;
  var distance_in_seconds = ((today - Date.parse(from)) / 1000);
  var distance_in_minutes = Math.floor(distance_in_seconds / 60);

  if (distance_in_minutes == 0) { return 'less than a minute ago'; }
  if (distance_in_minutes == 1) { return 'a minute ago'; }
  if (distance_in_minutes < 45) { return distance_in_minutes + ' minutes ago'; }
  if (distance_in_minutes < 90) { return 'about 1 hour ago'; }
  if (distance_in_minutes < 1440) { return 'about ' + Math.round(distance_in_minutes / 60) + ' hours ago'; }
  if (distance_in_minutes < 2880) { return '1 day ago'; }
  if (distance_in_minutes < 43200) { return Math.floor(distance_in_minutes / 1440) + ' days ago'; }
  if (distance_in_minutes < 86400) { return 'about 1 month ago'; }
  if (distance_in_minutes < 525960) { return Math.floor(distance_in_minutes / 43200) + ' months ago'; }
  if (distance_in_minutes < 1051199) { return 'about 1 year ago'; }

  return 'over ' + Math.floor(distance_in_minutes / 525960) + ' years ago';
}

// Augments the `githubLineNumberElement` on mouse hover with the commit info about the line
function updatePullRequestLineNumberElement(githubLineNumberElement, relativeFileURL, lineNumber) {

  var commitInfo = getCommitInfo(relativeFileURL, lineNumber);

  // Check if we have a valid commit info and if the mouse is still hovering over the element
  if (!commitInfo || !$(githubLineNumberElement).data('mouseIsHovering'))
    return;

  // Remove the hover handler that creates the augmentation
  $(githubLineNumberElement).unbind();
  $(githubLineNumberElement).data('mouseIsHovering', false);

  var linesHeight = 16;
  var commitBracketHeigth = (commitInfo.endLineNumber - commitInfo.startLineNumber + 1) * linesHeight + 2;
  var left = $(githubLineNumberElement).outerWidth() * 2 + 3;
  var top = $(githubLineNumberElement).position().top - (lineNumber - commitInfo.startLineNumber) * linesHeight;

  var commitBracket = $('
').appendTo(githubLineNumberElement)

  var commitInfo = $('
' + commitInfo.message +
                       '
by ' + commitInfo.author + ', ' + distance_of_time_in_words(commitInfo.date) +'
' +
                     '
')
                   .appendTo(githubLineNumberElement);

  $(githubLineNumberElement).hover(function () {
    commitInfo.show();
    commitBracket.show();
  }, function () {
    commitBracket.hide();
    commitInfo.hide();
  });
}

function updatePullRequest() {
  if (isPullRequestPage()) {

    // Modify all line numbers to detect if the mouse hovers over them
    var sourceCodeLines = $('.data').find('.line_numbers.linkable-line-number').filter('td[id*="R"]');

    $.each(sourceCodeLines, function(i, githubLineNumberElement) {
      $(githubLineNumberElement).hover(function () {

        $(githubLineNumberElement).data('mouseIsHovering', true);

        var relativeFileURL = $(githubLineNumberElement).parents('.file').children('.meta').attr('data-path');
        var lineNumber = parseInt($(githubLineNumberElement).text());

        if (relativeFileURL && lineNumber) {
          blame(getPullRequestHeadBranchFork(),
                getPullRequestHeadBranch(),
                relativeFileURL,
                lineNumber,
                function() {
                  updatePullRequestLineNumberElement(githubLineNumberElement, relativeFileURL, lineNumber);
                });
        }
      },
      function () {
        $(githubLineNumberElement).data('mouseIsHovering', false);
      });
    });
  }
}

// Detect a github page. I use this method instead of an URL check to support github enterprise
// instances.
function isGithubSite() {
	return $('meta[property="og:site_name"]').attr('content') === "GitHub";
}

// Main function. Executed after on document end (as defined in manifest.json)
if(isGithubSite()) {
	updateLineNumberButtons();
  updatePullRequest();
	gotoLine();
}<commit_msg>Fix bracket position and length.<commit_after>// Try to find diff file line numbers on the current page and link them their locations
function updateLineNumberButtons() {
	$('.linkable-line-number').each(function(i, el) {
    	el.onclick = function(mouseEvent) {
      		var line = $.trim(el.innerText);
      		if(parseInt(line)) {
        		// `line` seems to be a valid line number. Generate the URL to view the file at this line.
        		var baseURL = $(el).first().parentsUntil('.diff-view').last().find('.grouped-button')[0].href;
        		var lineParameter = '#L' + line + '-' + line;

        		// If the used presses the `alt` key we try to open the file for editing:
        		if(mouseEvent.altKey) {
          			var branch = getPullRequestHeadBranch();

          			if(branch) {
            			baseURL = baseURL.replace(/blob\/[a-z0-9]+/, 'edit/' + branch);
            			lineParameter = '?gotoLine=' + line;
          			} else {
            			alert('Sorry, you can\'t edit this file because you\'re not on a named branch');
          			}
        		}

        		window.open(baseURL + lineParameter, '_blank');
      		}
    	}
  	})
}

// Read a URL parameter from the current window URL
function getURLParameter(sParam) {
	var sPageURL = window.location.search.substring(1);
  	var sURLVariables = sPageURL.split('&');
    	for (var i = 0; i < sURLVariables.length; i++) {
        	var sParameterName = sURLVariables[i].split('=');
        	if (sParameterName[0] == sParam) {
            	return sParameterName[1];
        }
    }
}

// Check for a valid `gotoLine` URL parameter (generated by github magic) and try to find the github
// editor window in order to jump to the specified line.
function gotoLine() {
 	var line = parseInt(getURLParameter('gotoLine'));
 	if(line) {
		$(window).load(function() {
   			location.href = 'javascript:editor.ace.gotoLine(' + line + ', 0, false);' +
   			                ' editor.ace.scrollToRow(' + (line-1) + ');'
    	});
  	}
}

// Returns `true` if we are on a Github Pull Request page
function isPullRequestPage() {
  var pullRequestMatcher =/pull\/[0-9]+(\/files)?$/;
  return pullRequestMatcher.exec(window.location.pathname);
}

// Returns a Github URL
function getFileURL(command, fork, branch, file)
{
  return window.location.origin + '/' +
         fork +
         window.location.pathname.match(/\/[-A-Za-z0-9_]+/g)[1] + '/' +
         command + '/' + branch + '/' + file;
}

// Returns a Github blame URL
function getBlameURL(fork, branch, file)
{
  return getFileURL('blame', fork, branch, file);
}

// Returns the head branch of the current Pull Request
function getPullRequestHeadBranch() {
    return $('.pull-description .commit-ref .css-truncate-target')
      .last()
      .text();
}

// Returns the fork of the head branch of the current Pull Request
function getPullRequestHeadBranchFork() {
    var fork = $('.pull-description .commit-ref .css-truncate-target')
                .last()
                .prev()
                .text();

    // If the head and base branch is in the same fork, we need to read the fork name differently:
    if (!fork) {
      fork = window.location.pathname.match(/\/[-A-Za-z0-9_]+/g)[0];
      fork = fork.substring(1, fork.length);
    }
    return fork;
}

// Blame cache dictionary
//    Key: github blame URL
//    Value: Dictionary StartLine --> CommitInfo
var gitBlameCache = {};

// Read a commit info from the blame cache
function getCommitInfo(file, lineNumber) {

  // Go up in the file until we find the first line of a commit
  var i = lineNumber;
  while (  i >= 0 && !(i in gitBlameCache[file]) ) i--;

  if (i >= 0)
    return gitBlameCache[file][i];
  else
    return undefined;
}

// Performs git blame on a file in a branch and
// calls the callback with parameters `file`, `startLineNumber` and `commitMessage`
function blame(fork, branch, file, lineNumber, callback) {

  // Do request the blame if it was already requested
  if (file in gitBlameCache) {
    callback();
    return;
  }

  gitBlameCache[file] = {};

  var blameURL = getBlameURL(fork, branch, file);
  console.log(blameURL);
  $.ajax({
    url: blameURL,
    success: function(data, textStatus, jqXHR) {
      console.log('Received blame for ' + file);
      $(data).each(function(){
        if ($(this).is('div')) {
          var sections = $('.highlight .section-first', this);

          for (var i=0; i<sections.length; i++)
          {
            var author = $('.commitinfo', sections[i]).find('[rel="author"]').html();
            if (!author) {
              author = $('.commitinfo', sections[i]).find('a').last().html();
            }

            var commitDate = $('.commitinfo .date', sections[i]).html();
            var commitMessage = $('.commitinfo .message', sections[i]).attr('title');
            var startLineNumber = parseInt($('.line-number', sections[i]).html());

            if (i<sections.length-1) {
              var endLineNumber = parseInt($('.line-number', sections[i+1]).html()) - 1;
            } else {
              var endLineNumber = parseInt($('.line-number', this).last().html());
            }

            var commitInfo = {
              author: author,
              date: commitDate,
              message: commitMessage,
              startLineNumber: startLineNumber,
              endLineNumber: endLineNumber
            };

            gitBlameCache[file][startLineNumber] = commitInfo;
          }
        }
      });
      callback();
    },
    error: function(jqXHR, textStatus, errorThrown) {
      // In case of an timeout we want to reload the blame again. In all other cases not. E.g.
      // github returns an error if we perform a blame on an image.
      if (textStatus === "timeout") {
        delete gitBlameCache[file];
      }
    }
  });
}

// Returns a string containing the distance of time in words between `from` and now
// Source: https://github.com/drinks/jquery-relative-date/blob/master/jquery.relative-date.js
function distance_of_time_in_words(from) {
  var today = new Date;
  var distance_in_seconds = ((today - Date.parse(from)) / 1000);
  var distance_in_minutes = Math.floor(distance_in_seconds / 60);

  if (distance_in_minutes == 0) { return 'less than a minute ago'; }
  if (distance_in_minutes == 1) { return 'a minute ago'; }
  if (distance_in_minutes < 45) { return distance_in_minutes + ' minutes ago'; }
  if (distance_in_minutes < 90) { return 'about 1 hour ago'; }
  if (distance_in_minutes < 1440) { return 'about ' + Math.round(distance_in_minutes / 60) + ' hours ago'; }
  if (distance_in_minutes < 2880) { return '1 day ago'; }
  if (distance_in_minutes < 43200) { return Math.floor(distance_in_minutes / 1440) + ' days ago'; }
  if (distance_in_minutes < 86400) { return 'about 1 month ago'; }
  if (distance_in_minutes < 525960) { return Math.floor(distance_in_minutes / 43200) + ' months ago'; }
  if (distance_in_minutes < 1051199) { return 'about 1 year ago'; }

  return 'over ' + Math.floor(distance_in_minutes / 525960) + ' years ago';
}

// Augments the `githubLineNumberElement` on mouse hover with the commit info about the line
function updatePullRequestLineNumberElement(githubLineNumberElement, relativeFileURL, lineNumber) {

  var commitInfo = getCommitInfo(relativeFileURL, lineNumber);

  // Check if we have a valid commit info and if the mouse is still hovering over the element
  if (!commitInfo || !$(githubLineNumberElement).data('mouseIsHovering'))
    return;

  // Remove the hover handler that creates the augmentation
  $(githubLineNumberElement).unbind();
  $(githubLineNumberElement).data('mouseIsHovering', false);

  var top;
  var bottom;

  // Find top most line number of the commit
  var lineNumberElement = $(githubLineNumberElement);
  do {
    top = lineNumberElement.position().top;

    var parent = lineNumberElement.parent().prev();
    while (parent.hasClass('inline-comments')) {
      parent = parent.prev();
    }

    lineNumberElement = parent.find('.line_numbers.linkable-line-number').filter('td[id*="R"]');
    var i = parseInt(lineNumberElement.text());
  } while (isNaN(i) === false && i >= commitInfo.startLineNumber)

  // Find bottom most line number of the commit
  lineNumberElement = $(githubLineNumberElement);
  do {
    bottom = lineNumberElement.position().top + lineNumberElement.height();

    var parent = lineNumberElement.parent().next();
    while (parent.hasClass('inline-comments')) {
      parent = parent.next();
    }

    lineNumberElement = parent.find('.line_numbers.linkable-line-number').filter('td[id*="R"]');
    var i = parseInt(lineNumberElement.text());
  } while (isNaN(i) === false && i <= commitInfo.endLineNumber)

  var commitBracketHeigth = bottom - top + 2;
  var left = $(githubLineNumberElement).outerWidth() * 2 + 3;

  var commitBracket = $('
').appendTo(githubLineNumberElement)

  var commitInfo = $('
' + commitInfo.message +
                       '
by ' + commitInfo.author + ', ' + distance_of_time_in_words(commitInfo.date) +'
' +
                     '
')
                   .appendTo(githubLineNumberElement);

  $(githubLineNumberElement).hover(function () {
    commitInfo.show();
    commitBracket.show();
  }, function () {
    commitBracket.hide();
    commitInfo.hide();
  });
}

function updatePullRequest() {
  if (isPullRequestPage()) {

    // Modify all line numbers to detect if the mouse hovers over them
    var sourceCodeLines = $('.data').find('.line_numbers.linkable-line-number').filter('td[id*="R"]');

    $.each(sourceCodeLines, function(i, githubLineNumberElement) {
      $(githubLineNumberElement).hover(function () {

        $(githubLineNumberElement).data('mouseIsHovering', true);

        var relativeFileURL = $(githubLineNumberElement).parents('.file').children('.meta').attr('data-path');
        var lineNumber = parseInt($(githubLineNumberElement).text());

        if (relativeFileURL && lineNumber) {
          blame(getPullRequestHeadBranchFork(),
                getPullRequestHeadBranch(),
                relativeFileURL,
                lineNumber,
                function() {
                  updatePullRequestLineNumberElement(githubLineNumberElement, relativeFileURL, lineNumber);
                });
        }
      },
      function () {
        $(githubLineNumberElement).data('mouseIsHovering', false);
      });
    });
  }
}

// Detect a github page. I use this method instead of an URL check to support github enterprise
// instances.
function isGithubSite() {
	return $('meta[property="og:site_name"]').attr('content') === "GitHub";
}

// Main function. Executed after on document end (as defined in manifest.json)
if(isGithubSite()) {
	updateLineNumberButtons();
  updatePullRequest();
	gotoLine();
}<|endoftext|>


<commit_before>'use strict';

import React from 'react';
import ReactDOM from 'react-dom';
import ConfiguredRadium from './ConfiguredRadium';
import baseStyles from './baseStyles';
import BurgerIcon from './BurgerIcon';
import CrossIcon from './CrossIcon';

export default (styles) => {

  return ConfiguredRadium(React.createClass({

    propTypes: {
      customBurgerIcon: React.PropTypes.oneOfType([
        React.PropTypes.element,
        React.PropTypes.oneOf([false])
      ]),
      customCrossIcon: React.PropTypes.oneOfType([
        React.PropTypes.element,
        React.PropTypes.oneOf([false])
      ]),
      id: React.PropTypes.string,
      isOpen: React.PropTypes.bool,
      noOverlay: React.PropTypes.bool,
      onStateChange: React.PropTypes.func,
      outerContainerId: styles && styles.outerContainer ? React.PropTypes.string.isRequired : React.PropTypes.string,
      pageWrapId: styles && styles.pageWrap ? React.PropTypes.string.isRequired : React.PropTypes.string,
      right: React.PropTypes.bool,
      styles: React.PropTypes.object,
      width: React.PropTypes.number
    },

    toggleMenu() {
      // Order important: handle wrappers before setting sidebar state.
      this.applyWrapperStyles();

      const newState = { isOpen: !this.state.isOpen };
      this.setState(newState, this.props.onStateChange.bind(null, newState));
    },

    // Applies component-specific styles to external wrapper elements.
    applyWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, true);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, true);
      }
    },

    // Removes component-specific styles applied to external wrapper elements.
    clearWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, false);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, false);
      }
    },

    // Sets or unsets styles on DOM elements outside the menu component.
    // This is necessary for correct page interaction with some of the menus.
    // Throws and returns if the required external elements don't exist,
    // which means any external page animations won't be applied.
    handleExternalWrapper(id, wrapperStyles, set) {
      const html = document.querySelector('html');
      const body = document.querySelector('body');
      const wrapper = document.getElementById(id);

      if (!wrapper) {
        console.error("Element with ID '" + id + "' not found");
        return;
      }

      const builtStyles = wrapperStyles(this.state.isOpen, this.props.width, this.props.right);

      for (const prop in builtStyles) {
        if (builtStyles.hasOwnProperty(prop)) {
          wrapper.style[prop] = set ? builtStyles[prop] : '';
        }
      }

      // Prevent any horizontal scroll.
      [html, body].forEach((element) => {
        element.style['overflow-x'] = set ? 'hidden' : '';
      });
    },

    // Builds styles incrementally for a given element.
    getStyles(el, index) {
      const propName = 'bm' + el.replace(el.charAt(0), el.charAt(0).toUpperCase());

      // Set base styles.
      let output = baseStyles[el] ? [baseStyles[el](this.state.isOpen, this.props.width, this.props.right)] : [];

      // Add animation-specific styles.
      if (styles[el]) {
        output.push(styles[el](this.state.isOpen, this.props.width, this.props.right, index + 1));
      }

      // Add custom styles.
      if (this.props.styles[propName]) {
        output.push(this.props.styles[propName]);
      }

      return output;
    },

    listenForClose(e) {
      e = e || window.event;

      if (this.state.isOpen && (e.key === 'Escape' || e.keyCode === 27)) {
        this.toggleMenu();
      }
    },

    getDefaultProps() {
      return {
        id: '',
        noOverlay: false,
        onStateChange: () => {},
        outerContainerId: '',
        pageWrapId: '',
        styles: {},
        width: 300
      };
    },

    getInitialState() {
      return { isOpen: false };
    },

    componentWillMount() {
      if (!styles) {
        throw new Error('No styles supplied');
      }

      // Allow initial open state to be set by props.
      if (this.props.isOpen) {
        this.toggleMenu();
      }
    },

    componentDidMount() {
      window.onkeydown = this.listenForClose;
    },

    componentWillUnmount() {
      window.onkeydown = null;

      this.clearWrapperStyles();
    },

    componentDidUpdate() {
      if (styles.svg && this.isMounted()) {
        const morphShape = ReactDOM.findDOMNode(this, 'bm-morph-shape');
        let Snap, s, path;

        try {
          // This will throw with Webpack.
          Snap = require('snapsvg');
          s = Snap(morphShape);
          path = s.select('path');
        } catch (e) {
          console.warn('It looks like you might be using Webpack. Unfortunately, Elastic and Bubble are not currently supported with Webpack builds due to their Snap.svg dependency. See https://github.com/adobe-webplatform/Snap.svg/issues/341 for more info.');
          return;
        }

        if (this.state.isOpen) {
          // Animate SVG path.
          styles.svg.animate(path);
        } else {
          // Reset path (timeout ensures animation happens off screen).
          setTimeout(() => {
            path.attr('d', styles.svg.pathInitial);
          }, 300);
        }
      }
    },

    componentWillReceiveProps(nextProps) {
      if (typeof nextProps.isOpen !== 'undefined' && nextProps.isOpen !== this.state.isOpen) {
        this.toggleMenu();
      }
    },

    render() {
      return (

          {!this.props.noOverlay ?

 : null}

            {styles.svg ? (

                <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 800" preserveAspectRatio="none">
                  <path d={styles.svg.pathInitial}/>
                </svg>

            ) : null}

                {React.Children.map(this.props.children, (item, index) => {
                  const extraProps = {
                    key: index,
                    style: this.getStyles('item', index)
                  };
                  return React.cloneElement(item, extraProps);
                })}

              <CrossIcon onClick={this.toggleMenu} styles={this.props.styles} customIcon={this.props.customCrossIcon ? this.props.customCrossIcon : null} />

          <BurgerIcon onClick={this.toggleMenu} styles={this.props.styles} customIcon={this.props.customBurgerIcon ? this.props.customBurgerIcon : null} />

      );
    }
  }));
};
<commit_msg>Move React.PropTypes.oneOfType checks onto single line<commit_after>'use strict';

import React from 'react';
import ReactDOM from 'react-dom';
import ConfiguredRadium from './ConfiguredRadium';
import baseStyles from './baseStyles';
import BurgerIcon from './BurgerIcon';
import CrossIcon from './CrossIcon';

export default (styles) => {

  return ConfiguredRadium(React.createClass({

    propTypes: {
      customBurgerIcon: React.PropTypes.oneOfType([React.PropTypes.element, React.PropTypes.oneOf([false])]),
      customCrossIcon: React.PropTypes.oneOfType([React.PropTypes.element, React.PropTypes.oneOf([false])]),
      id: React.PropTypes.string,
      isOpen: React.PropTypes.bool,
      noOverlay: React.PropTypes.bool,
      onStateChange: React.PropTypes.func,
      outerContainerId: styles && styles.outerContainer ? React.PropTypes.string.isRequired : React.PropTypes.string,
      pageWrapId: styles && styles.pageWrap ? React.PropTypes.string.isRequired : React.PropTypes.string,
      right: React.PropTypes.bool,
      styles: React.PropTypes.object,
      width: React.PropTypes.number
    },

    toggleMenu() {
      // Order important: handle wrappers before setting sidebar state.
      this.applyWrapperStyles();

      const newState = { isOpen: !this.state.isOpen };
      this.setState(newState, this.props.onStateChange.bind(null, newState));
    },

    // Applies component-specific styles to external wrapper elements.
    applyWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, true);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, true);
      }
    },

    // Removes component-specific styles applied to external wrapper elements.
    clearWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, false);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, false);
      }
    },

    // Sets or unsets styles on DOM elements outside the menu component.
    // This is necessary for correct page interaction with some of the menus.
    // Throws and returns if the required external elements don't exist,
    // which means any external page animations won't be applied.
    handleExternalWrapper(id, wrapperStyles, set) {
      const html = document.querySelector('html');
      const body = document.querySelector('body');
      const wrapper = document.getElementById(id);

      if (!wrapper) {
        console.error("Element with ID '" + id + "' not found");
        return;
      }

      const builtStyles = wrapperStyles(this.state.isOpen, this.props.width, this.props.right);

      for (const prop in builtStyles) {
        if (builtStyles.hasOwnProperty(prop)) {
          wrapper.style[prop] = set ? builtStyles[prop] : '';
        }
      }

      // Prevent any horizontal scroll.
      [html, body].forEach((element) => {
        element.style['overflow-x'] = set ? 'hidden' : '';
      });
    },

    // Builds styles incrementally for a given element.
    getStyles(el, index) {
      const propName = 'bm' + el.replace(el.charAt(0), el.charAt(0).toUpperCase());

      // Set base styles.
      let output = baseStyles[el] ? [baseStyles[el](this.state.isOpen, this.props.width, this.props.right)] : [];

      // Add animation-specific styles.
      if (styles[el]) {
        output.push(styles[el](this.state.isOpen, this.props.width, this.props.right, index + 1));
      }

      // Add custom styles.
      if (this.props.styles[propName]) {
        output.push(this.props.styles[propName]);
      }

      return output;
    },

    listenForClose(e) {
      e = e || window.event;

      if (this.state.isOpen && (e.key === 'Escape' || e.keyCode === 27)) {
        this.toggleMenu();
      }
    },

    getDefaultProps() {
      return {
        id: '',
        noOverlay: false,
        onStateChange: () => {},
        outerContainerId: '',
        pageWrapId: '',
        styles: {},
        width: 300
      };
    },

    getInitialState() {
      return { isOpen: false };
    },

    componentWillMount() {
      if (!styles) {
        throw new Error('No styles supplied');
      }

      // Allow initial open state to be set by props.
      if (this.props.isOpen) {
        this.toggleMenu();
      }
    },

    componentDidMount() {
      window.onkeydown = this.listenForClose;
    },

    componentWillUnmount() {
      window.onkeydown = null;

      this.clearWrapperStyles();
    },

    componentDidUpdate() {
      if (styles.svg && this.isMounted()) {
        const morphShape = ReactDOM.findDOMNode(this, 'bm-morph-shape');
        let Snap, s, path;

        try {
          // This will throw with Webpack.
          Snap = require('snapsvg');
          s = Snap(morphShape);
          path = s.select('path');
        } catch (e) {
          console.warn('It looks like you might be using Webpack. Unfortunately, Elastic and Bubble are not currently supported with Webpack builds due to their Snap.svg dependency. See https://github.com/adobe-webplatform/Snap.svg/issues/341 for more info.');
          return;
        }

        if (this.state.isOpen) {
          // Animate SVG path.
          styles.svg.animate(path);
        } else {
          // Reset path (timeout ensures animation happens off screen).
          setTimeout(() => {
            path.attr('d', styles.svg.pathInitial);
          }, 300);
        }
      }
    },

    componentWillReceiveProps(nextProps) {
      if (typeof nextProps.isOpen !== 'undefined' && nextProps.isOpen !== this.state.isOpen) {
        this.toggleMenu();
      }
    },

    render() {
      return (

          {!this.props.noOverlay ?

 : null}

            {styles.svg ? (

                <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 800" preserveAspectRatio="none">
                  <path d={styles.svg.pathInitial}/>
                </svg>

            ) : null}

                {React.Children.map(this.props.children, (item, index) => {
                  const extraProps = {
                    key: index,
                    style: this.getStyles('item', index)
                  };
                  return React.cloneElement(item, extraProps);
                })}

              <CrossIcon onClick={this.toggleMenu} styles={this.props.styles} customIcon={this.props.customCrossIcon ? this.props.customCrossIcon : null} />

          <BurgerIcon onClick={this.toggleMenu} styles={this.props.styles} customIcon={this.props.customBurgerIcon ? this.props.customBurgerIcon : null} />

      );
    }
  }));
};
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * 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.
 */

/**
 * JSONUtil -- Provides JSON++ marshalling support.
 *
 * Like regular JSON, with the following differences:
 *  1. Marshalls to/from FOAM Objects, rather than maps.
 *  2. Object Model information is encoded as 'model: "ModelName"'
 *  3. Default Values are not marshalled, saving disk space and network bandwidth.
 *  4. Support for marshalling functions.
 *  5. Support for property filtering, ie. only output non-transient properties.
 *  6. Support for 'pretty' and 'compact' modes.
 *
 *  TODO:
 *    Replace with JSONParser.js, when finished.
 *    Maybe rename to FON (FOAM Object Notation, pronounced 'phone') to avoid
 *    confusion with regular JSON syntax.
 **/

var AbstractFormatter = {
  keyify: function(str) { return '"' + str + '"'; },

  stringify: function(obj) {
    var buf = '';

    this.output(function() {
      for (var i = 0; i < arguments.length; i++)
        buf += arguments[i];
    }, obj);

    return buf;
  },

  stringifyObject: function(obj, opt_defaultModel) {
    var buf = '';

    this.outputObject_(function() {
      for (var i = 0; i < arguments.length; i++)
        buf += arguments[i];
    }, obj, opt_defaultModel);

    return buf;
  },

  /** @param p a predicate function or an mLang **/
  where: function(p) {
    return {
      __proto__: this,
      p: ( p.f && p.f.bind(p) ) || p
    };
  },

  p: function() { return true; }
};

var JSONUtil = {

  escape: function(str) {
    return str
      .replace(/\\/g, '\\\\')
      .replace(/"/g, '\\"')
      .replace(/[\x00-\x1f]/g, function(c) {
        return "\\u00" + ((c.charCodeAt(0) < 0x10) ?
                          '0' + c.charCodeAt(0).toString(16) :
                          c.charCodeAt(0).toString(16));
      });
  },

  parseToMap: function(str) {
    return eval('(' + str + ')');
  },

  parse: function(X, str, seq) {
    return this.mapToObj(X, this.parseToMap(str), undefined, seq);
  },

  arrayToObjArray: function(X, a, opt_defaultModel, seq) {
    for ( var i = 0 ; i < a.length ; i++ ) {
      if ( ( ! DEBUG ) && a[i].debug ) {
        a.splice(i,1);
        i--;
      } else {
        a[i] = this.mapToObj(X, a[i], opt_defaultModel, seq);
      }
    }
    return a;
  },

  /**
   * Convert JS-Maps which contain the 'model_' property, into
   * instances of that model.
   **/
  mapToObj: function(X, obj, opt_defaultModel, seq) {
    if ( ! obj || typeof obj.model_ === 'object' ) return obj;

    if ( Array.isArray(obj) ) return this.arrayToObjArray(X, obj, undefined, seq);

    if ( obj instanceof Function ) return obj;

    if ( obj instanceof Date ) return obj;

    if ( obj instanceof Object ) {
      var j = 0;
      for ( var key in obj ) {
        if ( key != 'model_' && key != 'prototype_' ) obj[key] = this.mapToObj(X, obj[key], null, seq);
        j++;
      }

      if ( opt_defaultModel && ! obj.model_ ) return opt_defaultModel.create(obj);

      if ( obj.model_ ) {
        var newObj = X.lookup(obj.model_);
        if ( ( ! newObj || ! newObj.finished__ ) ) {
          var future = afuture();
          seq && seq.push(future.get);

          arequire(obj.model_, X)(function(model) {
            if ( ! model ) {
               if ( DEBUG && obj.model_ !== 'Template' && obj.model_ !== 'ArrayProperty' && obj.model_ !== 'ViewFactoryProperty' && obj.model_ !== 'Documentation' && obj.model_ !== 'DocumentationProperty' && obj.model_ !== 'CSSProperty' && obj.model_ !== 'FunctionProperty' )
                 console.warn('Failed to dynamically load: ', obj.model_);
              future.set(obj);
              return;
            }
            var tmp = model.create(obj);
            obj.become(tmp);
            future.set(obj);
          });

          return obj;
        }
        return newObj ? newObj.create(obj, X) : obj;
      }
      return obj
    }

    return obj;
  },

  compact: {
    __proto__: AbstractFormatter,

    output: function(out, obj, opt_defaultModel) {
      if ( Array.isArray(obj) ) {
        this.outputArray_(out, obj);
      }
      else if ( typeof obj === 'string' ) {
        out('"');
        out(JSONUtil.escape(obj));
        out('"');
      }
      else if ( obj instanceof Function ) {
        this.outputFunction_(out, obj);
      }
      else if ( obj instanceof Date ) {
        out(obj.getTime());
      }
      else if ( obj instanceof Object ) {
        if ( obj.model_ )
          this.outputObject_(out, obj);
        else
          this.outputMap_(out, obj);
      }
      else if ( typeof obj === 'number' ) {
        if ( ! isFinite(obj) ) obj = null;
        out(obj);
      }
      else {
        out(obj === undefined ? null : obj);
      }
    },

    outputObject_: function(out, obj, opt_defaultModel) {
      var str   = '';
      var first = true;

      out('{');
      if ( obj.model_.id !== opt_defaultModel ) {
        this.outputModel_(out, obj);
        first = false;
     }

      var properties = obj.model_.getRuntimeProperties();
      for ( var key in properties ) {
        var prop = properties[key];

        if ( ! this.p(prop) ) continue;

        if ( prop.name in obj.instance_ ) {
          var val = obj[prop.name];
          if ( Array.isArray(val) && ! val.length ) continue;
          if ( ! first ) out(',');
          out(this.keyify(prop.name), ': ');
          if ( Array.isArray(val) && prop.subType ) {
            this.outputArray_(out, val, prop.subType);
          } else {
            this.output(out, val);
          }
          first = false;
        }
      }

      out('}');
    },

    outputModel_: function(out, obj) {
      out('model_:"')
      if ( obj.model_.package ) out(obj.model_.package, '.')
      out(obj.model_.name, '"');
    },

    outputMap_: function(out, obj) {
      var str   = '';
      var first = true;

      out('{');

      for ( var key in obj ) {
        var val = obj[key];

        if ( ! first ) out(',');
        out(this.keyify(key), ': ');
        this.output(out, val);

        first = false;
      }

      out('}');
    },

    outputArray_: function(out, a, opt_defaultModel) {
      if ( a.length == 0 ) { out('[]'); return out; }

      var str   = '';
      var first = true;

      out('[');

      for ( var i = 0 ; i < a.length ; i++, first = false ) {
        var obj = a[i];

        if ( ! first ) out(',');

        this.output(out, obj, opt_defaultModel);
      }

      out(']');
    },

    outputFunction_: function(out, obj) { out(obj); }
  },

  pretty: {
    __proto__: AbstractFormatter,

    output: function(out, obj, opt_defaultModel, opt_indent) {
      var indent = opt_indent || '';

      if ( Array.isArray(obj) ) {
        this.outputArray_(out, obj, null, indent);
      }
      else if ( typeof obj == 'string' ) {
        out('"');
        out(JSONUtil.escape(obj));
        out('"');
      }
      else if ( obj instanceof Function ) {
        this.outputFunction_(out, obj, indent);
      }
      else if ( obj instanceof Date ) {
        out("new Date('", obj, "')");
      }
      else if ( obj instanceof Object ) {
        if ( obj.model_ )
          this.outputObject_(out, obj, null, indent);
        else
          this.outputMap_(out, obj, indent);
      } else if ( typeof obj === 'number' ) {
        if ( ! isFinite(obj) ) obj = null;
        out(obj);
      } else {
        if ( obj === undefined ) obj = null;
        out(obj);
      }
    },

    outputObject_: function(out, obj, opt_defaultModel, opt_indent) {
      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out(/*"\n", */indent, '{\n');
      if ( obj.model_.id && obj.model_.id !== opt_defaultModel ) {
        this.outputModel_(out, obj, nestedIndent);
        first = false;
      }

      var properties = obj.model_.getRuntimeProperties();
      for ( var key in properties ) {
        var prop = properties[key];

        if ( ! this.p(prop) ) continue;

        if ( prop.name === 'parent' ) continue;
        if ( prop.name in obj.instance_ ) {
          var val = obj[prop.name];
          if ( Array.isArray(val) && ! val.length ) continue;
          if ( ! first ) out(',\n');
          out(nestedIndent, this.keyify(prop.name), ': ');
          if ( Array.isArray(val) && prop.subType ) {
            this.outputArray_(out, val, prop.subType, nestedIndent);
          } else {
            this.output(out, val, null, nestedIndent);
          }
          first = false;
        }
      }

      out('\n', indent, '}');
    },

    outputModel_: function(out, obj, indent) {
      out(indent, '"model_": "', obj.model_.id, '"');
    },

    outputMap_: function(out, obj, opt_indent) {
      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out(/*"\n",*/ indent, '{\n', nestedIndent);

      for ( var key in obj ) {
        var val = obj[key];

        if ( ! first ) out(',\n');
        out(nestedIndent, this.keyify(key), ': ');
        this.output(out, val, null, nestedIndent);

        first = false;
      }

      out('\n', indent, '}');
    },

    outputArray_: function(out, a, opt_defaultModel, opt_indent) {
      if ( a.length == 0 ) { out('[]'); return out; }

      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out('[\n');

      for ( var i = 0 ; i < a.length ; i++, first = false ) {
        var obj = a[i];

        if ( ! first ) out(',\n');

        this.output(out, obj, opt_defaultModel, nestedIndent);
      }

      out('\n', indent, ']');
    },

    outputFunction_: function(out, obj, indent) {
      var str = obj.toString();
      var lines = str.split('\n');

      if ( lines.length == 1 ) { out(str); return; }

      var minIndent = 10000;
      for ( var i = 0 ; i < lines.length ; i++ ) {
        var j = 0;
        for ( ; j < lines[i].length && lines[i].charAt(j) === ' ' && j < minIndent ; j++ );
        if ( j > 0 && j < minIndent ) minIndent = j;
      }

      if ( minIndent === 10000 ) { out(str); return; }

      for ( var i = 0 ; i < lines.length ; i++ ) {
        if ( lines[i].length && lines[i].charAt(0) === ' ' ) {
          lines[i] = indent + lines[i].substring(minIndent);
        }
        out(lines[i]);
        if ( i < lines.length-1 ) out('\n');
      }
    }
  },

  moreCompact: {
    __proto__: AbstractFormatter,
    // TODO: use short-names
  },

  compressed: {
    __proto__: AbstractFormatter,

    stringify: function(obj) {
      return Iuppiter.Base64.encode(Iuppiter.compress(JSONUtil.compact.stringify(obj),true));
    }
  }

};

JSONUtil.prettyModel = {
  __proto__: JSONUtil.pretty,

  outputModel_: function(out, obj, indent) {
    out(indent, 'model_: "', obj.model_.id, '"');
  },

  keys_: {},

  keyify: function(str) {
    if ( ! this.keys_.hasOwnProperty(str) ) {
      this.keys_[str] =
        /^[a-zA-Z\$_][0-9a-zA-Z$_]*$/.test(str) ?
        str :
        '"' + str + '"';
    }

    return this.keys_[str];
  }
};

JSONUtil.stringify       = JSONUtil.pretty.stringify.bind(JSONUtil.pretty);
JSONUtil.stringifyObject = JSONUtil.pretty.stringifyObject.bind(JSONUtil.pretty);
JSONUtil.output          = JSONUtil.pretty.output.bind(JSONUtil.pretty);
JSONUtil.where           = JSONUtil.pretty.where.bind(JSONUtil.pretty);

var NOT_TRANSIENT = function(prop) { return ! prop.transient; };
<commit_msg>Fix for last fix.<commit_after>/**
 * @license
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * 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.
 */

/**
 * JSONUtil -- Provides JSON++ marshalling support.
 *
 * Like regular JSON, with the following differences:
 *  1. Marshalls to/from FOAM Objects, rather than maps.
 *  2. Object Model information is encoded as 'model: "ModelName"'
 *  3. Default Values are not marshalled, saving disk space and network bandwidth.
 *  4. Support for marshalling functions.
 *  5. Support for property filtering, ie. only output non-transient properties.
 *  6. Support for 'pretty' and 'compact' modes.
 *
 *  TODO:
 *    Replace with JSONParser.js, when finished.
 *    Maybe rename to FON (FOAM Object Notation, pronounced 'phone') to avoid
 *    confusion with regular JSON syntax.
 **/

var AbstractFormatter = {
  keyify: function(str) { return '"' + str + '"'; },

  stringify: function(obj) {
    var buf = '';

    this.output(function() {
      for (var i = 0; i < arguments.length; i++)
        buf += arguments[i];
    }, obj);

    return buf;
  },

  stringifyObject: function(obj, opt_defaultModel) {
    var buf = '';

    this.outputObject_(function() {
      for (var i = 0; i < arguments.length; i++)
        buf += arguments[i];
    }, obj, opt_defaultModel);

    return buf;
  },

  /** @param p a predicate function or an mLang **/
  where: function(p) {
    return {
      __proto__: this,
      p: ( p.f && p.f.bind(p) ) || p
    };
  },

  p: function() { return true; }
};

var JSONUtil = {

  escape: function(str) {
    return str
      .replace(/\\/g, '\\\\')
      .replace(/"/g, '\\"')
      .replace(/[\x00-\x1f]/g, function(c) {
        return "\\u00" + ((c.charCodeAt(0) < 0x10) ?
                          '0' + c.charCodeAt(0).toString(16) :
                          c.charCodeAt(0).toString(16));
      });
  },

  parseToMap: function(str) {
    return eval('(' + str + ')');
  },

  parse: function(X, str, seq) {
    return this.mapToObj(X, this.parseToMap(str), undefined, seq);
  },

  arrayToObjArray: function(X, a, opt_defaultModel, seq) {
    for ( var i = 0 ; i < a.length ; i++ ) {
      if ( ( ! DEBUG ) && a[i].debug ) {
        a.splice(i,1);
        i--;
      } else {
        a[i] = this.mapToObj(X, a[i], opt_defaultModel, seq);
      }
    }
    return a;
  },

  /**
   * Convert JS-Maps which contain the 'model_' property, into
   * instances of that model.
   **/
  mapToObj: function(X, obj, opt_defaultModel, seq) {
    if ( ! obj || typeof obj.model_ === 'object' ) return obj;

    if ( Array.isArray(obj) ) return this.arrayToObjArray(X, obj, undefined, seq);

    if ( obj instanceof Function ) return obj;

    if ( obj instanceof Date ) return obj;

    if ( obj instanceof Object ) {
      var j = 0;
      for ( var key in obj ) {
        if ( key != 'model_' && key != 'prototype_' ) obj[key] = this.mapToObj(X, obj[key], null, seq);
        j++;
      }

      if ( opt_defaultModel && ! obj.model_ ) return opt_defaultModel.create(obj);

      if ( obj.model_ ) {
        var newObj = X.lookup(obj.model_);
        if ( ( ! newObj || ! newObj.finished__ ) ) {
          var future = afuture();
          seq && seq.push(future.get);

          arequire(obj.model_, X)(function(model) {
            if ( ! model ) {
               if ( DEBUG && obj.model_ !== 'Template' && obj.model_ !== 'ArrayProperty' && obj.model_ !== 'ViewFactoryProperty' && obj.model_ !== 'Documentation' && obj.model_ !== 'DocumentationProperty' && obj.model_ !== 'CSSProperty' && obj.model_ !== 'FunctionProperty' )
                 console.warn('Failed to dynamically load: ', obj.model_);
              future.set(obj);
              return;
            }
            var tmp = model.create(obj);
            obj.become(tmp);
            future.set(obj);
          });

          return obj;
        }
        return newObj ? newObj.create(obj, X) : obj;
      }
      return obj
    }

    return obj;
  },

  compact: {
    __proto__: AbstractFormatter,

    output: function(out, obj, opt_defaultModel) {
      if ( Array.isArray(obj) ) {
        this.outputArray_(out, obj);
      }
      else if ( typeof obj === 'string' ) {
        out('"');
        out(JSONUtil.escape(obj));
        out('"');
      }
      else if ( obj instanceof Function ) {
        this.outputFunction_(out, obj);
      }
      else if ( obj instanceof Date ) {
        out(obj.getTime());
      }
      else if ( obj instanceof Object ) {
        if ( obj.model_ )
          this.outputObject_(out, obj);
        else
          this.outputMap_(out, obj);
      }
      else if ( typeof obj === 'number' ) {
        if ( ! isFinite(obj) ) obj = null;
        out(obj);
      }
      else {
        out(obj === undefined ? null : obj);
      }
    },

    outputObject_: function(out, obj, opt_defaultModel) {
      var str   = '';
      var first = true;

      out('{');
      if ( obj.model_.id !== opt_defaultModel ) {
        this.outputModel_(out, obj);
        first = false;
     }

      var properties = obj.model_.getRuntimeProperties();
      for ( var key in properties ) {
        var prop = properties[key];

        if ( ! this.p(prop) ) continue;

        if ( prop.name in obj.instance_ ) {
          var val = obj[prop.name];
          if ( Array.isArray(val) && ! val.length ) continue;
          if ( ! first ) out(',');
          out(this.keyify(prop.name), ': ');
          if ( Array.isArray(val) && prop.subType ) {
            this.outputArray_(out, val, prop.subType);
          } else {
            this.output(out, val);
          }
          first = false;
        }
      }

      out('}');
    },

    outputModel_: function(out, obj) {
      out('model_:"')
      if ( obj.model_.package ) out(obj.model_.package, '.')
      out(obj.model_.name, '"');
    },

    outputMap_: function(out, obj) {
      var str   = '';
      var first = true;

      out('{');

      for ( var key in obj ) {
        var val = obj[key];

        if ( ! first ) out(',');
        out(this.keyify(key), ': ');
        this.output(out, val);

        first = false;
      }

      out('}');
    },

    outputArray_: function(out, a, opt_defaultModel) {
      if ( a.length == 0 ) { out('[]'); return out; }

      var str   = '';
      var first = true;

      out('[');

      for ( var i = 0 ; i < a.length ; i++, first = false ) {
        var obj = a[i];

        if ( ! first ) out(',');

        this.output(out, obj, opt_defaultModel);
      }

      out(']');
    },

    outputFunction_: function(out, obj) { out(obj); }
  },

  pretty: {
    __proto__: AbstractFormatter,

    output: function(out, obj, opt_defaultModel, opt_indent) {
      var indent = opt_indent || '';

      if ( Array.isArray(obj) ) {
        this.outputArray_(out, obj, null, indent);
      }
      else if ( typeof obj == 'string' ) {
        out('"');
        out(JSONUtil.escape(obj));
        out('"');
      }
      else if ( obj instanceof Function ) {
        this.outputFunction_(out, obj, indent);
      }
      else if ( obj instanceof Date ) {
        out("new Date('", obj, "')");
      }
      else if ( obj instanceof Object ) {
        if ( obj.model_ )
          this.outputObject_(out, obj, opt_defaultModel, indent);
        else
          this.outputMap_(out, obj, indent);
      } else if ( typeof obj === 'number' ) {
        if ( ! isFinite(obj) ) obj = null;
        out(obj);
      } else {
        if ( obj === undefined ) obj = null;
        out(obj);
      }
    },

    outputObject_: function(out, obj, opt_defaultModel, opt_indent) {
      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out(/*"\n", */indent, '{\n');
      if ( obj.model_.id && obj.model_.id !== opt_defaultModel ) {
        this.outputModel_(out, obj, nestedIndent);
        first = false;
      }

      var properties = obj.model_.getRuntimeProperties();
      for ( var key in properties ) {
        var prop = properties[key];

        if ( ! this.p(prop) ) continue;

        if ( prop.name === 'parent' ) continue;
        if ( prop.name in obj.instance_ ) {
          var val = obj[prop.name];
          if ( Array.isArray(val) && ! val.length ) continue;
          if ( ! first ) out(',\n');
          out(nestedIndent, this.keyify(prop.name), ': ');
          if ( Array.isArray(val) && prop.subType ) {
            this.outputArray_(out, val, prop.subType, nestedIndent);
          } else {
            this.output(out, val, null, nestedIndent);
          }
          first = false;
        }
      }

      out('\n', indent, '}');
    },

    outputModel_: function(out, obj, indent) {
      out(indent, '"model_": "', obj.model_.id, '"');
    },

    outputMap_: function(out, obj, opt_indent) {
      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out(/*"\n",*/ indent, '{\n', nestedIndent);

      for ( var key in obj ) {
        var val = obj[key];

        if ( ! first ) out(',\n');
        out(nestedIndent, this.keyify(key), ': ');
        this.output(out, val, null, nestedIndent);

        first = false;
      }

      out('\n', indent, '}');
    },

    outputArray_: function(out, a, opt_defaultModel, opt_indent) {
      if ( a.length == 0 ) { out('[]'); return out; }

      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out('[\n');

      for ( var i = 0 ; i < a.length ; i++, first = false ) {
        var obj = a[i];

        if ( ! first ) out(',\n');

        this.output(out, obj, opt_defaultModel, nestedIndent);
      }

      out('\n', indent, ']');
    },

    outputFunction_: function(out, obj, indent) {
      var str = obj.toString();
      var lines = str.split('\n');

      if ( lines.length == 1 ) { out(str); return; }

      var minIndent = 10000;
      for ( var i = 0 ; i < lines.length ; i++ ) {
        var j = 0;
        for ( ; j < lines[i].length && lines[i].charAt(j) === ' ' && j < minIndent ; j++ );
        if ( j > 0 && j < minIndent ) minIndent = j;
      }

      if ( minIndent === 10000 ) { out(str); return; }

      for ( var i = 0 ; i < lines.length ; i++ ) {
        if ( lines[i].length && lines[i].charAt(0) === ' ' ) {
          lines[i] = indent + lines[i].substring(minIndent);
        }
        out(lines[i]);
        if ( i < lines.length-1 ) out('\n');
      }
    }
  },

  moreCompact: {
    __proto__: AbstractFormatter,
    // TODO: use short-names
  },

  compressed: {
    __proto__: AbstractFormatter,

    stringify: function(obj) {
      return Iuppiter.Base64.encode(Iuppiter.compress(JSONUtil.compact.stringify(obj),true));
    }
  }

};

JSONUtil.prettyModel = {
  __proto__: JSONUtil.pretty,

  outputModel_: function(out, obj, indent) {
    out(indent, 'model_: "', obj.model_.id, '"');
  },

  keys_: {},

  keyify: function(str) {
    if ( ! this.keys_.hasOwnProperty(str) ) {
      this.keys_[str] =
        /^[a-zA-Z\$_][0-9a-zA-Z$_]*$/.test(str) ?
        str :
        '"' + str + '"';
    }

    return this.keys_[str];
  }
};

JSONUtil.stringify       = JSONUtil.pretty.stringify.bind(JSONUtil.pretty);
JSONUtil.stringifyObject = JSONUtil.pretty.stringifyObject.bind(JSONUtil.pretty);
JSONUtil.output          = JSONUtil.pretty.output.bind(JSONUtil.pretty);
JSONUtil.where           = JSONUtil.pretty.where.bind(JSONUtil.pretty);

var NOT_TRANSIENT = function(prop) { return ! prop.transient; };
<|endoftext|>


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

class Input extends React.PureComponent {

  static ROOT = 'mdc-textfield__input';

  static propTypes = {
    disabled: PropTypes.bool,
    onBlur: PropTypes.func,
    onFocus: PropTypes.func,
  }

  constructor(props) {
    super(props);
    this.registerListeners = this.registerListeners.bind(this);
  }

  registerListeners(nativeInput) {
    const { onFocus, onBlur } = this.props;
    nativeInput.addEventListener('focus', onFocus);
    nativeInput.addEventListener('blur', onBlur);
  }

  render() {
    const { disabled, ...otherProps } = this.props;
    return (
      <input
        className={classnames(Input.ROOT)}
        disabled={disabled}
        type="text"
        ref={this.registerListeners}
        {...otherProps}
      />
    );
  }
}
export default Input;
<commit_msg>refactor(Textfield): remove unused event listeners<commit_after>import React, { PropTypes } from 'react';
import classnames from 'classnames';

const ROOT = 'mdc-textfield__input';
const propTypes = {
  disabled: PropTypes.bool,
};

const Input = ({ disabled, ...otherProps }) => (
  <input
    className={classnames(ROOT)}
    disabled={disabled}
    type="text"
    {...otherProps}
  />
);
Input.propTypes = propTypes;
export default Input;
<|endoftext|>