<commit_before>'use strict';

const View = require('@scola/view');

class SliderView extends View.Abstract {
  constructor() {
    super();

    this.all = [];
    this.current = [];
    this.pointer = 0;
    this.running = false;
    this.direction = 1;

    this.options({
      amount: 1,
      direction: true,
      duration: 300,
      orientation: 'horizontal',
      remove: false,
      rotate: true
    });
  }

  build() {
    this.element('container', 'div')
      .properties({
        className: 'scola slider'
      })
      .style({
        height: '100%',
        overflow: 'hidden',
        position: 'absolute',
        width: '100%'
      });

    if (this.i18n) {
      this.bindListener('locale', this.i18n, this.handleLocale);
    }
  }

  render() {
    return this.element('container');
  }

  handleLocale(event) {
    if (this.getOption('direction')) {
      this.direction = event.data.language.dir === 'rtl' ? -1 : 1;
    }
  }

  isRunning() {
    return this.running;
  }

  getPropertyName() {
    return this.getOption('orientation') === 'horizontal' ? 'x' : 'y';
  }

  append(element) {
    if (this.running) {
      return this;
    }

    this.all.push(element);

    this
      .setDimensions(element)
      .setPosition(element, this.all.indexOf(element));

    if (this.all.length <= this.getOption('amount')) {
      this.current.push(element);

      this.element('container')
        .append(element)
        .emit('slide', this.current);
    }

    return this;
  }

  forward() {
    if (this.running) {
      return this;
    }

    return this.slideForward(
      this.current,
      this.calculateForward()
    );
  }

  calculateForward() {
    const hasEnough = this.all.length >= 2 * this.getOption('amount');

    this.pointer += this.getOption('amount');

    if (this.pointer > this.all.length) {
      this.pointer -= this.all.length;
    }

    let elements = this.all.slice(
      this.pointer,
      this.pointer + this.getOption('amount')
    );

    const shortage = this.getOption('amount') - elements.length;

    if (shortage > 0) {
      if (this.getOption('rotate') && hasEnough) {
        elements = elements.concat(
          this.all.slice(0, shortage)
        );
      } else {
        this.pointer -= shortage;
      }
    }

    return elements;
  }

  slideForward(current, elements) {
    if (elements.length === 0) {
      return this;
    }

    this.running = true;
    this.current = [];

    const name = this.getPropertyName();

    let fromIndex = 0;
    let toIndex = 0;

    let cssFrom = {};
    let cssTo = {};

    current.forEach((element, index) => {
      if (elements.length - index <= 0) {
        this.current.push(element);
      }

      cssTo = {
        [name]: ((elements.length - index) * -100 * this.direction) + '%'
      };

      element
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0,
          onComplete: () => {
            if (this.current.indexOf(element) === -1) {
              this.element('container').detach(element);
            }
          }
        }, this);
    });

    elements.forEach((element, index) => {
      this.current.push(element);

      fromIndex = index + this.getOption('amount');
      toIndex = elements.length - index - this.getOption('amount');

      cssFrom = {
        [name]: (fromIndex * 100 * this.direction) + '%'
      };

      cssTo = {
        [name]: (toIndex * -100 * this.direction) + '%'
      };

      element
        .appendTo(this.element('container'))
        .animate({
          css: cssFrom,
          duration: 0,
          position: 0
        }, this)
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0
        }, this);
    });

    this.play(() => {
      this.element('container').emit('slide', this.current);
      this.running = false;
    });

    return this;
  }

  backward() {
    if (this.running) {
      return this;
    }

    return this.slideBackward(
      this.current,
      this.calculateBackward()
    );
  }

  calculateBackward() {
    const hasEnough = this.all.length >= 2 * this.getOption('amount');

    this.pointer -= this.getOption('amount');
    let amount = this.getOption('amount');

    if (this.pointer < 0) {
      if (this.getOption('rotate') && hasEnough) {
        this.pointer += this.all.length;
      } else {
        amount += this.pointer;
        this.pointer = 0;
      }
    }

    let elements = this.all.slice(
      this.pointer,
      this.pointer + amount
    );

    const shortage = this.getOption('amount') - elements.length;

    if (shortage > 0 && this.getOption('rotate') && hasEnough) {
      elements = elements.concat(
        this.all.slice(0, shortage)
      );
    }

    return elements;
  }

  slideBackward(current, elements) {
    if (elements.length === 0) {
      return this;
    }

    this.running = true;
    this.current = [];

    const name = this.getPropertyName();

    let cssFrom = {};
    let cssTo = {};

    elements.forEach((element, index) => {
      this.current.push(element);

      cssFrom = {
        [name]: ((elements.length - index) * -100 * this.direction) + '%'
      };

      cssTo = {
        [name]: (index * 100 * this.direction) + '%'
      };

      element
        .appendTo(this.element('container'))
        .animate({
          css: cssFrom,
          duration: 0,
          position: 0
        }, this)
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0
        }, this);
    });

    current.forEach((element, index) => {
      if (elements.length + index < this.getOption('amount')) {
        this.current.push(element);
      }

      cssTo = {
        [name]: ((elements.length + index) * 100 * this.direction) + '%'
      };

      element
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0,
          onComplete: () => {
            if (this.current.indexOf(element) === -1) {
              this.element('container').detach(element);

              if (this.getOption('remove')) {
                this.all.splice(this.all.indexOf(element), 1);
                element.getView().destroy();
              }
            }
          }
        }, this);
    });

    this.play(() => {
      this.element('container').emit('slide', this.current);
      this.running = false;
    });

    return this;
  }

  toward(target) {
    if (this.running) {
      return this;
    }

    const pointer = this.all.indexOf(target);

    if (pointer > this.pointer) {
      this.slideTowardForward(
        this.calculateTowardForward(pointer)
      );
    } else if (pointer < this.pointer) {
      this.slideTowardBackward(
        this.calculateTowardBackward(pointer)
      );
    }

    return this;
  }

  calculateTowardForward(pointer) {
    const elements = this.all.slice(
      this.pointer,
      pointer + this.getOption('amount')
    );

    this.pointer = Math.min(
      this.all.length - this.getOption('amount'),
      pointer
    );

    return elements;
  }

  slideTowardForward(elements) {
    if (elements.length === 0) {
      return this;
    }

    this.running = true;

    const current = this.current;
    const name = this.getPropertyName();

    let toIndex = 0;
    let cssFrom = {};
    let cssTo = {};

    this.current = this.all.slice(
      this.pointer,
      this.pointer + this.getOption('amount')
    );

    elements.forEach((element, index) => {
      toIndex = elements.length - index - this.getOption('amount');

      cssFrom = {
        [name]: (index * 100 * this.direction) + '%'
      };

      cssTo = {
        [name]: (toIndex * -100 * this.direction) + '%'
      };

      if (current.indexOf(element) === -1) {
        element
          .appendTo(this.element('container'))
          .animate({
            css: cssFrom,
            duration: 0,
            position: 0
          }, this);
      }

      element
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0,
          onComplete: () => {
            if (this.current.indexOf(element) === -1) {
              this.element('container').detach(element);
            }
          }
        }, this);
    });

    this.play(() => {
      this.element('container').emit('slide', this.current);
      this.running = false;
    });
  }

  calculateTowardBackward(pointer) {
    const elements = this.all.slice(
      pointer,
      this.pointer + this.getOption('amount')
    );

    this.pointer = pointer;

    return elements;
  }

  slideTowardBackward(elements) {
    if (elements.length === 0) {
      return this;
    }

    this.running = true;

    const name = this.getPropertyName();
    const current = this.current;

    this.current = elements.slice(
      0,
      this.getOption('amount')
    );

    let fromIndex = 0;
    let cssFrom = {};
    let cssTo = {};

    elements.forEach((element, index) => {
      fromIndex = elements.length - index - this.getOption('amount');

      cssFrom = {
        [name]: (fromIndex * -100 * this.direction) + '%'
      };

      cssTo = {
        [name]: (index * 100 * this.direction) + '%'
      };

      if (current.indexOf(element) === -1) {
        element
          .appendTo(this.element('container'))
          .animate({
            css: cssFrom,
            duration: 0,
            position: 0
          }, this);
      }

      element
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0,
          onComplete: () => {
            if (this.current.indexOf(element) === -1) {
              this.element('container').detach(element);
            }
          }
        }, this);
    });

    this.play(() => {
      this.element('container').emit('slide', this.current);
      this.running = false;
    });
  }

  reset() {
    return this
      .resetAll()
      .resetCurrent();
  }

  resetAll() {
    this.all.forEach((element) => {
      this.setDimensions(element);
    });

    return this;
  }

  resetCurrent(pointer) {
    pointer = pointer || 0;

    this.current.forEach((element) => {
      this.element('container').detach(element);
    });

    this.pointer = pointer;
    this.current = this.all.slice(
      this.pointer,
      this.pointer + this.getOption('amount')
    );

    this.current.forEach((element, index) => {
      this.element('container').append(element);
      this.setPosition(element, index);
    });

    return this;
  }

  setDimensions(element) {
    const dimensions = {
      height: '100%',
      width: '100%'
    };

    const name = this.getOption('orientation') === 'horizontal' ?
      'width' : 'height';

    dimensions[name] = (1 / this.getOption('amount') * 100) + '%';

    element.style(dimensions);

    return this;
  }

  setPosition(element, index) {
    const translate = [0, 0];
    const position = this.getOption('orientation') === 'horizontal' ? 0 : 1;

    translate[position] = (index * 100) + '%';

    element.style({
      transform: 'translate(' + translate.join(',') + ')'
    });

    return this;
  }
}

module.exports = SliderView;
<commit_msg>Append/prepend elements/views to slider, clear slides<commit_after>'use strict';

const View = require('@scola/view');

class SliderView extends View.Abstract {
  constructor() {
    super();

    this.all = [];
    this.current = [];
    this.pointer = 0;
    this.running = false;
    this.direction = 1;

    this.options({
      amount: 1,
      direction: true,
      duration: 300,
      orientation: 'horizontal',
      remove: false,
      rotate: true
    });
  }

  build() {
    this.element('container', 'div')
      .properties({
        className: 'scola slider'
      })
      .style({
        height: '100%',
        overflow: 'hidden',
        position: 'absolute',
        width: '100%'
      });

    if (this.i18n) {
      this.bindListener('locale', this.i18n, this.handleLocale);
    }
  }

  render() {
    return this.element('container');
  }

  handleLocale(event) {
    if (this.getOption('direction')) {
      this.direction = event.data.language.dir === 'rtl' ? -1 : 1;
    }
  }

  isRunning() {
    return this.running;
  }

  getPropertyName() {
    return this.getOption('orientation') === 'horizontal' ? 'x' : 'y';
  }

