<commit_before>/**
 * Created by Cory on 3/28/2016.
 */
'use strict';

// cache versioning
const VERSION = 'v1.0.14::';
// Static Cache Name -> for static assets
const STATIC_CACHE_NAME = VERSION + 'static';
// URLS/Pages Cache
const PAGE_CACHE_NAME = VERSION + 'page';
// Cache For Images
const IMG_CACHE_NAME = VERSION + 'img';

// set a maximum number of pages and images we will allow in our service worker cache
const MAXPAGES  = 30;
const MAXIMG    = 30;

// our URL Cache
const URLCACHE = [
  '/',
  '/blog'
];

// our static cache
const STATIC_CACHE = [
  'theme/CoryDowdy/css/app.04-18-2016.min.css',
  'theme/CoryDowdy/css/icons/icons.data.svg.01182016.css',
  'theme/CoryDowdy/js/navigation-04-17-2016.min.js'
];

// update our static cache on install
function updateStatic() {
  return caches.open(STATIC_CACHE_NAME)
    .then(cache => {
      // using current cookie based critical css approach and storing hte homepage on intial
      // install causes no CSS to be served because there is no CSS for some strange reason on mobile haha
      // so remove this for now
      cache.addAll(URLCACHE);
      return cache.addAll(STATIC_CACHE);
    });
}

// put items into our cache
function putInCache( cacheName, request, response) {
  caches.open(cacheName)
    .then( cache => cache.put(request, response) );
}

// limit the items in a particular cache
function trimCache( cacheName, max ) {
  caches.open(cacheName)
    .then( cache => {
      cache.keys()
        .then(keys => {
          if ( keys.length > max  ){
            cache.delete(keys[0])
              .then(trimCache(cacheName, max));
          }
        });
    });
}

// function to remove old caches that don't match the current cache version
function removeOldCache() {
  return caches.keys()
    .then( keys => {
      return Promise.all(keys
        .filter(key => key.indexOf(VERSION) !== 0 )
        .map(key => caches.delete(key) )
      );
    });
}

// install the service worker
self.addEventListener( 'install', event => {
  event.waitUntil(
    updateStatic()
      .then( () => self.skipWaiting() )
  );
});

// remove old data and caches
self.addEventListener('activate', event => {
  // use removeOldCache function
  event.waitUntil(
    removeOldCache()
      .then( () => self.clients.claim() )
  );
});

// receive a message from the global js ( navigation js in this instance )
// once that message is received we can trim the caches to the maximum amount allowed.
// this also keeps async loaded types from blowing past the cache maximum number allowed like imgs
self.addEventListener('message', event => {
  if (event.data.command === 'trimCaches') {
    removeOldCache(PAGE_CACHE_NAME, MAXPAGES);
    removeOldCache(IMG_CACHE_NAME, MAXIMG);
  }
});

self.addEventListener('fetch', event => {
  let request = event.request;
  let url = new URL(request.url);

  // Only deal with requests to my own server
  if (url.origin !== location.origin) {
    return;
  }

  // Ignore requests to some directories
  if (request.url.indexOf('/bolt') !== -1 || request.url.indexOf('/info') !== -1 || request.url.indexOf('/preview') !== -1) {
    return;
  }

  // For non-GET requests, try the network first, fall back to the offline page
  if (request.method !== 'GET') {
    event.respondWith(
      fetch(request)
        .catch( () => caches.match('/offline') )
    );
    return;
  }

  // if the request is for html look cache first fall back to the network
  if (request.headers.get('Accept').indexOf('text/html') !== -1) {
    //  Chrome bug: https://code.google.com/p/chromium/issues/detail?id=573937
    if (request.mode !== 'navigate') {
      request = new Request(url, {
        method: 'GET',
        headers: request.headers,
        mode: request.mode,
        credentials: request.credentials,
        redirect: request.redirect
      });
    }
    event.respondWith(
      caches.match(request)
        .then(response => {
          // cache bad thaaaang
          return response || fetch(request)
              .then( response => {
                  let copy = response.clone();
                  putInCache(PAGE_CACHE_NAME, request, copy);
                return response;
              })
              .catch( () => {
                // return cache match or fallback
                return caches.match(request)
                  .then( response => response || caches.match('/offline') );
              });
        })
    );
    return;
  }

  //  look in the cache first, fall back to the network
  event.respondWith(
    caches.match(request)
      .then(response => {
        // CACHE
        return response || fetch(request)
            .then( response => {
              // NETWORK
              // If the request is for an image, stash a copy of this image in the images cache
              if (request.headers.get('Accept').indexOf('image') !== -1) {
                let copy = response.clone();
                putInCache(IMG_CACHE_NAME, request, copy);
              }
              return response;
            })
            .catch( () => {
              // OFFLINE
              // borrowed from Jeremy Keith (@adactio)
              // https://adactio.com/journal/9844
              if (request.headers.get('Accept').indexOf('image') !== -1) {
                return new Response('<svg role="img" aria-labelledby="offline-title" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title id="offline-title">Offline</title><g fill="none" fill-rule="evenodd"><path fill="#D8D8D8" d="M0 0h400v300H0z"/><text fill="#9B9B9B" font-family="Helvetica Neue,Arial,Helvetica,sans-serif" font-size="72" font-weight="bold"><tspan x="93" y="172">offline</tspan></text></g></svg>', {headers: {'Content-Type': 'image/svg+xml'}});
              }
              if(request.headers.get('Accept').indexOf('text/html') !==1 ) {
                return caches.match(request)
                  .then( response => response || caches.match('/offline') );
              }
            });
      })
  );
});
<commit_msg>updated cache version to reflect new main css<commit_after>/**
 * Created by Cory on 3/28/2016.
 */
'use strict';

// cache versioning
const VERSION = 'v1.0.15.5::';
// Static Cache Name -> for static assets
const STATIC_CACHE_NAME = VERSION + 'static';
// URLS/Pages Cache
const PAGE_CACHE_NAME = VERSION + 'page';
// Cache For Images
const IMG_CACHE_NAME = VERSION + 'img';

// set a maximum number of pages and images we will allow in our service worker cache
const MAXPAGES  = 30;
const MAXIMG    = 30;

// our URL Cache
const URLCACHE = [
  '/',
  '/blog'
];

// our static cache
const STATIC_CACHE = [
  'theme/CoryDowdy/css/app.08-01-2016.min.css',
  'theme/CoryDowdy/css/icons/icons.data.svg.01182016.css',
  'theme/CoryDowdy/js/navigation-04-17-2016.min.js'
];

// update our static cache on install
function updateStatic() {
  return caches.open(STATIC_CACHE_NAME)
    .then(cache => {
      // using current cookie based critical css approach and storing hte homepage on intial
      // install causes no CSS to be served because there is no CSS for some strange reason on mobile haha
      // so remove this for now
      cache.addAll(URLCACHE);
      return cache.addAll(STATIC_CACHE);
    });
}

// put items into our cache
function putInCache( cacheName, request, response) {
  caches.open(cacheName)
    .then( cache => cache.put(request, response) );
}

// limit the items in a particular cache
function trimCache( cacheName, max ) {
  caches.open(cacheName)
    .then( cache => {
      cache.keys()
        .then(keys => {
          if ( keys.length > max  ){
            cache.delete(keys[0])
              .then(trimCache(cacheName, max));
          }
        });
    });
}

// function to remove old caches that don't match the current cache version
function removeOldCache() {
  return caches.keys()
    .then( keys => {
      return Promise.all(keys
        .filter(key => key.indexOf(VERSION) !== 0 )
        .map(key => caches.delete(key) )
      );
    });
}

// install the service worker
self.addEventListener( 'install', event => {
  event.waitUntil(
    updateStatic()
      .then( () => self.skipWaiting() )
  );
});

// remove old data and caches
self.addEventListener('activate', event => {
  // use removeOldCache function
  event.waitUntil(
    removeOldCache()
      .then( () => self.clients.claim() )
  );
});

// receive a message from the global js ( navigation js in this instance )
// once that message is received we can trim the caches to the maximum amount allowed.
// this also keeps async loaded types from blowing past the cache maximum number allowed like imgs
self.addEventListener('message', event => {
  if (event.data.command === 'trimCaches') {
    removeOldCache(PAGE_CACHE_NAME, MAXPAGES);
    removeOldCache(IMG_CACHE_NAME, MAXIMG);
  }
});

self.addEventListener('fetch', event => {
  let request = event.request;
  let url = new URL(request.url);

  // Only deal with requests to my own server
  if (url.origin !== location.origin) {
    return;
  }

  // Ignore requests to some directories
  if (request.url.indexOf('/bolt') !== -1 || request.url.indexOf('/info') !== -1 || request.url.indexOf('/preview') !== -1) {
    return;
  }

  // For non-GET requests, try the network first, fall back to the offline page
  if (request.method !== 'GET') {
    event.respondWith(
      fetch(request)
        .catch( () => caches.match('/offline') )
    );
    return;
  }

  // if the request is for html look cache first fall back to the network
  if (request.headers.get('Accept').indexOf('text/html') !== -1) {
    //  Chrome bug: https://code.google.com/p/chromium/issues/detail?id=573937
    if (request.mode !== 'navigate') {
      request = new Request(url, {
        method: 'GET',
        headers: request.headers,
        mode: request.mode,
        credentials: request.credentials,
        redirect: request.redirect
      });
    }
    event.respondWith(
      caches.match(request)
        .then(response => {
          // cache bad thaaaang
          return response || fetch(request)
              .then( response => {
                  let copy = response.clone();
                  putInCache(PAGE_CACHE_NAME, request, copy);
                return response;
              })
              .catch( () => {
                // return cache match or fallback
                return caches.match(request)
                  .then( response => response || caches.match('/offline') );
              });
        })
    );
    return;
  }

  //  look in the cache first, fall back to the network
  event.respondWith(
    caches.match(request)
      .then(response => {
        // CACHE
        return response || fetch(request)
            .then( response => {
              // NETWORK
              // If the request is for an image, stash a copy of this image in the images cache
              if (request.headers.get('Accept').indexOf('image') !== -1) {
                let copy = response.clone();
                putInCache(IMG_CACHE_NAME, request, copy);
              }
              return response;
            })
            .catch( () => {
              // OFFLINE
              // borrowed from Jeremy Keith (@adactio)
              // https://adactio.com/journal/9844
              if (request.headers.get('Accept').indexOf('image') !== -1) {
                return new Response('<svg role="img" aria-labelledby="offline-title" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title id="offline-title">Offline</title><g fill="none" fill-rule="evenodd"><path fill="#D8D8D8" d="M0 0h400v300H0z"/><text fill="#9B9B9B" font-family="Helvetica Neue,Arial,Helvetica,sans-serif" font-size="72" font-weight="bold"><tspan x="93" y="172">offline</tspan></text></g></svg>', {headers: {'Content-Type': 'image/svg+xml'}});
              }
              if(request.headers.get('Accept').indexOf('text/html') !==1 ) {
                return caches.match(request)
                  .then( response => response || caches.match('/offline') );
              }
            });
      })
  );
});
<|endoftext|>


<commit_before>// Copyright 2002-2013, University of Colorado Boulder

var assert = require( 'assert' );
var child_process = require( 'child_process' );

/**
 * Check out the shas for a project as specified in a dependencies.json file in its top level.
 *
 * TODO: should the parent project (the sim itself) also be checked out, ignored, or moved into its specified branch?  Right now it is ignored (i.e. left as it was when the task was started)
 * @param grunt
 * @param name of the project (repository)
 * @param toMaster whether master shouldocd be used, or dependencies.json shas should be used
 */
