<commit_before>'use strict';
angular.module('com.module.protocols')
  .controller('ProtocolsCtrl', function($scope, $state, $stateParams, CoreService,
    FormHelper, gettextCatalog, Protocol, ProtocolsService,Meta, $rootScope,Bioportal,ProtocolUsage,LoopBackAuth) {

$scope.user=LoopBackAuth.currentUserData;
$scope.isadmin=$rootScope.isadmin;
$scope.autocompleteResults=[];
$scope.protocolUsage={};
$scope.modelLoaded=false;

var BioportalSplitter=".";
var CategorySplitter="_";
var SpaceSplitter="0";
$scope.uiselectArray=["resources_pharmaceutical","goal_disease","resources_infastructure","resources_human","cohort_exposure","cohort_comorbidities","cohort_riskfactors","cohort_contraindications","cohort_medicalhistory","cohort_symptoms"];

//retrieve protocol model
  $scope.requiredProps=[];
  $scope.schemaProps={};
  $scope.formProps=[];

  var protocolId=$stateParams.id||$stateParams.parentId||'';
  if ( protocolId.length===24 ) {

    // console.log("there is a protocol id");
    Protocol.findById({
      id: protocolId
    }, function(protocol) {
      // console.log(protocol);
      $scope.protocol = protocol;
      $scope.fetchUsage();
      $scope.fetchHealthcenters();

    }, function(err) {
      $state.go('app.protocols.list');
      console.log(err);
    });

  } else {

    $scope.protocol = {};
  }

//autocomplete fetch from bioportal
$scope.bioportalAutocomplete = function(schema, options, search) {
  Bioportal.autocomplete(schema, options, search)
  .then(function(res){
    $scope.autocompleteResults=res.data.collection.map(function(obj){
      if(obj){
        var id=!!obj['cui']?obj['cui'][0]:(obj['id']||obj['@id']);
        return { "label": obj.prefLabel, "value": id+BioportalSplitter+obj.prefLabel  };
      }
    });
  },function(err){console.log(err);});
  return $scope.autocompleteResults;
};

  function capFirst(str) { return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}); }
  var propname=function(str){
    return capFirst(str.split(CategorySplitter)[1]||" ");
  };
  var catname=function(str){
    return capFirst(str.split(CategorySplitter)[0]||" ");
  };
  $scope.cName=catname;
  $scope.pName=propname;

  function buildModel() {

    Meta.getModelProperties(function(obj) {

    var curModel=obj.Protocol;
    var propCategories=[];

        for(var key in curModel){

          if( key.indexOf(CategorySplitter)>0 ){ //&& key.indexOf("Id")===-1 && key!=='id' && curModel.hasOwnProperty(key)){

            //schema builder
            var keyObj={};
            angular.copy(curModel[key],keyObj);
            // if(keyObj.enum) {
            //   keyObj.enum=keyObj.enum.map(function(item){
            //   return item.toString();
            //   });
            // }
            keyObj.title=gettextCatalog.getString(propname(key));
            if(keyObj.required){$scope.requiredProps.push(key);}
            keyObj.type=(curModel[key].stringType==="objectid")?"string":curModel[key].stringType;

          if($scope.uiselectArray.indexOf(key)>=0){
              keyObj.format="uiselect";
              keyObj.items=[];
                if(typeof $scope.protocol[key]==="string"){
                  keyObj.items=[{
                      "label":$scope.protocol[key].split(BioportalSplitter)[1],
                      "value":$scope.protocol[key]
                    }];
                } else if($scope.protocol[key] instanceof Array){
                  //map the string into object for the autocomplete
                  keyObj.items=$scope.protocol[key].map(function(str){
                    return {
                      "label":str.split(BioportalSplitter)[1],
                      "value":str
                    };
                  });
                }

            } else if (keyObj.type==="array"){
              keyObj.items={
                  "title":keyObj.title,
                  "type":"string"
              };
            } else {
              // console.log('Other types: '+key);
              // console.log(keyObj);
            }

            delete keyObj['required'];
            delete keyObj['stringType'];

            //form builder
            var category=catname(key);
            var item={};
            propCategories[category]=propCategories[category] || {
              "title":category,
              "items":[]
            }

            if(keyObj.format) {
              item={
                "key":key,
                "feedback":false,
                "placeholder":"Add "+propname(key),
                "options": {
                  "refreshDelay": 50,
                  "callback": $scope.bioportalAutocomplete
                }
              };
            } else if(keyObj.enum) {
              //console.log(JSON.stringify(keyObj));
              item=key;
            }
            else {
              item={
                "key":key,
                "placeholder":"Add "+propname(key),
                "feedback":true,
              };
            }

            //do foreign key stuff
            // var foreignModel=key.toString().split('Id')[0];
            // console.log(foreignModel);
            // keyObj.format="uiselect";
            // keyObj.items=categories.map(function(category) {
            //   return {
            //     value: category.id,
            //     label: category.name
            //   };
            // });

            if(key==='release_deviation' && $scope.protocol.parentId ) {
              propCategories[category].items.push(item);
            } else if(key!=='release_deviation'){
              propCategories[category].items.push(item);
            }
            $scope.schemaProps[key]=keyObj;
          }
        }

        $scope.formProps.push({
          "type":"fieldset",
          "title":"Clinical Protocol",
          "items":[{
            "type": "tabs",
            "tabs": Object.keys(propCategories).map(function (key) {return propCategories[key]})
          }]
        });

        $scope.formProps.push({
          "type":"actions",
          "items":[
             {
                "type":"submit",
                "style":"btn-info",
                "title":"Submit"
             },
             {
                "type":"button",
                "style":"btn-danger",
                "title":"Cancel",
                "onClick":"sayNo()"
             }
          ]
       });

            //protocol view/edit

          //create view tabs from formProps
          // console.log($scope.schemaProps);
          // console.log($scope.formProps);
          $scope.tabs=$scope.formProps[0].items[0].tabs;

          $scope.modelLoaded=true;

      });

      }

    $scope.schema = {
      type: 'object',
      title: 'Product',
      properties: $scope.schemaProps,
      required: $scope.requiredProps
    };

    $scope.form = $scope.formProps;

    $scope.toggleProtocolUsage=function(){
      console.log($scope.protocolUsage);
      if(!$scope.protocolUsage.id){
          ProtocolUsage.create($scope.protocolUsage, function(res) {
          $scope.protocolUsage=res;
          updateDashboard();
          $scope.fetchUsage();
          CoreService.toastSuccess(gettextCatalog.getString('Protocol usage'),
              gettextCatalog.getString('You are now using this protocol.'));

          });
        } else {
          ProtocolUsage.deleteById({"id":$scope.protocolUsage.id}, function(res) {
          updateDashboard();
          $scope.fetchUsage();
          CoreService.toastWarning(gettextCatalog.getString('Protocol usage stopped'),
              gettextCatalog.getString('You have stopped using this protocol.'));
          });

        }
    }

    $scope.delete = function(id) {
      ProtocolsService.deleteProtocol(id, function() {
        updateDashboard();
        $state.go('app.protocols.list', {}, { reload: true });
      });
    };

    $scope.fetchUsage=function(){
      var query={
            filter: {
              where:  {
                "userId": $scope.user.id,
                "protocolId": $scope.protocol.id
              }
            }
          };

       ProtocolUsage.find(query,function(usages) {

        $scope.fetchUsers();
         if(usages.length>0) {
            $scope.protocolUsage=usages[0];
         } else {
           $scope.protocolUsage={
            "userId":$scope.user.id,
            "protocolId":$scope.protocol.id
          };
         }
        },function(err){
         console.log(err);
        });

    };

    $scope.fetchUsers=function(){
       Protocol.usedBy({id:$scope.protocol.id},function(users) {
           if(users.length>0) $scope.pusers=users;
           else $scope.pusers=[{
            "firstName":"Nobody"
          }];
        },function(err){
          console.log(err);
        });
    };

    $scope.fetchHealthcenters=function(){
       Protocol.healthcenters({id:$scope.protocol.id},function(centers) {
        // console.log(centers);
         if(centers.length>0) $scope.pcenters=centers;
         else  $scope.pcenters=[{
            "name":"No Health centers"
          }];

        },function(err){
          console.log(err);
        });
    };

    $scope.onSubmit = function() {
      if($stateParams.parentId){
          $scope.protocol.id=null;
          delete $scope.protocol['id'];
          $scope.protocol.parentId=$stateParams.parentId;
          Protocol.create($scope.protocol, function() {
          CoreService.toastSuccess(gettextCatalog.getString('Protocol created'),
            gettextCatalog.getString('Your protocol is safe with us!'));
            updateDashboard();

          $state.go('app.protocols.list', {}, { reload: true });
          }, function(err) {
          console.log(err);
          });

      } else {
        if($scope.protocol.id){
        Protocol.upsert($scope.protocol, function() {
          CoreService.toastSuccess(gettextCatalog.getString('Protocol saved'),
            gettextCatalog.getString('Your protocol is safe with us!'));
            updateDashboard();

          $state.go('app.protocols.list', {}, { reload: true });
        }, function(err) {
          console.log(err);
        });
        } else {
          Protocol.create($scope.protocol, function() {
          CoreService.toastSuccess(gettextCatalog.getString('Protocol created'),
            gettextCatalog.getString('Your protocol is safe with us!'));
            updateDashboard();
          $state.go('app.protocols.list', {}, { reload: true });
          }, function(err) {
          console.log(err);
          });
        }
      }

    };

    function updateDashboard(){
      Protocol.count(function(pr){
        $rootScope.dashboardBox=$rootScope.dashboardBox.map(function(obj){
            if(obj.name==='Protocols') obj.quantity=pr.count;
            return obj;
        });
      });
    };

    //init

    if(!$scope.modelLoaded) buildModel();

  });

   //SUPER SEARCH FILTERS!!!

  // $scope.availableSearchParams=[];
  // var obj={};
  // for (var key in $scope.schemaProps) {
  //   obj=$scope.schemaProps[key];
  //   if(
  //     obj.type==="string" &&
  //     key!=="release_url" &&
  //     key!=="release_version" &&
  //     key!=="release_date" &&
  //     key!=="evidence_url" &&
  //     key!=="evidence_date"
  //   ) {
  //     // console.log(key+" is inserted to filters");
  //     $scope.availableSearchParams.push({"key":key,"name":catname(key)+" "+propname(key), "placeholder": propname(key)+"..."});
  //   }
  //   }

  //   // console.log(JSON.stringify($scope.schema));
  //   // console.log(JSON.stringify($scope.form));
  //   console.log($scope.schema);
  //   console.log($scope.form);
  // });
  <commit_msg>fix deviation condition on form<commit_after>'use strict';
