<commit_before>function GM_xmlhttpRequester(unsafeContentWin, chromeWindow) {
  this.unsafeContentWin = unsafeContentWin;
  this.chromeWindow = chromeWindow;
}

// this function gets called by user scripts in content security scope to
// start a cross-domain xmlhttp request.
//
// details should look like:
// {method,url,onload,onerror,onreadystatechange,headers,data}
// headers should be in the form {name:value,name:value,etc}
// can't support mimetype because i think it's only used for forcing
// text/xml and we can't support that
GM_xmlhttpRequester.prototype.contentStartRequest = function(details) {
  if (!GM_apiLeakCheck("GM_xmlhttpRequest")) {
    return;
  }

  // don't actually need the timer functionality, but this pops it
  // out into chromeWindow's thread so that we get that security
  // context.
  GM_log("> GM_xmlhttpRequest.contentStartRequest");

  // important to store this locally so that content cannot trick us up with
  // a fancy getter that checks the number of times it has been accessed,
  // returning a dangerous URL the time that we actually use it.
  var url = details.url;

  // make sure that we have an actual string so that we can't be fooled with
  // tricky toString() implementations.
  if (typeof url != "string") {
    throw new Error("Invalid url: url must be of type string");
  }

  var ioService = Components.classes["@mozilla.org/network/io-service;1"]
                  .getService(Components.interfaces.nsIIOService);
  var scheme = ioService.extractScheme(url);

  // This is important - without it, GM_xmlhttpRequest can be used to get
  // access to things like files and chrome. Careful.
  switch (scheme) {
    case "http":
    case "https":
    case "ftp":
      this.chromeWindow.setTimeout(
        GM_hitch(this, "chromeStartRequest", url, details), 0);
      break;
    default:
      throw new Error("Invalid url: " + url);
  }

  GM_log("< GM_xmlhttpRequest.contentStartRequest");
};

// this function is intended to be called in chrome's security context, so
// that it can access other domains without security warning
GM_xmlhttpRequester.prototype.chromeStartRequest = function(safeUrl, details) {
  GM_log("> GM_xmlhttpRequest.chromeStartRequest");
  var req = new this.chromeWindow.XMLHttpRequest();

  this.setupRequestEvent(this.unsafeContentWin, req, "onload", details);
  this.setupRequestEvent(this.unsafeContentWin, req, "onerror", details);
  this.setupRequestEvent(this.unsafeContentWin, req, "onreadystatechange",
                         details);

  req.open(details.method, safeUrl);

  if (details.overrideMimeType) {
    req.overrideMimeType(details.overrideMimeType);
  }

  if (details.headers) {
    for (var prop in details.headers) {
      req.setRequestHeader(prop, details.headers[prop]);
    }
  }

  var body = details.data ? details.data : null;
  if (details.binary) {
    // xhr supports binary?
    if (!req.sendAsBinary) {
      var err = new Error("Unavailable feature: " +
              "This version of Firefox does not support sending binary data " +
              "(you should consider upgrading to version 3 or newer.)");
      GM_logError(err);
      throw err;
    }
    req.sendAsBinary(body);
  } else {
    req.send(body);
  }

  GM_log("< GM_xmlhttpRequest.chromeStartRequest");
}

// arranges for the specified 'event' on xmlhttprequest 'req' to call the
// method by the same name which is a property of 'details' in the content
// window's security context.
GM_xmlhttpRequester.prototype.setupRequestEvent =
function(unsafeContentWin, req, event, details) {
  GM_log("> GM_xmlhttpRequester.setupRequestEvent");

  if (details[event]) {
    req[event] = function() {
      GM_log("> GM_xmlhttpRequester -- callback for " + event);

      var responseState = {
        // can't support responseXML because security won't
        // let the browser call properties on it
        responseText: req.responseText,
        readyState: req.readyState,
        responseHeaders: null,
        status: null,
        statusText: null,
        finalUrl: null
      };
      if (4 == req.readyState && 'onerror' != event) {
        responseState.responseHeaders = req.getAllResponseHeaders();
        responseState.status = req.status;
        responseState.statusText = req.statusText;
        responseState.finalUrl = req.channel.URI.spec;
      }

      // Pop back onto browser thread and call event handler.
      // Have to use nested function here instead of GM_hitch because
      // otherwise details[event].apply can point to window.setTimeout, which
      // can be abused to get increased priveledges.
      new XPCNativeWrapper(unsafeContentWin, "setTimeout()")
        .setTimeout(function(){details[event](responseState);}, 0);

      GM_log("< GM_xmlhttpRequester -- callback for " + event);
    }
  }

  GM_log("< GM_xmlhttpRequester.setupRequestEvent");
};
<commit_msg>Closes #1007<commit_after>function GM_xmlhttpRequester(unsafeContentWin, chromeWindow) {
  this.unsafeContentWin = unsafeContentWin;
  this.chromeWindow = chromeWindow;
}

// this function gets called by user scripts in content security scope to
// start a cross-domain xmlhttp request.
//
// details should look like:
// {method,url,onload,onerror,onreadystatechange,headers,data}
// headers should be in the form {name:value,name:value,etc}
// can't support mimetype because i think it's only used for forcing
// text/xml and we can't support that
GM_xmlhttpRequester.prototype.contentStartRequest = function(details) {
  if (!GM_apiLeakCheck("GM_xmlhttpRequest")) {
    return;
  }

  GM_log("> GM_xmlhttpRequest.contentStartRequest");

  // Store this value by looking at it exactly once, and guaranteeing (via null
  // prepend) that it is a string, and not an object that might play tricks
  // with multiple .toString() calls.
  var url = '' + details.url;

  try {
    var ioService = Components.classes["@mozilla.org/network/io-service;1"]
                    .getService(Components.interfaces.nsIIOService);
    var scheme = ioService.extractScheme(url);
  } catch (e) {
    // A malformed URL won't be parsed properly.
    throw new Error('Invalid URL: '+url);
  }

  // This is important - without it, GM_xmlhttpRequest can be used to get
  // access to things like files and chrome. Careful.
  switch (scheme) {
    case "http":
    case "https":
    case "ftp":
        var req = new this.chromeWindow.XMLHttpRequest();
        GM_hitch(this, "chromeStartRequest", url, details, req)();
      break;
    default:
      throw new Error("Invalid url: " + url);
  }

  GM_log("< GM_xmlhttpRequest.contentStartRequest");

  return {
    abort: function() {
      alert('got abort!');
      req.abort();
    }
  };
};

// this function is intended to be called in chrome's security context, so
// that it can access other domains without security warning
GM_xmlhttpRequester.prototype.chromeStartRequest =
function(safeUrl, details, req) {
  GM_log("> GM_xmlhttpRequest.chromeStartRequest");

  this.setupRequestEvent(this.unsafeContentWin, req, "onload", details);
  this.setupRequestEvent(this.unsafeContentWin, req, "onerror", details);
  this.setupRequestEvent(this.unsafeContentWin, req, "onreadystatechange",
                         details);

  req.open(details.method, safeUrl);

  if (details.overrideMimeType) {
    req.overrideMimeType(details.overrideMimeType);
  }

  if (details.headers) {
    for (var prop in details.headers) {
      req.setRequestHeader(prop, details.headers[prop]);
    }
  }

  var body = details.data ? details.data : null;
  if (details.binary) {
    // xhr supports binary?
    if (!req.sendAsBinary) {
      var err = new Error("Unavailable feature: " +
              "This version of Firefox does not support sending binary data " +
              "(you should consider upgrading to version 3 or newer.)");
      GM_logError(err);
      throw err;
    }
    req.sendAsBinary(body);
  } else {
    req.send(body);
  }

  GM_log("< GM_xmlhttpRequest.chromeStartRequest");
}

// arranges for the specified 'event' on xmlhttprequest 'req' to call the
// method by the same name which is a property of 'details' in the content
// window's security context.
GM_xmlhttpRequester.prototype.setupRequestEvent =
function(unsafeContentWin, req, event, details) {
  GM_log("> GM_xmlhttpRequester.setupRequestEvent");

  if (details[event]) {
    req[event] = function() {
      GM_log("> GM_xmlhttpRequester -- callback for " + event);

      var responseState = {
        // can't support responseXML because security won't
        // let the browser call properties on it
        responseText: req.responseText,
        readyState: req.readyState,
        responseHeaders: null,
        status: null,
        statusText: null,
        finalUrl: null
      };
      if (4 == req.readyState && 'onerror' != event) {
        responseState.responseHeaders = req.getAllResponseHeaders();
        responseState.status = req.status;
        responseState.statusText = req.statusText;
        responseState.finalUrl = req.channel.URI.spec;
      }

      // Pop back onto browser thread and call event handler.
      // Have to use nested function here instead of GM_hitch because
      // otherwise details[event].apply can point to window.setTimeout, which
      // can be abused to get increased priveledges.
      new XPCNativeWrapper(unsafeContentWin, "setTimeout()")
        .setTimeout(function(){details[event](responseState);}, 0);

      GM_log("< GM_xmlhttpRequester -- callback for " + event);
    }
  }

  GM_log("< GM_xmlhttpRequester.setupRequestEvent");
};
<|endoftext|>


<commit_before>// LAYOUT.JS
import utils from './utils';

/**
 * Base class for controlling the layout of each 'row' on the form
 * Can be extended & customised with the new object being passed to FormRender as the new layout object
 * Controls things like the label, help text, and how they fit together with the control itself
 */
export class layout {

  /**
   * Prepare the templates for layout
   * @param {Object} templates object containing custom or overwrite templates
   * @param {Boolean} preview - are we rendering a preview for the formBuilder stage
   */
  constructor(templates, preview) {
    this.preview = preview;

    // supported templates for outputting a field
    // preferred layout template can be indicated by specifying a 'layout' in the return object of control::build
    this.templates = {
      label: null, // can be overridden with a function(labelDOMElements, data) to generate the label element - returns a DOM element
      help: null, // can be overridden with a function(helpText, data) to generate the help element - returns a DOM element
      default: (field, label, help, data) => {
        // append help into the label
        if (help) {
          label.append(help);
        }

        // wrap the output in a form-group div & return
        let className = data.id ? `fb-${data.type} form-group field-${data.id}` : '';
        return this.markup('div', [label, field], {
          className: className
        });
      },
      noLabel: (field, label, help, data) => {
        // wrap the output in a form-group div & return without a label element
        let className = data.id ? `fb-${data.type} form-group field-${data.id}` : '';
        return this.markup('div', field, {
          className: className
        });
      },
      hidden: (field, label, help, data) => {
        // no wrapper any any visible elements
        return field;
      }
    };

    // merge in any custom templates
    if (templates) {
      this.templates = $.extend(this.templates, templates);
    }
    this.configure();
  }

  /**
   * this method is called by the constructor and should be overwritten for custom layouts that need to
   * process the configuration arguments prior to rendering
   */
  configure() {}