  append(element) {
    if (this.running) {
      return this;
    }

    this.all.push(element);

    this
      .setDimensions(element)
      .setPosition(element, this.all.indexOf(element));

    if (this.all.length <= this.getOption('amount')) {
      this.current.push(element);

      this.element('container')
        .append(element)
        .emit('slide', this.current);
    }

    return this;
  }

  appendView(...args) {
    return this.append(
      this.view(...args).render()
    );
  }

  prepend(element) {
    if (this.running) {
      return this;
    }

    this.all.unshift(element);

    this
      .setDimensions(element)
      .setPosition(element, this.all.indexOf(element));

    if (this.all.length <= this.getOption('amount')) {
      this.current.unshift(element);

      this.element('container')
        .prepend(element)
        .emit('slide', this.current);
    } else {
      this.pointer += 1;
    }

    return this;
  }

  prependView(...args) {
    return this.prepend(
      this.view(...args).render()
    );
  }

  forward() {
    if (this.running) {
      return this;
    }

    return this.slideForward(
      this.current,
      this.calculateForward()
    );
  }

  calculateForward() {
    const hasEnough = this.all.length >= 2 * this.getOption('amount');

    this.pointer += this.getOption('amount');

    if (this.pointer > this.all.length) {
      this.pointer -= this.all.length;
    }

    let elements = this.all.slice(
      this.pointer,
      this.pointer + this.getOption('amount')
    );

    const shortage = this.getOption('amount') - elements.length;

    if (shortage > 0) {
      if (this.getOption('rotate') && hasEnough) {
        elements = elements.concat(
          this.all.slice(0, shortage)
        );
      } else {
        this.pointer -= shortage;
      }
    }

    return elements;
  }

  slideForward(current, elements) {
    if (elements.length === 0) {
      return this;
    }

    this.running = true;
    this.current = [];

    const name = this.getPropertyName();

    let fromIndex = 0;
    let toIndex = 0;

    let cssFrom = {};
    let cssTo = {};

    current.forEach((element, index) => {
      if (elements.length - index <= 0) {
        this.current.push(element);
      }

      cssTo = {
        [name]: ((elements.length - index) * -100 * this.direction) + '%'
      };

      element
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0,
          onComplete: () => {
            if (this.current.indexOf(element) === -1) {
              this.element('container').detach(element);
            }
          }
        }, this);
    });

    elements.forEach((element, index) => {
      this.current.push(element);

      fromIndex = index + this.getOption('amount');
      toIndex = elements.length - index - this.getOption('amount');

      cssFrom = {
        [name]: (fromIndex * 100 * this.direction) + '%'
      };

      cssTo = {
        [name]: (toIndex * -100 * this.direction) + '%'
      };

      element
        .appendTo(this.element('container'))
        .animate({
          css: cssFrom,
          duration: 0,
          position: 0
        }, this)
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0
        }, this);
    });

    this.play(() => {
      this.element('container').emit('slide', this.current);
      this.running = false;
    });

    return this;
  }

  backward() {
    if (this.running) {
      return this;
    }

    return this.slideBackward(
      this.current,
      this.calculateBackward()
    );
  }

  calculateBackward() {
    const hasEnough = this.all.length >= 2 * this.getOption('amount');

    this.pointer -= this.getOption('amount');
    let amount = this.getOption('amount');

    if (this.pointer < 0) {
      if (this.getOption('rotate') && hasEnough) {
        this.pointer += this.all.length;
      } else {
        amount += this.pointer;
        this.pointer = 0;
      }
    }

    let elements = this.all.slice(
      this.pointer,
      this.pointer + amount
    );

    const shortage = this.getOption('amount') - elements.length;

    if (shortage > 0 && this.getOption('rotate') && hasEnough) {
      elements = elements.concat(
        this.all.slice(0, shortage)
      );
    }

    return elements;
  }

  slideBackward(current, elements) {
    if (elements.length === 0) {
      return this;
    }

    this.running = true;
    this.current = [];

    const name = this.getPropertyName();

    let cssFrom = {};
    let cssTo = {};

    elements.forEach((element, index) => {
      this.current.push(element);

      cssFrom = {
        [name]: ((elements.length - index) * -100 * this.direction) + '%'
      };

      cssTo = {
        [name]: (index * 100 * this.direction) + '%'
      };

      element
        .appendTo(this.element('container'))
        .animate({
          css: cssFrom,
          duration: 0,
          position: 0
        }, this)
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0
        }, this);
    });

    current.forEach((element, index) => {
      if (elements.length + index < this.getOption('amount')) {
        this.current.push(element);
      }

      cssTo = {
        [name]: ((elements.length + index) * 100 * this.direction) + '%'
      };

      element
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0,
          onComplete: () => {
            if (this.current.indexOf(element) === -1) {
              this.element('container').detach(element);

              if (this.getOption('remove')) {
                this.all.splice(this.all.indexOf(element), 1);
                element.getView().destroy();
              }
            }
          }
        }, this);
    });

    this.play(() => {
      this.element('container').emit('slide', this.current);
      this.running = false;
    });

    return this;
  }

  toward(target) {
    if (this.running) {
      return this;
    }

    const pointer = this.all.indexOf(target);

    if (pointer > this.pointer) {
      this.slideTowardForward(
        this.calculateTowardForward(pointer)
      );
    } else if (pointer < this.pointer) {
      this.slideTowardBackward(
        this.calculateTowardBackward(pointer)
      );
    }

    return this;
  }

  calculateTowardForward(pointer) {
    const elements = this.all.slice(
      this.pointer,
      pointer + this.getOption('amount')
    );

    this.pointer = Math.min(
      this.all.length - this.getOption('amount'),
      pointer
    );

    return elements;
  }

  slideTowardForward(elements) {
    if (elements.length === 0) {
      return this;
    }

    this.running = true;

    const current = this.current;
    const name = this.getPropertyName();

    let toIndex = 0;
    let cssFrom = {};
    let cssTo = {};

    this.current = this.all.slice(
      this.pointer,
      this.pointer + this.getOption('amount')
    );

    elements.forEach((element, index) => {
      toIndex = elements.length - index - this.getOption('amount');

      cssFrom = {
        [name]: (index * 100 * this.direction) + '%'
      };

      cssTo = {
        [name]: (toIndex * -100 * this.direction) + '%'
      };

      if (current.indexOf(element) === -1) {
        element
          .appendTo(this.element('container'))
          .animate({
            css: cssFrom,
            duration: 0,
            position: 0
          }, this);
      }

      element
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0,
          onComplete: () => {
            if (this.current.indexOf(element) === -1) {
              this.element('container').detach(element);
            }
          }
        }, this);
    });

    this.play(() => {
      this.element('container').emit('slide', this.current);
      this.running = false;
    });
  }

  calculateTowardBackward(pointer) {
    const elements = this.all.slice(
      pointer,
      this.pointer + this.getOption('amount')
    );

    this.pointer = pointer;

    return elements;
  }

  slideTowardBackward(elements) {
    if (elements.length === 0) {
      return this;
    }

    this.running = true;

    const name = this.getPropertyName();
    const current = this.current;

    this.current = elements.slice(
      0,
      this.getOption('amount')
    );

    let fromIndex = 0;
    let cssFrom = {};
    let cssTo = {};

    elements.forEach((element, index) => {
      fromIndex = elements.length - index - this.getOption('amount');

      cssFrom = {
        [name]: (fromIndex * -100 * this.direction) + '%'
      };

      cssTo = {
        [name]: (index * 100 * this.direction) + '%'
      };

      if (current.indexOf(element) === -1) {
        element
          .appendTo(this.element('container'))
          .animate({
            css: cssFrom,
            duration: 0,
            position: 0
          }, this);
      }

      element
        .animate({
          css: cssTo,
          duration: this.getOption('duration'),
          position: 0,
          onComplete: () => {
            if (this.current.indexOf(element) === -1) {
              this.element('container').detach(element);
            }
          }
        }, this);
    });

    this.play(() => {
      this.element('container').emit('slide', this.current);
      this.running = false;
    });
  }

  reset() {
    return this
      .resetAll()
      .resetCurrent();
  }

  resetAll() {
    this.all.forEach((element) => {
      this.setDimensions(element);
    });

    return this;
  }

  resetCurrent(pointer) {
    pointer = pointer || 0;

    this.current.forEach((element) => {
      this.element('container').detach(element);
    });

    this.pointer = pointer;
    this.current = this.all.slice(
      this.pointer,
      this.pointer + this.getOption('amount')
    );

    this.current.forEach((element, index) => {
      this.element('container').append(element);
      this.setPosition(element, index);
    });

    return this;
  }

  setDimensions(element) {
    const dimensions = {
      height: '100%',
      width: '100%'
    };

    const name = this.getOption('orientation') === 'horizontal' ?
      'width' : 'height';

    dimensions[name] = (1 / this.getOption('amount') * 100) + '%';

    element.style(dimensions);

    return this;
  }

  setPosition(element, index) {
    const translate = [0, 0];
    const position = this.getOption('orientation') === 'horizontal' ? 0 : 1;

    translate[position] = (index * 100) + '%';

    element.style({
      transform: 'translate(' + translate.join(',') + ')'
    });

    return this;
  }

  clearSlides(current) {
    if (this.running) {
      return this;
    }

    this.all.forEach((element) => {
      if (current !== false || this.current.indexOf(element) === -1) {
        element.getView().destroy();
      }
    });

    this.all = [];
    this.current = current !== false ? [] : this.current;
    this.pointer = 0;
    this.running = false;

    return this;
  }
}

module.exports = SliderView;
<|endoftext|>


<commit_before>//var SerialPort = require("serialport").SerialPort

var serialport = require("serialport");
var SerialPort = serialport.SerialPort; // localize object constructor
var s = require('sleep');
var stdin = process.openStdin();

var serialPort = new SerialPort("/dev/cu.LightBlue-Bean", {
  baudrate: 57600,
   parser: serialport.parsers.readline("\n")
}, false); // this is the openImmediately flag [default is true]

s.sleep(2);

serialPort.open(function (error) {
  if ( error ) {
    console.log('failed to open: '+error);
  } else {
    console.log('open');
    serialPort.on('data', function(data) {
      if( data != "\n")
      console.log('data received: ' + data);
    });

    stdin.addListener("data", function(d) {
      // note:  d is an object, and when converted to a string it will
      // end with a linefeed.  so we (rather crudely) account for that
      // with toString() and then trim()
      console.log("you entered: [" +
          d.toString().trim() + "]");

      serialPort.write( d.toString().trim()+"\n" , function(err, results) {
        //console.log('err ' + err);
        //console.log('results ' + results);
      });
    });
  }
});<commit_msg>se agrega express.io<commit_after>//var SerialPort = require("serialport").SerialPort
app = require('express.io')();
app.http().io();
app.listen(7076);