angular.module('com.module.protocols')
  .controller('ProtocolsCtrl', function($scope, $state, $stateParams, CoreService,
    FormHelper, gettextCatalog, Protocol, ProtocolsService,Meta, $rootScope,Bioportal,ProtocolUsage,LoopBackAuth) {

$scope.user=LoopBackAuth.currentUserData;
$scope.isadmin=$rootScope.isadmin;
$scope.autocompleteResults=[];
$scope.protocolUsage={};

var BioportalSplitter=".";
var CategorySplitter="_";
var SpaceSplitter="0";
$scope.uiselectArray=["resources_pharmaceutical","goal_disease","resources_infastructure","resources_human","cohort_exposure","cohort_comorbidities","cohort_riskfactors","cohort_contraindications","cohort_medicalhistory","cohort_symptoms"];

//retrieve protocol model
  $scope.requiredProps=[];
  $scope.schemaProps={};
  $scope.formProps=[];

  var protocolId=$stateParams.id||$stateParams.parentId||'';
  if ( protocolId.length===24 ) {

    // console.log("there is a protocol id");
    Protocol.findById({
      id: protocolId
    }, function(protocol) {
      // console.log(protocol);
      $scope.protocol = protocol;
      $scope.fetchUsage();
      $scope.fetchHealthcenters();

    }, function(err) {
      $state.go('app.protocols.list');
      console.log(err);
    });

  } else {

    $scope.protocol = {};
  }

//autocomplete fetch from bioportal
$scope.bioportalAutocomplete = function(schema, options, search) {
  Bioportal.autocomplete(schema, options, search)
  .then(function(res){
    $scope.autocompleteResults=res.data.collection.map(function(obj){
      if(obj){
        var id=!!obj['cui']?obj['cui'][0]:(obj['id']||obj['@id']);
        return { "label": obj.prefLabel, "value": id+BioportalSplitter+obj.prefLabel  };
      }
    });
  },function(err){console.log(err);});
  return $scope.autocompleteResults;
};

  function capFirst(str) { return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}); }
  var propname=function(str){
    return capFirst(str.split(CategorySplitter)[1]||" ");
  };
  var catname=function(str){
    return capFirst(str.split(CategorySplitter)[0]||" ");
  };
  $scope.cName=catname;
  $scope.pName=propname;

  function buildModel() {

    Meta.getModelProperties(function(obj) {

    var curModel=obj.Protocol;
    var propCategories=[];

        for(var key in curModel){

          if( key.indexOf(CategorySplitter)>0 ){ //&& key.indexOf("Id")===-1 && key!=='id' && curModel.hasOwnProperty(key)){

            //schema builder
            var keyObj={};
            angular.copy(curModel[key],keyObj);
            // if(keyObj.enum) {
            //   keyObj.enum=keyObj.enum.map(function(item){
            //   return item.toString();
            //   });
            // }
            keyObj.title=gettextCatalog.getString(propname(key));
            if(keyObj.required){$scope.requiredProps.push(key);}
            keyObj.type=(curModel[key].stringType==="objectid")?"string":curModel[key].stringType;

          if($scope.uiselectArray.indexOf(key)>=0){
              keyObj.format="uiselect";
              keyObj.items=[];
                if(typeof $scope.protocol[key]==="string"){
                  keyObj.items=[{
                      "label":$scope.protocol[key].split(BioportalSplitter)[1],
                      "value":$scope.protocol[key]
                    }];
                } else if($scope.protocol[key] instanceof Array){
                  //map the string into object for the autocomplete
                  keyObj.items=$scope.protocol[key].map(function(str){
                    return {
                      "label":str.split(BioportalSplitter)[1],
                      "value":str
                    };
                  });
                }

            } else if (keyObj.type==="array"){
              keyObj.items={
                  "title":keyObj.title,
                  "type":"string"
              };
            } else {
              // console.log('Other types: '+key);
              // console.log(keyObj);
            }

            delete keyObj['required'];
            delete keyObj['stringType'];

            //form builder
            var category=catname(key);
            var item={};
            propCategories[category]=propCategories[category] || {
              "title":category,
              "items":[]
            }

            if(keyObj.format) {
              item={
                "key":key,
                "feedback":false,
                "placeholder":"Add "+propname(key),
                "options": {
                  "refreshDelay": 50,
                  "callback": $scope.bioportalAutocomplete
                }
              };
            } else if(keyObj.enum) {
              //console.log(JSON.stringify(keyObj));
              item=key;
            }
            else {
              item={
                "key":key,
                "placeholder":"Add "+propname(key),
                "feedback":true,
              };
            }

            //do foreign key stuff
            // var foreignModel=key.toString().split('Id')[0];
            // console.log(foreignModel);
            // keyObj.format="uiselect";
            // keyObj.items=categories.map(function(category) {
            //   return {
            //     value: category.id,
            //     label: category.name
            //   };
            // });

            if(key==='release_deviation' && $stateParams.parentId ) {
              propCategories[category].items.push(item);
            } else if(key!=='release_deviation'){
              propCategories[category].items.push(item);
            }
            $scope.schemaProps[key]=keyObj;
          }
        }

        $scope.formProps.push({
          "type":"fieldset",
          "title":"Clinical Protocol",
          "items":[{
            "type": "tabs",
            "tabs": Object.keys(propCategories).map(function (key) {return propCategories[key]})
          }]
        });

        $scope.formProps.push({
          "type":"actions",
          "items":[
             {
                "type":"submit",
                "style":"btn-info",
                "title":"Submit"
             },
             {
                "type":"button",
                "style":"btn-danger",
                "title":"Cancel",
                "onClick":"sayNo()"
             }
          ]
       });

            //protocol view/edit

          //create view tabs from formProps
          // console.log($scope.schemaProps);
          // console.log($scope.formProps);
          $scope.tabs=$scope.formProps[0].items[0].tabs;

          $scope.modelLoaded=true;

      });

      }

    $scope.schema = {
      type: 'object',
      title: 'Product',
      properties: $scope.schemaProps,
      required: $scope.requiredProps
    };

    $scope.form = $scope.formProps;

    $scope.toggleProtocolUsage=function(){
      console.log($scope.protocolUsage);
      if(!$scope.protocolUsage.id){
          ProtocolUsage.create($scope.protocolUsage, function(res) {
          $scope.protocolUsage=res;
          updateDashboard();
          $scope.fetchUsage();
          CoreService.toastSuccess(gettextCatalog.getString('Protocol usage'),
              gettextCatalog.getString('You are now using this protocol.'));

          });
        } else {
          ProtocolUsage.deleteById({"id":$scope.protocolUsage.id}, function(res) {
          updateDashboard();
          $scope.fetchUsage();
          CoreService.toastWarning(gettextCatalog.getString('Protocol usage stopped'),
              gettextCatalog.getString('You have stopped using this protocol.'));
          });

        }
    }

    $scope.delete = function(id) {
      ProtocolsService.deleteProtocol(id, function() {
        updateDashboard();
        $state.go('app.protocols.list', {}, { reload: true });
      });
    };

    $scope.fetchUsage=function(){
      var query={
            filter: {
              where:  {
                "userId": $scope.user.id,
                "protocolId": $scope.protocol.id
              }
            }
          };

       ProtocolUsage.find(query,function(usages) {

        $scope.fetchUsers();
         if(usages.length>0) {
            $scope.protocolUsage=usages[0];
         } else {
           $scope.protocolUsage={
            "userId":$scope.user.id,
            "protocolId":$scope.protocol.id
          };
         }
        },function(err){
         console.log(err);
        });

    };

    $scope.fetchUsers=function(){
       Protocol.usedBy({id:$scope.protocol.id},function(users) {
           if(users.length>0) $scope.pusers=users;
           else $scope.pusers=[{
            "firstName":"Nobody"
          }];
        },function(err){
          console.log(err);
        });
    };

    $scope.fetchHealthcenters=function(){
       Protocol.healthcenters({id:$scope.protocol.id},function(centers) {
        // console.log(centers);
         if(centers.length>0) $scope.pcenters=centers;
         else  $scope.pcenters=[{
            "name":"No Health centers"
          }];

        },function(err){
          console.log(err);
        });
    };

    $scope.onSubmit = function() {
      if($stateParams.parentId){
          $scope.protocol.id=null;
          delete $scope.protocol['id'];
          $scope.protocol.parentId=$stateParams.parentId;
          Protocol.create($scope.protocol, function() {
          CoreService.toastSuccess(gettextCatalog.getString('Protocol created'),
            gettextCatalog.getString('Your protocol is safe with us!'));
            updateDashboard();

          $state.go('app.protocols.list', {}, { reload: true });
          }, function(err) {
          console.log(err);
          });

      } else {
        if($scope.protocol.id){
        Protocol.upsert($scope.protocol, function() {
          CoreService.toastSuccess(gettextCatalog.getString('Protocol saved'),
            gettextCatalog.getString('Your protocol is safe with us!'));
            updateDashboard();

          $state.go('app.protocols.list', {}, { reload: true });
        }, function(err) {
          console.log(err);
        });
        } else {
          Protocol.create($scope.protocol, function() {
          CoreService.toastSuccess(gettextCatalog.getString('Protocol created'),
            gettextCatalog.getString('Your protocol is safe with us!'));
            updateDashboard();
          $state.go('app.protocols.list', {}, { reload: true });
          }, function(err) {
          console.log(err);
          });
        }
      }

    };

    function updateDashboard(){
      Protocol.count(function(pr){
        $rootScope.dashboardBox=$rootScope.dashboardBox.map(function(obj){
            if(obj.name==='Protocols') obj.quantity=pr.count;
            return obj;
        });
      });
    };

    //init

    buildModel();

  });

   //SUPER SEARCH FILTERS!!!

  // $scope.availableSearchParams=[];
  // var obj={};
  // for (var key in $scope.schemaProps) {
  //   obj=$scope.schemaProps[key];
  //   if(
  //     obj.type==="string" &&
  //     key!=="release_url" &&
  //     key!=="release_version" &&
  //     key!=="release_date" &&
  //     key!=="evidence_url" &&
  //     key!=="evidence_date"
  //   ) {
  //     // console.log(key+" is inserted to filters");
  //     $scope.availableSearchParams.push({"key":key,"name":catname(key)+" "+propname(key), "placeholder": propname(key)+"..."});
  //   }
  //   }

  //   // console.log(JSON.stringify($scope.schema));
  //   // console.log(JSON.stringify($scope.form));
  //   console.log($scope.schema);
  //   console.log($scope.form);
  // });
  <|endoftext|>