  /**
   * Process the configuration from an element from the standard formData array
   * building the control, label and help text, and then putting them all together.
   * Should support the control object returning a DOM element, or an object containing
   * configuration properties:
   *   - field - the DOM element
   *   - noLabel - this control shouldn't have a label (nor a space for a label)
   *   - hidden - this control shouldn't render anything visible to the page
   * @param {Object} renderControl - the relevant control class
   * @param {Object} data - configuration data passed through formData for this control
   * @return {Object} element
   */
  build(renderControl, data) {
    // prepare the data
    if (this.preview) {
      if (data.name) {
        data.name = data.name + '-preview';
      } else {
        data.name = utils.nameAttr(data) + '-preview';
      }
    }
    data.id = data.name;
    this.data = $.extend({}, data);

    // build the control
    let control = new renderControl(data, this.preview);
    let field = control.build();
    if (typeof field !== 'object' || !field.field) {
      field = {field: field};
    }

    // build the label & help text
    let label = this.label();
    let help = this.help();

    // process the relevant layout template
    let template = this.templates[field.layout] || this.templates.default;
    let element = template(field.field, label, help, this.data);

    // handle templates returning jQuery elements
    if (element.jquery) {
      element = element[0];
    }

    // execute prerender events
    control.on('prerender')(element);

    // bind control on render events
    element.addEventListener('fieldRendered', control.on('render'));
    return element;
  }

  /**
   * Build a label element
   * @return {Object} dom element to render the label
   */
  label() {
    let label = this.data.label || '';
    let labelText = utils.parsedHtml(label);
    let labelContents = [labelText];
    if (this.data.required) {
      labelContents.push(this.markup('span', '*', {className: 'required'}));
    }

    // support an override template for labels
    if (typeof this.templates.label === 'function') {
      return this.templates.label(labelContents, this.data);
    }

    // generate a label element
    return this.markup('label', labelContents, {
      for: this.data.id,
      className: `fb-${this.data.type}-label`
    });
  }

  /**
   * Build a help element
   * @return {Object} dom element to render the help text
   */
  help() {
    if (!this.data.description) {
      return null;
    }

    // support an override template for labels
    if (typeof this.templates.help === 'function') {
      return this.templates.help(this.data.description, this.data);
    }

    // generate the default help element
    return this.markup('span', '?', {
      className: 'tooltip-element',
      tooltip: this.data.description
    });
  }

  /**
   * link to the utils.markup method
   * ideally this would be inherited from a parent 'dom' type element supporting dom helper type methods
   * @param {String} tag
   * @param {Object|String|Array} content
   * @param {Object} attributes
   * @return {Object} DOM element
   */
  markup(tag, content = '', attributes = {}) {
    return utils.markup(tag, content, attributes);
  }
}
<commit_msg>abstract layout template execution into processTemplate method. Better handling of jQuery object returns from label & help templates etc - fixes a bug<commit_after>// LAYOUT.JS
import utils from './utils';

/**
 * Base class for controlling the layout of each 'row' on the form
 * Can be extended & customised with the new object being passed to FormRender as the new layout object
 * Controls things like the label, help text, and how they fit together with the control itself
 */
export class layout {

  /**
   * Prepare the templates for layout
   * @param {Object} templates object containing custom or overwrite templates
   * @param {Boolean} preview - are we rendering a preview for the formBuilder stage
   */
  constructor(templates, preview) {
    this.preview = preview;

    // supported templates for outputting a field
    // preferred layout template can be indicated by specifying a 'layout' in the return object of control::build
    this.templates = {
      label: null, // can be overridden with a function(labelDOMElements, data) to generate the label element - returns a DOM element
      help: null, // can be overridden with a function(helpText, data) to generate the help element - returns a DOM element
      default: (field, label, help, data) => {
        // append help into the label
        if (help) {
          label.append(help);
        }

        // wrap the output in a form-group div & return
        let className = data.id ? `fb-${data.type} form-group field-${data.id}` : '';
        return this.markup('div', [label, field], {
          className: className
        });
      },
      noLabel: (field, label, help, data) => {
        // wrap the output in a form-group div & return without a label element
        let className = data.id ? `fb-${data.type} form-group field-${data.id}` : '';
        return this.markup('div', field, {
          className: className
        });
      },
      hidden: (field, label, help, data) => {
        // no wrapper any any visible elements
        return field;
      }
    };

    // merge in any custom templates
    if (templates) {
      this.templates = $.extend(this.templates, templates);
    }
    this.configure();
  }

  /**
   * this method is called by the constructor and should be overwritten for custom layouts that need to
   * process the configuration arguments prior to rendering
   */
  configure() {}

  /**
   * Process the configuration from an element from the standard formData array
   * building the control, label and help text, and then putting them all together.
   * Should support the control object returning a DOM element, or an object containing
   * configuration properties:
   *   - field - the DOM element
   *   - noLabel - this control shouldn't have a label (nor a space for a label)
   *   - hidden - this control shouldn't render anything visible to the page
   * @param {Object} renderControl - the relevant control class
   * @param {Object} data - configuration data passed through formData for this control
   * @return {Object} element
   */
  build(renderControl, data) {
    // prepare the data
    if (this.preview) {
      if (data.name) {
        data.name = data.name + '-preview';
      } else {
        data.name = utils.nameAttr(data) + '-preview';
      }
    }
    data.id = data.name;
    this.data = $.extend({}, data);

    // build the control
    let control = new renderControl(data, this.preview);
    let field = control.build();
    if (typeof field !== 'object' || !field.field) {
      field = {field: field};
    }

    // build the label & help text
    let label = this.label();
    let help = this.help();

    // process the relevant layout template
    let elementTemplate = this.isTemplate(field.layout) ? field.layout : 'default';
    let element = this.processTemplate(elementTemplate, field.field, label, help);

    // execute prerender events
    control.on('prerender')(element);

    // bind control on render events
    element.addEventListener('fieldRendered', control.on('render'));
    return element;
  }

  /**
   * Build a label element
   * @return {Object} dom element to render the label
   */
  label() {
    let label = this.data.label || '';
    let labelText = utils.parsedHtml(label);
    let labelContents = [labelText];
    if (this.data.required) {
      labelContents.push(this.markup('span', '*', {className: 'required'}));
    }

    // support an override template for labels
    if (this.isTemplate('label')) {
      return this.processTemplate('label', labelContents);
    }

    // generate a label element
    return this.markup('label', labelContents, {
      for: this.data.id,
      className: `fb-${this.data.type}-label`
    });
  }

  /**
   * Build a help element
   * @return {Object} dom element to render the help text
   */
  help() {
    if (!this.data.description) {
      return null;
    }

    // support an override template for labels
    if (this.isTemplate('help')) {
      return this.processTemplate('help', this.data.description);
    }

    // generate the default help element
    return this.markup('span', '?', {
      className: 'tooltip-element',
      tooltip: this.data.description
    });
  }

  /**
   * Determines if a template is defined for the specified key
   * @param template string template key to check for
   * @return {Boolean}
   */
  isTemplate(template) {
    return typeof this.templates[template] === 'function';
  }

  /**
   * Process a template & prepare the results
   * @param template - template key to execute
   * @param args - any number of args that should be passed to the template. this.data is sent as the last parameter to any template.
   * @return {DOMElement}
   */
  processTemplate(template, ...args) {
    let processed = this.templates[template](...args, this.data);
    if (processed.jquery) {
      processed = processed[0];
    }
    return processed;
  }

  /**
   * link to the utils.markup method
   * ideally this would be inherited from a parent 'dom' type element supporting dom helper type methods
   * @param {String} tag
   * @param {Object|String|Array} content
   * @param {Object} attributes
   * @return {Object} DOM element
   */
  markup(tag, content = '', attributes = {}) {
    return utils.markup(tag, content, attributes);
  }
}
<|endoftext|>


<commit_before>$(function() {

  console.log('Ready *__*');
  d3.select("body")
    .append("p")
    .text("New paragraph!");
  d3.csv("/public/data/small_samplers_newyear_casualties.csv", function(data) {
    console.log(data);
  });
});

<commit_msg>test d3 on A's page<commit_after>$(function() {

  console.log('Ready *__*');
  d3.select("body")
    .append("p")
    .text("New paragraph!");
  d3.csv("/public/data/100_samples_newyear_casualties.csv", function(data) {
    console.log(data);
  });
});

<|endoftext|>