// Setup the ready route, and emit talk event.
app.io.route('ready', function(req) {
    console.log('socket.io ready...');
    req.io.emit('talk', {
        message: 'io event from an io route on the server'
    })
})

// Send the client html.
app.get('/', function(req, res) {
    res.sendfile('../TimeSeriesChart.html')
})

var serialport = require("serialport");
var SerialPort = serialport.SerialPort; // localize object constructor
var s = require('sleep');
var stdin = process.openStdin();

var serialPort = new SerialPort("/dev/cu.LightBlue-Bean", {
  baudrate: 57600,
   parser: serialport.parsers.readline("\n")
}, false); // this is the openImmediately flag [default is true]

s.sleep(2);

serialPort.open(function (error) {
  if ( error ) {
    console.log('failed to open: '+error);
  } else {
    console.log('open');
    serialPort.on('data', function(data) {
      if( data != "\n")
      console.log('data received: ' + data);
    });

    stdin.addListener("data", function(d) {
      // note:  d is an object, and when converted to a string it will
      // end with a linefeed.  so we (rather crudely) account for that
      // with toString() and then trim()
      console.log("you entered: [" +
          d.toString().trim() + "]");

      serialPort.write( d.toString().trim()+"\n" , function(err, results) {
        //console.log('err ' + err);
        //console.log('results ' + results);
      });
    });
  }
});<|endoftext|>


<commit_before>// from https://github.com/alexpearce/alexpearce.github.com/blob/master/assets/js/alexpearce.js

// Capitalises a string
// Accepts:
//   str: string
// Returns:
//   string
var majusculeFirst = function(str) {
  var temp = str.charAt(0).toUpperCase();
  for (var i = 1; i < str.length; i++) {
    temp += str.charAt(i).toLowerCase();
  }
  return temp;
}

// Retrieves the value of a GET parameter with a given key
// Accepts:
//   param: string
// Returns:
//   string or null
var getParam = function(param) {
  var queryString = window.location.search.substring(1),
      queries = queryString.split("&");
  for (var i in queries) {
    var pair = queries[i].split("=");
    if (pair[0] == param) {
      return pair[1];
    }
  }
  return null;
};

// Filters posts with the condition `post['property'] == value`
// Accepts:
//   posts - array of post objects and a string
//   property - string of post object property to compare
//   value - filter value of property
// Returns:
//  array of post objects
var filterPostsByPropertyValue = function(posts, property, value) {
  var filteredPosts = [];
  // The last element is a null terminator
  posts.pop();
  for (var i in posts) {
    var post = posts[i],
        prop = post[property];

    // Last element of tags is null
    post.tags.pop();

    // The property could be a string, such as a post's category,
    // or an array, such as a post's tags
    if (prop.constructor == String) {
      if (prop.toLowerCase() == value.toLowerCase()) {
        filteredPosts.push(post);
      }
    } else if (prop.constructor == Array) {
      for (var j in prop) {
        if (prop[j].toLowerCase() == value.toLowerCase()) {
          filteredPosts.push(post);
        }
      }
    }
  }

  return filteredPosts;
};

// Formats search results and appends them to the DOM
// Accepts:
//   property: string of object type we're displaying
//   value: string of name of object we're displaying
//   posts: array of post objects
// Returns: nothing
var layoutResultsPage = function(property, value, posts) {
  // Make sure we're on the search results page
  var $container = $('#results');
  if ($container.length == 0) return;

  // Update the header
  var str = majusculeFirst(property) + " Listing for ‘" + majusculeFirst(value) + '’';
  $container.find('h1').text(str);

  // Loop through each post to format it
  for (var i in posts) {
    // Create an unordered list of the post's tags
    var tagsList = '
',
        post     = posts[i],
        tags     = post.tags;

    for (var j in tags) {
      tagsList += '
' + tags[j].toLowerCase() + '
';
    }
    tagsList += '
';

    $container.find('ul.results').append(
      '
'
        // Page anchor
        + ''
        + posts[i].title
        + ''
        // Post date
        + ' - '
        + posts[i].date.year + '-' + posts[i].date.month + '-' + posts[i].date.day
        + ''
        // Tags
        + tagsList
        + '
'
    );
  }
}

// Formats the search results page for no results
// Accepts:
//   property: string of object type we're displaying
//   value: string of name of object we're displaying
// Returns: nothing
var noResultsPage = function(property, value) {
  // Make sure we're on the search results page
  var $container = $('#results');
  if ($container.length == 0) return;

  $container.find('h1').text('No Results Found.').after('

');

  var txt = "We couldn't find anything associated with '" + value + "' here.";
  $container.find('p.nadda').text(txt);
};

// Replaces ERB-style tags with Liquid ones as we can't escape them in posts
// Accepts:
//   elements: jQuery elements in which to replace tags
// Returns: nothing
var replaceERBTags = function(elements) {
  elements.each(function() {
    // Only for text blocks at the moment as we'll strip highlighting otherwise
    var $this = $(this),
        txt   = $this.html();

    // Replace <%=  %>with {{ }}
    txt = txt.replace(new RegExp("<%=(.+?)%>", "g"), "{{$1}}");
    // Replace <% %> with {% %}
    txt = txt.replace(new RegExp("<%(.+?)%>", "g"), "{%$1%}");

    $this.html(txt);
  });
};

$(function() {
  var map = {
    'category' : getParam('category'),
    'tags'     : getParam('tags'),
    'search'   : getParam('search')
  };

  $.each(map, function(type, value) {
    if (value !== null) {
      $.getJSON('/search.json', function(data) {
        posts = filterPostsByPropertyValue(data, type, value);
        if (posts.length === 0) {
          noResultsPage(type, value);
        } else {
          layoutResultsPage(type, value, posts);
        }
      });
    }
  });

  // Replace ERB-style Liquid tags in highlighted code blocks...
  replaceERBTags($('div.highlight').find('code.text'));
  // ... and in inline code
  replaceERBTags($('p code'));
});
<commit_msg>Update alexpearce.js<commit_after>// from https://github.com/alexpearce/alexpearce.github.com/blob/master/assets/js/alexpearce.js

// Capitalises a string
// Accepts:
//   str: string
// Returns:
//   string
var majusculeFirst = function(str) {
  var temp = str.charAt(0).toUpperCase();
  for (var i = 1; i < str.length; i++) {
    temp += str.charAt(i).toLowerCase();
  }
  return temp;
}

// Retrieves the value of a GET parameter with a given key
// Accepts:
//   param: string
// Returns:
//   string or null
var getParam = function(param) {
  var queryString = window.location.search.substring(1),
      queries = queryString.split("&");
  for (var i in queries) {
    var pair = queries[i].split("=");
    if (pair[0] == param) {
      return pair[1];
    }
  }
  return null;
};

// Filters posts with the condition `post['property'] == value`
// Accepts:
//   posts - array of post objects and a string
//   property - string of post object property to compare
//   value - filter value of property
// Returns:
//  array of post objects
var filterPostsByPropertyValue = function(posts, property, value) {
  var filteredPosts = [];
  // The last element is a null terminator
  posts.pop();
  for (var i in posts) {
    var post = posts[i],
        prop = post[property];

    // Last element of tags is null
    post.tags.pop();

    // The property could be a string, such as a post's category,
    // or an array, such as a post's tags
    if (prop.constructor == String) {
      if (prop.toLowerCase() == value.toLowerCase()) {
        filteredPosts.push(post);
      }
    } else if (prop.constructor == Array) {
      for (var j in prop) {
        if (prop[j].toLowerCase() == value.toLowerCase()) {
          filteredPosts.push(post);
        }
      }
    }
  }

  return filteredPosts;
};

// Formats search results and appends them to the DOM
// Accepts:
//   property: string of object type we're displaying
//   value: string of name of object we're displaying
//   posts: array of post objects
// Returns: nothing
var layoutResultsPage = function(property, value, posts) {
  // Make sure we're on the search results page
  var $container = $('#results');
  if ($container.length == 0) return;

  // Update the header
  var str = majusculeFirst(property) + " Listing for ‘" + majusculeFirst(value) + '’';
  $container.find('h1').text(str);

  // Loop through each post to format it
  for (var i in posts) {
    // Create an unordered list of the post's tags
    var tagsList = '
',
        post     = posts[i],
        tags     = post.tags;

    for (var j in tags) {
      tagsList += '
' + tags[j].toLowerCase() + '
';
    }
    tagsList += '
';

    $container.find('ul.results').append(
      '
'
        // Page anchor
        + ''
        + posts[i].title
        + ''
        // Post date
        + ' - '
        + posts[i].date.year + '-' + posts[i].date.month + '-' + posts[i].date.day
        + ''
        // Tags
        + tagsList
        + '
'
    );
  }
}

// Formats the search results page for no results
// Accepts:
//   property: string of object type we're displaying
//   value: string of name of object we're displaying
// Returns: nothing
var noResultsPage = function(property, value) {
  // Make sure we're on the search results page
  var $container = $('#results');
  if ($container.length == 0) return;

  $container.find('h1').text('No Results Found.').after('

');

  var txt = "We couldn't find anything associated with '" + value + "' here.";
  $container.find('p.nadda').text(txt);
};

// Replaces ERB-style tags with Liquid ones as we can't escape them in posts
// Accepts:
//   elements: jQuery elements in which to replace tags
// Returns: nothing
var replaceERBTags = function(elements) {
  elements.each(function() {
    // Only for text blocks at the moment as we'll strip highlighting otherwise
    var $this = $(this),
        txt   = $this.html();

    // Replace <%=  %>with {{ }}
    txt = txt.replace(new RegExp("<%=(.+?)%>", "g"), "{{$1}}");
    // Replace <% %> with {% %}
    txt = txt.replace(new RegExp("<%(.+?)%>", "g"), "{%$1%}");

    $this.html(txt);
  });
};

$(function() {
  var map = {
    'category' : getParam('category'),
    'tags'     : getParam('tags'),
    'search'   : getParam('search')
  };

  $.each(map, function(type, value) {
    if (value !== null) {

      // vjava114 한글검색을 위해 추가함
		  value = decodeURIComponent(value);

      $.getJSON('/search.json', function(data) {
        posts = filterPostsByPropertyValue(data, type, value);
        if (posts.length === 0) {
          noResultsPage(type, value);
        } else {
          layoutResultsPage(type, value, posts);
        }
      });
    }
  });

  // Replace ERB-style Liquid tags in highlighted code blocks...
  replaceERBTags($('div.highlight').find('code.text'));
  // ... and in inline code
  replaceERBTags($('p code'));
});
<|endoftext|>


<commit_before>define(['jquery', 'underscore', 'backbone'], function($, _, Backbone) {
    return Backbone.Router.extend({
        routes: {
            'listing/:id': 'showListing'
        },

        initialize: function() {

        },

        showListing: function(id) {

        }
    });
});<commit_msg>routing attempt #1 of many<commit_after>define(['jquery', 'underscore', 'backbone'], function($, _, Backbone) {
    return Backbone.Router.extend({
        routes: {
            'listing/:id': 'showListing'
        },

        initialize: function() {

        },

        showListing: function(id) {
            this.item = new Models.Want({
                url: '/service/listings/get/' + id
            });

            this.item.fetch();

			this.modal = new Views.ViewItemModal({
				model: this.item,
				el: '#modal-container'
			});
        }
    });
});<|endoftext|>