<commit_before>class GeocodingService {
  constructor($http) {
    "ngInject";
    Object.assign(this, {
      $http
    });
  }

  lookupAddress(address) {
    return this.$http.get("https://nominatim.openstreetmap.org/search", {
      params: { format: "json", q: address }
    }).then((res) => {
      console.log(res)
      return res.data.map(p => {
        return {
          lat: parseFloat(p.lat),
          lng: parseFloat(p.lon),
          name: p.display_name
        }
      })
      // let hit = data.data[0];
      // return {
      //   latitude: parseFloat(hit.lat),
      //   longitude: parseFloat(hit.lon),
      //   name: hit.display_name
      // };
    });
  }
}

export default GeocodingService;
<commit_msg>geocoding: cleanup<commit_after>class GeocodingService {
  constructor($http) {
    "ngInject";
    Object.assign(this, {
      $http
    });
  }

  lookupAddress(address) {
    return this.$http.get("https://nominatim.openstreetmap.org/search", {
      params: { format: "json", q: address }
    }).then((res) => {
      console.log(res)
      return res.data.map(p => {
        return {
          lat: parseFloat(p.lat),
          lng: parseFloat(p.lon),
          name: p.display_name
        }
      })
    });
  }
}

export default GeocodingService;
<|endoftext|>


<commit_before>import React from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies
import { storiesOf, setAddon } from '@storybook/react';
import { withKnobs, select } from '@storybook/addon-knobs/react';
import JSXAddon from 'storybook-addon-jsx';
import { action } from '@storybook/addon-actions';

import { Component as Breadcrumb } from 'components/Breadcrumb/Breadcrumb';

setAddon(JSXAddon);

// Simple values to displays in the select fields.
const icons = [
  '',
  'font-icon-edit-list',
  'font-icon-calendar',
  'font-icon-p-home',
  'font-icon-cart'
];
const levels = ['First', 'Second', 'Third', 'Forth', 'Fifth', 'Sixth', 'Seventh', 'Eighth'];

// Build an action to handle the click on the crumbs
const crumbAction = (event) => {
  event.preventDefault();
  return action('onClick')(event);
};
crumbAction.toString = () => 'onClick';

/**
 * This method can be used to build an array of breadcrumbs
 * @param position 0-based index of the level
 * @param rank Textual representation of the rank level
 * @param string icon class to applu to the icon
 * @returns {Object[]}
 */
const buildBreadCrumb = (position, rank, icon) => {
  const level = levels[position];
  let crumb = [{
    text: `${level} level`,
    href: '#',
    onClick: crumbAction
  }];

  if (level === rank) {
    crumb[0].icon = { className: icon };
  } else {
    crumb = crumb.concat(buildBreadCrumb(position + 1, rank, icon));
  }

  return crumb;
};

storiesOf('Admin/Breadcrumb', module)
  .addDecorator(withKnobs)
  .addWithJSX('Breadcrumb', () => (
    <Breadcrumb crumbs={buildBreadCrumb(
        0,
        select('Number of levels', levels, 'First'),
        select('icon', icons)
    )}
    />
  ));
<commit_msg>Fix typo<commit_after>import React from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies
import { storiesOf, setAddon } from '@storybook/react';
import { withKnobs, select } from '@storybook/addon-knobs/react';
import JSXAddon from 'storybook-addon-jsx';
import { action } from '@storybook/addon-actions';

import { Component as Breadcrumb } from 'components/Breadcrumb/Breadcrumb';

setAddon(JSXAddon);

// Simple values to displays in the select fields.
const icons = [
  '',
  'font-icon-edit-list',
  'font-icon-calendar',
  'font-icon-p-home',
  'font-icon-cart'
];
const levels = ['First', 'Second', 'Third', 'Fourth', 'Fifth', 'Sixth', 'Seventh', 'Eighth'];

// Build an action to handle the click on the crumbs
const crumbAction = (event) => {
  event.preventDefault();
  return action('onClick')(event);
};
crumbAction.toString = () => 'onClick';

/**
 * This method can be used to build an array of breadcrumbs
 * @param position 0-based index of the level
 * @param rank Textual representation of the rank level
 * @param string icon class to applu to the icon
 * @returns {Object[]}
 */
const buildBreadCrumb = (position, rank, icon) => {
  const level = levels[position];
  let crumb = [{
    text: `${level} level`,
    href: '#',
    onClick: crumbAction
  }];

  if (level === rank) {
    crumb[0].icon = { className: icon };
  } else {
    crumb = crumb.concat(buildBreadCrumb(position + 1, rank, icon));
  }

  return crumb;
};

storiesOf('Admin/Breadcrumb', module)
  .addDecorator(withKnobs)
  .addWithJSX('Breadcrumb', () => (
    <Breadcrumb crumbs={buildBreadCrumb(
        0,
        select('Number of levels', levels, 'First'),
        select('icon', icons)
    )}
    />
  ));
<|endoftext|>


<commit_before>import Image from '../Image';

import getImageParameters from './getImageParameters';

/**
 * Use this function to support getting the output image of an algorithm from user-supplied
 * options.
 * @private
 * @param {Image} thisImage - Original image on which the algorithm will be applied
 * @param {object} options - Options object received by the algorithm
 * @param {Image} [options.out] - If set, must be an image compatible with the algorithm
 * @param {object} newParameters - Parameters that will be combined with the ones from `thisImage`.
 * @return {Image}
 */
export function getOutputImage(thisImage, options, newParameters) {
  const { out } = options;
  if (out === undefined) {
    return Image.createFrom(thisImage, newParameters);
  } else {
    if (!Image.isImage(out)) {
      throw new TypeError('out must be an Image object');
    }
    const requirements = Object.assign(getImageParameters(thisImage), newParameters);
    for (const property in requirements) {
      if (out[property] !== requirements[property]) {
        throw new RangeError(`cannot use out. Its ${property} must be "${requirements[property]}" (found "${out[property]}")`);
      }
    }
    return out;
  }
}

/**
 * Same as getOutputImage but allows for an `inPlace` option.
 * @param {Image} thisImage
 * @param {object} options
 * @param {boolean} [options.inPlace=false] - If true, thisImage is returned
 * @param {Image} [options.out]
 * @return {Image}
 */
export function getOutputImageOrInPlace(thisImage, options) {
  if (options.inPlace !== undefined && typeof options.inPlace !== 'boolean') {
    throw new TypeError('inPlace option must be a boolean');
  }
  if (options.inPlace) {
    if (options.out !== undefined) {
      throw new TypeError('out option must not be set if inPlace option is true');
    }
    return thisImage;
  }
  return getOutputImage(thisImage, options);
}
<commit_msg>doc: mark function as private<commit_after>import Image from '../Image';

import getImageParameters from './getImageParameters';

/**
 * Use this function to support getting the output image of an algorithm from user-supplied
 * options.
 * @private
 * @param {Image} thisImage - Original image on which the algorithm will be applied
 * @param {object} options - Options object received by the algorithm
 * @param {Image} [options.out] - If set, must be an image compatible with the algorithm
 * @param {object} newParameters - Parameters that will be combined with the ones from `thisImage`.
 * @return {Image}
 */
export function getOutputImage(thisImage, options, newParameters) {
  const { out } = options;
  if (out === undefined) {
    return Image.createFrom(thisImage, newParameters);
  } else {
    if (!Image.isImage(out)) {
      throw new TypeError('out must be an Image object');
    }
    const requirements = Object.assign(getImageParameters(thisImage), newParameters);
    for (const property in requirements) {
      if (out[property] !== requirements[property]) {
        throw new RangeError(`cannot use out. Its ${property} must be "${requirements[property]}" (found "${out[property]}")`);
      }
    }
    return out;
  }
}

/**
 * Same as getOutputImage but allows for an `inPlace` option.
 * @private
 * @param {Image} thisImage
 * @param {object} options
 * @param {boolean} [options.inPlace=false] - If true, thisImage is returned
 * @param {Image} [options.out]
 * @return {Image}
 */
export function getOutputImageOrInPlace(thisImage, options) {
  if (options.inPlace !== undefined && typeof options.inPlace !== 'boolean') {
    throw new TypeError('inPlace option must be a boolean');
  }
  if (options.inPlace) {
    if (options.out !== undefined) {
      throw new TypeError('out option must not be set if inPlace option is true');
    }
    return thisImage;
  }
  return getOutputImage(thisImage, options);
}
<|endoftext|>


<commit_before>/**
 * Copyright 2018 The Subscribe with Google Authors. 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.
 */
'use strict';