<commit_before>/* global $:true */
+ function($) {

  var defaults;

  var Photos = function(config) {
    this.initConfig(config);
    this.index = 0;
  }

  Photos.prototype = {
    initConfig: function (config) {
      this.config = $.extend({}, defaults, config);
      this.activeIndex = this.lastActiveIndex = this.config.initIndex;

      this.config.items = this.config.items.map(function(d, i) {
        if(typeof d === typeof 'a') {
          return {
            image: d,
            caption: ''
          }
        }
        return d;
      });

      this.tpl = $.t7.compile(this.config.tpl);
      if(this.config.autoOpen) this.open();
    },

    open: function (index) {
      if (this._open) return false;
      if (!this.modal) {
        this.modal = $(this.tpl(this.config)).appendTo(document.body);
        this.container = this.modal.find('.swiper-container');
        this.wrapper = this.modal.find('.swiper-wrapper');

        var hammer = new Hammer(this.container[0]);
        hammer.get('pinch').set({ enable: true });
        hammer.on('pinchstart', $.proxy(this.onGestureStart, this));
        hammer.on('pinchmove', $.proxy(this.onGestureChange, this));
        hammer.on('pinchend', $.proxy(this.onGestureEnd, this));
        this.modal.on($.touchEvents.start, $.proxy(this.onTouchStart, this));
        this.modal.on($.touchEvents.move, $.proxy(this.onTouchMove, this));
        this.modal.on($.touchEvents.end, $.proxy(this.onTouchEnd, this));

        //init index
        this.wrapper.transition(0);
        this.wrapper.transform('translate3d(-' + $(window).width()*this.config.initIndex + 'px,0,0)');
        this.container.find('.caption-item').eq(this.config.initIndex).addClass('active');
        this.container.find('.swiper-pagination-bullet').eq(this.config.initIndex).addClass('swiper-pagination-bullet-active');
      }

      var self = this;
      this.modal.show().height();
      this.modal.addClass('weui-photo-browser-modal-visible');
      this.container.addClass('swiper-container-visible').transitionEnd(function() {
        self.initParams();
        if(self.config.onOpen) {
          self.config.onOpen.call(self);
        }
      });

      this._open = true;
      if(index !== undefined) {
        this.slideTo(index, 0);
      }
    },

    close: function() {
      this.container.transitionEnd($.proxy(function() {
        this.modal.hide();
        this._open = false;
        if(this.config.onClose) this.config.onClose.call(this);
      }, this));
      this.container.removeClass('swiper-container-visible');
      this.modal.removeClass('weui-photo-browser-modal-visible');
    },

    initParams: function () {
      if(this.containerHeight) return false;

      this.windowWidth = $(window).width();
      this.containerHeight = this.container.height();
      this.containerWidth = this.container.width();

      this.touchStart = {};

      this.wrapperTransform = 0;
      this.wrapperLastTransform = - $(window).width()*this.config.initIndex;
      this.wrapperDiff = 0;

      this.lastScale = 1;
      this.currentScale = 1;

      this.imageLastTransform = { x: 0, y: 0 };
      this.imageTransform = { x: 0, y: 0 };
      this.imageDiff = { x: 0, y: 0 };
      this.imageLastDiff = { x: 0, y: 0 };
    },

    onTouchStart: function (e) {
      if(this.scaling) return false;
      this.touching = true;
      this.touchStart = $.getTouchPosition(e);
      this.touchMove = null;
      this.touchStartTime = + new Date;
      this.wrapperDiff = 0;
      this.breakpointPosition = null;
    },

    onTouchMove: function (e) {
      if(!this.touching || this.scaling) return false;

      e.preventDefault();

      if(this.gestureImage) {
        var rect = this.gestureImage[0].getBoundingClientRect();
        if (rect.left >= 0 || rect.right <= this.windowWidth) {
          this.overflow = true;
        } else {
          this.overflow = false;
        }
      } else {
        this.oveflow = false;
      }
      var p = this.touchMove = $.getTouchPosition(e);
      if(this.currentScale === 1 || this.overflow) {
        if(this.breakpointPosition) {
          this.wrapperDiff = p.x - this.breakpointPosition.x;
        } else {
          this.wrapperDiff = p.x - this.touchStart.x;
        }
        if(this.activeIndex === 0 && this.wrapperDiff > 0) this.wrapperDiff = Math.pow(this.wrapperDiff, .8);
        if(this.activeIndex === this.config.items.length - 1 && this.wrapperDiff < 0) this.wrapperDiff = - Math.pow(-this.wrapperDiff, .8);
        this.wrapperTransform = this.wrapperLastTransform + this.wrapperDiff;
        this.doWrapperTransform();
      } else {
        var img = this.gestureImage;
        this.imageDiff = {
          x: p.x - this.touchStart.x,
          y: p.y - this.touchStart.y
        }

        this.imageTransform = {
          x: this.imageDiff.x + this.imageLastTransform.x,
          y: this.imageDiff.y + this.imageLastTransform.y
        };
        this.doImageTransform();

        this.breakpointPosition = p;

        this.imageLastDiff = this.imageDiff;
      }
    },

    onTouchEnd: function (e) {
      if(!this.touching) return false;
      this.touching = false;
      if(this.scaling) return false;
      var duration = (+ new Date) - this.touchStartTime;

      if(duration < 200 && (!this.touchMove || Math.abs(this.touchStart.x - this.touchMove.x) <= 2 && Math.abs(this.touchStart.y - this.touchMove.y) <= 2)) {
        this.onClick();
        return;
      }
      if(this.wrapperDiff > 0) {
        if(this.wrapperDiff > this.containerWidth/2 || (this.wrapperDiff > 20 && duration < 300)) {
          this.slidePrev();
        } else {
          this.slideTo(this.activeIndex, 200);
        }
      } else {
        if(- this.wrapperDiff > this.containerWidth/2 || (-this.wrapperDiff > 20 && duration < 300)) {
          this.slideNext();
        } else {
          this.slideTo(this.activeIndex, 200);
        }
      }

      this.imageLastTransform = this.imageTransform;

      this.adjust();
    },

    onClick: function () {
      var self = this;
      if (this._lastClickTime && ( + new Date - this._lastClickTime < 300)) {
        this.onDoubleClick();
        clearTimeout(this._clickTimeout);
      } else {
        this._clickTimeout = setTimeout(function () {
          self.close();
        }, 300);
      }
      this._lastClickTime = + new Date;
    },

    onDoubleClick: function () {
      this.gestureImage = this.container.find('.swiper-slide').eq(this.activeIndex).find('img');
      this.currentScale = this.currentScale > 1 ? 1 : 2;
      this.doImageTransform(200);
      this.adjust();
    },

    onGestureStart: function (e) {
      this.scaling = true;
      this.gestureImage = this.container.find('.swiper-slide').eq(this.activeIndex).find('img');
    },

    onGestureChange: function (e) {
      var s = this.lastScale * e.scale;
      if (s > this.config.maxScale) {
        s = this.config.maxScale + Math.pow((s - this.config.maxScale), 0.5);
      } else if (s < 1) {
        s = Math.pow(s, .5);
      }
      this.currentScale = s;
      this.doImageTransform();
    },

    onGestureEnd: function (e) {
      if (this.currentScale > this.config.maxScale) {
        this.currentScale = this.config.maxScale;
        this.doImageTransform(200);
      } else if (this.currentScale < 1) {
        this.currentScale = 1;
        this.doImageTransform(200);
      }
      this.lastScale = this.currentScale;
      this.scaling = false;
      this.adjust();
    },

    doWrapperTransform: function(duration, callback) {
      if (duration === 0) {
        var origin = this.wrapper.css('transition-property')
        this.wrapper.css('transition-property', 'none').transform('translate3d(' + this.wrapperTransform + 'px, 0, 0)');
        this.wrapper.css('transition-property', origin);
        callback()
      } else {
        this.wrapper.transitionEnd(function() {
          callback && callback();
        });
        this.wrapper.transition(duration || 0).transform('translate3d(' + this.wrapperTransform + 'px, 0, 0)');
      }
    },

    doImageTransform: function(duration, callback) {
      if(!this.gestureImage) return;
      this.gestureImage.transition(duration || 0).transform('translate3d(' + this.imageTransform.x + 'px,' + this.imageTransform.y + 'px, 0) scale(' + this.currentScale + ')');
      this._needAdjust = true;
    },

    adjust: function() {
      if(!this._needAdjust) return false;
      var img = this.gestureImage;
      if(!img) return false;
      if(this.currentScale === 1) {
        this.imageTransform = this.imageLastDiff =  {x:0,y:0};
        this.doImageTransform(200);
        return;
      }

      var rect = img[0].getBoundingClientRect();

      //调整上下
      if(rect.height < this.containerHeight) {  // 如果高度没容器高，则自动居中
        this.imageTransform.y = this.imageLastTransform.y = 0;
      } else {  //如果比容器高，那么要保证上下不能有空隙
        if(rect.top > 0) this.imageTransform.y = this.imageTransform.y - rect.top;
        else if(rect.bottom < this.containerHeight) this.imageTransform.y = this.imageTransform.y + this.containerHeight - rect.bottom;
      }

      this.doImageTransform(200);
      this._needAdjust = false; // must at last line, because doImageTransform will set this._needAdjust true
    },

    slideTo: function(index, duration) {
      if(index < 0) index = 0;
      if(index > this.config.items.length-1) index = this.config.items.length - 1;
      this.lastActiveIndex = this.activeIndex;
      this.activeIndex = index;
      this.wrapperTransform = - (index * this.containerWidth);
      this.wrapperLastTransform = this.wrapperTransform;
      this.doWrapperTransform(duration, $.proxy(function() {
        if(this.lastActiveIndex === this.activeIndex) return false; // active index not change
        this.container.find('.caption-item.active').removeClass('active');
        this.container.find('.swiper-slide-active').removeClass('swiper-slide-active');
        this.container.find('.swiper-pagination-bullet-active').removeClass('swiper-pagination-bullet-active');
        this.container.find('.caption-item').eq(this.activeIndex).addClass('active');
        this.container.find('.swiper-slide').eq(this.activeIndex).addClass('swiper-slide-active');
        this.container.find('.swiper-pagination-bullet').eq(this.activeIndex).addClass('swiper-pagination-bullet-active');

        //reset image transform
        this.container.find('.swiper-slide img[style]').transition(0).transform('translate3d(0,0,0) scale(1)');

        this.lastScale = 1;
        this.currentScale = 1;

        this.imageLastTransform = { x: 0, y: 0 };
        this.imageTransform = { x: 0, y: 0 };
        this.imageDiff = { x: 0, y: 0 };
        this.imageLastDiff = { x: 0, y: 0 };

        if(this.config.onSlideChange) {
          this.config.onSlideChange.call(this, this.activeIndex);
        }

      }, this));
    },
    slideNext: function() {
      return this.slideTo(this.activeIndex+1, 200);
    },
    slidePrev: function() {
      return this.slideTo(this.activeIndex-1, 200);
    }
  }

  defaults = Photos.prototype.defaults = {
    items: [],
    autoOpen: false, //初始化完成之后立刻打开
    onOpen: undefined,
    onClose: undefined,
    initIndex: 0, //打开时默认显示第几张
    maxScale: 3,
    onSlideChange: undefined,
    tpl: '
\

\

\
                {{#items}}\

\

\
                    \

\

\
                {{/items}}\

\

\
                {{#items}}\

{{caption}}
\
                {{/items}}\

\

\
                {{#items}}\
                \
                {{/items}}\

\

\

'
  }

  $.photoBrowser = function(params) {
    return new Photos(params);
  }
}($);
<commit_msg>fix #369<commit_after>/* global $:true */
+ function($) {

  var defaults;

  var Photos = function(config) {
    this.initConfig(config);
    this.index = 0;
  }

  Photos.prototype = {
    initConfig: function (config) {
      this.config = $.extend({}, defaults, config);
      this.activeIndex = this.lastActiveIndex = this.config.initIndex;

      this.config.items = this.config.items.map(function(d, i) {
        if(typeof d === typeof 'a') {
          return {
            image: d,
            caption: ''
          }
        }
        return d;
      });

      this.tpl = $.t7.compile(this.config.tpl);
      if(this.config.autoOpen) this.open();
    },

    open: function (index) {
      if (this._open) return false;
      if (!this.modal) {
        this.modal = $(this.tpl(this.config)).appendTo(document.body);
        this.container = this.modal.find('.swiper-container');
        this.wrapper = this.modal.find('.swiper-wrapper');

        var hammer = new Hammer(this.container[0]);
        hammer.get('pinch').set({ enable: true });
        hammer.on('pinchstart', $.proxy(this.onGestureStart, this));
        hammer.on('pinchmove', $.proxy(this.onGestureChange, this));
        hammer.on('pinchend', $.proxy(this.onGestureEnd, this));
        this.modal.on($.touchEvents.start, $.proxy(this.onTouchStart, this));
        this.modal.on($.touchEvents.move, $.proxy(this.onTouchMove, this));
        this.modal.on($.touchEvents.end, $.proxy(this.onTouchEnd, this));

        //init index
        this.wrapper.transition(0);
        this.wrapper.transform('translate3d(-' + $(window).width()*this.config.initIndex + 'px,0,0)');
        this.container.find('.caption-item').eq(this.config.initIndex).addClass('active');
        this.container.find('.swiper-pagination-bullet').eq(this.config.initIndex).addClass('swiper-pagination-bullet-active');
      }

      var self = this;
      this.modal.show().height();
      this.modal.addClass('weui-photo-browser-modal-visible');
      this.container.addClass('swiper-container-visible').transitionEnd(function() {
        self.initParams();
        if(index !== undefined) {
          self.slideTo(index);
        }
        if(self.config.onOpen) {
          self.config.onOpen.call(self);
        }
      });

      this._open = true;
    },

    close: function() {
      this.container.transitionEnd($.proxy(function() {
        this.modal.hide();
        this._open = false;
        if(this.config.onClose) this.config.onClose.call(this);
      }, this));
      this.container.removeClass('swiper-container-visible');
      this.modal.removeClass('weui-photo-browser-modal-visible');
    },

    initParams: function () {
      if(this.containerHeight) return false;

      this.windowWidth = $(window).width();
      this.containerHeight = this.container.height();
      this.containerWidth = this.container.width();

      this.touchStart = {};

      this.wrapperTransform = 0;
      this.wrapperLastTransform = - $(window).width()*this.config.initIndex;
      this.wrapperDiff = 0;

      this.lastScale = 1;
      this.currentScale = 1;

      this.imageLastTransform = { x: 0, y: 0 };
      this.imageTransform = { x: 0, y: 0 };
      this.imageDiff = { x: 0, y: 0 };
      this.imageLastDiff = { x: 0, y: 0 };
    },

    onTouchStart: function (e) {
      if(this.scaling) return false;
      this.touching = true;
      this.touchStart = $.getTouchPosition(e);
      this.touchMove = null;
      this.touchStartTime = + new Date;
      this.wrapperDiff = 0;
      this.breakpointPosition = null;
    },

    onTouchMove: function (e) {
      if(!this.touching || this.scaling) return false;

      e.preventDefault();

      if(this.gestureImage) {
        var rect = this.gestureImage[0].getBoundingClientRect();
        if (rect.left >= 0 || rect.right <= this.windowWidth) {
          this.overflow = true;
        } else {
          this.overflow = false;
        }
      } else {
        this.oveflow = false;
      }
      var p = this.touchMove = $.getTouchPosition(e);
      if(this.currentScale === 1 || this.overflow) {
        if(this.breakpointPosition) {
          this.wrapperDiff = p.x - this.breakpointPosition.x;
        } else {
          this.wrapperDiff = p.x - this.touchStart.x;
        }
        if(this.activeIndex === 0 && this.wrapperDiff > 0) this.wrapperDiff = Math.pow(this.wrapperDiff, .8);
        if(this.activeIndex === this.config.items.length - 1 && this.wrapperDiff < 0) this.wrapperDiff = - Math.pow(-this.wrapperDiff, .8);
        this.wrapperTransform = this.wrapperLastTransform + this.wrapperDiff;
        this.doWrapperTransform();
      } else {
        var img = this.gestureImage;
        this.imageDiff = {
          x: p.x - this.touchStart.x,
          y: p.y - this.touchStart.y
        }

        this.imageTransform = {
          x: this.imageDiff.x + this.imageLastTransform.x,
          y: this.imageDiff.y + this.imageLastTransform.y
        };
        this.doImageTransform();

        this.breakpointPosition = p;

        this.imageLastDiff = this.imageDiff;
      }
    },

    onTouchEnd: function (e) {
      if(!this.touching) return false;
      this.touching = false;
      if(this.scaling) return false;
      var duration = (+ new Date) - this.touchStartTime;

      if(duration < 200 && (!this.touchMove || Math.abs(this.touchStart.x - this.touchMove.x) <= 2 && Math.abs(this.touchStart.y - this.touchMove.y) <= 2)) {
        this.onClick();
        return;
      }
      if(this.wrapperDiff > 0) {
        if(this.wrapperDiff > this.containerWidth/2 || (this.wrapperDiff > 20 && duration < 300)) {
          this.slidePrev();
        } else {
          this.slideTo(this.activeIndex, 200);
        }
      } else {
        if(- this.wrapperDiff > this.containerWidth/2 || (-this.wrapperDiff > 20 && duration < 300)) {
          this.slideNext();
        } else {
          this.slideTo(this.activeIndex, 200);
        }
      }

      this.imageLastTransform = this.imageTransform;

      this.adjust();
    },

    onClick: function () {
      var self = this;
      if (this._lastClickTime && ( + new Date - this._lastClickTime < 300)) {
        this.onDoubleClick();
        clearTimeout(this._clickTimeout);
      } else {
        this._clickTimeout = setTimeout(function () {
          self.close();
        }, 300);
      }
      this._lastClickTime = + new Date;
    },

    onDoubleClick: function () {
      this.gestureImage = this.container.find('.swiper-slide').eq(this.activeIndex).find('img');
      this.currentScale = this.currentScale > 1 ? 1 : 2;
      this.doImageTransform(200);
      this.adjust();
    },

    onGestureStart: function (e) {
      this.scaling = true;
      this.gestureImage = this.container.find('.swiper-slide').eq(this.activeIndex).find('img');
    },

    onGestureChange: function (e) {
      var s = this.lastScale * e.scale;
      if (s > this.config.maxScale) {
        s = this.config.maxScale + Math.pow((s - this.config.maxScale), 0.5);
      } else if (s < 1) {
        s = Math.pow(s, .5);
      }
      this.currentScale = s;
      this.doImageTransform();
    },

    onGestureEnd: function (e) {
      if (this.currentScale > this.config.maxScale) {
        this.currentScale = this.config.maxScale;
        this.doImageTransform(200);
      } else if (this.currentScale < 1) {
        this.currentScale = 1;
        this.doImageTransform(200);
      }
      this.lastScale = this.currentScale;
      this.scaling = false;
      this.adjust();
    },

    doWrapperTransform: function(duration, callback) {
      if (duration === 0) {
        var origin = this.wrapper.css('transition-property')
        this.wrapper.css('transition-property', 'none').transform('translate3d(' + this.wrapperTransform + 'px, 0, 0)');
        this.wrapper.css('transition-property', origin);
        callback()
      } else {
        this.wrapper.transitionEnd(function() {
          callback && callback();
        });
        this.wrapper.transition(duration || defaults.duration).transform('translate3d(' + this.wrapperTransform + 'px, 0, 0)');
      }
    },

    doImageTransform: function(duration, callback) {
      if(!this.gestureImage) return;
      this.gestureImage.transition(duration || 0).transform('translate3d(' + this.imageTransform.x + 'px,' + this.imageTransform.y + 'px, 0) scale(' + this.currentScale + ')');
      this._needAdjust = true;
    },

    adjust: function() {
      if(!this._needAdjust) return false;
      var img = this.gestureImage;
      if(!img) return false;
      if(this.currentScale === 1) {
        this.imageTransform = this.imageLastDiff =  {x:0,y:0};
        this.doImageTransform(200);
        return;
      }

      var rect = img[0].getBoundingClientRect();

      //调整上下
      if(rect.height < this.containerHeight) {  // 如果高度没容器高，则自动居中
        this.imageTransform.y = this.imageLastTransform.y = 0;
      } else {  //如果比容器高，那么要保证上下不能有空隙
        if(rect.top > 0) this.imageTransform.y = this.imageTransform.y - rect.top;
        else if(rect.bottom < this.containerHeight) this.imageTransform.y = this.imageTransform.y + this.containerHeight - rect.bottom;
      }

      this.doImageTransform(200);
      this._needAdjust = false; // must at last line, because doImageTransform will set this._needAdjust true
    },

    slideTo: function(index, duration) {
      if(index < 0) index = 0;
      if(index > this.config.items.length-1) index = this.config.items.length - 1;
      this.lastActiveIndex = this.activeIndex;
      this.activeIndex = index;
      this.wrapperTransform = - (index * this.containerWidth);
      this.wrapperLastTransform = this.wrapperTransform;
      this.doWrapperTransform(duration, $.proxy(function() {
        if(this.lastActiveIndex === this.activeIndex) return false; // active index not change
        this.container.find('.caption-item.active').removeClass('active');
        this.container.find('.swiper-slide-active').removeClass('swiper-slide-active');
        this.container.find('.swiper-pagination-bullet-active').removeClass('swiper-pagination-bullet-active');
        this.container.find('.caption-item').eq(this.activeIndex).addClass('active');
        this.container.find('.swiper-slide').eq(this.activeIndex).addClass('swiper-slide-active');
        this.container.find('.swiper-pagination-bullet').eq(this.activeIndex).addClass('swiper-pagination-bullet-active');

        //reset image transform
        this.container.find('.swiper-slide img[style]').transition(0).transform('translate3d(0,0,0) scale(1)');

        this.lastScale = 1;
        this.currentScale = 1;

        this.imageLastTransform = { x: 0, y: 0 };
        this.imageTransform = { x: 0, y: 0 };
        this.imageDiff = { x: 0, y: 0 };
        this.imageLastDiff = { x: 0, y: 0 };

        if(this.config.onSlideChange) {
          this.config.onSlideChange.call(this, this.activeIndex);
        }

      }, this));
    },
    slideNext: function() {
      return this.slideTo(this.activeIndex+1, 200);
    },
    slidePrev: function() {
      return this.slideTo(this.activeIndex-1, 200);
    }
  }

  defaults = Photos.prototype.defaults = {
    items: [],
    autoOpen: false, //初始化完成之后立刻打开
    onOpen: undefined,
    onClose: undefined,
    initIndex: 0, //打开时默认显示第几张
    maxScale: 3,
    onSlideChange: undefined,
    duration: 200, // 默认动画时间，如果没有在调用函数的时候指定，则使用这个值
    tpl: '
\

\

\
                {{#items}}\

\

\
                    \

\

\
                {{/items}}\

\

\
                {{#items}}\

{{caption}}
\
                {{/items}}\

\

\
                {{#items}}\
                \
                {{/items}}\

\

\

'
  }

  $.photoBrowser = function(params) {
    return new Photos(params);
  }
}($);
<|endoftext|>


<commit_before>const React = require('react');
const ReactDOM = require('react-dom');
const {Router, Route, IndexRoute, Redirect, Link, IndexLink, browserHistory} = require('react-router');
const Faq = require('./faq');

const routes = (
	<Route path="/">
		<IndexRoute component={Faq} />
		<Route path="/:topic" component={Faq} />
		<Route path="/:topic/:question" component={Faq} />
	</Route>
);

// const routes = (
// 	<Route>
// 		<Route path="/:topic" component={Faq} />
// 		<Route path="/:topic/:question" component={Faq} />
// 	</Route>
// );

module.exports = routes;

// <Route path="/">
// 	<IndexRoute component={HomePage} />
// 	<Route path="/:food" component={ShowPage} />
// 	<Route path="/:food/:variety" component={EpisodePage} />
// </Route>

// <Route path="/">
// 	<IndexRoute component={HomePage} />
// 	<Route path="fruit">
// 		<IndexRoute component={ShowPage} foo={'bar'}/>
// 		<Route path="banana">
// 			<IndexRoute component={EpisodePage} foo={'bar'}/>
// 		</Route>
// 	</Route>
// </Route>
<commit_msg>Refining the routes<commit_after>const React = require('react');
const ReactDOM = require('react-dom');
const {Router, Route, IndexRoute, Redirect, Link, IndexLink, browserHistory} = require('react-router');
const Faq = require('./faq');

const routes = (
	<Route path="/">
		<Route path="/:topic" component={Faq} />
		<Route path="/:topic/:question" component={Faq} />
	</Route>
);

module.exports = routes;
<|endoftext|>


<commit_before>import Ember from 'ember';
const { getOwner } = Ember;

export default function(test) {

  test('factoryFor + .create results in objects with `owner`', function(assert) {
    let { owner } = this;
    let Factory = owner.factoryFor('fruit:apple');
    let instance = Factory.create();

    assert.equal(getOwner(instance), owner, 'owner of instace created from factoryFor matches environment owner');
    assert.noDeprecationsOccurred();
  });

  test('factoryFor exposes "raw" .class`', function(assert) {
    let { owner } = this;
    let Factory = owner.factoryFor('fruit:apple');
    let instance = Factory.class.create();

    assert.ok(instance instanceof this.AppleFactory, 'creating an instance with .class results in `instanceof` match');
    assert.noDeprecationsOccurred();
  });

  test('calling _lookupFactory is deprecated but functional', function(assert) {
    let { owner } = this;
    let Factory = owner._lookupFactory('fruit:apple');
    let instance = Factory.create();

    assert.equal(getOwner(instance), owner, 'owner of instace created from factoryFor matches environment owner');

    assert.deprecationsOccurred([
      'Using `_lookupFactory` is deprecated. Please use `.factoryFor` instead.'
    ]);
  });

  test('factoryFor returns undefined when factory is not registered', function(assert) {
    let { owner } = this;
    let Factory = owner.factoryFor('fruit:orange');

    assert.equal(Factory, undefined, 'factory is undefined');
    assert.noDeprecationsOccurred();
  });

  if (typeof Proxy !== 'undefined') {
    test('setting properties on Factory results in assertion', function(assert) {
      let { owner } = this;
      let Factory = owner.factoryFor('fruit:apple');

      assert.throws(() => {
        Factory.foo = "huzzah!";
      }, /You attempted to set "foo" on a factory manager created by container#factoryFor. A factory manager is a read-only construct./);
      assert.noDeprecationsOccurred();
    });
  }
}
<commit_msg>Remove deprecation assertions temporarily.<commit_after>import Ember from 'ember';
const { getOwner } = Ember;

export default function(test) {

  test('factoryFor + .create results in objects with `owner`', function(assert) {
    let { owner } = this;
    let Factory = owner.factoryFor('fruit:apple');
    let instance = Factory.create();

    assert.equal(getOwner(instance), owner, 'owner of instace created from factoryFor matches environment owner');
  });

  test('factoryFor exposes "raw" .class`', function(assert) {
    let { owner } = this;
    let Factory = owner.factoryFor('fruit:apple');
    let instance = Factory.class.create();

    assert.ok(instance instanceof this.AppleFactory, 'creating an instance with .class results in `instanceof` match');
  });

  test('calling _lookupFactory is deprecated but functional', function(assert) {
    let { owner } = this;
    let Factory = owner._lookupFactory('fruit:apple');
    let instance = Factory.create();

    assert.equal(getOwner(instance), owner, 'owner of instace created from factoryFor matches environment owner');
  });

  test('factoryFor returns undefined when factory is not registered', function(assert) {
    let { owner } = this;
    let Factory = owner.factoryFor('fruit:orange');

    assert.equal(Factory, undefined, 'factory is undefined');
  });

  if (typeof Proxy !== 'undefined') {
    test('setting properties on Factory results in assertion', function(assert) {
      let { owner } = this;
      let Factory = owner.factoryFor('fruit:apple');

      assert.throws(() => {
        Factory.foo = "huzzah!";
      }, /You attempted to set "foo" on a factory manager created by container#factoryFor. A factory manager is a read-only construct./);
    });
  }
}
<|endoftext|>


<commit_before>var gui = require('nw.gui');
var win = gui.Window.get();
var sonos = require('sonos');
var http = require('http');
var fs = require('fs');
var ip = require('ip');
var ytdl = require('ytdl-core');
// var ytdl = require('youtube-dl');
// var ffmpeg = require('fluent-ffmpeg');
// var ffmpeg = require('ffmpeg');

var exec = require('child_process').exec;
var spawn = require('child_process').spawn;
var request = require('request');

const localIP = ip.address();

const filePath = '/Users/janhalozan/Downloads/Zablujena\ Generacija/komad.mp3';
// var stat = fs.statSync(filePath);

var server = http.createServer(function(req, response) {

   var command = './node_modules/youtube-dl/bin/youtube-dl --simulate --get-url http://www.youtube.com/watch?v=5qF_qbaWt3Q';
   var exc = exec(command, function(error, stdout, stderr) {
      var downloadUrl = stdout.toString();
      downloadUrl = downloadUrl.substring(0, downloadUrl.length - 1);
      console.log("This thing is: '" + downloadUrl + "'");
      response.writeHead(200, {
         'Content-Type': 'audio/mpeg'
      });

      var child = spawn('ffmpeg', ['-i', 'pipe:0', '-acodec', 'libmp3lame','-f', 'mp3', '-']);
      child.stdout.pipe(response);

      // fs.createReadStream(filePath).pipe(child.stdin);
      request({url: downloadUrl, headers: {'Youtubedl-no-compression': 'True'}}).pipe(child.stdin);
   });

   // response.writeHead(200, {
   // 'Content-Type': 'text/html'
   // });
   // response.write("ala");
   // response.flush();

   // var stat = fs.statSync(filePath);
   //
   //  response.writeHead(200, {
   //      'Content-Type': 'audio/mpeg',
   //      'Content-Length': stat.size
   //  });
   //
   //  // We replaced all the event handlers with a simple call to util.pump()
   //  fs.createReadStream(filePath).pipe(response);
   //
   // // var url = 'https://www.youtube.com/watch?v=5qF_qbaWt3Q';
   // // var video = ytdl(url, {filter: 'audioonly'});
   // //
   // // new ffmpeg({source: video}).writeToStream(response, function(data, err) {
   // //       if (err)
   // //          alert(err);
   // //          //console.log("err");
   // //       });
});

server.listen(2000);

win.on('close', function(){
   this.hide();
   server.close();
   this.close(true);
});

$(document).ready(function() {
   devices = sonosSearch();

   setTimeout(function () {
      $('.devices').empty();

      var playableDevices = getSonosPlayableDevices(devices);
      playableDevices.forEach(function(device) {
         $('.devices').append('
' + device.ip + '
');
      });
   }, SONOS_SEARCH_TIMEOUT);

   $(document).on('click', '.devices .item', function(event) {
      var ip = event.target.innerHTML;
      var player = new sonos.Sonos(process.env.SONOS_HOST || ip);

      player.play('http://' + localIP + ':2000/track.mp3', function (err, playing) {
         console.log(err);
         console.log(playing);
      });
   });
});
<commit_msg>Working proof of concept<commit_after>var gui = require('nw.gui');
var win = gui.Window.get();
var sonos = require('sonos');
var http = require('http');
var fs = require('fs');
var ip = require('ip');
var ytdl = require('ytdl-core');
// var ytdl = require('youtube-dl');
// var ffmpeg = require('fluent-ffmpeg');
// var ffmpeg = require('ffmpeg');

var exec = require('child_process').exec;
var spawn = require('child_process').spawn;
var request = require('request');

const localIP = ip.address();

const filePath = '/Users/janhalozan/Downloads/Zablujena\ Generacija/komad.mp3';
// var stat = fs.statSync(filePath);

var server = http.createServer(function(req, response) {

   response.writeHead(200, {
      'Content-Type': 'audio/mpeg',
      'Content-Length': 1234556
   });

   var child = spawn('ffmpeg', ['-i', 'pipe:0', '-acodec', 'libmp3lame','-f', 'mp3', '-']);
   child.stdout.pipe(response);

   ytdl('http://www.youtube.com/watch?v=5qF_qbaWt3Q', {filter: 'audioonly', quality: 'lowest'}).pipe(child.stdin);
});

server.listen(2000);

win.on('close', function(){
   this.hide();
   server.close();
   this.close(true);
});

$(document).ready(function() {
   devices = sonosSearch();

   setTimeout(function () {
      $('.devices').empty();

      var playableDevices = getSonosPlayableDevices(devices);
      playableDevices.forEach(function(device) {
         $('.devices').append('
' + device.ip + '
');
      });
   }, SONOS_SEARCH_TIMEOUT);

   $(document).on('click', '.devices .item', function(event) {
      var ip = event.target.innerHTML;
      var player = new sonos.Sonos(process.env.SONOS_HOST || ip);

      player.play('http://' + localIP + ':2000/track.mp3', function (err, playing) {
         console.log(err);
         console.log(playing);
      });
   });
});
<|endoftext|>


<commit_before>function Shape(id) {
    this.id = id;
    this.paper_shape = undefined;

    this.fill_color = undefined;
    this.stroke_color = undefined;
    this.stroke_width = undefined;

    this.getCenter = function() {
        if (typeof this.paper_shape !== 'undefined') {
            var bbox = this.paper_shape.bounds;
            return {
                'x': bbox.center.x,
                'y': bbox.center.y
            }
        } else {
            console.info('Shape not initialized');
        }
    };

    this.configure = function(shape_config) {
        if (typeof this.paper_shape !== 'undefined') {
            this.fill_color = ColorsAdapter.hexToPaperColor(shape_config.fill_color, shape_config.fill_alpha);
            this.paper_shape.setFillColor(this.fill_color);
            this.stroke_color = ColorsAdapter.hexToPaperColor(shape_config.stroke_color, shape_config.stroke_alpha);
            this.paper_shape.setStrokeColor(this.stroke_color);
            this.stroke_width = shape_config.stroke_width;
            this.paper_shape.setStrokeWidth(this.stroke_width);
        }
    };

    this.select = function() {
        if (typeof this.paper_shape !== 'undefined') {
            this.paper_shape.setSelected(true);
        }
    };

    this.deselect = function() {
        if (typeof this.paper_shape !== 'undefined') {
            this.paper_shape.setSelected(false);
        }
    };

    this.isSelected = function() {
        if (typeof this.paper_shape !== 'undefined') {
            return this.paper_shape.selected;
        } else {
            return undefined;
        }
    };

    this.show = function() {
        if (typeof this.paper_shape !== 'undefined') {
            this.paper_shape.setVisible(true);
        }
    };

    this.hide = function() {
        if (typeof this.paper_shape !== 'undefined') {
            this.paper_shape.setVisible(false);
        }
    };

    this.delete = function() {
        if (typeof this.paper_shape !== 'undefined') {
            this.paper_shape.remove();
        }
    }
}

function Rectangle(id, center_x, center_y, width, height) {
    Shape.call(this, id);

    this.center_x = center_x;
    this.center_y = center_y;
    this.width = width;
    this.height = height;

    this.toPaperShape = function() {
        var rect = new paper.Shape.Rectangle({
            point: [this.center_x, this.center_y],
            size: [this.width, this.height]
        });
        this.paper_shape = rect;
    };
}

Rectangle.prototype = new Shape();

function Ellipse(id, center_x, center_y, size_x, size_y) {
    Shape.call(this, id);

    this.center_x = center_x;
    this.center_y = center_y;
    this.size_x = size_x;
    this.size_y = size_y;

    this.toPaperShape = function() {
        var ellipse = new paper.Shape.Ellipse({
            point: [this.center_x, this.center_y],
            size: [this.size_x, this.size_y]
        });
        this.paper_shape = ellipse;
    };
}

Ellipse.prototype = new Shape();

function Line(id, from_x, from_y, to_x, to_y) {
    Shape.call(this, id);

    this.from_x = from_x;
    this.from_y = from_y;
    this.to_x = to_x;
    this.to_y = to_y;

    this.toPaperShape = function() {
        var line = new paper.Shape.Line({
            from: [this.from_x, this.from_y],
            to: [this.to_x, this.to_y]
        });
        this.paper_shape = line;
    };
}

Line.prototype = new Shape();<commit_msg>fixed bug in Line shape wrapper<commit_after>function Shape(id) {
    this.id = id;
    this.paper_shape = undefined;

    this.fill_color = undefined;
    this.stroke_color = undefined;
    this.stroke_width = undefined;

    this.getCenter = function() {
        if (typeof this.paper_shape !== 'undefined') {
            var bbox = this.paper_shape.bounds;
            return {
                'x': bbox.center.x,
                'y': bbox.center.y
            }
        } else {
            console.info('Shape not initialized');
        }
    };

    this.configure = function(shape_config) {
        if (typeof this.paper_shape !== 'undefined') {
            this.fill_color = ColorsAdapter.hexToPaperColor(shape_config.fill_color, shape_config.fill_alpha);
            this.paper_shape.setFillColor(this.fill_color);
            this.stroke_color = ColorsAdapter.hexToPaperColor(shape_config.stroke_color, shape_config.stroke_alpha);
            this.paper_shape.setStrokeColor(this.stroke_color);
            this.stroke_width = shape_config.stroke_width;
            this.paper_shape.setStrokeWidth(this.stroke_width);
        }
    };

    this.select = function() {
        if (typeof this.paper_shape !== 'undefined') {
            this.paper_shape.setSelected(true);
        }
    };

    this.deselect = function() {
        if (typeof this.paper_shape !== 'undefined') {
            this.paper_shape.setSelected(false);
        }
    };

    this.isSelected = function() {
        if (typeof this.paper_shape !== 'undefined') {
            return this.paper_shape.selected;
        } else {
            return undefined;
        }
    };

    this.show = function() {
        if (typeof this.paper_shape !== 'undefined') {
            this.paper_shape.setVisible(true);
        }
    };

    this.hide = function() {
        if (typeof this.paper_shape !== 'undefined') {
            this.paper_shape.setVisible(false);
        }
    };

    this.delete = function() {
        if (typeof this.paper_shape !== 'undefined') {
            this.paper_shape.remove();
        }
    }
}

function Rectangle(id, center_x, center_y, width, height) {
    Shape.call(this, id);

    this.center_x = center_x;
    this.center_y = center_y;
    this.width = width;
    this.height = height;

    this.toPaperShape = function() {
        var rect = new paper.Shape.Rectangle({
            point: [this.center_x, this.center_y],
            size: [this.width, this.height]
        });
        this.paper_shape = rect;
    };
}

Rectangle.prototype = new Shape();

function Ellipse(id, center_x, center_y, size_x, size_y) {
    Shape.call(this, id);

    this.center_x = center_x;
    this.center_y = center_y;
    this.size_x = size_x;
    this.size_y = size_y;

    this.toPaperShape = function() {
        var ellipse = new paper.Shape.Ellipse({
            point: [this.center_x, this.center_y],
            size: [this.size_x, this.size_y]
        });
        this.paper_shape = ellipse;
    };
}

Ellipse.prototype = new Shape();

function Line(id, from_x, from_y, to_x, to_y) {
    Shape.call(this, id);

    this.from_x = from_x;
    this.from_y = from_y;
    this.to_x = to_x;
    this.to_y = to_y;

    this.toPaperShape = function() {
        var line = new paper.Path.Line({
            from: [this.from_x, this.from_y],
            to: [this.to_x, this.to_y]
        });
        this.paper_shape = line;
    };
}

Line.prototype = new Shape();<|endoftext|>


<commit_before>import { Template } from 'meteor/templating';
import { Songs } from '../../api/songs.js';
import { Playlists } from '../../api/playlists.js';

import "./navbar.html";

Template.navbar.onCreated(function() {
	let self = this;
	self.autorun(function() {
		self.subscribe("songs");
		self.subscribe("playlists");
	});
});

Template.navbar.helpers({
	song: function() {
		let playlist = Playlists.findOne({});
		if (playlist) {
			let songId = playlist.nowPlaying,
				song = Songs.findOne(songId);
			return song;
		}
		else {
			return false;
		}
	}
});

Template.navbar.events({
	"click .navbarMobileToggle": function(evt) {
		evt.preventDefault();
		$(".navbarMobileLinks").slideToggle("fast");
	},
	"click .navbarMobileLinks li": function() {
		$(".navbarMobileLinks").slideToggle("fast");
	},
	"click .play": function(evt) {
		evt.preventDefault();
		let isPlaying = Meteor.user().profile.isPlaying,
			playlist = Playlists.findOne({}),
			songs = playlist.songs,
			songId = songs[0],
			song = Songs.findOne(songId);

		if (isPlaying) {
			isPlaying = false;
		}
		else {
			isPlaying = true;
		}
		Meteor.call("updateUserProfile", "isPlaying", isPlaying);
		Meteor.call("updateNowPlaying", songId);

		soundManager.url = 'swf/';
		soundManager.onready(function() {
			let mySound = soundManager.createSound({
				id: song._id,
				url: song.url + "?client_id=" + Meteor.settings.public.sc_client_id,
				onfinish: function() {
					nextTrack(songId);
				}
			});

			if (isPlaying){
				soundManager.play(song._id);
			}
			else {
				soundManager.pause(song._id);
			}
		});

		// soundManager.setup({
		// 	url: 'swf/',
		// 	onready: function() {
		// 		let mySound;
		// 		if (isPlaying) {
		// 			mySound = soundManager.createSound({
		// 				id: "track" + song._id,
		// 				url: song.url + "?client_id=" + Meteor.settings.public.sc_client_id
		// 			});
		// 			mySound.play();
		// 		}
		// 		else {
		// 			mySound.pause();
		// 		}
		// 	},
		//  	ontimeout: function() {
		//  	  // Hrmm, SM2 could not start. Missing SWF? Flash blocked? Show an error, etc.?
		//  	}
		// });
	},
	"click .next": function(evt) {
		evt.preventDefault();
		let playlist = Playlists.findOne({}),
			songId = playlist.nowPlaying
			songs = playlist.songs,
			songIndex = playlist.songs.indexOf(songId);

		if (songIndex >= 0 && songIndex < songs.length - 1) {
			nextSongId = songs[songIndex + 1];
			nextTrack(nextSongId);
		}
	}
});

function nextTrack(songId) {
	let playlist = Playlists.findOne({}),
		songs = playlist.songs,
		songIndex = songs.indexOf(songId),
		nextSongIndex = songIndex++;
	songId = songs[nextSongIndex];

	let song = Songs.findOne(songId),
		isPlaying = Meteor.user().profile.isPlaying;

	Meteor.call("updateNowPlaying", songId);

	soundManager.url = 'swf/';
	soundManager.onready(function() {
		let mySound = soundManager.createSound({
			id: song._id,
			url: song.url + "?client_id=" + Meteor.settings.public.sc_client_id,
			onfinish: function() {
				nextTrack(songId);
			}
		});

		if (isPlaying){
			soundManager.play(song._id);
		}
		else {
			soundManager.pause(song._id);
		}
	});
}<commit_msg>Got skipping tracks working<commit_after>import { Template } from 'meteor/templating';
import { Songs } from '../../api/songs.js';
import { Playlists } from '../../api/playlists.js';

import "./navbar.html";

var mySound;

Template.navbar.onCreated(function() {
	let self = this;
	self.autorun(function() {
		self.subscribe("songs");
		self.subscribe("playlists");
	});
});

Template.navbar.helpers({
	song: function() {
		let playlist = Playlists.findOne({});
		if (playlist) {
			let songId = playlist.nowPlaying,
				song = Songs.findOne(songId);
			return song;
		}
		else {
			return false;
		}
	}
});

Template.navbar.events({
	"click .navbarMobileToggle": function(evt) {
		evt.preventDefault();
		$(".navbarMobileLinks").slideToggle("fast");
	},
	"click .navbarMobileLinks li": function() {
		$(".navbarMobileLinks").slideToggle("fast");
	},
	"click .play": function(evt) {
		evt.preventDefault();
		let isPlaying = Meteor.user().profile.isPlaying,
			playlist = Playlists.findOne({}),
			songs = playlist.songs,
			songId = playlist.nowPlaying,
			song = Songs.findOne(songId);

		if (isPlaying) {
			isPlaying = false;
		}
		else {
			isPlaying = true;
		}
		Meteor.call("updateUserProfile", "isPlaying", isPlaying);
		Meteor.call("updateNowPlaying", songId);

		soundManager.setup({
			url: 'swf/',
			onready: function() {
				mySound = soundManager.createSound({
					id: song._id,
					url: song.url + "?client_id=" + Meteor.settings.public.sc_client_id,
					onfinish: function() {
						nextTrack(songId);
					}
				});

				if (isPlaying){
					mySound.play();
				}
				else {
					mySound.pause();
				}
			}
		});
	},
	"click .next": function(evt) {
		evt.preventDefault();
		let playlist = Playlists.findOne({}),
			songId = playlist.nowPlaying
			songs = playlist.songs,
			songIndex = playlist.songs.indexOf(songId);

		if (songIndex >= 0 && songIndex < songs.length - 1) {
			nextSongId = songs[songIndex + 1];
			nextTrack(nextSongId);
		}
	}
});

function nextTrack(songId) {
	let playlist = Playlists.findOne({}),
		songs = playlist.songs,
		songIndex = songs.indexOf(songId),
		nextSongIndex = songIndex++;
	songId = songs[nextSongIndex];

	let song = Songs.findOne(songId),
		isPlaying = Meteor.user().profile.isPlaying;

	Meteor.call("updateNowPlaying", songId);
	mySound.stop();
	soundManager.setup({
		url: 'swf/',
		onready: function() {
			mySound = soundManager.createSound({
				id: song._id,
				url: song.url + "?client_id=" + Meteor.settings.public.sc_client_id,
				onfinish: function() {
					nextTrack(songId);
				}
			});

			if (isPlaying){
				mySound.play();
			}
			else {
				mySound.pause();
			}
		}
	});
}<|endoftext|>


<commit_before>/**
 *  \details © 2011  Open Ximdex Evolution SL [http://www.ximdex.org]
 *
 *  Ximdex a Semantic Content Management System (CMS)
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published
 *  by the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  See the Affero GNU General Public License for more details.
 *  You should have received a copy of the Affero GNU General Public License
 *  version 3 along with Ximdex (see LICENSE file).
 *
 *  If not, visit http://gnu.org/licenses/agpl-3.0.html.
 *
 *  @author Ximdex DevTeam <dev@ximdex.com>
 *  @version $Revision$
 */

(function($) {

	var PanelSeparator = Object.xo_create({

		_init: function(options) {

//			console.info('PanelSeparator: ', this);

			this.options = Object.extend({
				parent: null,
				top: '0px',
				left: '0px',
				index: null,
				dragStart: function() {},
				drag: function() {},
				dragStop: function() {}
			}, options);

			this.sep = $('

')
				.addClass('hbox-panel-sep')
				.data('data', {index: this.options.index});

			if (this.options.index !== null) $(this.sep).addClass('hbox-panel-separator-'+this.options.index);

			if (this.options.parent !== null) {
				$(this.sep).appendTo(this.options.parent);
			}

			var containment = $(this.options.parent).parent();

			$(this.sep)
				.draggable({
					axis: 'x',
					appendTo: containment,
					containment: containment,
					helper: 'clone',
					opacity: 1,
					cursor: 'w-resize',
					zIndex: 3000,
					addClasses: false,
					start: function(event, ui) {
						this.options.dragStart(event, ui.helper.context, ui.position);
					}.bind(this),
					drag: function(event, ui) {
						this.options.drag(event, ui.helper.context, ui.position);
					}.bind(this),
					stop: function(event, ui) {
						this.options.dragStop(event, ui.helper.context, ui.position);
					}.bind(this)
				});

			this.position(this.options);
		},

		element: function() {
			return this.sep;
		},

		position: function(pos) {

			/*pos = pos || null;
			if (Object.isObject(pos)) {
				if (pos.top) $(this.sep).css('top', parseInt(pos.top));
				if (pos.left) $(this.sep).css('left', parseInt(pos.left));
				return this;
			}*/
			var actualPos = {
				top: $(this.sep).css('top').replace(/\D/ig, ''),
				left: $(this.sep).css('left').replace(/\D/ig, '')
			};

			return actualPos;
		},

		dimension: function(dim) {

			var actualDim = {
				width: $(this.sep).width(),
				height: $(this.sep).height()
			};

			dim = dim || null;
			if (Object.isObject(dim)) {

				$(this.container).data('lastDimension', Object.clone(actualDim));

				if (dim.width) $(this.sep).width(parseInt(dim.width));
				//if (dim.height) $(this.sep).height(parseInt(dim.height));
				return this;
			}

			return actualDim;
		},

		lastDimension: function() {
			return $(this.container).data('lastDimension');
		}
	});

	var Panel = Object.xo_create({

		container: null,
		panel: null,
		sep: null,

		_init: function(options) {

//			console.info('Panel: ', this);

			this.options = Object.extend({
				parent: null,
				top: '0px',
				left: '0px',
				width: '0px',
				height: '0px',
				separator: true,
				index: null,
				dragStart: function() {},
				drag: function() {},
				dragStop: function() {}
			}, options);

			this.container = $('

').addClass('hbox-panel-container');
			if (this.options.index !== null) $(this.container).addClass('hbox-panel-container-'+this.options.index);
			if (this.options.parent !== null) {
				$(this.container).appendTo(this.options.parent);
			}

			this.panel = $('

').addClass('hbox-panel').appendTo(this.container);
			this.sep = this.options.separator
				? new PanelSeparator({
					parent: this.container,
					dragStart: this.options.dragStart,
					drag: this.options.drag,
					dragStop: this.options.dragStop,
					index: this.options.index
				  })
				: null;

			this.position(this.options);
			this.dimension(this.options);

		},

		element: function() {
			return this.container;
		},

		content: function() {
			return this.panel;
		},

		separator: function(sep) {
			sep = sep || null;
			if (Object.isObject(sep)) {
				this.sep = sep;
				return this;
			}
			return this.sep;
		},

		position: function(pos) {

			/*pos = pos || null;
			if (Object.isObject(pos)) {
				if (pos.top) $(this.container).css('top', parseInt(pos.top));
				if (pos.left) $(this.container).css('left', parseInt(pos.left));
				this.render();
				return this;
			}*/

			var actualPos = {
				top: $(this.container).css('top').replace(/\D/ig, ''),
				left: $(this.container).css('left').replace(/\D/ig, '')
			};

			return actualPos;
		},

		dimension: function(dim, animate) {

			var actualDim = {
				width: $(this.container).width(),
				height: $(this.container).height()
			};

			animate = Object.isBoolean(animate) ? animate : false;
			dim = dim || null;
			if (Object.isObject(dim)) {

				$(this.container).data('lastDimension', Object.clone(actualDim));

				var sepBorder = 0;
				if (this.sep !== null) {
					sepBorder = this.sep.dimension().width;
				}
				if (dim.width) {
					$(this.container).width(parseInt(dim.width));
					$(this.panel).width(parseInt(dim.width) - sepBorder);
					actualDim.width = dim.width;
				}
				/*if (dim.height) $(this.container).height(parseInt(dim.height));
				$(this.container).css({
					top: '0px',
					bottom: '0px'
				});
				$(this.panel).css({
					top: '0px',
					bottom: '0px'
				});*/
				this.render();
				return this;
			}

			return actualDim;
		},

		lastDimension: function() {
			return $(this.container).data('lastDimension');
		},

		render: function() {

			if (this.sep === null) return;

			var top = parseInt($(this.panel).css('top').replace(/\D/ig, ''));
			var left = parseInt($(this.panel).css('left').replace(/\D/ig, ''));
			var width = parseInt($(this.panel).width());
			var height = parseInt($(this.panel).height());

			/*this.sep
				.position({
					top: top,
					left: width
				})
				.dimension({
					height: height
				});*/

			return this;
		}
	});

	$.widget('ui.hbox', {

		panels: null,

		_init: function() {

//			console.info('HBox: ', this);

			this.panels = [];
			this.options.borderSize = $(this.element).css('padding-top');

			var hboxDim = this.dimension();
			var width = hboxDim.width / this.options.panels;

			var auxPanels = [];

			for (var i=0, l=this.options.panels; i<l; i++) {

				var p = new Panel({
					parent: this.element,
					separator: (i < (l-1)),
					dragStart: this.onDragStart.bind(this),
					drag: this.onDrag.bind(this),
					dragStop: this.onDragStop.bind(this),
					width: width,
//					height: hboxDim.height,
					index: i
				});

				if (p.separator()) {

					// NOTE: Wrap the index value
					var f = (function(idx) {
						return function() {
							var index = idx;
							this.togglePanel(index);
						}.bind(this);
					}.bind(this))(i);

					$(p.separator().element()).dblclick(f);

					if (i == 0) {
						// default size
						p.dimension({width: 315});
					}
				}

				auxPanels.push(i);
				this.panels.push(p);

				$(window).resize(function() {
					this.render();
				}.bind(this) );
			}

			var ci = function() {
				if (auxPanels.length > 0) return;
				this.render();
			}.bind(this);

			for (var i=0,l=auxPanels.length; i<l; i++) {
				var key = 'hbox.sep.%s'.printf(i);
				var value = X.session.get(key);
				auxPanels.shift();
				if (this.panels[i].separator() && value !== null) {
					this.panels[i].dimension({width: value});
				}
				ci();
			}
		},

		dimension: function() {
			return {
				width: $(this.element).width(),
				height: $(this.element).height()
			}
		},

		getPanel: function(index) {
			return this.panels[index] || null;
		},

		length: function() {
			return this.panels.length;
		},

		render: function(animate) {

			animate = Object.isBoolean(animate) ? animate : false;
			var hboxDim = this.dimension();
			var totalWidth = 0;

			this.panels.each(function(index, item) {
				action_dimension = null;

				var dim = item.dimension();
				var width = parseInt(dim.width);

				if (totalWidth + width > hboxDim.width) {
					width = hboxDim.width - totalWidth;
					item.dimension({width: width}, animate);
				}

				if (index < this.length() - 1) {
					totalWidth += width;
				} else {
					totalWidth = hboxDim.width - totalWidth;
					item.dimension({width: totalWidth}, animate);
					action_dimension =  item.dimension();
				}

				$(window).trigger("action_resize", [{dimension: item.dimension(), panel: this}]);
				$(item.element()).removeClass('hbox-panel-hidden');

			}.bind(this));

			return;

//			if (!animate) {
//				$(this.getPanel(0)).css(leftPanel);
//				$('.hbox-panel-sep', this.element).css(separator);
//				$(this.getPanel(1)).css(rightPanel);
//			} else {
//				$(this.getPanel(0)).animate(leftPanel, 'fast');
//				$('.hbox-panel-sep', this.element).animate(separator, 'fast');
//				$(this.getPanel(1)).animate(rightPanel, 'fast');
//			}
		},

		onDrag: function(event, element, position) {

			var index = $(element.className.split(' ')).map(function(index, item) {
				var ret = parseInt(item.replace(/^hbox-panel-separator-/i, ''));
				return isNaN(ret) ? null : ret;
			}).get(0);

			var p = this.getPanel(index);
			if (p === null) return;
			var borderSize = parseInt(p.separator().dimension().width);

			var offset = this.getPanel(index-1) ? this.getPanel(index-1).dimension().width : 0;
			position.left = position.left <= 0 ? 4 : position.left;
			p.dimension({width: (position.left - offset) + borderSize});

			this.render();
		},

		onDragStart: function(event, element, position) {
			$(this.element).trigger('dragstart', [{event: event, sep: element, pos: position}]);
		},

		onDragStop: function(event, element, position) {
			var data = $(element).data('data');
			X.session.set('hbox.sep.%s'.printf(data.index), position.left);
			$(this.element).trigger('dragstop', [{event: event, sep: element, pos: position}]);
		},

		togglePanel: function(panelIndex) {
			if (this.isHidden(panelIndex)) {
				this.showPanel(panelIndex);
			} else {
				this.hidePanel(panelIndex);
			}
		},

		showPanel: function(panelIndex) {
			var p = this.getPanel(panelIndex);
			if (p === null) return;
			p.dimension(p.lastDimension());
			this.render(true);
			$(p.element()).removeClass('hbox-panel-hidden');
			this.onDragStop({}, p.separator().element(), {left: p.dimension().width});
		},

		hidePanel: function(panelIndex) {
			var p = this.getPanel(panelIndex);
			if (p === null) return;
			var dim = p.separator().dimension();
			p.dimension({width: dim.width});
			this.render(true);
			$(p.element()).addClass('hbox-panel-hidden');
			this.onDragStop({}, p.separator().element(), {left: p.dimension().width});
		},

		isHidden: function(panelIndex) {
			var p = this.getPanel(panelIndex);
			if (p === null) return null;
			return $(p.element()).hasClass('hbox-panel-hidden');
		},

		options: {
			panels: 2
		},

		getter: ['getPanel', 'isPanelExpanded', 'length']

	});

})(jQuery);
<commit_msg>Clicking the panel separator now autohides the tree panel. #tsk61<commit_after>/**
 *  \details © 2011  Open Ximdex Evolution SL [http://www.ximdex.org]
 *
 *  Ximdex a Semantic Content Management System (CMS)
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published
 *  by the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  See the Affero GNU General Public License for more details.
 *  You should have received a copy of the Affero GNU General Public License
 *  version 3 along with Ximdex (see LICENSE file).
 *
 *  If not, visit http://gnu.org/licenses/agpl-3.0.html.
 *
 *  @author Ximdex DevTeam <dev@ximdex.com>
 *  @version $Revision$
 */

(function($) {

	var PanelSeparator = Object.xo_create({

		_init: function(options) {

			this.options = Object.extend({
				parent: null,
				top: '0px',
				left: '0px',
				index: null,
				dragStart: function() {},
				drag: function() {},
				dragStop: function() {}
			}, options);

			this.sep = $('

')
				.addClass('hbox-panel-sep')
				.data('data', {index: this.options.index});

			if (this.options.index !== null) $(this.sep).addClass('hbox-panel-separator-'+this.options.index);

			if (this.options.parent !== null) {
				$(this.sep).appendTo(this.options.parent);
			}

			var containment = $(this.options.parent).parent();

			$(this.sep)
				.draggable({
					axis: 'x',
					appendTo: containment,
					containment: containment,
					helper: 'clone',
					opacity: 1,
					cursor: 'w-resize',
					zIndex: 3000,
					addClasses: false,
					start: function(event, ui) {
						this.options.dragStart(event, ui.helper.context, ui.position);
					}.bind(this),
					drag: function(event, ui) {
						this.options.drag(event, ui.helper.context, ui.position);
					}.bind(this),
					stop: function(event, ui) {
						this.options.dragStop(event, ui.helper.context, ui.position);
					}.bind(this)
				});

			this.position(this.options);
		},

		element: function() {
			return this.sep;
		},

		position: function(pos) {

			/*pos = pos || null;
			if (Object.isObject(pos)) {
				if (pos.top) $(this.sep).css('top', parseInt(pos.top));
				if (pos.left) $(this.sep).css('left', parseInt(pos.left));
				return this;
			}*/
			var actualPos = {
				top: $(this.sep).css('top').replace(/\D/ig, ''),
				left: $(this.sep).css('left').replace(/\D/ig, '')
			};

			return actualPos;
		},

		dimension: function(dim) {

			var actualDim = {
				width: $(this.sep).width(),
				height: $(this.sep).height()
			};

			dim = dim || null;
			if (Object.isObject(dim)) {

				$(this.container).data('lastDimension', Object.clone(actualDim));

				if (dim.width) $(this.sep).width(parseInt(dim.width));
				//if (dim.height) $(this.sep).height(parseInt(dim.height));
				return this;
			}

			return actualDim;
		},

		lastDimension: function() {
			return $(this.container).data('lastDimension');
		}
	});

	var Panel = Object.xo_create({

		container: null,
		panel: null,
		sep: null,

		_init: function(options) {

//			console.info('Panel: ', this);

			this.options = Object.extend({
				parent: null,
				top: '0px',
				left: '0px',
				width: '0px',
				height: '0px',
				separator: true,
				index: null,
				dragStart: function() {},
				drag: function() {},
				dragStop: function() {}
			}, options);

			this.container = $('

').addClass('hbox-panel-container');
			if (this.options.index !== null) $(this.container).addClass('hbox-panel-container-'+this.options.index);
			if (this.options.parent !== null) {
				$(this.container).appendTo(this.options.parent);
			}

			this.panel = $('

').addClass('hbox-panel').appendTo(this.container);
			this.sep = this.options.separator
				? new PanelSeparator({
					parent: this.container,
					dragStart: this.options.dragStart,
					drag: this.options.drag,
					dragStop: this.options.dragStop,
					index: this.options.index
				  })
				: null;

			this.position(this.options);
			this.dimension(this.options);

		},

		element: function() {
			return this.container;
		},

		content: function() {
			return this.panel;
		},

		separator: function(sep) {
			sep = sep || null;
			if (Object.isObject(sep)) {
				this.sep = sep;
				return this;
			}
			return this.sep;
		},

		position: function(pos) {

			/*pos = pos || null;
			if (Object.isObject(pos)) {
				if (pos.top) $(this.container).css('top', parseInt(pos.top));
				if (pos.left) $(this.container).css('left', parseInt(pos.left));
				this.render();
				return this;
			}*/

			var actualPos = {
				top: $(this.container).css('top').replace(/\D/ig, ''),
				left: $(this.container).css('left').replace(/\D/ig, '')
			};

			return actualPos;
		},

		dimension: function(dim, animate, saveWidth) {
			var actualDim = {
				width: this.options.renderWidth,
				height: $(this.container).height()
			};

			animate = Object.isBoolean(animate) ? animate : false;

			dim = dim || null;
			if (Object.isObject(dim)) {
				if (saveWidth) {
					this.options.expandedWidth = Object.clone(actualDim);
				}

				var sepBorder = 0;
				if (this.sep !== null) {
					sepBorder = this.sep.dimension().width;
				}
				if (dim.width) {
					if (animate) {
						$(this.container).stop();
						$(this.panel).stop();
						$(this.container).animate({'width': parseInt(dim.width)}, 300, 'easeInOutQuad');
						$(this.panel).animate({'width': parseInt(dim.width) - sepBorder}, 300, 'easeInOutQuad');
					} else {
						$(this.container).width(parseInt(dim.width));
						$(this.panel).width(parseInt(dim.width) - sepBorder);
					}
					actualDim.width = dim.width;
					this.options.renderWidth = dim.width;
				}
				/*if (dim.height) $(this.container).height(parseInt(dim.height));
				$(this.container).css({
					top: '0px',
					bottom: '0px'
				});
				$(this.panel).css({
					top: '0px',
					bottom: '0px'
				});*/
				this.render();
				return this;
			}
			return actualDim;
		},

		render: function() {

			if (this.sep === null) return;

			var top = parseInt($(this.panel).css('top').replace(/\D/ig, ''));
			var left = parseInt($(this.panel).css('left').replace(/\D/ig, ''));
			var width = parseInt($(this.panel).width());
			var height = parseInt($(this.panel).height());

			/*this.sep
				.position({
					top: top,
					left: width
				})
				.dimension({
					height: height
				});*/

			return this;
		}
	});

	$.widget('ui.hbox', {

		panels: null,

		_init: function() {

//			console.info('HBox: ', this);

			this.panels = [];
			this.options.borderSize = $(this.element).css('padding-top');

			var hboxDim = this.dimension();
			var width = hboxDim.width / this.options.panels;

			var auxPanels = [];

			for (var i=0, l=this.options.panels; i<l; i++) {

				var p = new Panel({
					parent: this.element,
					separator: (i < (l-1)),
					dragStart: this.onDragStart.bind(this),
					drag: this.onDrag.bind(this),
					dragStop: this.onDragStop.bind(this),
					width: width,
//					height: hboxDim.height,
					index: i
				});

				if (p.separator()) {
					p.autoHide = true;
					//NOTE: Wrap the index value
					var f = (function(idx) {
						return function() {
							var index = idx;
							if (!p.autoHide) {
								this.hidePanel(index);
								p.autoHide = true;
							} else {
								p.autoHide = false;
							}
						}.bind(this);
					}.bind(this))(i);

					$(p.separator().element()).click(f);

					if (i == 0) {
						// default size
						p.dimension({width: 315});
					}
					var showCallback = (function(idx) {
						return function() {
							if (p.autoHide && this.isHidden(idx)) {
								var index = idx;
								this.showPanel(index);
							}
						}.bind(this);
					}.bind(this))(i);

					var hideCallback = (function(idx) {
						return function(event) {
							if (p.autoHide && !this.isHidden(idx) && $('.xim-actions-menu').length == 0 && event.clientX > 6) {
								var index = idx;
								this.hidePanel(index);
							}
						}.bind(this);
					}.bind(this))(i);

					$(p.separator().element()).mouseover(showCallback);
					p.container.mouseleave(hideCallback);
				}

				auxPanels.push(i);
				this.panels.push(p);

				$(window).resize(function() {
					this.render();
				}.bind(this) );
			}

			var ci = function() {
				if (auxPanels.length > 0) return;
				this.render();
			}.bind(this);

			for (var i=0,l=auxPanels.length; i<l; i++) {
				var key = 'hbox.sep.%s'.printf(i);
				var value = X.session.get(key);
				auxPanels.shift();
				if (this.panels[i].separator() && value !== null) {
					this.panels[i].dimension({width: value});
				}
				ci();
			}
		},

		dimension: function() {
			return {
				width: $(this.element).width(),
				height: $(this.element).height()
			}
		},

		getPanel: function(index) {
			return this.panels[index] || null;
		},

		length: function() {
			return this.panels.length;
		},

		render: function(animate) {

			animate = Object.isBoolean(animate) ? animate : false;
			var hboxDim = this.dimension();
			var totalWidth = 0;

			this.panels.each(function(index, item) {
				action_dimension = null;
				var dim = item.dimension();
				var width = parseInt(dim.width);
				if (totalWidth + width > hboxDim.width) {
					width = hboxDim.width - totalWidth;
					item.dimension({width: width}, animate);
				}

				if (index < this.length() - 1) {
					totalWidth += width;
				} else {
					totalWidth = hboxDim.width - totalWidth;
					item.dimension({width: totalWidth}, animate);
					action_dimension =  item.dimension();
				}

				$(window).trigger("action_resize", [{dimension: item.dimension(), panel: this}]);
				$(item.element()).removeClass('hbox-panel-hidden');

			}.bind(this));

			return;

//			if (!animate) {
//				$(this.getPanel(0)).css(leftPanel);
//				$('.hbox-panel-sep', this.element).css(separator);
//				$(this.getPanel(1)).css(rightPanel);
//			} else {
//				$(this.getPanel(0)).animate(leftPanel, 'fast');
//				$('.hbox-panel-sep', this.element).animate(separator, 'fast');
//				$(this.getPanel(1)).animate(rightPanel, 'fast');
//			}
		},

		onDrag: function(event, element, position) {
			var index = $(element.className.split(' ')).map(function(index, item) {
				var ret = parseInt(item.replace(/^hbox-panel-separator-/i, ''));
				return isNaN(ret) ? null : ret;
			}).get(0);

			var p = this.getPanel(index);
			if (p === null) return;
			var borderSize = parseInt(p.separator().dimension().width);

			var offset = this.getPanel(index-1) ? this.getPanel(index-1).dimension().width : 0;
			position.left = position.left <= 0 ? 4 : position.left;
			p.dimension({width: (position.left - offset) + borderSize});

			this.render();
		},

		onDragStart: function(event, element, position) {
			$(this.element).trigger('dragstart', [{event: event, sep: element, pos: position}]);
		},

		onDragStop: function(event, element, position) {
			var data = $(element).data('data');
			X.session.set('hbox.sep.%s'.printf(data.index), position.left);
			$(this.element).trigger('dragstop', [{event: event, sep: element, pos: position}]);
		},

		togglePanel: function(panelIndex) {
			if (this.isHidden(panelIndex)) {
				this.showPanel(panelIndex);
			} else {
				this.hidePanel(panelIndex);
			}
		},

		showPanel: function(panelIndex) {
			var p = this.getPanel(panelIndex);
			if (p === null) return;
			p.dimension(p.options.expandedWidth, true);
			this.render(true);
			$(p.element()).removeClass('hbox-panel-hidden');
			p.hidden = false;
			//this.onDragStop({}, p.separator().element(), {left: p.dimension().width});
		},

		hidePanel: function(panelIndex) {
			var p = this.getPanel(panelIndex);
			if (p === null) return;
			var dim = p.separator().dimension();
			p.dimension({width: dim.width}, true, true);
			this.render(true);
			$(p.element()).addClass('hbox-panel-hidden');
			p.hidden = true;
			//this.onDragStop({}, p.separator().element(), {left: p.dimension().width});
		},

		isHidden: function(panelIndex) {
			var p = this.getPanel(panelIndex);
			if (p === null) return null;
			return p.hidden;
		},

		options: {
			panels: 2
		},

		getter: ['getPanel', 'isPanelExpanded', 'length']

	});

})(jQuery);
<|endoftext|>