<commit_before>var options;

// Performs an ajax request
function ajaxRequest(request, callback) {

    var xhr = new XMLHttpRequest();
    var response = request.response;
    var method = request.method;
    var url = request.url;
    xhr.onreadystatechange = function () {

        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                if (method == 'HEAD') {
                    callback({url:url, headers:xhr.getAllResponseHeaders()});
                } else {
                    if (response === 'URL') {
                        callback(xhr.responseURL);
                    } else {
                        callback(xhr.responseText);
                    }
                }
            } else {
                callback(null);
            }
        }
    }

    xhr.open(request.method, request.url, true);
    for (var i in request.headers) {
        xhr.setRequestHeader(request.headers[i].header, request.headers[i].value);
    }
    xhr.send(request.data);
}

function onMessage(message, sender, callback) {
    switch (message.action) {
        case 'downloadFile':
            chrome.permissions.request({
                permissions: ['downloads']
            }, function (granted) {
                if (granted) {
                    chrome.downloads.download({url: message.url, filename: message.filename, conflictAction: message.conflictAction, saveAs: false});
                    return true;
                } else {
                    return false;
                }
            });
        case 'ajaxGet':
            ajaxRequest({url:message.url, response:message.response, method:'GET', headers:message.headers}, callback);
            return true;
        case 'ajaxGetHeaders':
            ajaxRequest({url:message.url, response:message.response, method:'HEAD'}, callback);
            return true;
        case 'ajaxRequest':
            ajaxRequest(message, callback);
            return true;
        case 'showPageAction':
            // Firefox url is located at sender.url, copy sender.url to sender.tab.url
            if (!sender.tab.url && sender.url)
                sender.tab.url = sender.url
            showPageAction(sender.tab);
            callback();
            return true;
        case 'addUrlToHistory':
            chrome.permissions.contains({permissions: ['history']}, function(granted) {
                if (granted) {
                    chrome.history.addUrl({url:message.url});
                }
            });
            break;
        case 'getOptions':
            callback(options);
            return true;
        case 'setOption':
            options[message.name] = message.value;
            localStorage.options = JSON.stringify(options);
            sendOptions(message.options);
            break;
        case 'optionsChanged':
            options = message.options;
            manageHeadersRewrite();
            break;
        case 'saveOptions':
            localStorage.options = JSON.stringify(message.options);
            sendOptions(message.options);
            break;
        case 'setItem':
            localStorage.setItem(message.id, message.data);
            break;
        case 'getItem':
            callback(localStorage.getItem(message.id));
            return true;
        case 'removeItem':
            localStorage.removeItem(message.id);
            break;
        case 'openViewWindow':
            var url = message.createData.url;
            if (url.indexOf('facebook.com/photo/download') !== -1) {
                message.createData.url = 'data:text/html,';
            }
            chrome.windows.create(message.createData, function (window) {
                chrome.tabs.executeScript(window.tabs[0].id, {file:'js/viewWindow.js'});
            });
            break;
        case 'openViewTab':
            chrome.tabs.query({active: true}, function (tabs) {
                message.createData.index = tabs[0].index;
                if (!message.createData.active)
                    message.createData.index++;
                var url = message.createData.url;
                if (url.indexOf('facebook.com/photo/download') !== -1) {
                    message.createData.url = 'data:text/html,';
                }
                chrome.tabs.create(message.createData, function (tab) {
                    chrome.tabs.executeScript(tab.id, {file:'js/viewTab.js'});
                });
            });
            break;
        case 'updateViewWindow':
            chrome.windows.getCurrent(window => { chrome.windows.update(window.id, { width:message.updateData.width, height:message.updateData.height, top:message.updateData.top, left:message.updateData.left }) });
            break;
        case 'storeHeaderSettings':
            storeHeaderSettings(message);
            break;
    }
}

function showPageAction(tab) {
    if (!tab) {
        return;
    }
    if (!options.extensionEnabled || isExcludedSite(tab.url)) {
        chrome.pageAction.setIcon({tabId:tab.id, path:'../images/icon19d.png'});
    } else {
        chrome.pageAction.setIcon({tabId:tab.id, path:'../images/icon19.png'});
    }
    chrome.pageAction.show(tab.id);
}

function init() {
    // Load options
    options = loadOptions();

    // Bind events
    chrome.runtime.onMessage.addListener(onMessage);

    manageHeadersRewrite();
}

// Add or remove web request listeners
function manageHeadersRewrite() {
    if (options.allowHeadersRewrite) {
        // check that permissions are granted, otherwise remove listeners
        chrome.permissions.contains({permissions: ['webRequest','webRequestBlocking']}, function (granted) {
            if (granted) addWebRequestListeners();
            if (!granted) removeWebRequestListeners();
        });
    } else {
        removeWebRequestListeners();
    }
}
// Store HZ+ dates of installation & last update
chrome.runtime.onInstalled.addListener((details) => {

    const reason = details.reason;
    let d = new Date();
    let options = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric' };

    switch (reason) {
        case 'install':
            localStorage['HoverZoomInstallation'] = d.toLocaleDateString(undefined, options);
            break;
        case 'update':
            localStorage['HoverZoomLastUpdate'] = d.toLocaleDateString(undefined, options);
            break;
        case 'chrome_update':
        case 'shared_module_update':
        default:
            // Other install events within the browser
            break;
    }
})

// - store request's header(s) setting(s) = modification(s) to be applied to request's header(s) just before sending request to server
//   e.g: add/modify "Origin" header to deal with CORS limitations
// - store response's header(s) setting(s) = modification(s) to be applied to response's header(s) just after receiving response from server
//   e.g: add/modify "Access-Control-Allow-Origin" header so browser allows content display
function storeHeaderSettings(message) {
    console.log('storeHeaderSettings ' + message.requestOrResponse);
    // check that:
    // - header(s) rewrite is allowed
    // and
    // - permissions are granted
    if (!options.allowHeadersRewrite) return;
    chrome.permissions.contains({permissions: ['webRequest','webRequestBlocking']}, function (granted) {
        if (!granted) return;
    });
    console.log('storeHeaderSettings ' + message.requestOrResponse + ' granted');
    let hoverZoomHeaderSettings = sessionStorage.getItem('HoverZoomHeaderSettings') || '{}';
    hoverZoomHeaderSettings = JSON.parse(hoverZoomHeaderSettings);
    let settings = (message.requestOrResponse == 'request' ? hoverZoomHeaderSettings.requetes || [] : hoverZoomHeaderSettings.responses || []);
    let index = settings.findIndex(s => s.url == message.url);
    if (index != -1) settings.splice(index, 1); // remove old settings
    settings.push({ url:message.url, skipInitiator:message.skipInitiator, headers:message.headers }); // add new settings
    if (message.requestOrResponse == 'request') hoverZoomHeaderSettings.requetes = settings;
    else hoverZoomHeaderSettings.responses = settings;
    sessionStorage.setItem('HoverZoomHeaderSettings', JSON.stringify(hoverZoomHeaderSettings));
}

// update request header(s) just before sending
function updateRequestHeaders(e) {
    console.log('updateRequestHeaders');
    console.log(e);

    let settings = findHeaderSettings(e.url, "request");
    if (! settings) return;

    // check if update must be skipped because of initiator
    if (settings.skipInitiator && e.initiator.indexOf(settings.skipInitiator) != -1) {
        console.log('skip: initiator');
        return;
    }

    return { requestHeaders: updateHeaders(e.requestHeaders, settings) };
}

// update response header(s) just after receiving
function updateResponseHeaders(e) {
    console.log('updateResponseHeaders');
    console.log(e);

    let settings = findHeaderSettings(e.url, "response");
    if (! settings) return;

    // check if update must be skipped because of initiator
    if (settings.skipInitiator && e.initiator.indexOf(settings.skipInitiator) != -1) {
        console.log('skip: initiator');
        return;
    }

    return { responseHeaders: updateHeaders(e.responseHeaders, settings) };
}

// find header(s) setting(s) associated with url that triggered the listener
function findHeaderSettings(url, requestOrResponse) {
    let hoverZoomHeaderSettings = sessionStorage.getItem('HoverZoomHeaderSettings') || '{}';
    hoverZoomHeaderSettings = JSON.parse(hoverZoomHeaderSettings);
    let reqres = (requestOrResponse == 'request' ? hoverZoomHeaderSettings.requetes || [] : hoverZoomHeaderSettings.responses || []);
    let settings = reqres.find(s => url.indexOf(s.url) != -1);
    if (! settings) {
        console.log('skip: no settings');
        return null; // no settings found for url
    }
    return settings;
}

// update header(s) according to plug-in settings
function updateHeaders(headers, settings) {
    settings.headers.forEach(h => {
        // types of update:
        // - 'remove':  remove header
        // - 'replace': replace header, if header does not exist then do nothing
        // - 'add':     add header, if header already exists then replace it
        if (h.typeOfUpdate == 'remove') {
            let index = headers.findIndex(rh => rh.name.toLowerCase() == h.name.toLowerCase());
            if (index != -1) headers.splice(index, 1);
        }
        if (h.typeOfUpdate == 'replace') {
            let index = headers.findIndex(rh => rh.name.toLowerCase() == h.name.toLowerCase());
            if (index != -1) headers[index] = { 'name':h.name, 'value':h.value };
        }
        if (h.typeOfUpdate == 'add') {
            let index = headers.findIndex(rh => rh.name.toLowerCase() == h.name.toLowerCase());
            if (index != -1) headers[index] = { 'name':h.name, 'value':h.value };
            else headers.push( { 'name':h.name, 'value':h.value } );
        }
    })
    console.log(headers);
    return headers;
}

// add listeners for web requests:
// - onBeforeSendHeaders
// - onHeadersReceived
// so they can be edited on-the-fly to enable API calls from plug-ins
// https://developer.chrome.com/docs/extensions/reference/webRequest/
function addWebRequestListeners() {

    console.log('addWebRequestListeners');

    if (! chrome.webRequest.onBeforeSendHeaders.hasListeners())
        chrome.webRequest.onBeforeSendHeaders.addListener(updateRequestHeaders, { urls : ["<all_urls>"] }, ["blocking", "requestHeaders", "extraHeaders"]);
    if (! chrome.webRequest.onHeadersReceived.hasListeners())
        chrome.webRequest.onHeadersReceived.addListener(updateResponseHeaders, { urls : ["<all_urls>"] }, ["blocking", "responseHeaders", "extraHeaders"]);
}