module.exports = function( grunt, projectName, toMaster ) {
  'use strict';

  var dependencies = grunt.file.readJSON( 'dependencies.json' );
  var done = grunt.task.current.async();
  var numToCheckOut = 0;
  var numCheckedOut = 0;
  for ( var property in dependencies ) {
    if ( property !== 'comment' && property !== projectName ) {
      numToCheckOut++;
    }
  }

  for ( property in dependencies ) {
    if ( property !== 'comment' && property !== projectName && dependencies.hasOwnProperty( property ) ) {

      (function( property ) {

        assert( typeof( dependencies[ property ].branch !== 'undefined' ) && typeof( dependencies[ property ].sha !== 'undefined' ) );

        console.log( "Checking out dependency " + property + ': ' + dependencies[ property ].branch + '@' + dependencies[ property ].sha );

        //To execute something from a different directory:
        //cp.exec('foocommand', { cwd: 'path/to/dir/' }, callback);
        //http://stackoverflow.com/questions/14026967/calling-child-process-exec-in-node-as-though-it-was-executed-in-a-specific-folde
        var command = 'git checkout ' + ( toMaster ? 'master' : dependencies[ property ].sha );
        child_process.exec( command, { cwd: '../' + property }, function( error1, stdout1, stderr1 ) {
          assert( !error1, "error in " + command );
          console.log( 'Finished checkout.' );
          console.log( stdout1 );
          console.log( stderr1 );
          numCheckedOut = numCheckedOut + 1;
          if ( numToCheckOut === numCheckedOut ) {
            done();
          }
        } );
      })( property );
    }
  }
};<commit_msg>Fixed a doc typo, see #77<commit_after>// Copyright 2002-2013, University of Colorado Boulder

var assert = require( 'assert' );
var child_process = require( 'child_process' );

/**
 * Check out the shas for a project as specified in a dependencies.json file in its top level.
 *
 * TODO: should the parent project (the sim itself) also be checked out, ignored, or moved into its specified branch?  Right now it is ignored (i.e. left as it was when the task was started)
 * @param grunt
 * @param name of the project (repository)
 * @param toMaster whether master should be used, or dependencies.json shas should be used
 */
module.exports = function( grunt, projectName, toMaster ) {
  'use strict';

  var dependencies = grunt.file.readJSON( 'dependencies.json' );
  var done = grunt.task.current.async();
  var numToCheckOut = 0;
  var numCheckedOut = 0;
  for ( var property in dependencies ) {
    if ( property !== 'comment' && property !== projectName ) {
      numToCheckOut++;
    }
  }

  for ( property in dependencies ) {
    if ( property !== 'comment' && property !== projectName && dependencies.hasOwnProperty( property ) ) {

      (function( property ) {

        assert( typeof( dependencies[ property ].branch !== 'undefined' ) && typeof( dependencies[ property ].sha !== 'undefined' ) );

        console.log( "Checking out dependency " + property + ': ' + dependencies[ property ].branch + '@' + dependencies[ property ].sha );

        //To execute something from a different directory:
        //cp.exec('foocommand', { cwd: 'path/to/dir/' }, callback);
        //http://stackoverflow.com/questions/14026967/calling-child-process-exec-in-node-as-though-it-was-executed-in-a-specific-folde
        var command = 'git checkout ' + ( toMaster ? 'master' : dependencies[ property ].sha );
        child_process.exec( command, { cwd: '../' + property }, function( error1, stdout1, stderr1 ) {
          assert( !error1, "error in " + command );
          console.log( 'Finished checkout.' );
          console.log( stdout1 );
          console.log( stderr1 );
          numCheckedOut = numCheckedOut + 1;
          if ( numToCheckOut === numCheckedOut ) {
            done();
          }
        } );
      })( property );
    }
  }
};<|endoftext|>


<commit_before>module.exports = {
	dev: {
		cwd: ['<%= path.tmpdev %>'],
		src: ['**/*.{js,json,html}','!**/*.min.js'],
	},
	dist: {
	}
}<commit_msg>src bugfix<commit_after>module.exports = {
	dev: {
		src: ['<%= path.tmpdev %>**/*.{js,json,html}','!**/*.min.js'],
	},
	dist: {
		src: ['<%= path.tmpdist %>**/*.{js,json,html}','!**/*.min.js'],
	}
}<|endoftext|>


<commit_before>/* Magic Mirror
 * Module: MMM-EFA-departures
 *
 * By gefangenimnetz, Dom1n1c / https://github.com/Dom1n1c/MMM-EFA-departures
 * MIT Licensed.
 *
 * v0.0.1
 */

Module.register("MMM-EFA-departures", {

    defaults: {
		efaUrl: "http://efa.vrr.de/standard/XSLT_DM_REQUEST",
		stopID: "20018235",						//stopID offered by the provider
		stopName: "MMM-EFA is loading",			//initial module name
		lines: ['all'], 						//lines: ['RBG:72782: :H','RBG:72782: :R'] would only show the line 782, operated by "Rheinbahn" in Düsseldorf (both directions)
		reload: 60000,							//interval in ms (60000=60s)
		realDepTime: true,						//use real-time data
		toggleDepTime: false,					//Toggle relative/absolute time
		toggleDepTimePerReload: 6,				//Every 10 seconds
		fade: true,								//fade brightness
		fadePoint: 0.25,						//Start on 1/4th of the list. (1/maxDepartures would be ideal)
		maxDepartures: 4						//maximum amount of departures displayed
    },

    start: function () {
        var self = this;
        Log.info("Starting module: " + this.name);
        this.sendSocketNotification("CONFIG", this.config);
        setInterval(function () {
            self.sendSocketNotification("CONFIG", self.config);
        }, this.config.reload);

        moment.updateLocale('de', {
            relativeTime: {
                future: 'in %s',
                past: 'vor %s',
                s: 'ein paar Sek.',
                m: '1 Min.',
                mm: '%d Min.',
                h: '1 Std.',
                hh: '%d Std.',
                d: '1 Tag',
                dd: '%d Tagen',
                M: '1 Mon.',
                MM: '%s Mon.',
                y: '1 Jahr',
                yy: '%s Jahren'
            }
        });
    },

    getStyles: function () {
        return ["MMM-EFA-departures.css"];
    },

    getScripts: function () {
        return ["moment.js", "classie.js"];
    },

    socketNotificationReceived: function (notification, payload) {
        if (notification === "TRAMS" + this.config.stopID) {
            this.efa_data = payload;
            this.config.stopName = payload.departureList[0].stopName;
            this.updateDom();
        }
    },

    getDom: function () {
        var wrapper = document.createElement("div");
        var header = document.createElement("header");
        header.innerHTML = this.config.stopName;
        wrapper.appendChild(header);

        if (!this.efa_data) {
            var text = document.createElement("div");
            //text.innerHTML = this.translate("LOADING");
            text.innerHTML = "LOADING";
            wrapper.appendChild(text);
        } else {
            var departuresTable = document.createElement("table");
            departuresTable.classList.add("small", "table");
            departuresTable.border = '0';

            var departures = this.efa_data.departureList;

            if (this.config.toggleDepTime) {
                window.clearInterval(this.toggleTimeInt);
                this.toggleTimeInt = window.setInterval(function () {
                    classie.toggle(departuresTable, 'departures__departure--show-time');
                }, (this.config.reload / this.config.toggleDepTimePerReload));
            }

            for (var d in departures) {

                var departureRow = this.createDataRow(departures[d]);

                if (this.config.fade && this.config.fadePoint < 1) {
                    if (this.config.fadePoint < 0) {
                        this.config.fadePoint = 0;
                    }
                    var startingPoint = departures.length * this.config.fadePoint;
                    var steps = departures.length - startingPoint;
                    if (d >= startingPoint) {
                        var currentStep = d - startingPoint;
                        departureRow.style.opacity = 1 - (1 / steps * currentStep);
                    }
                }

                departuresTable.appendChild(departureRow);

            }
            wrapper.appendChild(departuresTable);
        }
        return wrapper;
    },

    createDataRow: function (data) {

        var row = document.createElement("tr");

        var line = document.createElement("td");
        line.className = "departures__departure__line";
        line.innerHTML = '' + data.servingLine.number + '';
        row.appendChild(line);

        var destination = document.createElement("td");
        destination.innerHTML = '' + data.servingLine.direction +'';
        row.appendChild(destination);

        var departureTime = new Date;
		if (this.config.realDepTime) {
		departureTime = new Date(data.realDateTime.year, data.realDateTime.month - 1, data.realDateTime.day, data.realDateTime.hour, data.realDateTime.minute, 0);
		} else {
		departureTime = new Date(data.dateTime.year, data.dateTime.month - 1, data.dateTime.day, data.dateTime.hour, data.dateTime.minute, 0);
		}
        var departure = document.createElement("td");
        departure.className = "departures__departure";
        departure.innerHTML = '' + moment(departureTime).format('HH:mm') + '' + moment(departureTime).fromNow() + '';

        row.appendChild(departure);

        return row;
    }
});
<commit_msg>fix typos<commit_after>/* Magic Mirror
 * Module: MMM-EFA-departures
 *
 * By gefangenimnetz, Dom1n1c / https://github.com/Dom1n1c/MMM-EFA-departures
 * MIT Licensed.
 *
 * v0.0.1
 */