const argv = require('minimist')(process.argv.slice(2));
const closureCompiler = require('@ampproject/google-closure-compiler');
const fs = require('fs-extra');
const gulp = require('gulp');
const path = require('path');
const pumpify = require('pumpify');
const rename = require('gulp-rename');
const replace = require('gulp-replace');
const resolveConfig = require('./compile-config').resolveConfig;
const sourcemaps = require('gulp-sourcemaps');
const {isCiBuild} = require('../ci');
const {red} = require('ansi-colors');
const {VERSION: internalRuntimeVersion} = require('./internal-version');
const through = require('through2');
const os = require('os');

const queue = [];
let inProgress = 0;
const MAX_PARALLEL_CLOSURE_INVOCATIONS = 4;

// Compiles code with the closure compiler. This is intended only for
// production use. During development we intent to continue using
// babel, as it has much faster incremental compilation.
exports.closureCompile = function (
  entryModuleFilename,
  outputDir,
  outputFilename,
  options
) {
  // Rate limit closure compilation to MAX_PARALLEL_CLOSURE_INVOCATIONS
  // concurrent processes.
  return new Promise(function (resolve) {
    function start() {
      inProgress++;
      compile(entryModuleFilename, outputDir, outputFilename, options).then(
        function () {
          if (isCiBuild()) {
            // When printing simplified log in CI, use dot for each task.
            process.stdout.write('.');
          }
          inProgress--;
          next();
          resolve();
        },
        function (e) {
          console./*OK*/ error(red('Compilation error', e.message));
          process.exit(1);
        }
      );
    }
    function next() {
      if (!queue.length) {
        // When printing simplified log in CI, print EOF after
        // all closure compiling task are done.
        if (isCiBuild()) {
          process.stdout.write('\n');
        }
        return;
      }
      if (inProgress < MAX_PARALLEL_CLOSURE_INVOCATIONS) {
        queue.shift()();
      }
    }
    queue.push(start);
    next();
  });
};