// remove listeners for web requests:
// - onBeforeSendHeaders
// - onHeadersReceived
// also remove headers settings since they are not used anymore
function removeWebRequestListeners() {

    console.log('removeWebRequestListeners');

    if (chrome.webRequest.onBeforeSendHeaders.hasListeners())
        chrome.webRequest.onBeforeSendHeaders.removeListener(updateRequestHeaders);
    if (chrome.webRequest.onHeadersReceived.hasListeners())
        chrome.webRequest.onHeadersReceived.removeListener(updateResponseHeaders);

    sessionStorage.removeItem('HoverZoomHeaderSettings');
}

init();
<commit_msg>Removal of console outputs<commit_after>var options;

// Performs an ajax request
function ajaxRequest(request, callback) {

    var xhr = new XMLHttpRequest();
    var response = request.response;
    var method = request.method;
    var url = request.url;
    xhr.onreadystatechange = function () {

        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                if (method == 'HEAD') {
                    callback({url:url, headers:xhr.getAllResponseHeaders()});
                } else {
                    if (response === 'URL') {
                        callback(xhr.responseURL);
                    } else {
                        callback(xhr.responseText);
                    }
                }
            } else {
                callback(null);
            }
        }
    }

    xhr.open(request.method, request.url, true);
    for (var i in request.headers) {
        xhr.setRequestHeader(request.headers[i].header, request.headers[i].value);
    }
    xhr.send(request.data);
}

function onMessage(message, sender, callback) {
    switch (message.action) {
        case 'downloadFile':
            chrome.permissions.request({
                permissions: ['downloads']
            }, function (granted) {
                if (granted) {
                    chrome.downloads.download({url: message.url, filename: message.filename, conflictAction: message.conflictAction, saveAs: false});
                    return true;
                } else {
                    return false;
                }
            });
        case 'ajaxGet':
            ajaxRequest({url:message.url, response:message.response, method:'GET', headers:message.headers}, callback);
            return true;
        case 'ajaxGetHeaders':
            ajaxRequest({url:message.url, response:message.response, method:'HEAD'}, callback);
            return true;
        case 'ajaxRequest':
            ajaxRequest(message, callback);
            return true;
        case 'showPageAction':
            // Firefox url is located at sender.url, copy sender.url to sender.tab.url
            if (!sender.tab.url && sender.url)
                sender.tab.url = sender.url
            showPageAction(sender.tab);
            callback();
            return true;
        case 'addUrlToHistory':
            chrome.permissions.contains({permissions: ['history']}, function(granted) {
                if (granted) {
                    chrome.history.addUrl({url:message.url});
                }
            });
            break;
        case 'getOptions':
            callback(options);
            return true;
        case 'setOption':
            options[message.name] = message.value;
            localStorage.options = JSON.stringify(options);
            sendOptions(message.options);
            break;
        case 'optionsChanged':
            options = message.options;
            manageHeadersRewrite();
            break;
        case 'saveOptions':
            localStorage.options = JSON.stringify(message.options);
            sendOptions(message.options);
            break;
        case 'setItem':
            localStorage.setItem(message.id, message.data);
            break;
        case 'getItem':
            callback(localStorage.getItem(message.id));
            return true;
        case 'removeItem':
            localStorage.removeItem(message.id);
            break;
        case 'openViewWindow':
            var url = message.createData.url;
            if (url.indexOf('facebook.com/photo/download') !== -1) {
                message.createData.url = 'data:text/html,';
            }
            chrome.windows.create(message.createData, function (window) {
                chrome.tabs.executeScript(window.tabs[0].id, {file:'js/viewWindow.js'});
            });
            break;
        case 'openViewTab':
            chrome.tabs.query({active: true}, function (tabs) {
                message.createData.index = tabs[0].index;
                if (!message.createData.active)
                    message.createData.index++;
                var url = message.createData.url;
                if (url.indexOf('facebook.com/photo/download') !== -1) {
                    message.createData.url = 'data:text/html,';
                }
                chrome.tabs.create(message.createData, function (tab) {
                    chrome.tabs.executeScript(tab.id, {file:'js/viewTab.js'});
                });
            });
            break;
        case 'updateViewWindow':
            chrome.windows.getCurrent(window => { chrome.windows.update(window.id, { width:message.updateData.width, height:message.updateData.height, top:message.updateData.top, left:message.updateData.left }) });
            break;
        case 'storeHeaderSettings':
            storeHeaderSettings(message);
            break;
    }
}

function showPageAction(tab) {
    if (!tab) {
        return;
    }
    if (!options.extensionEnabled || isExcludedSite(tab.url)) {
        chrome.pageAction.setIcon({tabId:tab.id, path:'../images/icon19d.png'});
    } else {
        chrome.pageAction.setIcon({tabId:tab.id, path:'../images/icon19.png'});
    }
    chrome.pageAction.show(tab.id);
}

function init() {
    // Load options
    options = loadOptions();

    // Bind events
    chrome.runtime.onMessage.addListener(onMessage);

    manageHeadersRewrite();
}

// Add or remove web request listeners
function manageHeadersRewrite() {
    if (options.allowHeadersRewrite) {
        // check that permissions are granted, otherwise remove listeners
        chrome.permissions.contains({permissions: ['webRequest','webRequestBlocking']}, function (granted) {
            if (granted) addWebRequestListeners();
            if (!granted) removeWebRequestListeners();
        });
    } else {
        removeWebRequestListeners();
    }
}
// Store HZ+ dates of installation & last update
chrome.runtime.onInstalled.addListener((details) => {

    const reason = details.reason;
    let d = new Date();
    let options = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric' };

    switch (reason) {
        case 'install':
            localStorage['HoverZoomInstallation'] = d.toLocaleDateString(undefined, options);
            break;
        case 'update':
            localStorage['HoverZoomLastUpdate'] = d.toLocaleDateString(undefined, options);
            break;
        case 'chrome_update':
        case 'shared_module_update':
        default:
            // Other install events within the browser
            break;
    }
})

// - store request's header(s) setting(s) = modification(s) to be applied to request's header(s) just before sending request to server
//   e.g: add/modify "Origin" header to deal with CORS limitations
// - store response's header(s) setting(s) = modification(s) to be applied to response's header(s) just after receiving response from server
//   e.g: add/modify "Access-Control-Allow-Origin" header so browser allows content display
function storeHeaderSettings(message) {
    // check that:
    // - header(s) rewrite is allowed
    // and
    // - permissions are granted
    if (!options.allowHeadersRewrite) return;
    chrome.permissions.contains({permissions: ['webRequest','webRequestBlocking']}, function (granted) {
        if (!granted) return;
    });

    let hoverZoomHeaderSettings = sessionStorage.getItem('HoverZoomHeaderSettings') || '{}';
    hoverZoomHeaderSettings = JSON.parse(hoverZoomHeaderSettings);
    let settings = (message.requestOrResponse == 'request' ? hoverZoomHeaderSettings.requetes || [] : hoverZoomHeaderSettings.responses || []);
    let index = settings.findIndex(s => s.url == message.url);
    if (index != -1) settings.splice(index, 1); // remove old settings
    settings.push({ url:message.url, skipInitiator:message.skipInitiator, headers:message.headers }); // add new settings
    if (message.requestOrResponse == 'request') hoverZoomHeaderSettings.requetes = settings;
    else hoverZoomHeaderSettings.responses = settings;
    sessionStorage.setItem('HoverZoomHeaderSettings', JSON.stringify(hoverZoomHeaderSettings));
}

// update request header(s) just before sending
function updateRequestHeaders(e) {
    let settings = findHeaderSettings(e.url, "request");
    if (! settings) return;

    // check if update must be skipped because of initiator
    if (settings.skipInitiator && e.initiator.indexOf(settings.skipInitiator) != -1) return;

    return { requestHeaders: updateHeaders(e.requestHeaders, settings) };
}

// update response header(s) just after receiving
function updateResponseHeaders(e) {
    let settings = findHeaderSettings(e.url, "response");
    if (! settings) return;

    // check if update must be skipped because of initiator
    if (settings.skipInitiator && e.initiator.indexOf(settings.skipInitiator) != -1) return;

    return { responseHeaders: updateHeaders(e.responseHeaders, settings) };
}

// find header(s) setting(s) associated with url that triggered the listener
function findHeaderSettings(url, requestOrResponse) {
    let hoverZoomHeaderSettings = sessionStorage.getItem('HoverZoomHeaderSettings') || '{}';
    hoverZoomHeaderSettings = JSON.parse(hoverZoomHeaderSettings);
    let reqres = (requestOrResponse == 'request' ? hoverZoomHeaderSettings.requetes || [] : hoverZoomHeaderSettings.responses || []);
    let settings = reqres.find(s => url.indexOf(s.url) != -1);
    if (! settings) return null; // no settings found for url
    return settings;
}

// update header(s) according to plug-in settings
function updateHeaders(headers, settings) {
    settings.headers.forEach(h => {
        // types of update:
        // - 'remove':  remove header
        // - 'replace': replace header, if header does not exist then do nothing
        // - 'add':     add header, if header already exists then replace it
        if (h.typeOfUpdate == 'remove') {
            let index = headers.findIndex(rh => rh.name.toLowerCase() == h.name.toLowerCase());
            if (index != -1) headers.splice(index, 1);
        }
        if (h.typeOfUpdate == 'replace') {
            let index = headers.findIndex(rh => rh.name.toLowerCase() == h.name.toLowerCase());
            if (index != -1) headers[index] = { 'name':h.name, 'value':h.value };
        }
        if (h.typeOfUpdate == 'add') {
            let index = headers.findIndex(rh => rh.name.toLowerCase() == h.name.toLowerCase());
            if (index != -1) headers[index] = { 'name':h.name, 'value':h.value };
            else headers.push( { 'name':h.name, 'value':h.value } );
        }
    })
    return headers;
}

// add listeners for web requests:
// - onBeforeSendHeaders
// - onHeadersReceived
// so they can be edited on-the-fly to enable API calls from plug-ins
// https://developer.chrome.com/docs/extensions/reference/webRequest/
function addWebRequestListeners() {
    if (! chrome.webRequest.onBeforeSendHeaders.hasListeners())
        chrome.webRequest.onBeforeSendHeaders.addListener(updateRequestHeaders, { urls : ["<all_urls>"] }, ["blocking", "requestHeaders", "extraHeaders"]);
    if (! chrome.webRequest.onHeadersReceived.hasListeners())
        chrome.webRequest.onHeadersReceived.addListener(updateResponseHeaders, { urls : ["<all_urls>"] }, ["blocking", "responseHeaders", "extraHeaders"]);
}