Module.register("MMM-EFA-departures", {

    defaults: {
        efaUrl: "http://efa.vrr.de/standard/XSLT_DM_REQUEST",
        stopID: "20018235",                     //stopID offered by the provider
        stopName: "MMM-EFA is loading",         //initial module name
        lines: ['all'],                         //lines: ['RBG:72782: :H','RBG:72782: :R'] would only show the line 782, operated by "Rheinbahn" in Düsseldorf (both directions)
        reload: 60000,                          //interval in ms (60000=60s)
        realDepTime: true,                      //use real-time data
        toggleDepTime: false,                   //Toggle relative/absolute time
        toggleDepTimePerReload: 6,              //Every 10 seconds
        fade: true,                             //fade brightness
        fadePoint: 0.25,                        //Start on 1/4th of the list. (1/maxDepartures would be ideal)
        maxDepartures: 4                        //maximum amount of departures displayed
    },

    start: function () {
        var self = this;
        Log.info("Starting module: " + this.name);
        this.sendSocketNotification("CONFIG", this.config);
        setInterval(function () {
            self.sendSocketNotification("CONFIG", self.config);
        }, this.config.reload);

        moment.updateLocale('de', {
            relativeTime: {
                future: 'in %s',
                past: 'vor %s',
                s: 'ein paar Sek.',
                m: '1 Min.',
                mm: '%d Min.',
                h: '1 Std.',
                hh: '%d Std.',
                d: '1 Tag',
                dd: '%d Tagen',
                M: '1 Mon.',
                MM: '%s Mon.',
                y: '1 Jahr',
                yy: '%s Jahren'
            }
        });
    },

    getStyles: function () {
        return ["MMM-EFA-departures.css"];
    },

    getScripts: function () {
        return ["moment.js", "classie.js"];
    },

    socketNotificationReceived: function (notification, payload) {
        if (notification === "TRAMS" + this.config.stopID) {
            this.efa_data = payload;
            this.config.stopName = payload.departureList[0].stopName;
            this.updateDom();
        }
    },

    getDom: function () {
        var wrapper = document.createElement("div");
        var header = document.createElement("header");
        header.innerHTML = this.config.stopName;
        wrapper.appendChild(header);

        if (!this.efa_data) {
            var text = document.createElement("div");
            //text.innerHTML = this.translate("LOADING");
            text.innerHTML = "LOADING";
            wrapper.appendChild(text);
        } else {
            var departuresTable = document.createElement("table");
            departuresTable.classList.add("small", "table");
            departuresTable.border = '0';

            var departures = this.efa_data.departureList;

            if (this.config.toggleDepTime) {
                window.clearInterval(this.toggleTimeInt);
                this.toggleTimeInt = window.setInterval(function () {
                    classie.toggle(departuresTable, 'departures__departure--show-time');
                }, (this.config.reload / this.config.toggleDepTimePerReload));
            }

            for (var d in departures) {

                var departureRow = this.createDataRow(departures[d]);

                if (this.config.fade && this.config.fadePoint < 1) {
                    if (this.config.fadePoint < 0) {
                        this.config.fadePoint = 0;
                    }
                    var startingPoint = departures.length * this.config.fadePoint;
                    var steps = departures.length - startingPoint;
                    if (d >= startingPoint) {
                        var currentStep = d - startingPoint;
                        departureRow.style.opacity = 1 - (1 / steps * currentStep);
                    }
                }

                departuresTable.appendChild(departureRow);

            }
            wrapper.appendChild(departuresTable);
        }
        return wrapper;
    },

    createDataRow: function (data) {

        var row = document.createElement("tr");

        var line = document.createElement("td");
        line.className = "departures__departure__line";
        line.innerHTML = '' + data.servingLine.number + '';
        row.appendChild(line);

        var destination = document.createElement("td");
        destination.innerHTML = '' + data.servingLine.direction +'';
        row.appendChild(destination);

        var departureTime = new Date;
        if (this.config.realDepTime) {
        departureTime = new Date(data.realDateTime.year, data.realDateTime.month - 1, data.realDateTime.day, data.realDateTime.hour, data.realDateTime.minute, 0);
        } else {
        departureTime = new Date(data.dateTime.year, data.dateTime.month - 1, data.dateTime.day, data.dateTime.hour, data.dateTime.minute, 0);
        }
        var departure = document.createElement("td");
        departure.className = "departures__departure";
        departure.innerHTML = '' + moment(departureTime).fromNow() + '' + moment(departureTime).format('HH:mm') + '';
        row.appendChild(departure);

        return row;
    }
});
<|endoftext|>