function compile(entryModuleFilenames, outputDir, outputFilename, options) {
  return new Promise((resolve) => {
    let entryModuleFilename;
    if (entryModuleFilenames instanceof Array) {
      entryModuleFilename = entryModuleFilenames[0];
    } else {
      entryModuleFilename = entryModuleFilenames;
      entryModuleFilenames = [entryModuleFilename];
    }
    const checkTypes = options.checkTypes || argv.typecheck_only;
    const intermediateFilename = entryModuleFilename
      .replace(/\//g, '_')
      .replace(/^\./, '');
    // If undefined/null or false then we're ok executing the deletions
    // and mkdir.
    const unneededFiles = [];
    if (fs.existsSync(intermediateFilename)) {
      fs.unlinkSync(intermediateFilename);
    }
    const srcs = [
      // Files under build/. Should be sparse.
      'build/css/**/*.css.js',
      'src/*.js',
      'src/**/*.js',
      '!src/*-babel.js',
      'third_party/gpay/**/*.js',
      'node_modules/promise-pjs/promise.js',
      'node_modules/web-activities/activity-ports.js',
      //'node_modules/core-js/modules/**.js',
      // Not sure what these files are, but they seem to duplicate code
      // one level below and confuse the compiler.
      '!node_modules/core-js/modules/library/**.js',
      // Don't include tests.
      '!**-test.js',
      '!**_test.js',
      '!**/test-*.js',
      '!**/*-test.js',
      '!**/*.extern.js',
    ];
    if (options.extraGlobs) {
      srcs.push.apply(srcs, options.extraGlobs);
    }
    // Many files include the polyfills, but we only want to deliver them
    // once. Since all files automatically wait for the main binary to load
    // this works fine.
    if (options.includePolyfills) {
      srcs.push(
        '!build/fake-module/src/polyfills.js',
        '!build/fake-module/src/polyfills/**/*.js'
      );
    } else {
      srcs.push('!src/polyfills.js');
      unneededFiles.push('build/fake-module/src/polyfills.js');
    }
    unneededFiles.forEach(function (fake) {
      if (!fs.existsSync(fake)) {
        fs.writeFileSync(
          fake,
          '// Not needed in closure compiler\n' +
            'export function deadCode() {}'
        );
      }
    });

    let externs = ['build-system/extern.js'];
    if (options.externs) {
      externs = externs.concat(options.externs);
    }

    /*eslint "google-camelcase/google-camelcase": 0*/
    const compilerOptions = {
      compilation_level: options.compilationLevel || 'SIMPLE',
      // Turns on more optimizations.
      assume_function_wrapper: true,
      // Transpile from modern JavaScript to ES5.
      language_in: 'ECMASCRIPT_2020',
      language_out: 'ECMASCRIPT5',
      // We do not use the polyfills provided by closure compiler.
      // If you need a polyfill. Manually include them in the
      // respective top level polyfills.js files.
      rewrite_polyfills: false,
      externs,
      js_module_root: ['build/fake-module/'],
      entry_point: entryModuleFilenames,
      module_resolution: 'NODE',
      package_json_entry_names: 'module,main',
      process_common_js_modules: true,
      // This strips all files from the input set that aren't explicitly
      // required.
      dependency_mode: 'PRUNE',
      isolation_mode: 'IIFE',
      warning_level: 'DEFAULT',
      // Turn off warning for "Unknown @define" since we use define to pass
      // args such as FORTESTING to our runner.
      // Turn off warning for "Partial alias" since it's unavoidable with
      // certain dependencies.
      jscomp_off: ['unknownDefines', 'partialAlias'],
      define: [],
      hide_warnings_for: [
        'src/polyfills/',
        'src/proto/',
        'node_modules/',
        'third_party/',
      ],
      jscomp_error: [],
    };

    // Apply AMP's optimizations, reducing binary size by roughly 25%.
    // https://github.com/ampproject/amp-closure-compiler/blob/a2c1262c6bb2acfafb5f6672283bbac5623e4a1d/src/org/ampproject/AmpCodingConvention.java#L71
    compilerOptions.define.push('AMP_MODE=true');

    // For now do type check separately
    if (argv.typecheck_only || checkTypes) {
      // Don't modify compilation_level to a lower level since
      // it won't do strict type checking if its whitespace only.
      compilerOptions.define.push('TYPECHECK_ONLY=true');
      compilerOptions.jscomp_error.push(
        'checkTypes',
        'accessControls',
        'const',
        'constantProperty',
        'globalThis'
      );
      compilerOptions.conformance_configs =
        'build-system/conformance-config.textproto';
    }
    if (argv.pseudoNames) {
      compilerOptions.define.push('PSEUDO_NAMES=true');
    }
    if (argv.fortesting) {
      compilerOptions.define.push('FORTESTING=true');
    }

    if (compilerOptions.define.length == 0) {
      delete compilerOptions.define;
    }

    let stream = gulp
      .src(srcs, {base: './'})
      .pipe(sourcemaps.init())
      .pipe(makeSourcemapsRelative(closureCompiler.gulp()(compilerOptions)))
      .pipe(rename(intermediateFilename))
      .pipe(gulp.dest('build/cc/'))
      .on('error', function (err) {
        console./*OK*/ error(red('Error compiling', entryModuleFilenames));
        console./*OK*/ error(red(err.message));
        process.exit(1);
      });

    // If we're only doing type checking, no need to output the files.
    if (!argv.typecheck_only) {
      stream = stream.pipe(rename(outputFilename)).pipe(
        sourcemaps.write('.', {
          sourceRoot: `https://raw.githubusercontent.com/subscriptions-project/swg-js/${internalRuntimeVersion}/`,
          includeContent: false,
        })
      );

      // Replacements.
      const replacements = resolveConfig();
      for (const k in replacements) {
        stream = stream.pipe(
          replace(new RegExp('\\$' + k + '\\$', 'g'), replacements[k])
        );
      }

      // Appends a newline terminator to .map files
      stream = stream.pipe(through.obj((file, _, cb) => {
        if(file.sourceMap && file.path.endsWith('.map')) {
          file.contents = Buffer.concat([
            file.contents,
            Buffer.from(os.EOL)
          ]);
        }

        cb(null, file);
      }));

      // Complete build: dist and source maps.
      stream = stream.pipe(gulp.dest(outputDir)).on('end', resolve);
    }
    return stream;
  });
}

/**
 * Normalize the sourcemap file paths before pushing into Closure.
 * Closure don't follow Gulp's normal sourcemap "root" pattern. Gulp considers
 * all files to be relative to the CWD by default, meaning a file `src/foo.js`
 * with a sourcemap alongside points to `src/foo.js`. Closure considers each
 * file relative to the sourcemap. Since the sourcemap for `src/foo.js` "lives"
 * in `src/`, it ends up resolving to `src/src/foo.js`.
 *
 * @param {!NodeJS.WritableStream} closureStream
 * @return {!NodeJS.WritableStream}
 */
function makeSourcemapsRelative(closureStream) {
  const relativeSourceMap = sourcemaps.mapSources((source, file) => {
    const dir = path.dirname(file.sourceMap.file);
    return path.relative(dir, source);
  });

  return pumpify.obj(relativeSourceMap, closureStream);
}
<commit_msg>chore: fix lint<commit_after>/**
 * Copyright 2018 The Subscribe with Google Authors. 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.
 */
'use strict';

const argv = require('minimist')(process.argv.slice(2));
const closureCompiler = require('@ampproject/google-closure-compiler');
const fs = require('fs-extra');
const gulp = require('gulp');
const os = require('os');
const path = require('path');
const pumpify = require('pumpify');
const rename = require('gulp-rename');
const replace = require('gulp-replace');
const resolveConfig = require('./compile-config').resolveConfig;
const sourcemaps = require('gulp-sourcemaps');
const through = require('through2');
const {isCiBuild} = require('../ci');
const {red} = require('ansi-colors');
const {VERSION: internalRuntimeVersion} = require('./internal-version');

const queue = [];
let inProgress = 0;
const MAX_PARALLEL_CLOSURE_INVOCATIONS = 4;

// Compiles code with the closure compiler. This is intended only for
// production use. During development we intent to continue using
// babel, as it has much faster incremental compilation.
exports.closureCompile = function (
  entryModuleFilename,
  outputDir,
  outputFilename,
  options
) {
  // Rate limit closure compilation to MAX_PARALLEL_CLOSURE_INVOCATIONS
  // concurrent processes.
  return new Promise(function (resolve) {
    function start() {
      inProgress++;
      compile(entryModuleFilename, outputDir, outputFilename, options).then(
        function () {
          if (isCiBuild()) {
            // When printing simplified log in CI, use dot for each task.
            process.stdout.write('.');
          }
          inProgress--;
          next();
          resolve();
        },
        function (e) {
          console./*OK*/ error(red('Compilation error', e.message));
          process.exit(1);
        }
      );
    }
    function next() {
      if (!queue.length) {
        // When printing simplified log in CI, print EOF after
        // all closure compiling task are done.
        if (isCiBuild()) {
          process.stdout.write('\n');
        }
        return;
      }
      if (inProgress < MAX_PARALLEL_CLOSURE_INVOCATIONS) {
        queue.shift()();
      }
    }
    queue.push(start);
    next();
  });
};

function compile(entryModuleFilenames, outputDir, outputFilename, options) {
  return new Promise((resolve) => {
    let entryModuleFilename;
    if (entryModuleFilenames instanceof Array) {
      entryModuleFilename = entryModuleFilenames[0];
    } else {
      entryModuleFilename = entryModuleFilenames;
      entryModuleFilenames = [entryModuleFilename];
    }
    const checkTypes = options.checkTypes || argv.typecheck_only;
    const intermediateFilename = entryModuleFilename
      .replace(/\//g, '_')
      .replace(/^\./, '');
    // If undefined/null or false then we're ok executing the deletions
    // and mkdir.
    const unneededFiles = [];
    if (fs.existsSync(intermediateFilename)) {
      fs.unlinkSync(intermediateFilename);
    }
    const srcs = [
      // Files under build/. Should be sparse.
      'build/css/**/*.css.js',
      'src/*.js',
      'src/**/*.js',
      '!src/*-babel.js',
      'third_party/gpay/**/*.js',
      'node_modules/promise-pjs/promise.js',
      'node_modules/web-activities/activity-ports.js',
      //'node_modules/core-js/modules/**.js',
      // Not sure what these files are, but they seem to duplicate code
      // one level below and confuse the compiler.
      '!node_modules/core-js/modules/library/**.js',
      // Don't include tests.
      '!**-test.js',
      '!**_test.js',
      '!**/test-*.js',
      '!**/*-test.js',
      '!**/*.extern.js',
    ];
    if (options.extraGlobs) {
      srcs.push.apply(srcs, options.extraGlobs);
    }
    // Many files include the polyfills, but we only want to deliver them
    // once. Since all files automatically wait for the main binary to load
    // this works fine.
    if (options.includePolyfills) {
      srcs.push(
        '!build/fake-module/src/polyfills.js',
        '!build/fake-module/src/polyfills/**/*.js'
      );
    } else {
      srcs.push('!src/polyfills.js');
      unneededFiles.push('build/fake-module/src/polyfills.js');
    }
    unneededFiles.forEach(function (fake) {
      if (!fs.existsSync(fake)) {
        fs.writeFileSync(
          fake,
          '// Not needed in closure compiler\n' +
            'export function deadCode() {}'
        );
      }
    });

    let externs = ['build-system/extern.js'];
    if (options.externs) {
      externs = externs.concat(options.externs);
    }

    /*eslint "google-camelcase/google-camelcase": 0*/
    const compilerOptions = {
      compilation_level: options.compilationLevel || 'SIMPLE',
      // Turns on more optimizations.
      assume_function_wrapper: true,
      // Transpile from modern JavaScript to ES5.
      language_in: 'ECMASCRIPT_2020',
      language_out: 'ECMASCRIPT5',
      // We do not use the polyfills provided by closure compiler.
      // If you need a polyfill. Manually include them in the
      // respective top level polyfills.js files.
      rewrite_polyfills: false,
      externs,
      js_module_root: ['build/fake-module/'],
      entry_point: entryModuleFilenames,
      module_resolution: 'NODE',
      package_json_entry_names: 'module,main',
      process_common_js_modules: true,
      // This strips all files from the input set that aren't explicitly
      // required.
      dependency_mode: 'PRUNE',
      isolation_mode: 'IIFE',
      warning_level: 'DEFAULT',
      // Turn off warning for "Unknown @define" since we use define to pass
      // args such as FORTESTING to our runner.
      // Turn off warning for "Partial alias" since it's unavoidable with
      // certain dependencies.
      jscomp_off: ['unknownDefines', 'partialAlias'],
      define: [],
      hide_warnings_for: [
        'src/polyfills/',
        'src/proto/',
        'node_modules/',
        'third_party/',
      ],
      jscomp_error: [],
    };

    // Apply AMP's optimizations, reducing binary size by roughly 25%.
    // https://github.com/ampproject/amp-closure-compiler/blob/a2c1262c6bb2acfafb5f6672283bbac5623e4a1d/src/org/ampproject/AmpCodingConvention.java#L71
    compilerOptions.define.push('AMP_MODE=true');

    // For now do type check separately
    if (argv.typecheck_only || checkTypes) {
      // Don't modify compilation_level to a lower level since
      // it won't do strict type checking if its whitespace only.
      compilerOptions.define.push('TYPECHECK_ONLY=true');
      compilerOptions.jscomp_error.push(
        'checkTypes',
        'accessControls',
        'const',
        'constantProperty',
        'globalThis'
      );
      compilerOptions.conformance_configs =
        'build-system/conformance-config.textproto';
    }
    if (argv.pseudoNames) {
      compilerOptions.define.push('PSEUDO_NAMES=true');
    }
    if (argv.fortesting) {
      compilerOptions.define.push('FORTESTING=true');
    }

    if (compilerOptions.define.length == 0) {
      delete compilerOptions.define;
    }

    let stream = gulp
      .src(srcs, {base: './'})
      .pipe(sourcemaps.init())
      .pipe(makeSourcemapsRelative(closureCompiler.gulp()(compilerOptions)))
      .pipe(rename(intermediateFilename))
      .pipe(gulp.dest('build/cc/'))
      .on('error', function (err) {
        console./*OK*/ error(red('Error compiling', entryModuleFilenames));
        console./*OK*/ error(red(err.message));
        process.exit(1);
      });

    // If we're only doing type checking, no need to output the files.
    if (!argv.typecheck_only) {
      stream = stream.pipe(rename(outputFilename)).pipe(
        sourcemaps.write('.', {
          sourceRoot: `https://raw.githubusercontent.com/subscriptions-project/swg-js/${internalRuntimeVersion}/`,
          includeContent: false,
        })
      );

      // Replacements.
      const replacements = resolveConfig();
      for (const k in replacements) {
        stream = stream.pipe(
          replace(new RegExp('\\$' + k + '\\$', 'g'), replacements[k])
        );
      }

      // Appends a newline terminator to .map files
      stream = stream.pipe(
        through.obj((file, _, cb) => {
          if (file.sourceMap && file.path.endsWith('.map')) {
            file.contents = Buffer.concat([file.contents, Buffer.from(os.EOL)]);
          }

          cb(null, file);
        })
      );

      // Complete build: dist and source maps.
      stream = stream.pipe(gulp.dest(outputDir)).on('end', resolve);
    }
    return stream;
  });
}

/**
 * Normalize the sourcemap file paths before pushing into Closure.
 * Closure don't follow Gulp's normal sourcemap "root" pattern. Gulp considers
 * all files to be relative to the CWD by default, meaning a file `src/foo.js`
 * with a sourcemap alongside points to `src/foo.js`. Closure considers each
 * file relative to the sourcemap. Since the sourcemap for `src/foo.js` "lives"
 * in `src/`, it ends up resolving to `src/src/foo.js`.
 *
 * @param {!NodeJS.WritableStream} closureStream
 * @return {!NodeJS.WritableStream}
 */
function makeSourcemapsRelative(closureStream) {
  const relativeSourceMap = sourcemaps.mapSources((source, file) => {
    const dir = path.dirname(file.sourceMap.file);
    return path.relative(dir, source);
  });

  return pumpify.obj(relativeSourceMap, closureStream);
}
<|endoftext|>


<commit_before>function dayNight(day, night) {
  // syntax: dayNight((function() { day opts }), (function() { night opts }));
  if(dayNight.arguments.length !== 2) {
    return window.console.error("dayNight function should have day and night opts!");
  }

  var darkened = ((localStorage.darkened && (/^(true|false)$/).test(localStorage.darkened)) ? JSON.parse(localStorage.darkened) : false);
  // boolean for page state: restore or apply day mode

  var lights = {
    on: function() { day.bind(document).apply(); },
    off: function() { night.bind(document).apply(); }
  };

  if(!(/^interactive|complete$/).test(document.readyState)) {
    window.requestAnimationFrame(function() { dayNight(day, night); });
  } else {
    var btn = document.createElement("div"),
        sun = "\u2600\uFE0E",
        moon = "\u263D",
        fluents = function(){
          return {
            bottom: (darkened ? 10 : 8) + 'px',
            left: (darkened ? 38 : 44) + 'px',
            transform: (darkened ? '' : 'rotate(45deg)')
          };
        };
        // fluents change depending on day/night

    btn.setAttribute("id", "night_btn");
    Object.assign(btn.style, {
      position: 'fixed',
      font: '32px/24px "Open Sans"',
      color: 'inherit',
      zIndex: String(1e+4),
      opacity: '0.6',
      cursor: 'pointer'
    });
    document.body.insertBefore(btn, document.body.firstElementChild);

    var cycle = function() {
      darkened ? lights.off() : lights.on();
      btn.setAttribute("title", "Toggle " + (darkened ? "day" : "night") + " mode.");
      btn.innerText = (darkened ? sun : moon);
      Object.assign(btn.style, fluents());
    };
    // changing scope
    cycle();

    var int, opacity;
    var translucent = function(e) {
      clearInterval(int);
      var opacityMax = ((/enter/).test(e.type) ? 1.1 : 0.5);
      opacity = function(){
        return (Math.round((parseFloat(btn.style.opacity) + ((/enter/).test(e.type) ? 0.1 : -0.1)) * 1e2) / 1e2);
        // if mouseenter increment opacity, else - decrement; round for right parsing
      };
      int = setInterval(function() {
        if(opacity() === opacityMax) {
          clearInterval(int);
        } else {
          btn.style.opacity = String(opacity());
        }
      }, 40);
    };

    ['mouseenter', 'mouseleave'].forEach(function(e) {
      btn.addEventListener(e, function() { translucent(e); });
    });

    btn.onclick = function(){
      darkened = !darkened;
      // booleans hooray!
      cycle();
    };
  }

  window.onbeforeunload = function(){ localStorage.darkened = darkened; };
  // store mode for staying the same in night/day mode;
}
<commit_msg>daynight faster and fixed opacity<commit_after>function dayNight(day, night) {
  // syntax: dayNight((function() { day opts }), (function() { night opts }));
  if(dayNight.arguments.length !== 2) {
    return window.console.error("dayNight function should have day and night opts!");
  }

  var darkened = ((localStorage.darkened && (/^(true|false)$/).test(localStorage.darkened)) ? JSON.parse(localStorage.darkened) : false);
  // boolean for page state: restore or apply day mode

  var lights = {
    on: function() { day.bind(document).apply(); },
    off: function() { night.bind(document).apply(); }
  };

  if(!document.body) {
    window.requestAnimationFrame(function() { dayNight(day, night); });
  } else {
    var btn = document.createElement("div"),
        sun = "\u2600\uFE0E",
        moon = "\u263D",
        fluents = function(){
          return {
            bottom: (darkened ? 10 : 8) + 'px',
            left: (darkened ? 38 : 44) + 'px',
            transform: (darkened ? '' : 'rotate(45deg)')
          };
        };
        // fluents change depending on day/night

    btn.setAttribute("id", "night_btn");
    Object.assign(btn.style, {
      position: 'fixed',
      font: '32px/24px "Open Sans"',
      color: 'inherit',
      zIndex: String(1e+4),
      opacity: '0.6',
      cursor: 'pointer'
    });
    document.body.insertBefore(btn, document.body.firstElementChild);

    var cycle = function() {
      darkened ? lights.off() : lights.on();
      btn.setAttribute("title", "Toggle " + (darkened ? "day" : "night") + " mode.");
      btn.innerText = (darkened ? sun : moon);
      Object.assign(btn.style, fluents());
    };
    // changing scope
    cycle();

    var int, opacity;
    var translucent = function(e) {
      clearInterval(int);
      var opacityMax = ((/enter/).test(e.type) ? 1.1 : 0.5);
      opacity = function(){
        return (Math.round((parseFloat(btn.style.opacity) + ((/enter/).test(e.type) ? 0.1 : -0.1)) * 10) / 10);
        // if mouseenter increment opacity, else - decrement; round for correct parsing
      };
      int = setInterval(function() {
        if(opacity() === opacityMax) {
          clearInterval(int);
        } else {
          btn.style.opacity = String(opacity());
        }
      }, 40);
    };

    ['mouseenter', 'mouseleave'].forEach(function(e) {
      btn.addEventListener(e, function() { translucent(e); });
    });

    btn.onclick = function(){
      darkened = !darkened;
      // booleans hooray!
      cycle();
    };
  }

  window.onbeforeunload = function(){ localStorage.darkened = darkened; };
  // store mode for staying the same in night/day mode;
}
<|endoftext|>


<commit_before>import delegate from './delegate'
import { each } from '../../utils/generic'

export default function initialize () {

	let activeContainerIds = []
	let activeSequenceIds = []

	each(this.store.elements, element => {
		if (activeContainerIds.indexOf(element.containerId) === -1) {
			activeContainerIds.push(element.containerId)
		}
		if (activeSequenceIds.indexOf(element.sequence.id) === -1) {
			activeSequenceIds.push(element.sequence.id)
		}
	})

	each(this.store.sequences, sequence => {
		if (activeSequenceIds.indexOf(sequence.id) === -1) {
			delete this.store.sequences[sequence.id]
		}
	})

	each(this.store.containers, container => {

		if (activeContainerIds.indexOf(container.id) === -1) {
			container.node.removeEventListener('scroll', delegate)
			container.node.removeEventListener('resize', delegate)
			delete this.store.containers[container.id]

		} else if (container.node === document.documentElement) {
			window.addEventListener('scroll', delegate.bind(this))
			window.addEventListener('resize', delegate.bind(this))

		} else {
			container.node.addEventListener('scroll', delegate.bind(this))
			container.node.addEventListener('resize', delegate.bind(this))
		}
	})

	/**
	 * Manually invoke delegate once to capture
	 * element and container dimensions, container
	 * scroll position, and trigger any valid reveals
	 */
	delegate.call(this)

	/**
	 * And with that, initialization is complete so
	 * let's update our initialization timeout and state.
	 */
	this.initTimeout = null
	this.initialized = true
}
<commit_msg>add comments to initialization flow<commit_after>import delegate from './delegate'
import { each } from '../../utils/generic'

export default function initialize () {

	/**
	 * Let's take stock of which containers and sequences
	 * our current store of elements is actively using.
	 */
	let activeContainerIds = []
	let activeSequenceIds = []

	each(this.store.elements, element => {
		if (activeContainerIds.indexOf(element.containerId) === -1) {
			activeContainerIds.push(element.containerId)
		}
		if (activeSequenceIds.indexOf(element.sequence.id) === -1) {
			activeSequenceIds.push(element.sequence.id)
		}
	})

	/**
	 * Remove unused sequences.
	 */
	each(this.store.sequences, sequence => {
		if (activeSequenceIds.indexOf(sequence.id) === -1) {
			delete this.store.sequences[sequence.id]
		}
	})

	each(this.store.containers, container => {

		/**
		 * Remove unused containers.
		 */
		if (activeContainerIds.indexOf(container.id) === -1) {
			container.node.removeEventListener('scroll', delegate)
			container.node.removeEventListener('resize', delegate)
			delete this.store.containers[container.id]

		/**
		 * The default container is the <html> element, and in
		 * this case we listen for scroll events on the window.
		 */
		} else if (container.node === document.documentElement) {
			window.addEventListener('scroll', delegate.bind(this))
			window.addEventListener('resize', delegate.bind(this))

		/**
		 * Otherwise listen for scroll events directly on the container.
		 */
		} else {
			container.node.addEventListener('scroll', delegate.bind(this))
			container.node.addEventListener('resize', delegate.bind(this))
		}
	})

	/**
	 * Manually invoke delegate once to capture
	 * element and container dimensions, container
	 * scroll position, and trigger any valid reveals
	 */
	delegate.call(this)

	/**
	 * And with that, initialization is complete so
	 * let's update our initialization timeout and state.
	 */
	this.initTimeout = null
	this.initialized = true
}
<|endoftext|>


<commit_before>import { ElementAssembler } from 'dommodule/lib/ElementAssembler'

let undefined

const { assign, getPrototypeOf } = Object
const { HTMLElement } = window

const CLASS_PREFIX_RE = /^HTML/
const HTML_NAMESPACE_URI = 'http://www.w3.org/1999/xhtml'

/**
 * @see https://www.w3.org/TR/html/single-page.html#htmlelement
 * @abstract
 */
export class HTMLElementAssembler extends ElementAssembler {
    /**
     * @param {*} [init]
     */
    create(init) {
        super.create(init)
        this.classList = this.constructor.classList
    }

    /**
     * Click the element
     */
    click() {
        this.node.click()
    }

    /**
     * Focus the element
     */
    focus() {
        this.node.focus()
    }

    /**
     * Blur the element
     */
    blur() {
        this.node.blur()
    }

    /**
     * @param {string} accessKey
     */
    set accessKey(accessKey) {
        this.node.accessKey = accessKey
    }

    /**
     * @returns {string}
     */
    get accessKey() {
        return this.node.accessKey
    }

    /**
     * @param {string} contentEditable
     */
    set contentEditable(contentEditable) {
        this.node.contentEditable = contentEditable
    }

    /**
     * @returns {string}
     */
    get contentEditable() {
        return this.node.contentEditable
    }

    /**
     * @param {{}} dataset
     */
    set dataset(dataset) {
        const _dataset = this.dataset
        for(let name in dataset) {
            if(dataset.hasOwnProperty(name)) {
                const value = dataset[name]
                if(value === null) {
                    delete _dataset[name]
                }
                else if(value !== undefined) {
                    _dataset[name] = dataset[name]
                }
            }
        }
    }

    /**
     * @returns {{}} DOMStringMap
     */
    get dataset() {
        return this.node.dataset
    }

    /**
     * @param {string} dir
     */
    set dir(dir) {
        this.node.dir = dir
    }

    /**
     * @returns {string}
     */
    get dir() {
        return this.node.dir
    }

    /**
     * @param {string} innerHTML
     */
    set innerHTML(innerHTML) {
        this.node.innerHTML = innerHTML
    }

    /**
     * @returns {string}
     */
    get innerHTML() {
        return this.node.innerHTML
    }

    /**
     * @param {string} innerText
     */
    set innerText(innerText) {
        this.node.innerText = innerText
    }

    /**
     * @returns {string}
     */
    get innerText() {
        return this.node.innerText
    }

    /**
     * @returns {boolean}
     */
    get isContentEditable() {
        return this.node.isContentEditable
    }

    /**
     * @param {string} lang
     */
    set lang(lang) {
        this.node.lang = lang
    }

    /**
     * @returns {string}
     */
    get lang() {
        return this.node.lang
    }

    /**
     * @param {{}} style
     */
    set style(style) {
        assign(this.node.style, style)
    }

    /**
     * @returns {{}} CSSStyleDeclaration
     */
    get style() {
        return this.node.style
    }

    /**
     * @param {number|null} tabIndex
     */
    set tabIndex(tabIndex) {
        if(tabIndex === null) {
            this.removeAttr('tabindex')
        }
        else this.node.tabIndex = tabIndex
    }

    /**
     * @returns {number|null}
     */
    get tabIndex() {
        const tabIndex = this.node.tabIndex
        return this.hasAttr('tabindex') || tabIndex > -1?
            tabIndex :
            null
    }

    /**
     * @param {string} title
     */
    set title(title) {
        this.node.title = title
    }

    /**
     * @returns {string}
     */
    get title() {
        return this.node.title
    }

    /**
     * @param {boolean} translate
     */
    set translate(translate) {
        this.node.translate = translate
    }

    /**
     * @returns {boolean}
     */
    get translate() {
        return this.node.translate
    }

    /**
     * @param {boolean} hidden
     */
    set hidden(hidden) {
        this.node.hidden = hidden
    }

    /**
     * @returns {boolean}
     */
    get hidden() {
        return this.node.hidden
    }

    /**
     * @returns {string[]}
     */
    static get classList() {
        const { superAssembler } = this
        const classList = []
        let object = this
        let proto
        if(this !== superAssembler) {
            while(proto = getPrototypeOf(object)) {
                if(proto !== superAssembler) {
                    classList.push(object.name)
                    object = proto
                }
                else break
            }
        }
        return classList
    }

    /**
     * @returns {class} HTMLDocumentAssembler|DocumentAssembler
     * @override
     */
    static get documentAssembler() {
        return HTMLElementAssembler.HTMLDocumentAssembler || super.documentAssembler
    }

    /**
     * @returns {interface} HTMLElement
     * @override
     */
    static get interface() {
        return HTMLElement || super.interface
    }

    /**
     * @returns {string}
     * @override
     */
    static get localName() {
        const { superAssembler } = this
        let object = this
        let proto
        if(this === superAssembler) {
            return ''
        }
        while(proto = getPrototypeOf(object)) {
            if(proto === superAssembler) {
                break
            }
            else object = proto
        }
        return object.name.replace(CLASS_PREFIX_RE, '').toLowerCase()
    }

    /**
     * @returns {string}
     * @override
     */
    static get namespace() {
        return HTML_NAMESPACE_URI
    }

    /**
     * @returns {class} HTMLElementAssembler
     * @override
     */
    static get superAssembler() {
        return HTMLElementAssembler
    }
}

HTMLElementAssembler.register()
<commit_msg>HTMLElementAssembler.style: allow setting the cssText string<commit_after>import { ElementAssembler } from 'dommodule/lib/ElementAssembler'

let undefined

const { assign, getPrototypeOf } = Object
const { HTMLElement } = window

const CLASS_PREFIX_RE = /^HTML/
const HTML_NAMESPACE_URI = 'http://www.w3.org/1999/xhtml'

/**
 * @see https://www.w3.org/TR/html/single-page.html#htmlelement
 * @abstract
 */
export class HTMLElementAssembler extends ElementAssembler {
    /**
     * @param {*} [init]
     */
    create(init) {
        super.create(init)
        this.classList = this.constructor.classList
    }

    /**
     * Click the element
     */
    click() {
        this.node.click()
    }

    /**
     * Focus the element
     */
    focus() {
        this.node.focus()
    }

    /**
     * Blur the element
     */
    blur() {
        this.node.blur()
    }

    /**
     * @param {string} accessKey
     */
    set accessKey(accessKey) {
        this.node.accessKey = accessKey
    }

    /**
     * @returns {string}
     */
    get accessKey() {
        return this.node.accessKey
    }

    /**
     * @param {string} contentEditable
     */
    set contentEditable(contentEditable) {
        this.node.contentEditable = contentEditable
    }

    /**
     * @returns {string}
     */
    get contentEditable() {
        return this.node.contentEditable
    }

    /**
     * @param {{}} dataset
     */
    set dataset(dataset) {
        const _dataset = this.dataset
        for(let name in dataset) {
            if(dataset.hasOwnProperty(name)) {
                const value = dataset[name]
                if(value === null) {
                    delete _dataset[name]
                }
                else if(value !== undefined) {
                    _dataset[name] = dataset[name]
                }
            }
        }
    }

    /**
     * @returns {{}} DOMStringMap
     */
    get dataset() {
        return this.node.dataset
    }

    /**
     * @param {string} dir
     */
    set dir(dir) {
        this.node.dir = dir
    }

    /**
     * @returns {string}
     */
    get dir() {
        return this.node.dir
    }

    /**
     * @param {string} innerHTML
     */
    set innerHTML(innerHTML) {
        this.node.innerHTML = innerHTML
    }

    /**
     * @returns {string}
     */
    get innerHTML() {
        return this.node.innerHTML
    }

    /**
     * @param {string} innerText
     */
    set innerText(innerText) {
        this.node.innerText = innerText
    }

    /**
     * @returns {string}
     */
    get innerText() {
        return this.node.innerText
    }

    /**
     * @returns {boolean}
     */
    get isContentEditable() {
        return this.node.isContentEditable
    }

    /**
     * @param {string} lang
     */
    set lang(lang) {
        this.node.lang = lang
    }

    /**
     * @returns {string}
     */
    get lang() {
        return this.node.lang
    }

    /**
     * @param {*} style {{}|string}
     */
    set style(style) {
        if(typeof style === 'string') {
            this.node.style = style
        }
        else assign(this.node.style, style)
    }

    /**
     * @returns {CSSStyleDeclaration}
     */
    get style() {
        return this.node.style
    }

    /**
     * @param {number|null} tabIndex
     */
    set tabIndex(tabIndex) {
        if(tabIndex === null) {
            this.removeAttr('tabindex')
        }
        else this.node.tabIndex = tabIndex
    }

    /**
     * @returns {number|null}
     */
    get tabIndex() {
        const tabIndex = this.node.tabIndex
        return this.hasAttr('tabindex') || tabIndex > -1?
            tabIndex :
            null
    }

    /**
     * @param {string} title
     */
    set title(title) {
        this.node.title = title
    }

    /**
     * @returns {string}
     */
    get title() {
        return this.node.title
    }

    /**
     * @param {boolean} translate
     */
    set translate(translate) {
        this.node.translate = translate
    }

    /**
     * @returns {boolean}
     */
    get translate() {
        return this.node.translate
    }

    /**
     * @param {boolean} hidden
     */
    set hidden(hidden) {
        this.node.hidden = hidden
    }

    /**
     * @returns {boolean}
     */
    get hidden() {
        return this.node.hidden
    }

    /**
     * @returns {string[]}
     */
    static get classList() {
        const { superAssembler } = this
        const classList = []
        let object = this
        let proto
        if(this !== superAssembler) {
            while(proto = getPrototypeOf(object)) {
                if(proto !== superAssembler) {
                    classList.push(object.name)
                    object = proto
                }
                else break
            }
        }
        return classList
    }

    /**
     * @returns {class} HTMLDocumentAssembler|DocumentAssembler
     * @override
     */
    static get documentAssembler() {
        return HTMLElementAssembler.HTMLDocumentAssembler || super.documentAssembler
    }

    /**
     * @returns {interface} HTMLElement
     * @override
     */
    static get interface() {
        return HTMLElement || super.interface
    }

    /**
     * @returns {string}
     * @override
     */
    static get localName() {
        const { superAssembler } = this
        let object = this
        let proto
        if(this === superAssembler) {
            return ''
        }
        while(proto = getPrototypeOf(object)) {
            if(proto === superAssembler) {
                break
            }
            else object = proto
        }
        return object.name.replace(CLASS_PREFIX_RE, '').toLowerCase()
    }

    /**
     * @returns {string}
     * @override
     */
    static get namespace() {
        return HTML_NAMESPACE_URI
    }

    /**
     * @returns {class} HTMLElementAssembler
     * @override
     */
    static get superAssembler() {
        return HTMLElementAssembler
    }
}

HTMLElementAssembler.register()
<|endoftext|>


<commit_before>/*******************************************************************************
 * @license
 * Copyright (c) 2013 VMware, Inc. All Rights Reserved.
 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE
 * ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
 * CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
 * You can obtain a current copy of the Eclipse Public License from
 * http://www.opensource.org/licenses/eclipse-1.0.php
 *
 * Contributors:
 *     Kris De Volder (VMWare) - initial API and implementation
 ******************************************************************************/

/*global define window require console */

//
// This is meant to be or become a 'nice' and easy to use
// api for contributing functionality to the scripted editor.
//

define(function (require) {

	var when = require('when');
	var deref = require('scripted/utils/deref');
	var actions = require('scripted/keybindings/action-info');

	var saveHooks = require('scripted/editor/save-hooks');

	/**
	 * Create an accessor function to easily navigate a typical JSON like
	 * configuration object. The function acceps a variable number of arguments,
	 * each argument a property to navigate in the object. Navigation is 'safe'
	 * and returns the first 'falsy' value that is accessed in the navigation
	 * path.
	 */
	function makeConfigFunction(object) {
		return function() {
			var props = arguments;
			return deref(object, arguments);
		};
	}

	return {

		/**
		 * Add a save transform function. The function is called just prior to
		 * saving the contents of the editor and is given a chance to transform the text
		 * in the editor.
		 *
		 * @param {function(text:String, path:String, configuration:function(...String):Object):String?} transformFun
		 */
		addSaveTransform: function (transformFun) {

			//Use lower-level preSave hook to grab editor text, apply transformFun
			//and put contents back into the editor.
			saveHooks.onPreSave(function (editor, path) {
				//TODO: there's no real guarantee the config is initialized by now
				// but mostly it will be ok unless someone saves really early on in the lifecycle.
				var config = makeConfigFunction(deref(window, ['scripted', 'config' ]));
				return when(undefined, function () {
					return transformFun(editor.getText(), path, config);
				}).otherwise(function (err) {
					//If something went wrong with this transform
					//don't reject the save. Just ignore that transform.
					if (err) {
						if (err.stack) {
							console.log(err);
							console.log(err.stack);
						} else {
							console.error(err);
						}
					}
					return when.resolve();
				}).then(function(newText) {
					if (typeof(newText)==='string') {
						//TODO: work harder at preserving selection relative to text
						// even if text has shifted ?
						var oldSelection = editor.getSelection();
						var oldScroll = editor.getScroll();

						editor.setText(newText);
						editor.setSelection(oldSelection.start, oldSelection.end);
						editor.setScroll(oldScroll);
					}
				});
			});
		},

		/**
		 * Associate a handler function with a given actionID for all existing and future
		 * scripted editors. Any prior handlers assigned to the id are overwritten.
		 *

		 * A readable 'name' option can be provided. This name will be used in places
		 * like the help side panel instead of the actionID.
		 *

		 * A 'global' flag option can be provided. If set to a true value, then keybindings
		 * triggering this action will also trigger even if an editor does not have focus.
		 * Globally triggered actions will be redirected to the last editor that had
		 * focus.
		 *
		 * @param {String} actionID
		 * @param {{handler:function(Editor),name:?String,global:?Boolean}} spec
		 */
		setAction: function (actionID, spec) {
			actions.setAction(actionID, spec);
		}
	};

});<commit_msg>bit more added to support adding annotations in a plugin - needs refactoring though<commit_after>/*******************************************************************************
 * @license
 * Copyright (c) 2013 VMware, Inc. All Rights Reserved.
 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE
 * ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
 * CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
 * You can obtain a current copy of the Eclipse Public License from
 * http://www.opensource.org/licenses/eclipse-1.0.php
 *
 * Contributors:
 *     Kris De Volder (VMWare) - initial API and implementation
 ******************************************************************************/

/*global define window require console */

//
// This is meant to be or become a 'nice' and easy to use
// api for contributing functionality to the scripted editor.
//

define(function (require) {

	var when = require('when');
	var deref = require('scripted/utils/deref');
	var actions = require('scripted/keybindings/action-info');

	var saveHooks = require('scripted/editor/save-hooks');

	var editorUtils = require('scripted/utils/editorUtils');
	var annotationModule = require('orion/textview/annotations');

	var annotationManager = require('scripted/editor/annotationManager');

	/**
	 * Create an accessor function to easily navigate a typical JSON like
	 * configuration object. The function acceps a variable number of arguments,
	 * each argument a property to navigate in the object. Navigation is 'safe'
	 * and returns the first 'falsy' value that is accessed in the navigation
	 * path.
	 */
	function makeConfigFunction(object) {
		return function() {
			var props = arguments;
			return deref(object, arguments);
		};
	}

	return {
		/**
		 * Add a save transform function. The function is called just prior to
		 * saving the contents of the editor and is given a chance to transform the text
		 * in the editor.
		 *
		 * @param {function(text:String, path:String, configuration:function(...String):Object):String?} transformFun
		 */
		addSaveTransform: function (transformFun) {

			//Use lower-level preSave hook to grab editor text, apply transformFun
			//and put contents back into the editor.
			saveHooks.onPreSave(function (editor, path) {
				//TODO: there's no real guarantee the config is initialized by now
				// but mostly it will be ok unless someone saves really early on in the lifecycle.
				var config = makeConfigFunction(deref(window, ['scripted', 'config' ]));
				return when(undefined, function () {
					return transformFun(editor.getText(), path, config);
				}).otherwise(function (err) {
					//If something went wrong with this transform
					//don't reject the save. Just ignore that transform.
					if (err) {
						if (err.stack) {
							console.log(err);
							console.log(err.stack);
						} else {
							console.error(err);
						}
					}
					return when.resolve();
				}).then(function(newText) {
					if (typeof(newText)==='string') {
						//TODO: work harder at preserving selection relative to text
						// even if text has shifted ?
						var oldSelection = editor.getSelection();
						var oldScroll = editor.getScroll();

						editor.setText(newText);
						editor.setSelection(oldSelection.start, oldSelection.end);
						editor.setScroll(oldScroll);
					}
				});
			});
		},

		/**
		 * Associate a handler function with a given actionID for all existing and future
		 * scripted editors. Any prior handlers assigned to the id are overwritten.
		 *

		 * A readable 'name' option can be provided. This name will be used in places
		 * like the help side panel instead of the actionID.
		 *

		 * A 'global' flag option can be provided. If set to a true value, then keybindings
		 * triggering this action will also trigger even if an editor does not have focus.
		 * Globally triggered actions will be redirected to the last editor that had
		 * focus.
		 *
		 * @param {String} actionID
		 * @param {{handler:function(Editor),name:?String,global:?Boolean}} spec
		 */
		setAction: function (actionID, spec) {
			actions.setAction(actionID, spec);
		},

		/**
		 * Load the supplied css data.
		 *
		 * @param {String} css
		 */
		loadCss: function(css) {
			var textnode = document.createTextNode(css);
			var cssref = document.createElement("style");
			cssref.setAttribute("rel","stylesheet");
			cssref.setAttribute("type","text/css");
			cssref.appendChild(textnode);
			document.getElementsByTagName("head")[0].appendChild(cssref);
		},

		/**
		 * Register a new annotation type. The name should use a dotted form, e.g. example.foo
		 * and the 'foo' will be used as a class for associated styling.
		 * The optional lineStyling determines if occurrences of this annotation will
		 * style the entire line or just a range on a line.
		 *
		 * @param {String} annotationTypeName
		 * @param {Boolean} [lineStyling] true if this annotation styles the line
		 */
		registerAnnotationType: function(annotationTypeName, lineStyling) {
			annotationManager.registerAnnotationType(annotationTypeName,lineStyling);
		},

		// TODO this API feels a little odd, maybe it would be better if it took two lists of annotations
		// but that means the caller will have to mess around locating them.
		/**
		 * Remove existing annotations of the specified types and add the new supplied annotations.
		 *
		 * @param [String] existingTypes array of names of existing annotation types to be removed
		 * @param [{text:String,type:String,start:?Number,end:?Number,line:?Number}] newAnnotations the array of new annotations to add
		 */
		replaceAnnotations: function(existingTypes, newAnnotations) {
			var editor = editorUtils.getCurrentEditor();
			annotationManager.ensureEditorConfiguredWithAnnotations(editor);
			var annotationModel = editor.getAnnotationModel();
			var textModel = annotationModel.getTextModel();
			var toRemove = [];
			if (existingTypes) {
				var existingIter = annotationModel.getAnnotations(0,textModel.getCharCount());
				while (existingIter.hasNext()) {
					var existingAnno = existingIter.next();
					for (var e=0; e<existingTypes.length; e++) {
						if (existingAnno.type===existingTypes[e]) {
							toRemove.push(existingAnno);
							break;
						}
					}
				}
			}
			var orionAnnotations = [];
			for (var a =0;a<newAnnotations.length;a++) {
				var annotation = newAnnotations[a];
				var start,end;
				if (annotation.start) {
					start = annotation.start;
					if (annotation.end) {
						end = annotation.end;
					} else {
						end = start+1;
					}
				} else {
					start = textModel.getLineStart(annotation.line-1);
					end = start+1;
				}
				orionAnnotations.push(annotationModule.AnnotationType.createAnnotation(annotation.type,start,end,annotation.text));
			}
			annotationModel.replaceAnnotations(toRemove,orionAnnotations);
		}

	};

});
<|endoftext|>


<commit_before>(function() {
  'use strict';

  angular.module('app.config')
    .config(navigation);

  /** @ngInject */
  function navigation(NavigationProvider) {
    NavigationProvider.configure({
      items: {
        primary: [
          {
            title: 'Dashboard',
            'state': 'dashboard',
            icon: 'fa fa-dashboard'
          },
          {
            title: 'My Services',
            state: 'services',
            icon: 'fa fa-file-o',
            count: 12
          },
          {
            title: 'My Requests',
            state: 'order-history',
            icon: 'fa fa-file-text-o',
            count: 2
          },
          {
            title: 'Service Catalog',
            state: 'marketplace',
            icon: 'fa fa-copy'
          }
        ],
        secondary: [
          {
            title: 'Help',
            icon: 'fa fa-question-circle',
            state: 'help'
          },
          {
            title: 'About Me',
            icon: 'fa fa-user',
            state: 'about-me'
          },
          {
            title: 'Search',
            icon: 'fa fa-search',
            state: 'search'
          }
        ]
      }
    });
  }
})();
<commit_msg>Remove some single quotes from a key<commit_after>(function() {
  'use strict';

  angular.module('app.config')
    .config(navigation);

  /** @ngInject */
  function navigation(NavigationProvider) {
    NavigationProvider.configure({
      items: {
        primary: [
          {
            title: 'Dashboard',
            state: 'dashboard',
            icon: 'fa fa-dashboard'
          },
          {
            title: 'My Services',
            state: 'services',
            icon: 'fa fa-file-o',
            count: 12
          },
          {
            title: 'My Requests',
            state: 'order-history',
            icon: 'fa fa-file-text-o',
            count: 2
          },
          {
            title: 'Service Catalog',
            state: 'marketplace',
            icon: 'fa fa-copy'
          }
        ],
        secondary: [
          {
            title: 'Help',
            icon: 'fa fa-question-circle',
            state: 'help'
          },
          {
            title: 'About Me',
            icon: 'fa fa-user',
            state: 'about-me'
          },
          {
            title: 'Search',
            icon: 'fa fa-search',
            state: 'search'
          }
        ]
      }
    });
  }
})();
<|endoftext|>