// remove listeners for web requests:
// - onBeforeSendHeaders
// - onHeadersReceived
// also remove headers settings since they are not used anymore
function removeWebRequestListeners() {
    if (chrome.webRequest.onBeforeSendHeaders.hasListeners())
        chrome.webRequest.onBeforeSendHeaders.removeListener(updateRequestHeaders);
    if (chrome.webRequest.onHeadersReceived.hasListeners())
        chrome.webRequest.onHeadersReceived.removeListener(updateResponseHeaders);

    sessionStorage.removeItem('HoverZoomHeaderSettings');
}

init();
<|endoftext|>


<commit_before>'use strict';

/* Listens for messages from content script */
chrome.runtime.onMessage.addListener((message, sender) => {
    const tabId = sender.tab.id;
    switch (message.type) {
        case 'download'     : {download(tabId, message); break;}
        case 'button_style' : {addButtonStyles(tabId); break;}
        case 'page_style'   : {switchPageStyles(tabId, message.style, message.turnOn); break;}
    }
});

/* To override "user" originated css rules form other extensions */
function addButtonStyles(tabId){
    chrome.tabs.insertCSS(tabId, {
        allFrames   : true,
        cssOrigin   : 'user',
        runAt       : 'document_start',
        file        : 'css/button.css',
    }, () => {
        if (chrome.extension.lastError) {return;}
        chrome.tabs.sendMessage(tabId, 'css_injected');
    });
}

function switchPageStyles(tabId, style, turnOn){
    const action = turnOn ? 'insertCSS' : 'removeCSS';
    chrome.tabs[action](tabId, {
        allFrames   : true,
        cssOrigin   : 'user',
        code        : style,
    });
}