<commit_before>CodeMirror.defineMode("commonlisp", function (config) {
  var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/;
  var numLiteral = /^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/;
  var symbol = /[^\s'`,@()\[\]";]/;
  var type;

  function readSym(stream) {
    while (ch = stream.next()) {
      if (ch == "\\") stream.next();
      else if (!symbol.test(ch)) { stream.backUp(1); break; }
    }
    return stream.current();
  }

  function base(stream, state) {
    if (stream.eatSpace()) {type = "ws"; return null;}
    if (stream.match(numLiteral)) return "number";
    var ch = stream.next();
    if (ch == "\\") ch = stream.next();

    if (ch == '"') return (state.tokenize = inString)(stream, state);
    else if (ch == "(") { type = "open"; return "bracket"; }
    else if (ch == ")" || ch == "]") { type = "close"; return "bracket"; }
    else if (ch == ";") { stream.skipToEnd(); type = "ws"; return "comment"; }
    else if (/['`,@]/.test(ch)) return null;
    else if (ch == "|") {
      if (stream.skipTo("|")) { stream.next(); return "symbol"; }
      else { stream.skipToEnd(); return "error"; }
    } else if (ch == "#") {
      if (stream.eat("[")) { type = "open"; return "bracket"; }
      else if (stream.eat(/[+\-=\.]/)) return null;
      else if (stream.match(/^\d+#/)) return null;
      else if (stream.eat("|")) return (state.tokenize = inComment)(stream, state);
      else if (stream.eat(":")) { readSym(stream); return "meta"; }
      else { stream.next(); return "error"; }
    } else {
      var name = readSym(stream);
      if (name == ".") return null;
      type = "symbol";
      if (name == "nil" || name == "t") return "atom";
      if (name.charAt(0) == ":") return "keyword";
      return "variable";
    }
  }

  function inString(stream, state) {
    var escaped = false, next;
    while (next = stream.next()) {
      if (next == '"' && !escaped) { state.tokenize = base; break; }
      escaped = !escaped && next == "\\";
    }
    return "string";
  }

  function inComment(stream, state) {
    var next, last;
    while (next = stream.next()) {
      if (next == "#" && last == "|") { state.tokenize = base; break; }
      last = next;
    }
    type = "ws";
    return "comment";
  }

  return {
    startState: function () {
      return {ctx: {prev: null, start: 0, indentTo: 0}, tokenize: base};
    },

    token: function (stream, state) {
      if (stream.sol() && typeof state.ctx.indentTo != "number")
        state.ctx.indentTo = state.ctx.start + 1;

      type = null;
      var style = state.tokenize(stream, state);
      if (type != "ws") {
        if (state.ctx.indentTo == null) {
          if (type == "symbol" && assumeBody.test(stream.current()))
            state.ctx.indentTo = state.ctx.start + config.indentUnit;
          else
            state.ctx.indentTo = "next";
        } else if (state.ctx.indentTo == "next") {
          state.ctx.indentTo = stream.column();
        }
      }
      if (type == "open") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};
      else if (type == "close") state.ctx = state.ctx.prev;
      return style;
    },

    indent: function (state, textAfter) {
      var i = state.ctx.indentTo;
      return typeof i == "number" ? i : state.ctx.start + 1;
    }
  };
});

CodeMirror.defineMIME("text/x-common-lisp", "commonlisp");
<commit_msg>[commonlisp mode] Fix accidental global<commit_after>CodeMirror.defineMode("commonlisp", function (config) {
  var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/;
  var numLiteral = /^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/;
  var symbol = /[^\s'`,@()\[\]";]/;
  var type;

  function readSym(stream) {
    var ch;
    while (ch = stream.next()) {
      if (ch == "\\") stream.next();
      else if (!symbol.test(ch)) { stream.backUp(1); break; }
    }
    return stream.current();
  }

  function base(stream, state) {
    if (stream.eatSpace()) {type = "ws"; return null;}
    if (stream.match(numLiteral)) return "number";
    var ch = stream.next();
    if (ch == "\\") ch = stream.next();

    if (ch == '"') return (state.tokenize = inString)(stream, state);
    else if (ch == "(") { type = "open"; return "bracket"; }
    else if (ch == ")" || ch == "]") { type = "close"; return "bracket"; }
    else if (ch == ";") { stream.skipToEnd(); type = "ws"; return "comment"; }
    else if (/['`,@]/.test(ch)) return null;
    else if (ch == "|") {
      if (stream.skipTo("|")) { stream.next(); return "symbol"; }
      else { stream.skipToEnd(); return "error"; }
    } else if (ch == "#") {
      if (stream.eat("[")) { type = "open"; return "bracket"; }
      else if (stream.eat(/[+\-=\.]/)) return null;
      else if (stream.match(/^\d+#/)) return null;
      else if (stream.eat("|")) return (state.tokenize = inComment)(stream, state);
      else if (stream.eat(":")) { readSym(stream); return "meta"; }
      else { stream.next(); return "error"; }
    } else {
      var name = readSym(stream);
      if (name == ".") return null;
      type = "symbol";
      if (name == "nil" || name == "t") return "atom";
      if (name.charAt(0) == ":") return "keyword";
      return "variable";
    }
  }

  function inString(stream, state) {
    var escaped = false, next;
    while (next = stream.next()) {
      if (next == '"' && !escaped) { state.tokenize = base; break; }
      escaped = !escaped && next == "\\";
    }
    return "string";
  }

  function inComment(stream, state) {
    var next, last;
    while (next = stream.next()) {
      if (next == "#" && last == "|") { state.tokenize = base; break; }
      last = next;
    }
    type = "ws";
    return "comment";
  }

  return {
    startState: function () {
      return {ctx: {prev: null, start: 0, indentTo: 0}, tokenize: base};
    },

    token: function (stream, state) {
      if (stream.sol() && typeof state.ctx.indentTo != "number")
        state.ctx.indentTo = state.ctx.start + 1;

      type = null;
      var style = state.tokenize(stream, state);
      if (type != "ws") {
        if (state.ctx.indentTo == null) {
          if (type == "symbol" && assumeBody.test(stream.current()))
            state.ctx.indentTo = state.ctx.start + config.indentUnit;
          else
            state.ctx.indentTo = "next";
        } else if (state.ctx.indentTo == "next") {
          state.ctx.indentTo = stream.column();
        }
      }
      if (type == "open") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};
      else if (type == "close") state.ctx = state.ctx.prev;
      return style;
    },

    indent: function (state, textAfter) {
      var i = state.ctx.indentTo;
      return typeof i == "number" ? i : state.ctx.start + 1;
    }
  };
});

CodeMirror.defineMIME("text/x-common-lisp", "commonlisp");
<|endoftext|>


<commit_before>var testr, require, define;

(function() {

	var origRequire = require,
		origDefine = define,
		origOnScriptLoad = require.onScriptLoad,
		noop = function() {},
		moduleMap = {},
		stubMap = {},
		lastDefArgs;

	// tests
	function isArray(a) {
		return toString.call(a) == '[object Array]';
	}
	function isObject(o) {
		return typeof o === 'object' && !isArray(o);
	}

	// deep copy
	function deepCopy(src) {
		var tgt = isObject(src) ? {} : [];
		for (var prop in src) {
			if (src.hasOwnProperty(prop)) {
				var val = src[prop];
				tgt[prop] = (isArray(val) || isObject(val)) ? deepCopy(val) : val;
			};
		}
		return tgt;
	}

	// listen for require call
	require = function(deps) {
		origRequire(deps, function() {
			// auto-add all specs and stubs
			var specs = [], stubs = [],
				requireSpec = origRequire.config({
					context: 'spec',
					baseUrl: 'spec'
				}),
				requireStub = origRequire.config({
					context: 'stub',
					baseUrl: 'stub'
				});

			for (var path in moduleMap) {
				if (moduleMap.hasOwnProperty(path)) {
					specs.push(path + '.spec');
					stubs.push(path + '.stub');
				};
			}

			// add scrips to page (likely to result in many 404s, can this be fixed?)
			requireSpec(specs, noop);
			requireStub(stubs, noop);
		});
	};

	// listen for define call
	define = function() {
		var deps = (arguments.length > 1 && arguments[0]);
		lastDefArgs = [].slice.call(arguments)
		origDefine(deps, noop);
	};

	// listen for script load events
	origRequire.onScriptLoad = function(e) {
		var node = e.currentTarget,
			moduleName = e.currentTarget.getAttribute('data-requiremodule'),
			moduleContext = e.currentTarget.getAttribute('data-requirecontext'),
			map = (moduleContext === 'stub') ? stubMap : moduleMap;

		// store module definition function and list of dependencies
		map[moduleName] = {
			module: lastDefArgs.pop(),
			deps: lastDefArgs.pop()
		}

		origOnScriptLoad.apply(null, arguments);
	};

	// create modules on the fly with module map
	testr = function(moduleName, stubs, useExternal) {
		var depModules = [],
			moduleDef, module, deps, i,
			args = [].slice.call(arguments);

		// check parameters
		if (typeof moduleName !== 'string') {
			throw Error('module name must be a string');
		}
		if (!useExternal && typeof stubs === 'boolean') {
			useExternal = stubs;
		} else if (stubs && !isObject(stubs)) {
			throw Error('stubs must be given as an object');
		}

		// get module definition from map
		moduleDef = (useExternal && stubMap[moduleName + '.stub']) || moduleMap[moduleName];
		if (!moduleDef) {
			throw Error('module has not been loaded: ' + moduleName);
		}

		// shortcuts
		module = moduleDef.module;
		deps = moduleDef.deps;

		// load up dependencies
		if (deps) {
			for (i = 0; i < deps.length; i += 1) {
				var depName = deps[i],
					stub = stubs && stubs[depName];

				args[0] = depName;
				depModules.push(stub || testr.apply(null, args));
			}
		}

		// return clean instance of module
		return (typeof module === 'function') ? module.apply(null, depModules) : deepCopy(module);
	}

}());

<commit_msg>code clean<commit_after>var testr, require, define;

(function() {

	var origRequire = require,
		origDefine = define,
		origOnScriptLoad = require.onScriptLoad,
		noop = function() {},
		moduleMap = {},
		stubMap = {},
		lastDefArgs;

	// type detection
	function isArray(a) {
		return toString.call(a) == '[object Array]';
	}
	function isObject(o) {
		return typeof o === 'object' && !isArray(o);
	}

	// deep copy
	function deepCopy(src) {
		var tgt = isObject(src) ? {} : [];
		for (var prop in src) {
			if (src.hasOwnProperty(prop)) {
				var val = src[prop];
				tgt[prop] = (isArray(val) || isObject(val)) ? deepCopy(val) : val;
			};
		}
		return tgt;
	}

	// listen for require call
	require = function(deps) {
		origRequire(deps, function() {
			// auto-add all specs and stubs
			var specs = [], stubs = [],
				requireSpec = origRequire.config({
					context: 'spec',
					baseUrl: 'spec'
				}),
				requireStub = origRequire.config({
					context: 'stub',
					baseUrl: 'stub'
				});

			for (var path in moduleMap) {
				if (moduleMap.hasOwnProperty(path)) {
					specs.push(path + '.spec');
					stubs.push(path + '.stub');
				};
			}

			// add scrips to page (likely to result in many 404s, can this be fixed?)
			requireSpec(specs, noop);
			requireStub(stubs, noop);
		});
	};

	// listen for define call
	define = function() {
		var deps = (arguments.length > 1 && arguments[0]);
		lastDefArgs = [].slice.call(arguments)
		origDefine(deps, noop);
	};

	// listen for script load events
	origRequire.onScriptLoad = function(e) {
		var node = e.currentTarget,
			moduleName = e.currentTarget.getAttribute('data-requiremodule'),
			moduleContext = e.currentTarget.getAttribute('data-requirecontext'),
			map = (moduleContext === 'stub') ? stubMap : moduleMap;

		// tell requirejs the script has loaded
		origOnScriptLoad.apply(null, arguments);

		// don't store references to spec files
		if (moduleContext === 'spec') {
			return;
		}

		// clean module name
		moduleName = moduleName.replace(/\.stub$/i, '');

		// store module definition function and list of dependencies
		map[moduleName] = {
			module: lastDefArgs.pop(),
			deps: lastDefArgs.pop()
		}
	};

	// create modules on the fly with module map
	testr = function(moduleName, stubs, useExternal) {
		var depModules = [],
			moduleDef, module, deps, i,
			args = [].slice.call(arguments);

		// check parameters
		if (typeof moduleName !== 'string') {
			throw Error('module name must be a string');
		}
		if (!useExternal && typeof stubs === 'boolean') {
			useExternal = stubs;
		} else if (stubs && !isObject(stubs)) {
			throw Error('stubs must be given as an object');
		}

		// get module definition from map
		moduleDef = (useExternal && stubMap[moduleName]) || moduleMap[moduleName];
		if (!moduleDef) {
			throw Error('module has not been loaded: ' + moduleName);
		}

		// shortcuts
		module = moduleDef.module;
		deps = moduleDef.deps;

		// load up dependencies
		if (deps) {
			for (i = 0; i < deps.length; i += 1) {
				var depName = deps[i],
					stub = stubs && stubs[depName];

				args[0] = depName;
				depModules.push(stub || testr.apply(null, args));
			}
		}

		// return clean instance of module
		return (typeof module === 'function') ? module.apply(null, depModules) : deepCopy(module);
	}

}());

<|endoftext|>


<commit_before>/*global it, describe, expect */
var BEMHelper = require('./index');

function resultWithClassName(className) {
  return {
    className: className
  };
}

describe('react-bem-helper', function() {
  var bemhelper = new BEMHelper('block');

  it('should return className for the block when no arguments given', function() {
    var bemhelperWithoutPrefix = new BEMHelper({
      name: 'block',
      prefix: ''
    });

    expect(bemhelper('')).toEqual(resultWithClassName('block'));
    expect(bemhelper()).toEqual(resultWithClassName('block'));
  });

  it('should return classNames for the block and modifier when modifier given', function() {
    expect(bemhelper('', 'funny')).toEqual(resultWithClassName('block block--funny'));
  });

  it('should return className for the element when element is given', function() {
    expect(bemhelper('element')).toEqual(resultWithClassName('block__element'));
  });

  it('should return classNames for the element and the modifier when a modifier is given', function() {
    expect(bemhelper('element', 'modifier')).toEqual(resultWithClassName('block__element block__element--modifier'));
  });

  describe('when using object as arguments', function() {
    it ('should return className for the block when empty object given', function() {
      expect(bemhelper({})).toEqual(resultWithClassName('block'));
    });

    it('should return className for the element when element is given', function() {
      expect(bemhelper({
        element: 'element'
      })).toEqual(resultWithClassName('block__element'));
    });

    it('should return classNames for the block and modifier when modifier given', function() {
      expect(bemhelper({
        modifier: 'modifier'
      })).toEqual(resultWithClassName('block block--modifier'));
    });

    it('should return classNames for the block and modifier when modifier given as object', function() {
      expect(bemhelper({
        modifiers: { 'modifier': true }
      })).toEqual(resultWithClassName('block block--modifier'));
    });

    it('should return classNames for the element and the modifier when a modifier is given', function() {
      expect(bemhelper({
        element: 'element',
        modifier: 'modifier'
      })).toEqual(resultWithClassName('block__element block__element--modifier'));
    });

    it('should return classNames for the element and the modifier when a modifier is given', function() {
      expect(bemhelper({
        element: 'element',
        modifier: 'modifier'
      })).toEqual(resultWithClassName('block__element block__element--modifier'));
    });
  });

  describe(', when given multiple modifiers', function() {
    it('as an array, should return classNames for the element and each modifier given', function() {
      var modifiers = ['one', 'two three'];
      expect(bemhelper('', modifiers)).toEqual(resultWithClassName('block block--one block--two block--three'));
    });

    it('as an object, should return classNames for the element and each modifier that is truthy', function() {
      var modifiers = {
        'one': false,
        'two': true,
        'three': false,
        'four': function() { return false; },
        'five': function() { return true; },
        'six seven': true
      };

      var result = 'block block--two block--five block--six block--seven';
      expect(bemhelper('', modifiers)).toEqual(resultWithClassName(result));
      expect(bemhelper(null, modifiers)).toEqual(resultWithClassName(result));
      expect(bemhelper({ modifiers: modifiers })).toEqual(resultWithClassName(result));
    });
  });

  it('should append extra classNames when given as an array', function() {
    var extraClasses = ['one', 'two'];
    expect(bemhelper('', null, extraClasses)).toEqual(resultWithClassName('block one two'));

    expect(bemhelper('element', '', extraClasses)).toEqual(resultWithClassName('block__element one two'));
    expect(bemhelper({ extra: extraClasses })).toEqual(resultWithClassName('block one two'));
  });

  it('should append extra classNames for truthy values when given as an object', function() {
    var extraClasses = {
      'one': false,
      'two': true,
      'three': false,
      'four five': true
    };

    expect(bemhelper('', '', extraClasses)).toEqual(resultWithClassName('block two four five'));
    expect(bemhelper({ extra: extraClasses })).toEqual(resultWithClassName('block two four five'));
  });

  it('when given a prefix, should append generated BEM classes with that', function() {
    var prefixedBEM = new BEMHelper({
      name: 'block',
      prefix: 'mh-'
    });

    expect(prefixedBEM('')).toEqual(resultWithClassName('mh-block'));
    expect(prefixedBEM('element')).toEqual(resultWithClassName('mh-block__element'));
    expect(prefixedBEM('', 'modifier')).toEqual(resultWithClassName('mh-block mh-block--modifier'));
    expect(prefixedBEM('', '', 'class')).toEqual(resultWithClassName('mh-block class'));
  });

  it('when modifierDelimiter option is set, should prefix modifier with that', function() {
    var modifierBem = new BEMHelper({
      name: 'block',
      modifierDelimiter: '_'
    });

    expect(modifierBem('', 'modifier')).toEqual(resultWithClassName('block block_modifier'));

    var modifierBem = new BEMHelper({
      name: 'block',
      modifierDelimiter: '🐘'
    });

    expect(modifierBem('', 'modifier')).toEqual(resultWithClassName('block block🐘modifier'));
  });

  it('should return a string instead of an object when outputIsString is set true', function() {
    var stringBem = new BEMHelper({
      name: 'block',
      outputIsString: true
    });

    expect(stringBem('')).toBe('block');
    expect(stringBem('element')).toBe('block__element');
    expect(stringBem('element', 'modifier')).toBe('block__element block__element--modifier');
  });

  describe('when using withDefaults', function() {
    var HelperWithDefaults = BEMHelper.withDefaults({
      prefix: 'pfx-',
      modifierDelimiter: '_',
      outputIsString: true
    });

    it('should apply the defaults', function() {
      var bem1 = new HelperWithDefaults('block')
      var bem2 = new HelperWithDefaults({
        name: 'block'
      });

      expect(bem1('element', 'modifier')).toBe('pfx-block__element pfx-block__element_modifier');
      expect(bem2('element', 'modifier')).toBe('pfx-block__element pfx-block__element_modifier');
    });

    it('should be able to override the defaults', function() {
      var bem = new HelperWithDefaults({
        name: 'block',
        prefix: '',
        modifierDelimiter: '@',
        outputIsString: false
      });

      expect(bem('element', 'modifier')).toEqual(resultWithClassName('block__element block__element@modifier'));
    });
  });
});
<commit_msg>Add test for falsy modifiers<commit_after>/*global it, describe, expect */
var BEMHelper = require('./index');

function resultWithClassName(className) {
  return {
    className: className
  };
}

describe('react-bem-helper', function() {
  var bemhelper = new BEMHelper('block');

  it('should return className for the block when no arguments given', function() {
    var bemhelperWithoutPrefix = new BEMHelper({
      name: 'block',
      prefix: ''
    });

    expect(bemhelper('')).toEqual(resultWithClassName('block'));
    expect(bemhelper()).toEqual(resultWithClassName('block'));
  });

  it('should return classNames for the block and modifier when modifier given', function() {
    expect(bemhelper('', 'funny')).toEqual(resultWithClassName('block block--funny'));
  });

  it('should return className for the element when element is given', function() {
    expect(bemhelper('element')).toEqual(resultWithClassName('block__element'));
  });

  it('should return classNames for the element and the modifier when a modifier is given', function() {
    expect(bemhelper('element', 'modifier')).toEqual(resultWithClassName('block__element block__element--modifier'));
  });

  describe('when using object as arguments', function() {
    it ('should return className for the block when empty object given', function() {
      expect(bemhelper({})).toEqual(resultWithClassName('block'));
    });

    it('should return className for the element when element is given', function() {
      expect(bemhelper({
        element: 'element'
      })).toEqual(resultWithClassName('block__element'));
    });

    it('should return classNames for the block and modifier when modifier given', function() {
      expect(bemhelper({
        modifier: 'modifier'
      })).toEqual(resultWithClassName('block block--modifier'));
    });

    it('should return classNames for the block and modifier when modifier given as object', function() {
      expect(bemhelper({
        modifiers: { 'modifier': true }
      })).toEqual(resultWithClassName('block block--modifier'));
    });

    it('should return classNames for the element and the modifier when a modifier is given', function() {
      expect(bemhelper({
        element: 'element',
        modifier: 'modifier'
      })).toEqual(resultWithClassName('block__element block__element--modifier'));
    });

    it('should return classNames for the element and the modifier when a modifier is given', function() {
      expect(bemhelper({
        element: 'element',
        modifier: 'modifier'
      })).toEqual(resultWithClassName('block__element block__element--modifier'));
    });
  });

  describe(', when given multiple modifiers', function() {
    it('as an array, should return classNames for the element and each modifier given', function() {
      var modifiers = ['one', 'two three'];
      expect(bemhelper('', modifiers)).toEqual(resultWithClassName('block block--one block--two block--three'));
    });

    it('as an array containing falsy values, should ignore them', function() {
      var modifiers = ['one', false, 0, null, '', undefined];
      expect(bemhelper('', modifiers)).toEqual(resultWithClassName('block block--one'));
    })

    it('as an object, should return classNames for the element and each modifier that is truthy', function() {
      var modifiers = {
        'one': false,
        'two': true,
        'three': false,
        'four': function() { return false; },
        'five': function() { return true; },
        'six seven': true
      };

      var result = 'block block--two block--five block--six block--seven';
      expect(bemhelper('', modifiers)).toEqual(resultWithClassName(result));
      expect(bemhelper(null, modifiers)).toEqual(resultWithClassName(result));
      expect(bemhelper({ modifiers: modifiers })).toEqual(resultWithClassName(result));
    });
  });

  it('should append extra classNames when given as an array', function() {
    var extraClasses = ['one', 'two'];
    expect(bemhelper('', null, extraClasses)).toEqual(resultWithClassName('block one two'));

    expect(bemhelper('element', '', extraClasses)).toEqual(resultWithClassName('block__element one two'));
    expect(bemhelper({ extra: extraClasses })).toEqual(resultWithClassName('block one two'));
  });

  it('should append extra classNames for truthy values when given as an object', function() {
    var extraClasses = {
      'one': false,
      'two': true,
      'three': false,
      'four five': true
    };

    expect(bemhelper('', '', extraClasses)).toEqual(resultWithClassName('block two four five'));
    expect(bemhelper({ extra: extraClasses })).toEqual(resultWithClassName('block two four five'));
  });

  it('when given a prefix, should append generated BEM classes with that', function() {
    var prefixedBEM = new BEMHelper({
      name: 'block',
      prefix: 'mh-'
    });

    expect(prefixedBEM('')).toEqual(resultWithClassName('mh-block'));
    expect(prefixedBEM('element')).toEqual(resultWithClassName('mh-block__element'));
    expect(prefixedBEM('', 'modifier')).toEqual(resultWithClassName('mh-block mh-block--modifier'));
    expect(prefixedBEM('', '', 'class')).toEqual(resultWithClassName('mh-block class'));
  });

  it('when modifierDelimiter option is set, should prefix modifier with that', function() {
    var modifierBem = new BEMHelper({
      name: 'block',
      modifierDelimiter: '_'
    });

    expect(modifierBem('', 'modifier')).toEqual(resultWithClassName('block block_modifier'));

    var modifierBem = new BEMHelper({
      name: 'block',
      modifierDelimiter: '🐘'
    });

    expect(modifierBem('', 'modifier')).toEqual(resultWithClassName('block block🐘modifier'));
  });

  it('should return a string instead of an object when outputIsString is set true', function() {
    var stringBem = new BEMHelper({
      name: 'block',
      outputIsString: true
    });

    expect(stringBem('')).toBe('block');
    expect(stringBem('element')).toBe('block__element');
    expect(stringBem('element', 'modifier')).toBe('block__element block__element--modifier');
  });

  describe('when using withDefaults', function() {
    var HelperWithDefaults = BEMHelper.withDefaults({
      prefix: 'pfx-',
      modifierDelimiter: '_',
      outputIsString: true
    });

    it('should apply the defaults', function() {
      var bem1 = new HelperWithDefaults('block')
      var bem2 = new HelperWithDefaults({
        name: 'block'
      });

      expect(bem1('element', 'modifier')).toBe('pfx-block__element pfx-block__element_modifier');
      expect(bem2('element', 'modifier')).toBe('pfx-block__element pfx-block__element_modifier');
    });

    it('should be able to override the defaults', function() {
      var bem = new HelperWithDefaults({
        name: 'block',
        prefix: '',
        modifierDelimiter: '@',
        outputIsString: false
      });

      expect(bem('element', 'modifier')).toEqual(resultWithClassName('block__element block__element@modifier'));
    });
  });
});
<|endoftext|>


<commit_before>// 中文编码 utf8
function ylist(container, generator, $Y) {
    const cache_height = 2000;
    var restHeight = cache_height;
    var list = container || div();
    list.autoFix = true;
    var saved_itemIndex;
    addClass(list, 'list-' + $Y.toLowerCase());
    if (!list.renders) {
        list.renders = [];
    }
    list.renders.push(function () {
        var a = saved_itemIndex;
        saved_itemIndex = void 0;
        if (a !== void 0) scrollTo(a);
    });
    //取底部元素
    var getLastElement = function (nodeType) {
        var children = nodeType === 1 ? list.children : list.childNodes;
        for (var cx = children.length - 1; cx >= 0; cx--) {
            var child = children[cx];
            if (isFinite(child.index) || nodeType === 2 && child.offsetHeight) {
                return child;
            }
        }
        return null;
    };
    //取底部元素
    var getIndexedElement = function (index) {
        var children = list.childNodes;
        for (var cx = children.length - 1; cx >= 0; cx--) {
            var child = children[cx];
            if (isFinite(child.index) && child.index === index) {
                return child;
            }
        }
        return null;
    };

    //取顶部元素
    var getFirstElement = function (nodeType) {
        var children = nodeType === 1 ? list.children : list.childNodes;
        for (var cx = 0, dx = children.length; cx < dx; cx++) {
            var child = children[cx];
            if (isFinite(child.index) || nodeType === 2 && child.offsetHeight) {
                return child;
            }
        }
        return null;
    };
    var getFirstVisibleElement = function (deltaY = 0) {
        var children = list.children;
        var { scrollTop } = list;
        scrollTop += deltaY;
        for (var cx = 0, dx = children.length; cx < dx; cx++) {
            var child = children[cx];
            if (isFinite(child.index) && child.offsetTop + child.offsetHeight >= scrollTop) {
                return child;
            }
        }
        return null;
    };
    var getLastVisibleElement = function (deltaY = 0) {
        var { scrollTop } = list;
        scrollTop += deltaY;
        var children = list.children;
        for (var cx = children.length - 1; cx >= 0; cx--) {
            var child = children[cx];
            if (isFinite(child.index) && child.offsetTop < scrollTop + list.clientHeight) {
                return child;
            }
        }
        return null;
    };
    //元素表
    var getChildrenMap = function () {
        var children = list.children;
        var map = {};
        for (var cx = 0, dx = children.length; cx < dx; cx++) {
            var child = children[cx];
            if (isFinite(child.index)) {
                map[child.index] = child;
            }
        }
        return map;
    };
    //设置当前下标
    var scrollTo = function (itemIndex) {
        if (!list.offsetHeight || !list.offsetWidth) {
            saved_itemIndex = itemIndex;
            return;
        }
        var index = itemIndex | 0;
        var ratio = itemIndex - index || 0;
        if (index < 0) index = 0;
        var childrenMap = getChildrenMap();
        var offsetBottom = 0, ratioTop = 0, offset = +index || 0, last_item = getFirstElement() || null, last_index = last_item && last_item.index || offset;
        var count = 0, delta = 1, bottom_item, offsett = offset, offsetb = offset, top_item;
        while (offsetBottom - ratioTop <= list.clientHeight + cache_height) {
            var item = childrenMap[offset];
            if (!item || item.id) {
                item = generator(offset);
                if (!item) {
                    if (delta < 0) break;
                    delta = -1;
                    offset = index - 1;
                    bottom_item = getIndexedElement(offsetb);
                    last_item = getIndexedElement(index);
                    last_index = index;
                    continue;
                }
                item.index = offset;
                if (last_index > offset) {
                    list.insertBefore(item, last_item);
                } else {
                    list.insertBefore(item, getNextSibling(last_item));
                }
                last_index = offset;
                last_item = item;
            }
            if (delta > 0) {
                offset++;
                offsetb = offset;
                bottom_item = item;
                if (!top_item) top_item = item;
            } else {
                offset--;
                offsett = offset;
                if (!bottom_item) bottom_item = item;
                top_item = item;
            }
            offsetBottom = bottom_item.offsetTop + bottom_item.offsetHeight;
            ratioTop = top_item.offsetTop + top_item.offsetHeight * ratio;
            if (count++ > 600) throw new Error("多于600个元素需要绘制！");
        }
        for (var k in childrenMap) {
            k = +k;
            if (!(k <= offsetb && k >= offsett)) {
                remove(childrenMap[k]);
            }
        }
        var indexed_item = getIndexedElement(index) || bottom_item;
        if (indexed_item) {
            list.scrollTop = indexed_item.offsetTop + indexed_item.offsetHeight * ratio - parseFloat(getComputedStyle(list).paddingTop);
        }
    };
    var runbuild = function () {
        patchBottom();
        patchTop();
        var firstElement = getFirstElement(1), y;
        if (firstElement) {
            y = firstElement.index * firstElement.offsetHeight;
        } else {
            y = 0;
        }

        css(topinsert, {
            height: fromOffset(y)
        });
        return y;
    };
    var rebuild = function () {
        if (!/^(?:auto|scroll)$/i.test(getComputedStyle(list).overflowY)) return;
        var saved_y, inc = 0;
        if (rebuild.ing) cancelAnimationFrame(rebuild.ing);
        var run = function () {
            var y = runbuild();
            if (y !== saved_y) {
                saved_y = y;
                inc = 0;
                return;
            }
            inc += 8;
            if (inc < 1000) {
                rebuild.ing = requestAnimationFrame(run);
            } else {
                rebuild.ing = 0;
            }
        };
        rebuild.ing = requestAnimationFrame(run);
    };
    on("scroll")(list, rebuild);
    var topinsert = document.createElement('ylist-insert');
    list.insertBefore(topinsert, list.firstChild);
    //计算当前高度
    var currentY = function () {
        var firstElement = getFirstElement(1);
        if (!firstElement) return;
        return firstElement.index * firstElement.offsetHeight + list.scrollTop;
    };
    var getBottomElement = function (last_element) {
        if (!last_element) return null;
        var with_elements = last_element.with;
        return with_elements && with_elements.length ? with_elements[with_elements.length - 1] : last_element;
    };
    var getNextSibling = function (last_element) {
        var bottom_element = getBottomElement(last_element);
        return bottom_element ? bottom_element.nextSibling : null;
    };
    var getOffsetHeight = function (element) {
        var temp = element;
        do {
            var next = getNextSibling(temp);
            if (!next) return element.offsetHeight;
            temp = next;
        } while (next.offsetTop === element.offsetTop);
        return next.offsetTop - element.offsetTop;
    };
    var patchBottom = function (deltaY = 0) {
        var childrenMap = getChildrenMap();
        var last_element = getLastElement();
        if (!last_element || !last_element.offsetHeight) return;
        let { scrollTop } = list;
        scrollTop += deltaY;
        var offsetBottom = getOffsetHeight(last_element) + last_element.offsetTop;
        var offset = last_element.index || 0;
        //追加元素到底部
        while (offsetBottom <= scrollTop + list.clientHeight + cache_height) {
            offset++;
            var item = childrenMap[offset];
            if (!item || item.itemid) {
                item = generator(offset);
                if (!item) {
                    restHeight = 0;
                    break;
                } else if (!restHeight) {
                    restHeight = cache_height;
                }
                item.index = offset;
                list.insertBefore(item, getNextSibling(last_element));
            }
            if (!item.offsetHeight) {
                console.warn(item, '!item.offsetHeight');
                break;
            }
            offsetBottom = item.offsetTop + getOffsetHeight(item);
            last_element = item;
        }
        var collection = [];
        for (var k in childrenMap) {
            let item = childrenMap[k];
            if (item.offsetTop + getOffsetHeight(item) + cache_height < scrollTop) {
                collection.push(item);
            } else {
                break;
            }
        }
        if (collection.length) {
            var item = collection[collection.length - 1];
            scrollTop -= item.offsetTop + getOffsetHeight(item) - collection[0].offsetTop;
            var { paddingCount, paddingMax } = list;
            if (paddingCount > 0 && paddingMax > 0 && paddingCount < paddingMax) {
                let item = collection[collection.length - 1];
                while (paddingCount > 0) {
                    if (!item) break;
                    paddingCount--;
                    collection.push(item.nextSibling);
                    item = item.nextSibling;
                }
            }
            remove(collection);
        }
        //滚动到相应的位置
        return scrollTop - list.scrollTop;
    };
    var patchTop = function (deltaY = 0) {
        var childrenMap = getChildrenMap();
        var first_element, flag_element = first_element = getFirstElement(1);
        if (!flag_element || !isFinite(flag_element.offsetTop)) return;
        var offset = flag_element.index || 0;
        var offsetTop = flag_element.offsetTop;
        var { scrollTop } = list;
        scrollTop += deltaY;
        //追加元素到顶部
        var targetHeight = cache_height + first_element.offsetTop;
        var { paddingCount, paddingMax } = list;
        if (!(paddingCount > 0 && paddingMax > 0 && paddingCount < paddingMax) || !(scrollTop < targetHeight)) {
            paddingCount = 0;
        }
        while (scrollTop < targetHeight || paddingCount > 0) {
            offset--;
            if (!(scrollTop < targetHeight)) {
                paddingCount--;
            }
            if (!(offset >= 0)) {
                break;
            }
            var item = childrenMap[offset];
            if (!item || item.itemid) {
                item = generator(offset);
                if (!item) break;
                item.index = offset;
                childrenMap[offset] = item;
                list.insertBefore(item, first_element);
                scrollTop += flag_element.offsetTop - offsetTop;
                offsetTop = flag_element.offsetTop;
                first_element = item;
            }
        }
        //滚动到相应位置
        if (scrollTop < 0) scrollTop = 0;
        //-list_scrollTop + lElem_offsetTop = -list_newScrollTop + lElem_newoffsetTop + deltaY
        var last_element = getLastElement(1);
        var { clientHeight } = list;
        while (last_element && last_element.offsetTop > clientHeight + scrollTop + cache_height) {
            remove(last_element);
            last_element = getLastElement(1);
        }
        return scrollTop - list.scrollTop;
    };
    //滚动一定的距离
    var scrollBy = function (deltaY) {
        var deltaScroll;
        if (deltaY > 0) {
            deltaScroll = patchBottom(deltaY);
        } else {
            deltaScroll = patchTop(deltaY);
        }
        if (deltaScroll) list.scrollTop += deltaScroll;
    };
    list.stopY = function () {
        var firstElement = getFirstVisibleElement();
        if (!firstElement) return;
        var paddingTop = parseFloat(getComputedStyle(list).paddingTop);
        var paddingBottom = parseFloat(getComputedStyle(list).paddingBottom);

        var scrolled_t = (list.scrollTop + paddingTop - firstElement.offsetTop) / firstElement.offsetHeight;
        var last_y = currentY();
        if (scrolled_t > .5) {
            var target_ty = last_y + (1 - scrolled_t) * firstElement.offsetHeight;
        } else {
            var target_ty = last_y - scrolled_t * firstElement.offsetHeight;
        }
        var lastElement = getLastVisibleElement();
        var scrolled_b = (list.scrollTop + list.clientHeight - lastElement.offsetTop - paddingBottom) / lastElement.offsetHeight;
        if (scrolled_b > .5) {
            var target_by = last_y + (1 - scrolled_b) * lastElement.offsetHeight;
        } else {
            var target_by = last_y - scrolled_b * lastElement.offsetHeight;
        }
        var target_y = Math.abs(target_ty - last_y) > Math.abs(target_by - last_y) ? target_by : target_ty;
        var delta = Math.min(calcPixel(60), list.clientHeight >> 2);
        if (lastElement.offsetHeight >= delta && firstElement.offsetHeight >= delta) {
            return last_y;
        }
        var resultY = this.Top(Math.abs(target_y - last_y) > 1 ? (target_y + last_y) >> 1 : target_y);
        if (resultY === last_y) {
            target_y = resultY;
        }
        return target_y;
    };
    //导出方法
    list.go = scrollTo;
    list.Height = function () {
        var elem = getLastElement(2);
        var listRestHeight = elem ? elem.offsetHeight + elem.offsetTop - list.scrollTop : list.clientHeight;
        return currentY() + listRestHeight + restHeight;
    };
    list.Top = function (y) {
        if (isFinite(y)) {
            var last_y = currentY();
            if (y !== last_y) {
                scrollBy(y - last_y);
            }
        }
        return currentY();
    };
    list.scrollBy = scrollBy;
    list.index = function () {
        var firstElement = getFirstVisibleElement();
        if (!firstElement) return;
        var index = firstElement.index;
        var scrolled = (list.scrollTop - firstElement.offsetTop + parseFloat(getComputedStyle(list).paddingTop)) / firstElement.offsetHeight;
        return index + scrolled;
    };
    list.topIndex = function () {
        var element = getFirstElement(1);
        return element ? element.index : 0;
    };
    vbox(list, $Y);
    return list;
}
var allArgumentsNames = arguments[arguments.length - 1];
var xlist = arriswise(ylist, allArgumentsNames.concat([].slice.call(arguments, 0)));

var getGeneratorFromArray = function (source) {
    return function (index) {
        if (index >= source.length) return null;
        return block(source[index]);
    };
};

/**
 *
 * @param {Boolean|Array|Function} generator
 */
function list() {
    var generator, $Y, container;
    {
        for (let cx = 0, dx = arguments.length; cx < dx; cx++) {
            let arg = arguments[cx];
            switch (typeof arg) {
                case "string":
                    $Y = arg;
                    break;
                case "function":
                    generator = arg;
                    break;
                default:
                    if (isNode(arg)) container = arg;
            }
        }
    }
    var bindSrc = null;
    if (container instanceof Array) {
        generator = getGeneratorFromArray(container);
        bindSrc = container;
        container = div();
    } else if (container && !generator) {
        var src = container.getAttribute("src") || container.getAttribute("ng-src") || container.getAttribute("v-src");
        if (src) {
            var parsedSrc = render.parseRepeat(src);
            if (!parsedSrc) {
                container.setAttribute("ng-src", src);
                container.removeAttribute("src");
                var generator = getGenerator(container);
            } else {
                container.setAttribute("ng-src", parsedSrc.srcName);
                container.removeAttribute("src");
                var generator = getGenerator(container, parsedSrc);
            }
            care(container, function () {
                var index = container.index();
                container.clean();
                container.go(index || 0);
            });
            bindSrc = true;
        }
    }

    if (!$Y) {
        if (container) {
            $Y = container.getAttribute("direction") || container.tagName;
        }
    }
    $Y = /^[xh]|[xh]$/i.test($Y) ? "X" : "Y";
    var list = ($Y === "X" ? xlist : ylist)(container, generator, $Y);
    if (bindSrc instanceof Array) {
        list.src = bindSrc;
        container.go(container.index() || 0);
    } else if (bindSrc === true) {
        container.go(container.index() || 0);
    }
    list.clean = function () {
        var children = (container || list).children;
        children = [].concat.apply([], children).filter(c => c.nodeType === 1 && isFinite(c.index));
        remove(children);
    };

    return list;
}<commit_msg>解决静态数据有时不能初始化的问题<commit_after>// 中文编码 utf8
function ylist(container, generator, $Y) {
    const cache_height = 2000;
    var restHeight = cache_height;
    var list = container || div();
    list.autoFix = true;
    var saved_itemIndex;
    addClass(list, 'list-' + $Y.toLowerCase());
    if (!list.renders) {
        list.renders = [];
    }
    list.renders.push(function () {
        var a = saved_itemIndex;
        saved_itemIndex = void 0;
        if (a !== void 0) scrollTo(a);
    });
    //取底部元素
    var getLastElement = function (nodeType) {
        var children = nodeType === 1 ? list.children : list.childNodes;
        for (var cx = children.length - 1; cx >= 0; cx--) {
            var child = children[cx];
            if (isFinite(child.index) || nodeType === 2 && child.offsetHeight) {
                return child;
            }
        }
        return null;
    };
    //取底部元素
    var getIndexedElement = function (index) {
        var children = list.childNodes;
        for (var cx = children.length - 1; cx >= 0; cx--) {
            var child = children[cx];
            if (isFinite(child.index) && child.index === index) {
                return child;
            }
        }
        return null;
    };

    //取顶部元素
    var getFirstElement = function (nodeType) {
        var children = nodeType === 1 ? list.children : list.childNodes;
        for (var cx = 0, dx = children.length; cx < dx; cx++) {
            var child = children[cx];
            if (isFinite(child.index) || nodeType === 2 && child.offsetHeight) {
                return child;
            }
        }
        return null;
    };
    var getFirstVisibleElement = function (deltaY = 0) {
        var children = list.children;
        var { scrollTop } = list;
        scrollTop += deltaY;
        for (var cx = 0, dx = children.length; cx < dx; cx++) {
            var child = children[cx];
            if (isFinite(child.index) && child.offsetTop + child.offsetHeight >= scrollTop) {
                return child;
            }
        }
        return null;
    };
    var getLastVisibleElement = function (deltaY = 0) {
        var { scrollTop } = list;
        scrollTop += deltaY;
        var children = list.children;
        for (var cx = children.length - 1; cx >= 0; cx--) {
            var child = children[cx];
            if (isFinite(child.index) && child.offsetTop < scrollTop + list.clientHeight) {
                return child;
            }
        }
        return null;
    };
    //元素表
    var getChildrenMap = function () {
        var children = list.children;
        var map = {};
        for (var cx = 0, dx = children.length; cx < dx; cx++) {
            var child = children[cx];
            if (isFinite(child.index)) {
                map[child.index] = child;
            }
        }
        return map;
    };
    //设置当前下标
    var scrollTo = function (itemIndex) {
        if (!list.offsetHeight && !list.offsetWidth && !list.isMounted) {
            saved_itemIndex = itemIndex;
            return;
        }
        var index = itemIndex | 0;
        var ratio = itemIndex - index || 0;
        if (index < 0) index = 0;
        var childrenMap = getChildrenMap();
        var offsetBottom = 0, ratioTop = 0, offset = +index || 0, last_item = getFirstElement() || null, last_index = last_item && last_item.index || offset;
        var count = 0, delta = 1, bottom_item, offsett = offset, offsetb = offset, top_item;
        while (offsetBottom - ratioTop <= list.clientHeight + cache_height) {
            var item = childrenMap[offset];
            if (!item || item.id) {
                item = generator(offset);
                if (!item) {
                    if (delta < 0) break;
                    delta = -1;
                    offset = index - 1;
                    bottom_item = getIndexedElement(offsetb);
                    last_item = getIndexedElement(index);
                    last_index = index;
                    continue;
                }
                item.index = offset;
                if (last_index > offset) {
                    list.insertBefore(item, last_item);
                } else {
                    list.insertBefore(item, getNextSibling(last_item));
                }
                last_index = offset;
                last_item = item;
            }
            if (delta > 0) {
                offset++;
                offsetb = offset;
                bottom_item = item;
                if (!top_item) top_item = item;
            } else {
                offset--;
                offsett = offset;
                if (!bottom_item) bottom_item = item;
                top_item = item;
            }
            offsetBottom = bottom_item.offsetTop + bottom_item.offsetHeight;
            ratioTop = top_item.offsetTop + top_item.offsetHeight * ratio;
            if (count++ > 600) throw new Error("多于600个元素需要绘制！");
        }
        for (var k in childrenMap) {
            k = +k;
            if (!(k <= offsetb && k >= offsett)) {
                remove(childrenMap[k]);
            }
        }
        var indexed_item = getIndexedElement(index) || bottom_item;
        if (indexed_item) {
            list.scrollTop = indexed_item.offsetTop + indexed_item.offsetHeight * ratio - parseFloat(getComputedStyle(list).paddingTop);
        }
    };
    var runbuild = function () {
        patchBottom();
        patchTop();
        var firstElement = getFirstElement(1), y;
        if (firstElement) {
            y = firstElement.index * firstElement.offsetHeight;
        } else {
            y = 0;
        }

        css(topinsert, {
            height: fromOffset(y)
        });
        return y;
    };
    var rebuild = function () {
        if (!/^(?:auto|scroll)$/i.test(getComputedStyle(list).overflowY)) return;
        var saved_y, inc = 0;
        if (rebuild.ing) cancelAnimationFrame(rebuild.ing);
        var run = function () {
            var y = runbuild();
            if (y !== saved_y) {
                saved_y = y;
                inc = 0;
                return;
            }
            inc += 8;
            if (inc < 1000) {
                rebuild.ing = requestAnimationFrame(run);
            } else {
                rebuild.ing = 0;
            }
        };
        rebuild.ing = requestAnimationFrame(run);
    };
    on("scroll")(list, rebuild);
    var topinsert = document.createElement('ylist-insert');
    list.insertBefore(topinsert, list.firstChild);
    //计算当前高度
    var currentY = function () {
        var firstElement = getFirstElement(1);
        if (!firstElement) return;
        return firstElement.index * firstElement.offsetHeight + list.scrollTop;
    };
    var getBottomElement = function (last_element) {
        if (!last_element) return null;
        var with_elements = last_element.with;
        return with_elements && with_elements.length ? with_elements[with_elements.length - 1] : last_element;
    };
    var getNextSibling = function (last_element) {
        var bottom_element = getBottomElement(last_element);
        return bottom_element ? bottom_element.nextSibling : null;
    };
    var getOffsetHeight = function (element) {
        var temp = element;
        do {
            var next = getNextSibling(temp);
            if (!next) return element.offsetHeight;
            temp = next;
        } while (next.offsetTop === element.offsetTop);
        return next.offsetTop - element.offsetTop;
    };
    var patchBottom = function (deltaY = 0) {
        var childrenMap = getChildrenMap();
        var last_element = getLastElement();
        if (!last_element || !last_element.offsetHeight) return;
        let { scrollTop } = list;
        scrollTop += deltaY;
        var offsetBottom = getOffsetHeight(last_element) + last_element.offsetTop;
        var offset = last_element.index || 0;
        //追加元素到底部
        while (offsetBottom <= scrollTop + list.clientHeight + cache_height) {
            offset++;
            var item = childrenMap[offset];
            if (!item || item.itemid) {
                item = generator(offset);
                if (!item) {
                    restHeight = 0;
                    break;
                } else if (!restHeight) {
                    restHeight = cache_height;
                }
                item.index = offset;
                list.insertBefore(item, getNextSibling(last_element));
            }
            if (!item.offsetHeight) {
                console.warn(item, '!item.offsetHeight');
                break;
            }
            offsetBottom = item.offsetTop + getOffsetHeight(item);
            last_element = item;
        }
        var collection = [];
        for (var k in childrenMap) {
            let item = childrenMap[k];
            if (item.offsetTop + getOffsetHeight(item) + cache_height < scrollTop) {
                collection.push(item);
            } else {
                break;
            }
        }
        if (collection.length) {
            var item = collection[collection.length - 1];
            scrollTop -= item.offsetTop + getOffsetHeight(item) - collection[0].offsetTop;
            var { paddingCount, paddingMax } = list;
            if (paddingCount > 0 && paddingMax > 0 && paddingCount < paddingMax) {
                let item = collection[collection.length - 1];
                while (paddingCount > 0) {
                    if (!item) break;
                    paddingCount--;
                    collection.push(item.nextSibling);
                    item = item.nextSibling;
                }
            }
            remove(collection);
        }
        //滚动到相应的位置
        return scrollTop - list.scrollTop;
    };
    var patchTop = function (deltaY = 0) {
        var childrenMap = getChildrenMap();
        var first_element, flag_element = first_element = getFirstElement(1);
        if (!flag_element || !isFinite(flag_element.offsetTop)) return;
        var offset = flag_element.index || 0;
        var offsetTop = flag_element.offsetTop;
        var { scrollTop } = list;
        scrollTop += deltaY;
        //追加元素到顶部
        var targetHeight = cache_height + first_element.offsetTop;
        var { paddingCount, paddingMax } = list;
        if (!(paddingCount > 0 && paddingMax > 0 && paddingCount < paddingMax) || !(scrollTop < targetHeight)) {
            paddingCount = 0;
        }
        while (scrollTop < targetHeight || paddingCount > 0) {
            offset--;
            if (!(scrollTop < targetHeight)) {
                paddingCount--;
            }
            if (!(offset >= 0)) {
                break;
            }
            var item = childrenMap[offset];
            if (!item || item.itemid) {
                item = generator(offset);
                if (!item) break;
                item.index = offset;
                childrenMap[offset] = item;
                list.insertBefore(item, first_element);
                scrollTop += flag_element.offsetTop - offsetTop;
                offsetTop = flag_element.offsetTop;
                first_element = item;
            }
        }
        //滚动到相应位置
        if (scrollTop < 0) scrollTop = 0;
        //-list_scrollTop + lElem_offsetTop = -list_newScrollTop + lElem_newoffsetTop + deltaY
        var last_element = getLastElement(1);
        var { clientHeight } = list;
        while (last_element && last_element.offsetTop > clientHeight + scrollTop + cache_height) {
            remove(last_element);
            last_element = getLastElement(1);
        }
        return scrollTop - list.scrollTop;
    };
    //滚动一定的距离
    var scrollBy = function (deltaY) {
        var deltaScroll;
        if (deltaY > 0) {
            deltaScroll = patchBottom(deltaY);
        } else {
            deltaScroll = patchTop(deltaY);
        }
        if (deltaScroll) list.scrollTop += deltaScroll;
    };
    list.stopY = function () {
        var firstElement = getFirstVisibleElement();
        if (!firstElement) return;
        var paddingTop = parseFloat(getComputedStyle(list).paddingTop);
        var paddingBottom = parseFloat(getComputedStyle(list).paddingBottom);

        var scrolled_t = (list.scrollTop + paddingTop - firstElement.offsetTop) / firstElement.offsetHeight;
        var last_y = currentY();
        if (scrolled_t > .5) {
            var target_ty = last_y + (1 - scrolled_t) * firstElement.offsetHeight;
        } else {
            var target_ty = last_y - scrolled_t * firstElement.offsetHeight;
        }
        var lastElement = getLastVisibleElement();
        var scrolled_b = (list.scrollTop + list.clientHeight - lastElement.offsetTop - paddingBottom) / lastElement.offsetHeight;
        if (scrolled_b > .5) {
            var target_by = last_y + (1 - scrolled_b) * lastElement.offsetHeight;
        } else {
            var target_by = last_y - scrolled_b * lastElement.offsetHeight;
        }
        var target_y = Math.abs(target_ty - last_y) > Math.abs(target_by - last_y) ? target_by : target_ty;
        var delta = Math.min(calcPixel(60), list.clientHeight >> 2);
        if (lastElement.offsetHeight >= delta && firstElement.offsetHeight >= delta) {
            return last_y;
        }
        var resultY = this.Top(Math.abs(target_y - last_y) > 1 ? (target_y + last_y) >> 1 : target_y);
        if (resultY === last_y) {
            target_y = resultY;
        }
        return target_y;
    };
    //导出方法
    list.go = scrollTo;
    list.Height = function () {
        var elem = getLastElement(2);
        var listRestHeight = elem ? elem.offsetHeight + elem.offsetTop - list.scrollTop : list.clientHeight;
        return currentY() + listRestHeight + restHeight;
    };
    list.Top = function (y) {
        if (isFinite(y)) {
            var last_y = currentY();
            if (y !== last_y) {
                scrollBy(y - last_y);
            }
        }
        return currentY();
    };
    list.scrollBy = scrollBy;
    list.index = function () {
        var firstElement = getFirstVisibleElement();
        if (!firstElement) return;
        var index = firstElement.index;
        var scrolled = (list.scrollTop - firstElement.offsetTop + parseFloat(getComputedStyle(list).paddingTop)) / firstElement.offsetHeight;
        return index + scrolled;
    };
    list.topIndex = function () {
        var element = getFirstElement(1);
        return element ? element.index : 0;
    };
    vbox(list, $Y);
    return list;
}
var allArgumentsNames = arguments[arguments.length - 1];
var xlist = arriswise(ylist, allArgumentsNames.concat([].slice.call(arguments, 0)));

var getGeneratorFromArray = function (source) {
    return function (index) {
        if (index >= source.length) return null;
        return block(source[index]);
    };
};

/**
 *
 * @param {Boolean|Array|Function} generator
 */
function list() {
    var generator, $Y, container;
    {
        for (let cx = 0, dx = arguments.length; cx < dx; cx++) {
            let arg = arguments[cx];
            switch (typeof arg) {
                case "string":
                    $Y = arg;
                    break;
                case "function":
                    generator = arg;
                    break;
                default:
                    if (isNode(arg)) container = arg;
            }
        }
    }
    var bindSrc = null;
    if (container instanceof Array) {
        generator = getGeneratorFromArray(container);
        bindSrc = container;
        container = div();
    } else if (container && !generator) {
        var src = container.getAttribute("src") || container.getAttribute("ng-src") || container.getAttribute("v-src");
        if (src) {
            var parsedSrc = render.parseRepeat(src);
            if (!parsedSrc) {
                container.setAttribute("ng-src", src);
                container.removeAttribute("src");
                var generator = getGenerator(container);
            } else {
                container.setAttribute("ng-src", parsedSrc.srcName);
                container.removeAttribute("src");
                var generator = getGenerator(container, parsedSrc);
            }
            care(container, function () {
                var index = container.index();
                container.clean();
                container.go(index || 0);
            });
            bindSrc = true;
        }
    }

    if (!$Y) {
        if (container) {
            $Y = container.getAttribute("direction") || container.tagName;
        }
    }
    $Y = /^[xh]|[xh]$/i.test($Y) ? "X" : "Y";
    var list = ($Y === "X" ? xlist : ylist)(container, generator, $Y);
    if (bindSrc instanceof Array) {
        list.src = bindSrc;
        container.go(container.index() || 0);
    } else if (bindSrc === true) {
        container.go(container.index() || 0);
    }
    list.clean = function () {
        var children = (container || list).children;
        children = [].concat.apply([], children).filter(c => c.nodeType === 1 && isFinite(c.index));
        remove(children);
    };

    return list;
}<|endoftext|>


<commit_before><commit_msg>componentizd!<commit_after><|endoftext|>


<commit_before>var NoticeBanner = {
    dom_target: undefined,

    render_init: function(dom_taget) {
        NoticeBanner.dom_target  = dom_taget;
        WSData.fetch_notice_data(NoticeBanner.render);
    },

    render: function () {
        var notice_data = WSData.notice_data();
        Notices.get_categorized_critical_notices();

        if (notice_data.length > 0) {
            var source = $("#notice_banner").html();
            var template = Handlebars.compile(source);

            var html = template({
                "total_unread": Notices.get_total_unread(),
                "categorized_critical":
                    Notices.get_categorized_critical_notices()
            });
            NoticeBanner.dom_target.html(html);
        }
    }
};

<commit_msg>static critical notice category order<commit_after>var NoticeBanner = {
    dom_target: undefined,

    render_init: function(dom_taget) {
        NoticeBanner.dom_target  = dom_taget;
        WSData.fetch_notice_data(NoticeBanner.render);
    },

    render: function () {
        var notice_data = WSData.notice_data();

        if (notice_data.length > 0) {
            var source = $("#notice_banner").html();
            var template = Handlebars.compile(source);
            var notices = Notices.get_categorized_critical_notices();
            var sorted_notices = NoticeBanner._sort_categories(notices);

            var html = template({
                "total_unread": Notices.get_total_unread(),
                "categorized_critical": sorted_notices
            });
            NoticeBanner.dom_target.html(html);
        }
    },

    _sort_categories: function (notices) {
        var category_order = ['Holds',
        'Fees & Finances',
        'Graduation',
        'Academics',
        'Registration',
        'Insurance',
        'Legal',
        'Visa'];
        var sorted_notices = [];
        $.each(category_order, function(idx, category){
            if (category in notices) {
                sorted_notices.push(notices[category]);
            }

        });
        return sorted_notices;

    }
};

<|endoftext|>


<commit_before><commit_msg>Preview checkbox is now respected<commit_after><|endoftext|>


<commit_before>import * as VismaAPIClient from '../lib/api-client/visma'
import * as EpinovaAPIClient from '../lib/api-client/epinova'
import * as FileAPIClient from '../lib/api-client/files'
import * as APIClient from '../lib/api-client'
import * as JSONConnector from '../lib/http/json'
import config from './index'

export const connector = JSONConnector.defaults({
  headers: {
    'user-agent': 'imdikator:api-client',
    'accept': 'application/json,text/plain,* / *'
  }
})

const vismaAPI = VismaAPIClient.create({
  baseUrl: `http://${config.apiHost}/api/v1/`,
  connector: connector
})

const epinovaAPI = EpinovaAPIClient.create({
  baseUrl: `http://${config.contentApiHost}/api/`,
  connector: connector
})

const fileAPI = FileAPIClient.create()

export default APIClient.create({
  vismaAPI: vismaAPI,
  epinovaAPI: epinovaAPI,
  fileAPI: fileAPI
})
<commit_msg>Use protocol relative urls<commit_after>import * as VismaAPIClient from '../lib/api-client/visma'
import * as EpinovaAPIClient from '../lib/api-client/epinova'
import * as FileAPIClient from '../lib/api-client/files'
import * as APIClient from '../lib/api-client'
import * as JSONConnector from '../lib/http/json'
import config from './index'

export const connector = JSONConnector.defaults({
  headers: {
    'user-agent': 'imdikator:api-client',
    'accept': 'application/json,text/plain,* / *'
  }
})

const vismaAPI = VismaAPIClient.create({
  baseUrl: `//${config.apiHost}/api/v1/`,
  connector: connector
})

const epinovaAPI = EpinovaAPIClient.create({
  baseUrl: `//${config.contentApiHost}/api/`,
  connector: connector
})

const fileAPI = FileAPIClient.create()

export default APIClient.create({
  vismaAPI: vismaAPI,
  epinovaAPI: epinovaAPI,
  fileAPI: fileAPI
})
<|endoftext|>


<commit_before>import React, { Component, PropTypes, findDOMNode } from 'react';
import { uniqueId } from 'lodash/utility';

import MaskedInput from 'react-maskedinput/src/index.jsx';

import css from './FormInput.css';

export default class SharedFormInput extends Component {
  constructor(props) {
    super(props);

    this.handleChange = this.handleChange.bind(this);
    this.handleFocus = this.handleFocus.bind(this);
    this.handleBlur = this.handleBlur.bind(this);

    this.state = {
      focus: false,
      id: uniqueId('forminput'),
    };
  }

  focus() {
    return findDOMNode(this.refs.focusable).focus();
  }
  blur() {
    return findDOMNode(this.refs.focusable).blur();
  }

  handleFocus() {
    const { onFocus } = this.props;
    this.setState({
      focus: true,
    }, () => onFocus && onFocus());
  }

  handleBlur() {
    const { onBlur } = this.props;
    this.setState({
      focus: false,
    }, () => onBlur && onBlur());
  }

  handleChange(e) {
    const { onChange, transform } = this.props;
    let { value } = e.target;
    if (transform) {
      value = transform(value);
    }
    onChange(value);
  }

  render() {
    const {
      placeholder,
      borderless,
      required,
      pattern,
      masked,
      error,
      value,
      label,
      type,
    } = this.props;
    const { focus, id } = this.state;

    const active = value && !!value.length;
    const isInsideVariant = !!placeholder;

    const outerCSS = [
      css.container,
      required ? css.required : null,
      isInsideVariant ? css.labelInside : css.labelOutside,
      error ? css.error : null,
      active ? css.active : null,
      focus ? css.focus : null,
      borderless ? css.borderless : null,
    ].join(' ');

    const messageCSS = [
      css.message,
      error ? css.messageError : null,
    ].join(' ');

    return (

            {label}{required ? '*' : null}

          {masked ?
            <MaskedInput
              onFocus={this.handleFocus}
              onBlur={this.handleBlur}
              className={css.input}
              onChange={this.handleChange}
              value={value}
              id={id}
              type={type}
              pattern={pattern}
              placeholder={placeholder}
              ref="focusable"
            />
            :
            <input
              placeholder={placeholder}
              onFocus={this.handleFocus}
              onBlur={this.handleBlur}
              className={css.input}
              onChange={this.handleChange}
              value={value}
              id={id}
              type={type}
              ref="focusable"
            />
          }

          {this.props.error}

    );
  }
}

SharedFormInput.propTypes = {
  // Render a MaskedInput or not
  masked: PropTypes.bool.isRequired,

  onChange: PropTypes.func.isRequired,
  onFocus: PropTypes.func,
  onBlur: PropTypes.func,

  value: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  type: PropTypes.string.isRequired,
  pattern: PropTypes.string.isRequired,
  placeholder: PropTypes.string,

  transform: PropTypes.func,
  borderless: PropTypes.bool,
  required: PropTypes.bool,

  // If set, will display underneath the input
  error: PropTypes.string,
};
<commit_msg>SharedFormInput now supports the addition of native HTML attributes<commit_after>import React, { Component, PropTypes, findDOMNode } from 'react';
import { uniqueId } from 'lodash/utility';

import MaskedInput from 'react-maskedinput/src/index.jsx';

import css from './FormInput.css';

export default class SharedFormInput extends Component {
  constructor(props) {
    super(props);

    this.handleChange = this.handleChange.bind(this);
    this.handleFocus = this.handleFocus.bind(this);
    this.handleBlur = this.handleBlur.bind(this);

    this.state = {
      focus: false,
      id: uniqueId('forminput'),
    };
  }

  focus() {
    return findDOMNode(this.refs.focusable).focus();
  }
  blur() {
    return findDOMNode(this.refs.focusable).blur();
  }

  handleFocus() {
    const { onFocus } = this.props;
    this.setState({
      focus: true,
    }, () => onFocus && onFocus());
  }

  handleBlur() {
    const { onBlur } = this.props;
    this.setState({
      focus: false,
    }, () => onBlur && onBlur());
  }

  handleChange(e) {
    const { onChange, transform } = this.props;
    let { value } = e.target;
    if (transform) {
      value = transform(value);
    }
    onChange(value);
  }

  render() {
    const {
      placeholder,
      borderless,
      required,
      pattern,
      masked,
      error,
      value,
      label,
      ...remainingProps,
    } = this.props;
    const { focus, id } = this.state;

    const active = value && !!value.length;
    const isInsideVariant = !!placeholder;

    const outerCSS = [
      css.container,
      required ? css.required : null,
      isInsideVariant ? css.labelInside : css.labelOutside,
      error ? css.error : null,
      active ? css.active : null,
      focus ? css.focus : null,
      borderless ? css.borderless : null,
    ].join(' ');

    const messageCSS = [
      css.message,
      error ? css.messageError : null,
    ].join(' ');

    return (

            {label}{required ? '*' : null}

          {masked ?
            <MaskedInput
              {...remainingProps}
              onFocus={this.handleFocus}
              onBlur={this.handleBlur}
              className={css.input}
              onChange={this.handleChange}
              value={value}
              id={id}
              pattern={pattern}
              placeholder={placeholder}
              ref="focusable"
            />
            :
            <input
              {...remainingProps}
              placeholder={placeholder}
              onFocus={this.handleFocus}
              onBlur={this.handleBlur}
              className={css.input}
              onChange={this.handleChange}
              value={value}
              id={id}
              ref="focusable"
            />
          }

          {this.props.error}

    );
  }
}

SharedFormInput.propTypes = {
  // Render a MaskedInput or not
  masked: PropTypes.bool.isRequired,

  onChange: PropTypes.func.isRequired,
  onFocus: PropTypes.func,
  onBlur: PropTypes.func,

  value: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  pattern: PropTypes.string.isRequired,
  placeholder: PropTypes.string,

  transform: PropTypes.func,
  borderless: PropTypes.bool,
  required: PropTypes.bool,

  // If set, will display underneath the input
  error: PropTypes.string,
};
<|endoftext|>