/* For options initialization after installation */
chrome.runtime.onInstalled.addListener(initSettings);
function initSettings(details){
    chrome.runtime.onInstalled.removeListener(initSettings);
    chrome.storage.local.get(null, currentSettings => {
        const actualSettingsNames = Object.keys(settingsDefault),
            currentSettingsNames = Object.keys(currentSettings),
            newSettings = {},
            newSettingsList = arrayDiff(actualSettingsNames, currentSettingsNames),
            obsoleteSettingsList = arrayDiff(currentSettingsNames, actualSettingsNames);

        function arrayDiff(arr1, arr2){
            return arr1.filter(x => arr2.indexOf(x) === -1);
        }

        newSettingsList.forEach(
            settingName => newSettings[settingName] = settingsDefault[settingName]
        );

        /* START for converting pre-0.6.2 exclusions TODO: remove later */
        const previousVersion = details.reason === 'update' ? Number(details.previousVersion.replace(/\./g, '')) : null,
            previousExclusions = currentSettings['exclusions'];
        if (previousVersion && previousVersion < 62 && !/[.#]/.test(previousExclusions)) {
            newSettings['exclusions'] = previousExclusions.split(' ').map(x => `.${x}`).join(', ');
        }
        /* END TODO: remove later */

        chrome.storage.local.set(newSettings);
        chrome.storage.local.remove(obsoleteSettingsList);
    });
}

/* Turns on/off content script across all tabs */
function setCuteState(state){
    const stateProps = state ? {text: 'on', color: '#6D6'} : {text: 'off', color: '#D66'};

    chrome.browserAction.setBadgeText({text: stateProps.text});
    chrome.browserAction.setBadgeBackgroundColor({color: stateProps.color});
}

chrome.browserAction.onClicked.addListener(() => {
    chrome.storage.local.get('isCute', items => chrome.storage.local.set({'isCute': !items.isCute}));
});

chrome.storage.onChanged.addListener(changes => {
    if (typeof changes.isCute === 'undefined') {return;}
    setCuteState(changes.isCute.newValue);
});
chrome.storage.local.get('isCute', items => setCuteState(items.isCute));
<commit_msg>clear old "folders" setting<commit_after>'use strict';

/* Listens for messages from content script */
chrome.runtime.onMessage.addListener((message, sender) => {
    const tabId = sender.tab.id;
    switch (message.type) {
        case 'download'     : {download(tabId, message); break;}
        case 'button_style' : {addButtonStyles(tabId); break;}
        case 'page_style'   : {switchPageStyles(tabId, message.style, message.turnOn); break;}
    }
});

/* To override "user" originated css rules form other extensions */
function addButtonStyles(tabId){
    chrome.tabs.insertCSS(tabId, {
        allFrames   : true,
        cssOrigin   : 'user',
        runAt       : 'document_start',
        file        : 'css/button.css',
    }, () => {
        if (chrome.extension.lastError) {return;}
        chrome.tabs.sendMessage(tabId, 'css_injected');
    });
}

function switchPageStyles(tabId, style, turnOn){
    const action = turnOn ? 'insertCSS' : 'removeCSS';
    chrome.tabs[action](tabId, {
        allFrames   : true,
        cssOrigin   : 'user',
        code        : style,
    });
}

/* For options initialization after installation */
chrome.runtime.onInstalled.addListener(initSettings);
function initSettings(details){
    chrome.runtime.onInstalled.removeListener(initSettings);
    chrome.storage.local.get(null, currentSettings => {
        const actualSettingsNames = Object.keys(settingsDefault),
            currentSettingsNames = Object.keys(currentSettings),
            newSettings = {},
            newSettingsList = arrayDiff(actualSettingsNames, currentSettingsNames),
            obsoleteSettingsList = arrayDiff(currentSettingsNames, actualSettingsNames);

        function arrayDiff(arr1, arr2){
            return arr1.filter(x => arr2.indexOf(x) === -1);
        }

        newSettingsList.forEach(
            settingName => newSettings[settingName] = settingsDefault[settingName]
        );

        /* START for converting old settings TODO: remove later */
        if (details.reason === 'update') {
            const previousVersion = Number(details.previousVersion.replace(/\./g, '')),
                previousExclusions = currentSettings['exclusions'];

            if (previousVersion < 62 && !/[.#]/.test(previousExclusions)) {
                newSettings['exclusions'] = previousExclusions.split(' ').map(x => `.${x}`).join(', ');
            }
            if (previousVersion < 65) {
            	newSettings['folders'] = [];
            }
        }
        /* END TODO: remove later */

        chrome.storage.local.set(newSettings);
        chrome.storage.local.remove(obsoleteSettingsList);
    });
}

/* Turns on/off content script across all tabs */
function setCuteState(state){
    const stateProps = state ? {text: 'on', color: '#6D6'} : {text: 'off', color: '#D66'};

    chrome.browserAction.setBadgeText({text: stateProps.text});
    chrome.browserAction.setBadgeBackgroundColor({color: stateProps.color});
}

chrome.browserAction.onClicked.addListener(() => {
    chrome.storage.local.get('isCute', items => chrome.storage.local.set({'isCute': !items.isCute}));
});

chrome.storage.onChanged.addListener(changes => {
    if (typeof changes.isCute === 'undefined') {return;}
    setCuteState(changes.isCute.newValue);
});
chrome.storage.local.get('isCute', items => setCuteState(items.isCute));
<|endoftext|>


<commit_before>/* global Notification */

/**
 * ownCloud - Mail
 *
 * This file is licensed under the Affero General Public License version 3 or
 * later. See the COPYING file.
 *
 * @author Christoph Wurst <christoph@winzerhof-wurst.at>
 * @copyright Christoph Wurst 2015
 */

define(function(require) {
	'use strict';

	var OC = require('OC');

	/*jshint maxparams: 6 */
	return {
		showNotification: function(title, body, tag, icon, accountId, folderId) {
			// notifications not supported -> go away
			if (typeof Notification === 'undefined') {
				return;
			}
			// browser is active -> go away
			var isWindowFocused = document.querySelector(':focus') !== null;
			if (isWindowFocused) {
				return;
			}
			var notification = new Notification(
				title,
				{
					body: body,
					tag: tag,
					icon: icon
				}
			);
			notification.onclick = function() {
				require('app').UI.loadFolder(accountId, folderId, false);
				window.focus();
			};
			setTimeout(function() {
				notification.close();
			}, 5000);
		},
		showMailNotification: function(email, folder) {
			if (Notification.permission === 'granted' && folder.messages.length > 0) {
				var from = _.map(folder.messages, function(m) {
					return m.from;
				});
				from = _.uniq(from);
				if (from.length > 2) {
					from = from.slice(0, 2);
					from.push('…');
				} else {
					from = from.slice(0, 2);
				}
				// special layout if there is only 1 new message
				var body = '';
				if (folder.messages.length === 1) {
					var subject = _.map(folder.messages, function(m) {
						return m.subject;
					});
					body = t('mail',
						'{from}\n{subject}', {
							from: from.join(),
							subject: subject.join()
						});
				} else {
					body = n('mail',
						'%n new message in {folderName} \nfrom {from}',
						'%n new messages in {folderName} \nfrom {from}',
						folder.messages.length, {
							folderName: folder.name,
							from: from.join()
						});
				}
				// If it's okay let's create a notification
				var tag = 'not-' + folder.accountId + '-' + folder.name;
				var icon = OC.filePath('mail', 'img', 'mail-notification.png');
				require('app').BackGround.showNotification(email, body, tag, icon, folder.accountId, folder.id);
			}
		},
		checkForNotifications: function() {
			_.each(require('app').State.accounts, function(a) {
				var localAccount = require('app').State.folderView.collection.get(a.accountId);
				var folders = localAccount.get('folders');

				$.ajax(
					OC.generateUrl('apps/mail/accounts/{accountId}/folders/detectChanges', {accountId: a.accountId}), {
					data: JSON.stringify({folders: folders.toJSON()}),
					contentType: 'application/json; charset=utf-8',
					dataType: 'json',
					type: 'POST',
					success: function(jsondata) {
						_.each(jsondata, function(f) {
							// send notification
							if (f.newUnReadCounter > 0) {
								require('app').UI.changeFavicon(OC.filePath('mail', 'img', 'favicon-notification.png'));
								// only show one notification
								if (require('app').State.accounts.length === 1 || a.accountId === -1) {
									require('app').BackGround.showMailNotification(localAccount.get('email'), f);
								}
							}

							// update folder status
							var localFolder = folders.get(f.id);
							localFolder.set('uidvalidity', f.uidvalidity);
							localFolder.set('uidnext', f.uidnext);
							localFolder.set('unseen', f.unseen);
							localFolder.set('total', f.total);

							// reload if current selected folder has changed
							if (require('app').State.currentAccountId === f.accountId &&
								require('app').State.currentFolderId === f.id) {
								require('app').UI.messageView.collection.add(f.messages);
							}

							// Save new messages to the cached message list
							var cachedList = require('app').Cache.getMessageList(f.accountId, f.id);
							if (cachedList) {
								cachedList = cachedList.concat(f.messages);
								require('app').Cache.addMessageList(f.accountId, f.id, cachedList);
							}

							require('app').State.folderView.updateTitle();
						});
					}
				}
				);
			});
		},
		/**
		 * Fetch message of the current account/folder in background
		 *
		 * Uses a queue where message IDs are stored and fetched periodically
		 * The message is only fetched if it's not already cached
		 */
		messageFetcher: (function() {
			var accountId = null;
			var folderId = null;
			var pollIntervall = 3 * 1000;
			var queue = [];
			var timer = null;

			function fetch() {
				if (queue.length > 0) {
					// Empty waiting queue
					var messages = queue;
					queue = [];

					require('app').Communication.fetchMessages(accountId, folderId, messages, {
						onSuccess: function(messages) {
							require('app').Cache.addMessages(accountId, folderId, messages);
						}
					});
				}
			}

			return {
				start: function() {
					accountId = require('app').State.currentAccountId;
					folderId = require('app').State.currentFolderId;
					timer = setInterval(fetch, pollIntervall);
				},
				restart: function() {
					// Stop previous fetcher
					clearInterval(timer);

					// Clear waiting queue
					queue.length = 0;

					// Start again
					this.start();
				},
				push: function(message) {
					queue.push(message);
				}
			};
		}())
	};
});
<commit_msg>Refactor background<commit_after>/* global Notification */

/**
 * ownCloud - Mail
 *
 * This file is licensed under the Affero General Public License version 3 or
 * later. See the COPYING file.
 *
 * @author Christoph Wurst <christoph@winzerhof-wurst.at>
 * @copyright Christoph Wurst 2015
 */

define(function(require) {
	'use strict';

	var OC = require('OC');

	/*jshint maxparams: 6 */
	function showNotification(title, body, tag, icon, accountId, folderId) {
		// notifications not supported -> go away
		if (typeof Notification === 'undefined') {
			return;
		}
		// browser is active -> go away
		var isWindowFocused = document.querySelector(':focus') !== null;
		if (isWindowFocused) {
			return;
		}
		var notification = new Notification(
			title,
			{
				body: body,
				tag: tag,
				icon: icon
			}
		);
		notification.onclick = function() {
			require('app').UI.loadFolder(accountId, folderId, false);
			window.focus();
		};
		setTimeout(function() {
			notification.close();
		}, 5000);
	}

	function showMailNotification(email, folder) {
		if (Notification.permission === 'granted' && folder.messages.length > 0) {
			var from = _.map(folder.messages, function(m) {
				return m.from;
			});
			from = _.uniq(from);
			if (from.length > 2) {
				from = from.slice(0, 2);
				from.push('…');
			} else {
				from = from.slice(0, 2);
			}
			// special layout if there is only 1 new message
			var body = '';
			if (folder.messages.length === 1) {
				var subject = _.map(folder.messages, function(m) {
					return m.subject;
				});
				body = t('mail',
					'{from}\n{subject}', {
						from: from.join(),
						subject: subject.join()
					});
			} else {
				body = n('mail',
					'%n new message in {folderName} \nfrom {from}',
					'%n new messages in {folderName} \nfrom {from}',
					folder.messages.length, {
						folderName: folder.name,
						from: from.join()
					});
			}
			// If it's okay let's create a notification
			var tag = 'not-' + folder.accountId + '-' + folder.name;
			var icon = OC.filePath('mail', 'img', 'mail-notification.png');
			require('app').BackGround.showNotification(email, body, tag, icon, folder.accountId, folder.id);
		}
	}

	function checkForNotifications() {
		_.each(require('app').State.accounts, function(a) {
			var localAccount = require('app').State.folderView.collection.get(a.accountId);
			var folders = localAccount.get('folders');

			$.ajax(
				OC.generateUrl('apps/mail/accounts/{accountId}/folders/detectChanges', {accountId: a.accountId}), {
				data: JSON.stringify({folders: folders.toJSON()}),
				contentType: 'application/json; charset=utf-8',
				dataType: 'json',
				type: 'POST',
				success: function(jsondata) {
					_.each(jsondata, function(f) {
						// send notification
						if (f.newUnReadCounter > 0) {
							require('app').UI.changeFavicon(OC.filePath('mail', 'img', 'favicon-notification.png'));
							// only show one notification
							if (require('app').State.accounts.length === 1 || a.accountId === -1) {
								require('app').BackGround.showMailNotification(localAccount.get('email'), f);
							}
						}

						// update folder status
						var localFolder = folders.get(f.id);
						localFolder.set('uidvalidity', f.uidvalidity);
						localFolder.set('uidnext', f.uidnext);
						localFolder.set('unseen', f.unseen);
						localFolder.set('total', f.total);

						// reload if current selected folder has changed
						if (require('app').State.currentAccountId === f.accountId &&
							require('app').State.currentFolderId === f.id) {
							require('app').UI.messageView.collection.add(f.messages);
						}

						// Save new messages to the cached message list
						var cachedList = require('app').Cache.getMessageList(f.accountId, f.id);
						if (cachedList) {
							cachedList = cachedList.concat(f.messages);
							require('app').Cache.addMessageList(f.accountId, f.id, cachedList);
						}

						require('app').State.folderView.updateTitle();
					});
				}
			}
			);
		});
	}
	/**
	 * Fetch message of the current account/folder in background
	 *
	 * Uses a queue where message IDs are stored and fetched periodically
	 * The message is only fetched if it's not already cached
	 */
	function MessageFetcher() {
		var accountId = null;
		var folderId = null;
		var pollIntervall = 3 * 1000;
		var queue = [];
		var timer = null;

		function fetch() {
			if (queue.length > 0) {
				// Empty waiting queue
				var messages = queue;
				queue = [];

				require('app').Communication.fetchMessages(accountId, folderId, messages, {
					onSuccess: function(messages) {
						require('app').Cache.addMessages(accountId, folderId, messages);
					}
				});
			}
		}

		return {
			start: function() {
				accountId = require('app').State.currentAccountId;
				folderId = require('app').State.currentFolderId;
				timer = setInterval(fetch, pollIntervall);
			},
			restart: function() {
				// Stop previous fetcher
				clearInterval(timer);

				// Clear waiting queue
				queue.length = 0;

				// Start again
				this.start();
			},
			push: function(message) {
				queue.push(message);
			}
		};
	}

	return {
		messageFetcher: new MessageFetcher(),
		checkForNotifications: checkForNotifications,
		showNotification: showNotification,
		showMailNotification: showMailNotification
	};
});
<|endoftext|>


<commit_before>/* global chrome Github */
chrome.browserAction.onClicked.addListener((tab) => { // eslint-disable-line no-unused-vars
  chrome.tabs.create({
    url: chrome.extension.getURL('listen1.html'),
  }, (new_tab) => { // eslint-disable-line no-unused-vars
    // Tab opened.
  });
});

function hack_referer_header(details) {
  const replace_referer = true;
  let replace_origin = true;
  const add_referer = true;
  let add_origin = true;

  let referer_value = '';
  let origin_value = "";

  if (details.url.indexOf('://music.163.com/') !== -1) {
    referer_value = 'http://music.163.com/';
  }
  if (details.url.indexOf('://gist.githubusercontent.com/') !== -1) {
    referer_value = 'https://gist.githubusercontent.com/';
  }

  if (details.url.indexOf('api.xiami.com/') !== -1 || details.url.indexOf('.xiami.com/song/playlist/id/') !== -1
    || details.url.indexOf('www.xiami.com/api/') !== -1
  ) {
    add_origin = false;
    referer_value = 'https://www.xiami.com';
  }

  if (details.url.indexOf('www.xiami.com/api/search/searchSongs') !== -1) {
    const key = /key%22:%22(.*?)%22/.exec(details.url)[1];
    add_origin = false;
    referer_value = `https://www.xiami.com/search?key=${key}`;
  }

  if (details.url.indexOf('c.y.qq.com/') !== -1) {
    referer_value = 'https://y.qq.com/';
    origin_value = "https://y.qq.com";
  }
  if ((details.url.indexOf('i.y.qq.com/') !== -1)
    || (details.url.indexOf('qqmusic.qq.com/') !== -1)
    || (details.url.indexOf('music.qq.com/') !== -1)
    || (details.url.indexOf('imgcache.qq.com/') !== -1)) {
    referer_value = 'https://y.qq.com/';
  }

  if (details.url.indexOf('.kugou.com/') !== -1) {
    referer_value = 'http://www.kugou.com/';
  }

  if (details.url.indexOf('.kuwo.cn/') !== -1) {
    referer_value = 'http://www.kuwo.cn/';
  }

  if (details.url.indexOf('.bilibili.com/') !== -1 || details.url.indexOf(".bilivideo.com/") !== -1) {
    referer_value = 'https://www.bilibili.com/';
    replace_origin = false;
    add_origin = false;
  }
  if (details.url.indexOf('.migu.cn') !== -1) {
    referer_value = 'http://music.migu.cn/v3/music/player/audio?from=migu';
  }
  if (origin_value == "") {
    origin_value = referer_value;
  }

  let isRefererSet = false;
  let isOriginSet = false;
  const headers = details.requestHeaders;
  const blockingResponse = {};

  for (let i = 0, l = headers.length; i < l; i += 1) {
    if (replace_referer && (headers[i].name === 'Referer') && (referer_value !== '')) {
      headers[i].value = referer_value;
      isRefererSet = true;
    }
    if (replace_origin && (headers[i].name === 'Origin') && (origin_value !== '')) {
      headers[i].value = origin_value;
      isOriginSet = true;
    }
  }

  if (add_referer && (!isRefererSet) && (referer_value !== '')) {
    headers.push({
      name: 'Referer',
      value: referer_value,
    });
  }

  if (add_origin && (!isOriginSet) && (origin_value !== '')) {
    headers.push({
      name: 'Origin',
      value: origin_value,
    });
  }

  blockingResponse.requestHeaders = headers;
  return blockingResponse;
}

const urls = ['*://music.163.com/*', '*://*.xiami.com/*', '*://i.y.qq.com/*', '*://c.y.qq.com/*', '*://*.kugou.com/*', '*://*.kuwo.cn/*', '*://*.bilibili.com/*', "*://*.bilivideo.com/*", '*://*.migu.cn/*', '*://*.githubusercontent.com/*'];

try {
  chrome.webRequest.onBeforeSendHeaders.addListener(hack_referer_header, {
    urls: urls,
  }, ['requestHeaders', 'blocking','extraHeaders']);
}
catch(err) {
  // before chrome v72, extraHeader is not supported
  chrome.webRequest.onBeforeSendHeaders.addListener(hack_referer_header, {
    urls: urls,
  }, ['requestHeaders', 'blocking']);
}

/**
 * Get tokens.
 */

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  const code = request.query.split('=')[1];
  Github.handleCallback(code);
  sendResponse();
});

// at end of background.js
chrome.commands.onCommand.addListener((command) => {
  const [viewWindow] = chrome.extension.getViews().filter(p => p.location.href.endsWith('listen1.html'));

  switch (command) {
    case 'play_next':
      viewWindow.document.querySelector('.li-next').click();
      break;
    case 'play_prev':
      viewWindow.document.querySelector('.li-previous').click();
      break;
    case 'play_pause':
      viewWindow.document.querySelector('.play').click();
      break;
    default:
      // console.log('不支持的快捷键')
  }
});
<commit_msg>add wild url pattern for xiami s**.xiami.com<commit_after>/* global chrome Github */
chrome.browserAction.onClicked.addListener((tab) => { // eslint-disable-line no-unused-vars
  chrome.tabs.create({
    url: chrome.extension.getURL('listen1.html'),
  }, (new_tab) => { // eslint-disable-line no-unused-vars
    // Tab opened.
  });
});

function hack_referer_header(details) {
  const replace_referer = true;
  let replace_origin = true;
  const add_referer = true;
  let add_origin = true;

  let referer_value = '';
  let origin_value = "";

  if (details.url.indexOf('://music.163.com/') !== -1) {
    referer_value = 'http://music.163.com/';
  }
  if (details.url.indexOf('://gist.githubusercontent.com/') !== -1) {
    referer_value = 'https://gist.githubusercontent.com/';
  }

  if (details.url.indexOf(".xiami.com/") !== -1) {
    add_origin = false;
    referer_value = "https://www.xiami.com";
  }

  if (details.url.indexOf('www.xiami.com/api/search/searchSongs') !== -1) {
    const key = /key%22:%22(.*?)%22/.exec(details.url)[1];
    add_origin = false;
    referer_value = `https://www.xiami.com/search?key=${key}`;
  }

  if (details.url.indexOf('c.y.qq.com/') !== -1) {
    referer_value = 'https://y.qq.com/';
    origin_value = "https://y.qq.com";
  }
  if ((details.url.indexOf('i.y.qq.com/') !== -1)
    || (details.url.indexOf('qqmusic.qq.com/') !== -1)
    || (details.url.indexOf('music.qq.com/') !== -1)
    || (details.url.indexOf('imgcache.qq.com/') !== -1)) {
    referer_value = 'https://y.qq.com/';
  }

  if (details.url.indexOf('.kugou.com/') !== -1) {
    referer_value = 'http://www.kugou.com/';
  }

  if (details.url.indexOf('.kuwo.cn/') !== -1) {
    referer_value = 'http://www.kuwo.cn/';
  }

  if (details.url.indexOf('.bilibili.com/') !== -1 || details.url.indexOf(".bilivideo.com/") !== -1) {
    referer_value = 'https://www.bilibili.com/';
    replace_origin = false;
    add_origin = false;
  }
  if (details.url.indexOf('.migu.cn') !== -1) {
    referer_value = 'http://music.migu.cn/v3/music/player/audio?from=migu';
  }
  if (origin_value == "") {
    origin_value = referer_value;
  }

  let isRefererSet = false;
  let isOriginSet = false;
  const headers = details.requestHeaders;
  const blockingResponse = {};

  for (let i = 0, l = headers.length; i < l; i += 1) {
    if (replace_referer && (headers[i].name === 'Referer') && (referer_value !== '')) {
      headers[i].value = referer_value;
      isRefererSet = true;
    }
    if (replace_origin && (headers[i].name === 'Origin') && (origin_value !== '')) {
      headers[i].value = origin_value;
      isOriginSet = true;
    }
  }

  if (add_referer && (!isRefererSet) && (referer_value !== '')) {
    headers.push({
      name: 'Referer',
      value: referer_value,
    });
  }

  if (add_origin && (!isOriginSet) && (origin_value !== '')) {
    headers.push({
      name: 'Origin',
      value: origin_value,
    });
  }

  blockingResponse.requestHeaders = headers;
  return blockingResponse;
}

const urls = ['*://music.163.com/*', '*://*.xiami.com/*', '*://i.y.qq.com/*', '*://c.y.qq.com/*', '*://*.kugou.com/*', '*://*.kuwo.cn/*', '*://*.bilibili.com/*', "*://*.bilivideo.com/*", '*://*.migu.cn/*', '*://*.githubusercontent.com/*'];

try {
  chrome.webRequest.onBeforeSendHeaders.addListener(hack_referer_header, {
    urls: urls,
  }, ['requestHeaders', 'blocking','extraHeaders']);
}
catch(err) {
  // before chrome v72, extraHeader is not supported
  chrome.webRequest.onBeforeSendHeaders.addListener(hack_referer_header, {
    urls: urls,
  }, ['requestHeaders', 'blocking']);
}

/**
 * Get tokens.
 */

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  const code = request.query.split('=')[1];
  Github.handleCallback(code);
  sendResponse();
});

// at end of background.js
chrome.commands.onCommand.addListener((command) => {
  const [viewWindow] = chrome.extension.getViews().filter(p => p.location.href.endsWith('listen1.html'));

  switch (command) {
    case 'play_next':
      viewWindow.document.querySelector('.li-next').click();
      break;
    case 'play_prev':
      viewWindow.document.querySelector('.li-previous').click();
      break;
    case 'play_pause':
      viewWindow.document.querySelector('.play').click();
      break;
    default:
      // console.log('不支持的快捷键')
  }
});
<|endoftext|>


<commit_before>/* Background JS for Stylebot */

var currTabId;

var cache = {
    /*
        e.g. styles = {
            'google.com' : rules
        }
    */
    styles: {}
};

function init(){
    addListeners();
    loadStylesIntoCache();
}

function addListeners(){
    chrome.pageAction.onClicked.addListener(handlePageIconClick);

    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
        chrome.pageAction.show(tabId);
    });

    chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
        switch(request.name){
            case "enablePageIcon"   : enablePageIcon(sender.tab.id); break;
            case "disablePageIcon"  : disablePageIcon(sender.tab.id); break;
            case "copyToClipboard"  : copyToClipboard(request.text); break;
            case "save"             : save(request.domain, request.rules); break;
            case "getRulesForPage"  : sendResponse( { rules: getRulesForPage(request.domain) }); break;
        }
    });
}

/**
 * Page Action handling
 **/

// Toggle CSS editing when page icon is clicked
function handlePageIconClick(tab) {
    currTabId = tab.id;
    chrome.tabs.sendRequest(currTabId, { name: "toggle" }, function(response){
        if(response.status)
            enablePageIcon(currTabId);
        else
            disablePageIcon(currTabId);
    });
}

function enablePageIcon(tabId) {
    chrome.pageAction.setIcon({ tabId: tabId, path: "images/icon19_on.png" });
    chrome.pageAction.setTitle({ tabId: tabId, title: "Click to turn CSS editing off" });
}

function disablePageIcon(tabId) {
    chrome.pageAction.setIcon({ tabId: tabId, path: "images/icon19_off.png" });
    chrome.pageAction.setTitle({ tabId: tabId, title: "Click to turn CSS editing on" });
}

// Copy to Clipboard
function copyToClipboard(text) {
    var copyTextarea = document.createElement('textarea');
    document.body.appendChild(copyTextarea);
    copyTextarea.value = text;
    copyTextarea.select();
    document.execCommand('copy');
    document.body.removeChild(copyTextarea);
}

// save rules
function save(domain, rules) {
    cache.styles[domain] = rules;

    // for now, simply store them in localStorage. In future, they'll stored in a bookmark / db
    localStorage['stylebot_styles'] = JSON.stringify(cache.styles);
}

function loadStylesIntoCache() {
    cache.styles = JSON.parse(localStorage['stylebot_styles']);
}

function getRulesForPage(domain) {
    var rules = cache.styles[domain];
    console.log("Rules in background.js: " + rules);
    if(rules != undefined)
        return rules;
    else
        return null;
}

window.addEventListener('load', function(){
    init();
});<commit_msg>Part of url is checked instead of comparing document.domain when applying custom style<commit_after>/* Background JS for Stylebot */

var currTabId;

var cache = {
    /*
        e.g. styles = {
            'google.com' : rules
        }
    */
    styles: {}
};

function init(){
    addListeners();
    loadStylesIntoCache();
}

function addListeners(){
    chrome.pageAction.onClicked.addListener(handlePageIconClick);

    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
        chrome.pageAction.show(tabId);
    });

    chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
        switch(request.name){
            case "enablePageIcon"   : enablePageIcon(sender.tab.id); break;
            case "disablePageIcon"  : disablePageIcon(sender.tab.id); break;
            case "copyToClipboard"  : copyToClipboard(request.text); break;
            case "save"             : save(request.domain, request.rules); break;
            case "getRulesForPage"  : sendResponse( { rules: getRulesForPage(request.domain) }); break;
        }
    });
}

/**
 * Page Action handling
 **/

// Toggle CSS editing when page icon is clicked
function handlePageIconClick(tab) {
    currTabId = tab.id;
    chrome.tabs.sendRequest(currTabId, { name: "toggle" }, function(response){
        if(response.status)
            enablePageIcon(currTabId);
        else
            disablePageIcon(currTabId);
    });
}

function enablePageIcon(tabId) {
    chrome.pageAction.setIcon({ tabId: tabId, path: "images/icon19_on.png" });
    chrome.pageAction.setTitle({ tabId: tabId, title: "Click to turn CSS editing off" });
}

function disablePageIcon(tabId) {
    chrome.pageAction.setIcon({ tabId: tabId, path: "images/icon19_off.png" });
    chrome.pageAction.setTitle({ tabId: tabId, title: "Click to turn CSS editing on" });
}

// Copy to Clipboard
function copyToClipboard(text) {
    var copyTextarea = document.createElement('textarea');
    document.body.appendChild(copyTextarea);
    copyTextarea.value = text;
    copyTextarea.select();
    document.execCommand('copy');
    document.body.removeChild(copyTextarea);
}

// save rules
function save(url, rules) {
    cache.styles[url] = rules;

    // for now, simply store them in localStorage. In future, they'll stored in a bookmark / db
    localStorage['stylebot_styles'] = JSON.stringify(cache.styles);
}

function loadStylesIntoCache() {
    cache.styles = JSON.parse( localStorage['stylebot_styles'] );
}

function getRulesForPage(currentUrl) {
    var rules = {};
    for(var url in cache.styles)
    {
        if(currentUrl.indexOf(url) != -1)
        {
            for(var property in cache.styles[url])
                rules[property] = cache.styles[url][property];
        }
    }
    if(rules != undefined)
        return rules;
    else
        return null;
}

window.addEventListener('load', function(){
    init();
});<|endoftext|>