<commit_before>/*
* #%L
* $ lightbox_me
* %%
*  By: Buck Wilson
* %%
* Version : 2.3
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

(function($) {

    $.fn.lightbox_me = function(options) {

        return this.each(function() {

            var
                opts = $.extend({}, $.fn.lightbox_me.defaults, options),
                $overlay = $(),
                $self = $(this),
                $iframe = $(''),
                ie6 = ($.browser.msie && $.browser.version < 7);

            if (opts.showOverlay) {
                //check if there's an existing overlay, if so, make subequent ones clear
               var $currentOverlays = $(".js_lb_overlay:visible");
                if ($currentOverlays.length > 0){
                    $overlay = $('
');
                } else {
                    $overlay = $('
');
                }
            }

            /*----------------------------------------------------
               DOM Building
            ---------------------------------------------------- */
            if (ie6) {
                var src = /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank';
                $iframe.attr('src', src);
                $('body').append($iframe);
            } // iframe shim for ie6, to hide select elements
            $('body').append($self.hide()).append($overlay);

            /*----------------------------------------------------
               Overlay CSS stuffs
            ---------------------------------------------------- */

            // set css of the overlay
            if (opts.showOverlay) {
                setOverlayHeight(); // pulled this into a function because it is called on window resize.
                $overlay.css({ position: 'absolute', width: '100%', top: 0, left: 0, right: 0, bottom: 0, zIndex: (opts.zIndex + 2), display: 'none' });
				if (!$overlay.hasClass('lb_overlay_clear')){
                	$overlay.css(opts.overlayCSS);
                }
            }

            /*----------------------------------------------------
               Animate it in.
            ---------------------------------------------------- */
               //
            if (opts.showOverlay) {
                $overlay.fadeIn(opts.overlaySpeed, function() {
                    setSelfPosition();
                    $self[opts.appearEffect](opts.lightboxSpeed, function() { setOverlayHeight(); setSelfPosition(); opts.onLoad()});
                });
            } else {
                setSelfPosition();
                $self[opts.appearEffect](opts.lightboxSpeed, function() { opts.onLoad()});
            }

            /*----------------------------------------------------
               Hide parent if parent specified (parentLightbox should be jquery reference to any parent lightbox)
            ---------------------------------------------------- */
            if (opts.parentLightbox) {
                opts.parentLightbox.fadeOut(200);
            }

            /*----------------------------------------------------
               Bind Events
            ---------------------------------------------------- */

            $(window).resize(setOverlayHeight)
                     .resize(setSelfPosition)
                     .scroll(setSelfPosition);

            $(window).bind('keyup.lightbox_me', observeKeyPress);

            if (opts.closeClick) {
                $overlay.click(function(e) { closeLightbox(); e.preventDefault; });
            }
            $self.delegate(opts.closeSelector, "click", function(e) {
                closeLightbox(); e.preventDefault();
            });
            $self.bind('close', closeLightbox);
            $self.bind('reposition', setSelfPosition);

            /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
              -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */

            /*----------------------------------------------------
               Private Functions
            ---------------------------------------------------- */

            /* Remove or hide all elements */
            function closeLightbox() {
                var s = $self[0].style;
                if (opts.destroyOnClose) {
                    $self.add($overlay).remove();
                } else {
                    $self.add($overlay).hide();
                }

                //show the hidden parent lightbox
                if (opts.parentLightbox) {
                    opts.parentLightbox.fadeIn(200);
                }

                $iframe.remove();

				// clean up events.
                $self.undelegate(opts.closeSelector, "click");

                $(window).unbind('reposition', setOverlayHeight);
                $(window).unbind('reposition', setSelfPosition);
                $(window).unbind('scroll', setSelfPosition);
                $(window).unbind('keyup.lightbox_me');
                if (ie6)
                    s.removeExpression('top');
                opts.onClose();
            }

            /* Function to bind to the window to observe the escape/enter key press */
            function observeKeyPress(e) {
                if((e.keyCode == 27 || (e.DOM_VK_ESCAPE == 27 && e.which==0)) && opts.closeEsc) closeLightbox();
            }

            /* Set the height of the overlay
                    : if the document height is taller than the window, then set the overlay height to the document height.
                    : otherwise, just set overlay height: 100%
            */
            function setOverlayHeight() {
                if ($(window).height() < $(document).height()) {
                    $overlay.css({height: $(document).height() + 'px'});
                     $iframe.css({height: $(document).height() + 'px'});
                } else {
                    $overlay.css({height: '100%'});
                    if (ie6) {
                        $('html,body').css('height','100%');
                        $iframe.css('height', '100%');
                    } // ie6 hack for height: 100%; TODO: handle this in IE7
                }
            }

            /* Set the position of the modal'd window ($self)
                    : if $self is taller than the window, then make it absolutely positioned
                    : otherwise fixed
            */
            function setSelfPosition() {
                var s = $self[0].style;

                // reset CSS so width is re-calculated for margin-left CSS
                $self.css({left: '50%', marginLeft: ($self.outerWidth() / 2) * -1,  zIndex: (opts.zIndex + 3) });

                /* we have to get a little fancy when dealing with height, because lightbox_me
                    is just so fancy.
                 */

                // if the height of $self is bigger than the window and self isn't already position absolute
                if (($self.height() + 80  >= $(window).height()) && ($self.css('position') != 'absolute' || ie6)) {

                    // we are going to make it positioned where the user can see it, but they can still scroll
                    // so the top offset is based on the user's scroll position.
                    var topOffset = $(document).scrollTop() + 40;
                    $self.css({position: 'absolute', top: topOffset + 'px', marginTop: 0})
                    if (ie6) {
                        s.removeExpression('top');
                    }
                } else if ($self.height()+ 80  < $(window).height()) {
                    //if the height is less than the window height, then we're gonna make this thing position: fixed.
                    // in ie6 we're gonna fake it.
                    if (ie6) {
                        s.position = 'absolute';
                        if (opts.centered) {
                            s.setExpression('top', '(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"')
                            s.marginTop = 0;
                        } else {
                            var top = (opts.modalCSS && opts.modalCSS.top) ? parseInt(opts.modalCSS.top) : 0;
                            s.setExpression('top', '((blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"')
                        }
                    } else {
                        if (opts.centered) {
                            $self.css({ position: 'fixed', top: '50%', marginTop: ($self.outerHeight() / 2) * -1})
                        } else {
                            $self.css({ position: 'fixed'}).css(opts.modalCSS);
                        }

                    }
                }
            }

        });

    };

    $.fn.lightbox_me.defaults = {

        // animation
        appearEffect: "fadeIn",
        appearEase: "",
        overlaySpeed: 250,
        lightboxSpeed: 300,

        // close
        closeSelector: ".close",
        closeClick: true,
        closeEsc: true,

        // behavior
        destroyOnClose: false,
        showOverlay: true,
        parentLightbox: false,

        // callbacks
        onLoad: function() {},
        onClose: function() {},

        // style
        classPrefix: 'lb',
        zIndex: 999,
        centered: false,
        modalCSS: {top: '40px'},
        overlayCSS: {background: 'black', opacity: .3}
    }
})(jQuery);<commit_msg>Update license header so that it does not complain in the continuous-integration build<commit_after>/*
* #%L
* $ lightbox_me
* %%
* Copyright (C) 2011 Buck Wilson
* %%
* Version : 2.3
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

(function($) {

    $.fn.lightbox_me = function(options) {

        return this.each(function() {

            var
                opts = $.extend({}, $.fn.lightbox_me.defaults, options),
                $overlay = $(),
                $self = $(this),
                $iframe = $(''),
                ie6 = ($.browser.msie && $.browser.version < 7);

            if (opts.showOverlay) {
                //check if there's an existing overlay, if so, make subequent ones clear
               var $currentOverlays = $(".js_lb_overlay:visible");
                if ($currentOverlays.length > 0){
                    $overlay = $('
');
                } else {
                    $overlay = $('
');
                }
            }

            /*----------------------------------------------------
               DOM Building
            ---------------------------------------------------- */
            if (ie6) {
                var src = /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank';
                $iframe.attr('src', src);
                $('body').append($iframe);
            } // iframe shim for ie6, to hide select elements
            $('body').append($self.hide()).append($overlay);

            /*----------------------------------------------------
               Overlay CSS stuffs
            ---------------------------------------------------- */

            // set css of the overlay
            if (opts.showOverlay) {
                setOverlayHeight(); // pulled this into a function because it is called on window resize.
                $overlay.css({ position: 'absolute', width: '100%', top: 0, left: 0, right: 0, bottom: 0, zIndex: (opts.zIndex + 2), display: 'none' });
				if (!$overlay.hasClass('lb_overlay_clear')){
                	$overlay.css(opts.overlayCSS);
                }
            }

            /*----------------------------------------------------
               Animate it in.
            ---------------------------------------------------- */
               //
            if (opts.showOverlay) {
                $overlay.fadeIn(opts.overlaySpeed, function() {
                    setSelfPosition();
                    $self[opts.appearEffect](opts.lightboxSpeed, function() { setOverlayHeight(); setSelfPosition(); opts.onLoad()});
                });
            } else {
                setSelfPosition();
                $self[opts.appearEffect](opts.lightboxSpeed, function() { opts.onLoad()});
            }

            /*----------------------------------------------------
               Hide parent if parent specified (parentLightbox should be jquery reference to any parent lightbox)
            ---------------------------------------------------- */
            if (opts.parentLightbox) {
                opts.parentLightbox.fadeOut(200);
            }

            /*----------------------------------------------------
               Bind Events
            ---------------------------------------------------- */

            $(window).resize(setOverlayHeight)
                     .resize(setSelfPosition)
                     .scroll(setSelfPosition);

            $(window).bind('keyup.lightbox_me', observeKeyPress);

            if (opts.closeClick) {
                $overlay.click(function(e) { closeLightbox(); e.preventDefault; });
            }
            $self.delegate(opts.closeSelector, "click", function(e) {
                closeLightbox(); e.preventDefault();
            });
            $self.bind('close', closeLightbox);
            $self.bind('reposition', setSelfPosition);

            /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
              -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */

            /*----------------------------------------------------
               Private Functions
            ---------------------------------------------------- */

            /* Remove or hide all elements */
            function closeLightbox() {
                var s = $self[0].style;
                if (opts.destroyOnClose) {
                    $self.add($overlay).remove();
                } else {
                    $self.add($overlay).hide();
                }

                //show the hidden parent lightbox
                if (opts.parentLightbox) {
                    opts.parentLightbox.fadeIn(200);
                }

                $iframe.remove();

				// clean up events.
                $self.undelegate(opts.closeSelector, "click");

                $(window).unbind('reposition', setOverlayHeight);
                $(window).unbind('reposition', setSelfPosition);
                $(window).unbind('scroll', setSelfPosition);
                $(window).unbind('keyup.lightbox_me');
                if (ie6)
                    s.removeExpression('top');
                opts.onClose();
            }

            /* Function to bind to the window to observe the escape/enter key press */
            function observeKeyPress(e) {
                if((e.keyCode == 27 || (e.DOM_VK_ESCAPE == 27 && e.which==0)) && opts.closeEsc) closeLightbox();
            }

            /* Set the height of the overlay
                    : if the document height is taller than the window, then set the overlay height to the document height.
                    : otherwise, just set overlay height: 100%
            */
            function setOverlayHeight() {
                if ($(window).height() < $(document).height()) {
                    $overlay.css({height: $(document).height() + 'px'});
                     $iframe.css({height: $(document).height() + 'px'});
                } else {
                    $overlay.css({height: '100%'});
                    if (ie6) {
                        $('html,body').css('height','100%');
                        $iframe.css('height', '100%');
                    } // ie6 hack for height: 100%; TODO: handle this in IE7
                }
            }

            /* Set the position of the modal'd window ($self)
                    : if $self is taller than the window, then make it absolutely positioned
                    : otherwise fixed
            */
            function setSelfPosition() {
                var s = $self[0].style;

                // reset CSS so width is re-calculated for margin-left CSS
                $self.css({left: '50%', marginLeft: ($self.outerWidth() / 2) * -1,  zIndex: (opts.zIndex + 3) });

                /* we have to get a little fancy when dealing with height, because lightbox_me
                    is just so fancy.
                 */

                // if the height of $self is bigger than the window and self isn't already position absolute
                if (($self.height() + 80  >= $(window).height()) && ($self.css('position') != 'absolute' || ie6)) {

                    // we are going to make it positioned where the user can see it, but they can still scroll
                    // so the top offset is based on the user's scroll position.
                    var topOffset = $(document).scrollTop() + 40;
                    $self.css({position: 'absolute', top: topOffset + 'px', marginTop: 0})
                    if (ie6) {
                        s.removeExpression('top');
                    }
                } else if ($self.height()+ 80  < $(window).height()) {
                    //if the height is less than the window height, then we're gonna make this thing position: fixed.
                    // in ie6 we're gonna fake it.
                    if (ie6) {
                        s.position = 'absolute';
                        if (opts.centered) {
                            s.setExpression('top', '(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"')
                            s.marginTop = 0;
                        } else {
                            var top = (opts.modalCSS && opts.modalCSS.top) ? parseInt(opts.modalCSS.top) : 0;
                            s.setExpression('top', '((blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"')
                        }
                    } else {
                        if (opts.centered) {
                            $self.css({ position: 'fixed', top: '50%', marginTop: ($self.outerHeight() / 2) * -1})
                        } else {
                            $self.css({ position: 'fixed'}).css(opts.modalCSS);
                        }

                    }
                }
            }

        });

    };

    $.fn.lightbox_me.defaults = {

        // animation
        appearEffect: "fadeIn",
        appearEase: "",
        overlaySpeed: 250,
        lightboxSpeed: 300,

        // close
        closeSelector: ".close",
        closeClick: true,
        closeEsc: true,

        // behavior
        destroyOnClose: false,
        showOverlay: true,
        parentLightbox: false,

        // callbacks
        onLoad: function() {},
        onClose: function() {},

        // style
        classPrefix: 'lb',
        zIndex: 999,
        centered: false,
        modalCSS: {top: '40px'},
        overlayCSS: {background: 'black', opacity: .3}
    }
})(jQuery);
<|endoftext|>


<commit_before>var GFBSubscribe = function(){};

GFBSubscribe.prototype.scroller_activity_status = false;
GFBSubscribe.prototype.overlay_display_status = "hidden";

GFBSubscribe.prototype.overlay = function() {
  el = document.getElementById("gfb_widget_overlay");
  document.getElementById("gfb_response_message_success").style.display = "none";
  document.getElementById("gfb_response_message_error").style.display = "none";
  document.getElementById("gfb_subscribe_email_text").value = "";
  document.getElementById("gfb_intial_message").style.display = "inline";
  el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
  this.overlay_display_status = el.style.visibility;

  if (this.overlay_display_status == "visible") {
    this.scroller();
  }
}

GFBSubscribe.prototype.postData = function(email, url){
 var _this = this;

 if(this.isValidEmail(email) == true){
   var xmlhttp;
   if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
     xmlhttp=new XMLHttpRequest();
   } else {// code for IE6, IE5
     xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
   }

   xmlhttp.onreadystatechange = function(){
     if (xmlhttp.status == 0 || xmlhttp.status == 200)
       {
         var respTag = document.getElementById("gfb_response_message_success");
         respTag.innerHTML= "A confirmation email has been sent to your email address.
 Click the confirmation link to recieve the ebook.";
         respTag.style.display = "block";
         document.getElementById("gfb_intial_message").style.display = "none";
         document.getElementById("gfb_response_message_error").style.display = "none";

         setTimeout(function(){ _this.overlay(); }, 15000);
       }
     }

   xmlhttp.open("POST",url,true);
   xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
   xmlhttp.send("EMAIL="+email);

 } else {
   var respTag = document.getElementById("gfb_response_message_error");
   document.getElementById("gfb_response_message_success").style.display = "none";

   respTag.innerHTML= "Valid email address required";
   respTag.style.display = "block";
 }
}

GFBSubscribe.prototype.isValidEmail = function(entry) {
   return (entry.indexOf(".") > 2) && (entry.indexOf("@") > 0);
}

GFBSubscribe.prototype.scrollManager = function(isNotLoggedIn, scrollerActivityStatus) {
  if(typeof(isNotLoggedIn)==='undefined') isNotLoggedIn = true;
  if(typeof(scrollerActivityStatus)==='undefined') scrollerActivityStatus = false;

  this.scroller_activity_status = scrollerActivityStatus

  if (isNotLoggedIn) {
    this.scroller();
  }
}

GFBSubscribe.prototype.scroller = function() {
      var _this = this;
      window.onscroll = function () {
        if(_this.scroller_activity_status) {
          var docBody = document.body,
          docElement = document.documentElement,
          height

          if(typeof document.height !== 'undefined') {
            height = document.height // For webkit browsers
          } else {
            height = Math.max( docBody.scrollHeight, docBody.offsetHeight,docElement.clientHeight, docElement.scrollHeight, docElement.offsetHeight );
          }

          if(window.pageYOffset > (height/2)){
            if(_this.overlay_display_status == 'hidden' ){
              _this.overlay();
            }
          }
        }
        _this.scrollTracker();
      }
  }

  GFBSubscribe.prototype.scrollTracker = function() {
    var vertical_position = 0,
    formEl = document.getElementById("gfb_newsletter_signup_form")

    if(window.pageYOffset){
      vertical_position = window.pageYOffset;
    } else if(docElement.clientHeight){//ie
      vertical_position = docElement.scrollTop;
    } else if(docBody){//ie quirks
      vertical_position = docBody.scrollTop;
    }

    formEl.style.top = (vertical_position - 150) + 'px';
  }

var gfb_subscribe = new GFBSubscribe();
<commit_msg>Fix docElement undefined bug<commit_after>var GFBSubscribe = function(){};

GFBSubscribe.prototype.scroller_activity_status = false;
GFBSubscribe.prototype.overlay_display_status = "hidden";

GFBSubscribe.prototype.docBody = null;
GFBSubscribe.prototype.docElement = null;

GFBSubscribe.prototype.overlay = function() {
  el = document.getElementById("gfb_widget_overlay");
  document.getElementById("gfb_response_message_success").style.display = "none";
  document.getElementById("gfb_response_message_error").style.display = "none";
  document.getElementById("gfb_subscribe_email_text").value = "";
  document.getElementById("gfb_intial_message").style.display = "inline";
  el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
  this.overlay_display_status = el.style.visibility;

  if (this.overlay_display_status == "visible") {
    this.scroller();
  }
}

GFBSubscribe.prototype.postData = function(email, url){
 var _this = this;

 if(this.isValidEmail(email) == true){
   var xmlhttp;
   if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
     xmlhttp=new XMLHttpRequest();
   } else {// code for IE6, IE5
     xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
   }

   xmlhttp.onreadystatechange = function(){
     if (xmlhttp.status == 0 || xmlhttp.status == 200)
       {
         var respTag = document.getElementById("gfb_response_message_success");
         respTag.innerHTML= "A confirmation email has been sent to your email address.
 Click the confirmation link to recieve the ebook.";
         respTag.style.display = "block";
         document.getElementById("gfb_intial_message").style.display = "none";
         document.getElementById("gfb_response_message_error").style.display = "none";

         setTimeout(function(){ _this.overlay(); }, 15000);
       }
     }

   xmlhttp.open("POST",url,true);
   xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
   xmlhttp.send("EMAIL="+email);

 } else {
   var respTag = document.getElementById("gfb_response_message_error");
   document.getElementById("gfb_response_message_success").style.display = "none";

   respTag.innerHTML= "Valid email address required";
   respTag.style.display = "block";
 }
}

GFBSubscribe.prototype.isValidEmail = function(entry) {
   return (entry.indexOf(".") > 2) && (entry.indexOf("@") > 0);
}

GFBSubscribe.prototype.scrollManager = function(isNotLoggedIn, scrollerActivityStatus) {
  if(typeof(isNotLoggedIn)==='undefined') isNotLoggedIn = true;
  if(typeof(scrollerActivityStatus)==='undefined') scrollerActivityStatus = false;

  this.scroller_activity_status = scrollerActivityStatus

  this.docBody = document.body;
  this.docElement = document.documentElement;

  if (isNotLoggedIn) {
    this.scroller();
  }
}

GFBSubscribe.prototype.scroller = function() {
      var _this = this;
      window.onscroll = function () {
        var height;

        if(_this.scroller_activity_status) {
          if(typeof document.height !== 'undefined') {
            height = document.height // For webkit browsers
          } else {
            height = Math.max( _this.docBody.scrollHeight, _this.docBody.offsetHeight, _this.docElement.clientHeight, _this.docElement.scrollHeight, _this.docElement.offsetHeight);
          }

          if(window.pageYOffset > (height/2)){
            if(_this.overlay_display_status == 'hidden' ){
              _this.overlay();
            }
          }
        }
        _this.scrollTracker();
      }
  }

  GFBSubscribe.prototype.scrollTracker = function() {
    var vertical_position = 0,
    formEl = document.getElementById("gfb_newsletter_signup_form")

    if(window.pageYOffset){
      vertical_position = window.pageYOffset;
    } else if(this.docElement.clientHeight){//ie
      vertical_position = this.docElement.scrollTop;
    } else if(this.docBody){//ie quirks
      vertical_position = this.docBody.scrollTop;
    }

    formEl.style.top = (vertical_position - 150) + 'px';
  }

var gfb_subscribe = new GFBSubscribe();
<|endoftext|>


<commit_before>import React, {PureComponent} from 'react';
import Translate from 'react-translate-component';

import FeatureLinesEditor from './feature-viewer/feature-lines-editor';

class FeatureViewer extends PureComponent {
  constructor(props, context) {
    super(props, context);

    this.state = this.buildState(props);
  }

  numericField(field) {
    return ['opening', 'buildstart', 'closure'].includes(field);
  }

  visibleFields() {
    return ['opening', 'buildstart', 'closure', 'name', 'osm_id', 'osm_tags'];
  }

  editableFields() {
    return ['opening', 'buildstart', 'closure', 'name'];
  }

  componentWillReceiveProps(props) {
    this.setState(this.buildState(props));
  }

  buildState(props) {
    const opts = {fields: {}};

    const properties = props.feature ? props.feature.properties : null;

    if (!properties) return {};

    Object.entries(properties).map(entry => {
      const key = entry[0];
      const value = entry[1];

      if (!this.visibleFields().includes(key)) return;

      opts.fields[key] = value;
    });

    return opts;
  }

  onValueChange(e) {
    const key = e.target.attributes.name.value;
    const value = e.target.value;

    const modifiedFeature = Object.assign({}, this.props.feature);
    modifiedFeature.properties[key] = value;

    if (this.props.onFeatureChange) this.props.onFeatureChange(modifiedFeature);
  }

  onAddLine(newLine) {
    const modifiedFeature = Object.assign({}, this.props.feature);
    modifiedFeature.properties.lines.push(newLine);

    if (this.props.onFeatureChange) this.props.onFeatureChange(modifiedFeature);
  }

  onRemoveLine(urlName) {
    const modifiedFeature = Object.assign({}, this.props.feature);

    const lineIndex = modifiedFeature.properties.lines.findIndex(l => l.line_url_name == urlName);
    modifiedFeature.properties.lines.splice(lineIndex, 1);

    if (this.props.onFeatureChange) this.props.onFeatureChange(modifiedFeature);
  }

  render() {
    const properties = this.props.feature ? this.props.feature.properties : null;

    const content = this.props.feature ?

<Translate content={`editor.feature_viewer.fields.klasses_id.${properties.klass.toLowerCase()}`} with={{id: properties.id}} />

                  <FeatureLinesEditor
                    featureLines={this.props.feature.properties.lines || []}
                    lines={this.props.lines}
                    systems={this.props.systems}
                    onAddLine={this.onAddLine.bind(this)}
                    onRemoveLine={this.onRemoveLine.bind(this)}
                  />

              { Object.keys(this.state.fields).map((key) => {
                // We don't show the field at all if it's not editable and has no value
                if (!this.editableFields().includes(key) && !this.state.fields[key]) return;

                return (
                  <tr key={`${properties.id}_${key}`} className="c-table__row">
                    <Translate content={`editor.feature_viewer.fields.${key}`} />

                      { this.editableFields().includes(key) ?
                      <input className="c-field"
                             type={this.numericField(key) ? 'number' : 'text'}
                             name={key}
                             onChange={this.onValueChange.bind(this)}
                             value={this.state.fields[key]}/>
                        :
                        this.state.fields[key]
                      }

                )
              }) }

 : <Translate content="editor.feature_viewer.no_feature_selected" />;

    return (

<Translate content="editor.feature_viewer.selected_feature" />

        { content }

      )
  }
}

export default FeatureViewer
<commit_msg>Revert "Editor: handle feature with no lines set"<commit_after>import React, {PureComponent} from 'react';
import Translate from 'react-translate-component';

import FeatureLinesEditor from './feature-viewer/feature-lines-editor';

class FeatureViewer extends PureComponent {
  constructor(props, context) {
    super(props, context);

    this.state = this.buildState(props);
  }

  numericField(field) {
    return ['opening', 'buildstart', 'closure'].includes(field);
  }

  visibleFields() {
    return ['opening', 'buildstart', 'closure', 'name', 'osm_id', 'osm_tags'];
  }

  editableFields() {
    return ['opening', 'buildstart', 'closure', 'name'];
  }

  componentWillReceiveProps(props) {
    this.setState(this.buildState(props));
  }

  buildState(props) {
    const opts = {fields: {}};

    const properties = props.feature ? props.feature.properties : null;

    if (!properties) return {};

    Object.entries(properties).map(entry => {
      const key = entry[0];
      const value = entry[1];

      if (!this.visibleFields().includes(key)) return;

      opts.fields[key] = value;
    });

    return opts;
  }

  onValueChange(e) {
    const key = e.target.attributes.name.value;
    const value = e.target.value;

    const modifiedFeature = Object.assign({}, this.props.feature);
    modifiedFeature.properties[key] = value;

    if (this.props.onFeatureChange) this.props.onFeatureChange(modifiedFeature);
  }

  onAddLine(newLine) {
    const modifiedFeature = Object.assign({}, this.props.feature);
    modifiedFeature.properties.lines.push(newLine);

    if (this.props.onFeatureChange) this.props.onFeatureChange(modifiedFeature);
  }

  onRemoveLine(urlName) {
    const modifiedFeature = Object.assign({}, this.props.feature);

    const lineIndex = modifiedFeature.properties.lines.findIndex(l => l.line_url_name == urlName);
    modifiedFeature.properties.lines.splice(lineIndex, 1);

    if (this.props.onFeatureChange) this.props.onFeatureChange(modifiedFeature);
  }

  render() {
    const properties = this.props.feature ? this.props.feature.properties : null;

    const content = this.props.feature ?

<Translate content={`editor.feature_viewer.fields.klasses_id.${properties.klass.toLowerCase()}`} with={{id: properties.id}} />

                  <FeatureLinesEditor
                    featureLines={this.props.feature.properties.lines}
                    lines={this.props.lines}
                    systems={this.props.systems}
                    onAddLine={this.onAddLine.bind(this)}
                    onRemoveLine={this.onRemoveLine.bind(this)}
                  />

              { Object.keys(this.state.fields).map((key) => {
                // We don't show the field at all if it's not editable and has no value
                if (!this.editableFields().includes(key) && !this.state.fields[key]) return;

                return (
                  <tr key={`${properties.id}_${key}`} className="c-table__row">
                    <Translate content={`editor.feature_viewer.fields.${key}`} />

                      { this.editableFields().includes(key) ?
                      <input className="c-field"
                             type={this.numericField(key) ? 'number' : 'text'}
                             name={key}
                             onChange={this.onValueChange.bind(this)}
                             value={this.state.fields[key]}/>
                        :
                        this.state.fields[key]
                      }

                )
              }) }

 : <Translate content="editor.feature_viewer.no_feature_selected" />;

    return (

<Translate content="editor.feature_viewer.selected_feature" />

        { content }

      )
  }
}

export default FeatureViewer
<|endoftext|>


<commit_before>class Ranking extends BlazeComponent {
	template() {
		return 'ranking';
	}

	onRendered() {
		var freshData = Meteor.users.find({}, {
			fields: {
				'profile.firstName': 1,
				'profile.lastName': 1,
				'profile.points': 1
			}
		}).fetch();
		var userData = [];
		for (var i = 0; i < freshData.length; i++) {
			var list = [];
			list.push(freshData[i].fullName());
			list = list.concat(freshData[i].last5Games());
			userData.push(list);
		}
		userData.sort(function(a, b) {
			if (a[0] > b[0]) {
				return 1;
			}
			if (a[0] < b[0]) {
				return -1;
			}
			return 0;
		});
		var chart = c3.generate({
			bindto: '#rankingGraph',
			data: {
				type: 'line',
				columns: userData
			},
			axis: {
				y: {
					label: {
						text: 'Points',
						position: 'outer-middle',
					}
				},
				x: {
					label: {
						text: 'Derniers 5 matchs',
						position: 'outer-center',
					}
				}
			},
			grid: {
				y: {
					show: true
				}
			}
		});
		chart.load({
			columns: userData
		});
		$('tbody tr:nth-child(-n+3)').addClass('success');
		$('tbody tr:nth-last-child(-n+3)').addClass('danger');
	}

	playerData() {
		var freshData = Meteor.users.find({}, {
			fields: {
				'profile.firstName': 1,
				'profile.lastName': 1,
				'profile.points': 1,
			}
		}).fetch();
		var newList = [];
		for (var i = 0; i < freshData.length; i++) {
			if (freshData[i].profile.points.length > 9) {
				newList.push(freshData[i]);
			}
		}
		newList.sort(function(a, b) {
			if (a.currentPoints() > b.currentPoints()) {
				return -1;
			}
			if (a.currentPoints() < b.currentPoints()) {
				return 1;
			}
			return 0;
		});
		return newList;
	}

	index() {
		return this.currentData('@index') + 1;
	}
}

Ranking.register('Ranking');
<commit_msg>Set height of the graph<commit_after>class Ranking extends BlazeComponent {
	template() {
		return 'ranking';
	}

	onRendered() {
		var freshData = Meteor.users.find({}, {
			fields: {
				'profile.firstName': 1,
				'profile.lastName': 1,
				'profile.points': 1
			}
		}).fetch();
		var userData = [];
		for (var i = 0; i < freshData.length; i++) {
			var list = [];
			list.push(freshData[i].fullName());
			list = list.concat(freshData[i].last5Games());
			userData.push(list);
		}
		userData.sort(function(a, b) {
			if (a[0] > b[0]) {
				return 1;
			}
			if (a[0] < b[0]) {
				return -1;
			}
			return 0;
		});
		var chart = c3.generate({
			bindto: '#rankingGraph',
			size: {
				height: 480
			},
			data: {
				type: 'line',
				columns: userData
			},
			axis: {
				y: {
					label: {
						text: 'Points',
						position: 'outer-middle',
					}
				},
				x: {
					label: {
						text: 'Derniers 5 matchs',
						position: 'outer-center',
					}
				}
			},
			grid: {
				y: {
					show: true
				}
			}
		});
		chart.load({
			columns: userData
		});
		$('tbody tr:nth-child(-n+3)').addClass('success');
		$('tbody tr:nth-last-child(-n+3)').addClass('danger');
	}

	playerData() {
		var freshData = Meteor.users.find({}, {
			fields: {
				'profile.firstName': 1,
				'profile.lastName': 1,
				'profile.points': 1,
			}
		}).fetch();
		var newList = [];
		for (var i = 0; i < freshData.length; i++) {
			if (freshData[i].profile.points.length > 9) {
				newList.push(freshData[i]);
			}
		}
		newList.sort(function(a, b) {
			if (a.currentPoints() > b.currentPoints()) {
				return -1;
			}
			if (a.currentPoints() < b.currentPoints()) {
				return 1;
			}
			return 0;
		});
		return newList;
	}

	index() {
		return this.currentData('@index') + 1;
	}
}

Ranking.register('Ranking');
<|endoftext|>


<commit_before>import ExtractTextPlugin from 'extract-text-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import UglifyJSPlugin from 'uglifyjs-webpack-plugin';
import webpack, {optimize} from 'webpack';

const DEV = global.buildOptions.dev;
const globals = {
    __ENV__: `"${global.buildOptions.env}"`,
    __DEV__: String(DEV),
    __DESKTOP__: !!global.buildOptions.desktop,
    __API_URL__: JSON.stringify(global.buildOptions.publicPath || '/')
};

const devPlugins = [
    new webpack.NoErrorsPlugin()
];
export const extractTextPlugin = new ExtractTextPlugin('[name].css');

const prodPlugins = [
    extractTextPlugin,
    new UglifyJSPlugin({
        uglifyOptions: {
            mangle: false
        }
    }),
    new optimize.DedupePlugin(),
    new optimize.AggressiveMergingPlugin()
];

export default [
    new webpack.DefinePlugin(globals),
    new HtmlWebpackPlugin({
        favicon: './client/app/assets/icons/ngb-logo.png',
        template: './client/index.html.ejs',
        inject: 'body'
    }),
    function () { // sets build to failure if a compilation error occurred
        this.plugin('done', function (stats) {
            if (stats.compilation.errors && stats.compilation.errors.length) {
                console.log(stats.compilation.errors);
                process.exit(1);
            }
        });
    },
    ...(DEV ? devPlugins : prodPlugins)
];
<commit_msg>GUI build process: add hash to the css file name<commit_after>import ExtractTextPlugin from 'extract-text-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import UglifyJSPlugin from 'uglifyjs-webpack-plugin';
import webpack, {optimize} from 'webpack';

const DEV = global.buildOptions.dev;
const globals = {
    __ENV__: `"${global.buildOptions.env}"`,
    __DEV__: String(DEV),
    __DESKTOP__: !!global.buildOptions.desktop,
    __API_URL__: JSON.stringify(global.buildOptions.publicPath || '/')
};

const devPlugins = [
    new webpack.NoErrorsPlugin()
];
export const extractTextPlugin = new ExtractTextPlugin('[name].[hash].css');

const prodPlugins = [
    extractTextPlugin,
    new UglifyJSPlugin({
        uglifyOptions: {
            mangle: false
        }
    }),
    new optimize.DedupePlugin(),
    new optimize.AggressiveMergingPlugin()
];

export default [
    new webpack.DefinePlugin(globals),
    new HtmlWebpackPlugin({
        favicon: './client/app/assets/icons/ngb-logo.png',
        template: './client/index.html.ejs',
        inject: 'body'
    }),
    function () { // sets build to failure if a compilation error occurred
        this.plugin('done', function (stats) {
            if (stats.compilation.errors && stats.compilation.errors.length) {
                console.log(stats.compilation.errors);
                process.exit(1);
            }
        });
    },
    ...(DEV ? devPlugins : prodPlugins)
];
<|endoftext|>


<commit_before>import Ember from 'ember';
import { getContext } from 'ember-test-helpers';

function resetViews() {
  Ember.View.views = {};
}

export default function test(testName, callback) {
  function wrapper() {
    var context = getContext();

    resetViews();
    var result = callback.call(context);

    function failTestOnPromiseRejection(reason) {
      ok(false, reason);
    }

    Ember.run(function(){
      QUnit.stop();
      Ember.RSVP.Promise.cast(result)['catch'](failTestOnPromiseRejection)['finally'](QUnit.start);
    });
  }

  QUnit.test(testName, wrapper);
}
<commit_msg>Send full stack trace information on promise rejection<commit_after>import Ember from 'ember';
import { getContext } from 'ember-test-helpers';

function resetViews() {
  Ember.View.views = {};
}

export default function test(testName, callback) {
  function wrapper() {
    var context = getContext();

    resetViews();
    var result = callback.call(context);

    function failTestOnPromiseRejection(reason) {
      var message;
      if (reason instanceof Error) {
        message = reason.stack;
      } else {
        message = Ember.inspect(reason);
      }
      ok(false, message);
    }

    Ember.run(function(){
      QUnit.stop();
      Ember.RSVP.Promise.cast(result)['catch'](failTestOnPromiseRejection)['finally'](QUnit.start);
    });
  }

  QUnit.test(testName, wrapper);
}
<|endoftext|>


<commit_before>/**
 * Initialization code for the dashboard pages.
 */

'use strict';

var Raven = require('raven-js');
var $ = require('jquery');
var jstz = require('jstimezonedetect');

var $osf = require('js/osfHelpers');
var Dashboard = require('js/dashboard.js').Dashboard;
var m = require('mithril'); // exposes mithril methods, useful for redraw etc.

var ensureUserTimezone = function(savedTimezone, savedLocale, id) {
    var clientTimezone = jstz.determine().name();
    var clientLocale = window.navigator.userLanguage || window.navigator.language;

    if (savedTimezone !== clientTimezone || savedLocale !== clientLocale) {
        var url = '/api/v1/profile/';

        var request = $osf.putJSON(
            url,
            {
                'timezone': clientTimezone,
                'locale': clientLocale,
                'id': id
            }
        );
        request.fail(function(xhr, textStatus, error) {
            Raven.captureMessage('Could not set user timezone or locale', {
                url: url,
                textStatus: textStatus,
                error: error
            });
        });
    }
};

$(document).ready(function() {
    m.mount(document.getElementById('dashboard'), m.component(Dashboard, {wrapperSelector : '#dashboard'}));
    // TODO: new data does not have timezone information
    //ensureUserTimezone(result.timezone, result.locale, result.id);

    // Add active class to navigation for my projects page
    $('#osfNavMyProjects').addClass('active');
});

<commit_msg>Add error note with settimeout [skip ci]<commit_after>/**
 * Initialization code for the dashboard pages.
 */

'use strict';

var Raven = require('raven-js');
var $ = require('jquery');
var jstz = require('jstimezonedetect');

var $osf = require('js/osfHelpers');
var Dashboard = require('js/dashboard.js').Dashboard;
var m = require('mithril'); // exposes mithril methods, useful for redraw etc.

var ensureUserTimezone = function(savedTimezone, savedLocale, id) {
    var clientTimezone = jstz.determine().name();
    var clientLocale = window.navigator.userLanguage || window.navigator.language;

    if (savedTimezone !== clientTimezone || savedLocale !== clientLocale) {
        var url = '/api/v1/profile/';

        var request = $osf.putJSON(
            url,
            {
                'timezone': clientTimezone,
                'locale': clientLocale,
                'id': id
            }
        );
        request.fail(function(xhr, textStatus, error) {
            Raven.captureMessage('Could not set user timezone or locale', {
                url: url,
                textStatus: textStatus,
                error: error
            });
        });
    }
};

$(document).ready(function() {
    m.mount(document.getElementById('dashboard'), m.component(Dashboard, {wrapperSelector : '#dashboard'}));
    // TODO: new data does not have timezone information
    //ensureUserTimezone(result.timezone, result.locale, result.id);

    setTimeout(function(){
        if($('#dashboard .spinner-loading-wrapper').length > 0) {
            $('#dashboard').append('
This is taking longer than normal.
  Try reloading the page. If the problem persist contact us at support@cos.io.
')
        }
    }, 10000);
    // Add active class to navigation for my projects page
    $('#osfNavMyProjects').addClass('active');
});

<|endoftext|>


<commit_before>"use strict";

var test = require("tape");

var EntityPool = require("./entity-pool");

test("create returns an entity id", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	t.equal(typeof id, "number");
});

test("create returns different ids each time", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id1 = pool.create();
	var id2 = pool.create();
	t.notEqual(id1, id2);
});

test("destroy deletes a whole entity", function(t) {
	t.plan(1);

	t.throws(function() {
		var pool = new EntityPool();
		var id = pool.create();
		pool.destroy(id);
		pool.getComponent(id, "id");
	});
});

test("get with id returns the id", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	var result = pool.getComponent(id, "id");
	t.equal(result, id);
});

test("entity ids get reused", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var idA = pool.create();
	var idB = pool.create();
	pool.destroy(idA);
	var idC = pool.create();

	t.equal(idA, idC);
});

test("set with component can be fetched with get", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	var name = pool.getComponent(id, "name");

	t.equal(name, "jimmy");
});
test("set with component can be fetched with get", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	var name = pool.getComponent(id, "name");

	t.equal(name, "jimmy");
});
test("set with same component twice isn't in search twice", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "name", "jimmy");
	var results = pool.find("name");

	t.equal(results.length, 1);
});
test("set with existing component to undefined removes from search", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "name", undefined);
	var results = pool.find("name");

	t.equal(results.length, 0);
});

test("remove with component makes it unable to be fetched", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	pool.removeComponent(id, "name");
	var name = pool.getComponent(id, "name");

	t.equal(name, undefined);
});

test("find with no matching components returns empty list", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	var results = pool.find("does-not-exist");

	t.deepEqual(results, []);
});

test("find with matching component returns list with entities", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	var id2 = pool.create();
	pool.setComponent(id2, "name", "amy");
	var results = pool.find("name");

	t.deepEqual(results, [id, id2]);
});

test("find with deleted component returns empty list", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	pool.removeComponent(id, "name");
	var results = pool.find("name");

	t.deepEqual(results, []);
});

test("registerSearch with two components and entities already added returns entities", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "age", 8);
	pool.registerSearch("peopleWithAge", ["name", "age"]);
	var results = pool.find("peopleWithAge");

	t.deepEqual(results, [id]);
});

test("registerSearch with two components and entities added after returns entities", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.registerSearch("peopleWithAge", ["name", "age"]);
	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "age", 8);
	var results = pool.find("peopleWithAge");

	t.deepEqual(results, [id]);
});

test("registerSearch twice with same name throws", function(t) {
	t.plan(1);

	t.throws(function() {
		var pool = new EntityPool();
		pool.registerSearch("search", ["search"]);
		pool.registerSearch("search", ["search"]);
	});
});

test("remove removes an entity from a complex search", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.registerSearch("peopleWithAge", ["name", "age"]);
	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "age", 8);
	pool.removeComponent(id, "age");
	var results = pool.find("peopleWithAge");

	t.deepEqual(results, []);
});

test("load creates an entity", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	pool.load([{ id: 1, name: "jimmy" }]);
	var name = pool.getComponent(1, "name");

	t.deepEqual(name, "jimmy");
});

test("load increments next id", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	pool.load([{ id: 1, name: "jimmy" }]);
	var id = pool.create();

	t.deepEqual(id, 2);
});

test("save returns entities", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	var output = pool.save();

	t.deepEqual(output, [{ id: id, name: "jimmy"}]);
});

test("onAddComponent with callback is called after set", function(t) {
	t.plan(6);

	var pool = new EntityPool();
	var id = pool.create();
	function callback(entity, component, value) {
		t.equal(entity, id);
		t.equal(component, "name");
		t.equal(value, "jimmy");
	}
	pool.onAddComponent("name", callback);
	pool.onAddComponent("name", callback);

	pool.setComponent(id, "name", "jimmy");
});

test("onAddComponent with callback is not called on modifying existing component", function(t) {
	t.plan(3);

	var pool = new EntityPool();
	var id = pool.create();
	function callback(entity, component, value) {
		t.equal(entity, id);
		t.equal(component, "name");
		t.equal(value, "jimmy");
	}
	pool.onAddComponent("name", callback);

	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "name", "salazar");
});

test("onAddComponent with callback is not called until all data is loaded", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	function callback(entity) {
		t.equal(pool.getComponent(entity, "age"), 28);
	}
	pool.onAddComponent("name", callback);
	pool.load([{ id: 1, name: "jimmy", age: 28 }]);
});
test("onRemoveComponent with callback is called on removing component", function(t) {
	t.plan(3);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	function callback(entity, component, value) {
		t.equal(entity, id);
		t.equal(component, "name");
		t.equal(value, "jimmy");
	}
	pool.onRemoveComponent("name", callback);

	pool.removeComponent(id, "name");
});

test("onRemoveComponent with callback isn't called on removing nonexistant component", function(t) {
	t.plan(3);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	function callback(entity, component, value) {
		t.equal(entity, id);
		t.equal(component, "name");
		t.equal(value, "jimmy");
	}
	pool.onRemoveComponent("name", callback);

	pool.removeComponent(id, "name");
	pool.removeComponent(id, "name");
});
<commit_msg>Method names in EntityPool test descriptions updated.<commit_after>"use strict";

var test = require("tape");

var EntityPool = require("./entity-pool");

test("create returns an entity id", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	t.equal(typeof id, "number");
});

test("create returns different ids each time", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id1 = pool.create();
	var id2 = pool.create();
	t.notEqual(id1, id2);
});

test("destroy deletes a whole entity", function(t) {
	t.plan(1);

	t.throws(function() {
		var pool = new EntityPool();
		var id = pool.create();
		pool.destroy(id);
		pool.getComponent(id, "id");
	});
});

test("getComponent with id returns the id", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	var result = pool.getComponent(id, "id");
	t.equal(result, id);
});

test("entity ids get reused", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var idA = pool.create();
	var idB = pool.create();
	pool.destroy(idA);
	var idC = pool.create();

	t.equal(idA, idC);
});

test("setComponent with component can be fetched with getComponent", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	var name = pool.getComponent(id, "name");

	t.equal(name, "jimmy");
});
test("setComponent with component can be fetched with getComponent", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	var name = pool.getComponent(id, "name");

	t.equal(name, "jimmy");
});
test("setComponent with same component twice isn't in search twice", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "name", "jimmy");
	var results = pool.find("name");

	t.equal(results.length, 1);
});
test("setComponent with existing component to undefined removes from search", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "name", undefined);
	var results = pool.find("name");

	t.equal(results.length, 0);
});

test("removeComponent with component makes it unable to be fetched", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	pool.removeComponent(id, "name");
	var name = pool.getComponent(id, "name");

	t.equal(name, undefined);
});

test("find with no matching components returns empty list", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	var results = pool.find("does-not-exist");

	t.deepEqual(results, []);
});

test("find with matching component returns list with entities", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	var id2 = pool.create();
	pool.setComponent(id2, "name", "amy");
	var results = pool.find("name");

	t.deepEqual(results, [id, id2]);
});

test("find with deleted component returns empty list", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	pool.removeComponent(id, "name");
	var results = pool.find("name");

	t.deepEqual(results, []);
});

test("registerSearch with two components and entities already added returns entities", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "age", 8);
	pool.registerSearch("peopleWithAge", ["name", "age"]);
	var results = pool.find("peopleWithAge");

	t.deepEqual(results, [id]);
});

test("registerSearch with two components and entities added after returns entities", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.registerSearch("peopleWithAge", ["name", "age"]);
	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "age", 8);
	var results = pool.find("peopleWithAge");

	t.deepEqual(results, [id]);
});

test("registerSearch twice with same name throws", function(t) {
	t.plan(1);

	t.throws(function() {
		var pool = new EntityPool();
		pool.registerSearch("search", ["search"]);
		pool.registerSearch("search", ["search"]);
	});
});

test("removeComponent removes an entity from a complex search", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.registerSearch("peopleWithAge", ["name", "age"]);
	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "age", 8);
	pool.removeComponent(id, "age");
	var results = pool.find("peopleWithAge");

	t.deepEqual(results, []);
});

test("load creates an entity", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	pool.load([{ id: 1, name: "jimmy" }]);
	var name = pool.getComponent(1, "name");

	t.deepEqual(name, "jimmy");
});

test("load increments next id", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	pool.load([{ id: 1, name: "jimmy" }]);
	var id = pool.create();

	t.deepEqual(id, 2);
});

test("save returns entities", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	var output = pool.save();

	t.deepEqual(output, [{ id: id, name: "jimmy"}]);
});

test("onAddComponent with callback is called after set", function(t) {
	t.plan(6);

	var pool = new EntityPool();
	var id = pool.create();
	function callback(entity, component, value) {
		t.equal(entity, id);
		t.equal(component, "name");
		t.equal(value, "jimmy");
	}
	pool.onAddComponent("name", callback);
	pool.onAddComponent("name", callback);

	pool.setComponent(id, "name", "jimmy");
});

test("onAddComponent with callback is not called on modifying existing component", function(t) {
	t.plan(3);

	var pool = new EntityPool();
	var id = pool.create();
	function callback(entity, component, value) {
		t.equal(entity, id);
		t.equal(component, "name");
		t.equal(value, "jimmy");
	}
	pool.onAddComponent("name", callback);

	pool.setComponent(id, "name", "jimmy");
	pool.setComponent(id, "name", "salazar");
});

test("onAddComponent with callback is not called until all data is loaded", function(t) {
	t.plan(1);

	var pool = new EntityPool();
	function callback(entity) {
		t.equal(pool.getComponent(entity, "age"), 28);
	}
	pool.onAddComponent("name", callback);
	pool.load([{ id: 1, name: "jimmy", age: 28 }]);
});
test("onRemoveComponent with callback is called on removing component", function(t) {
	t.plan(3);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	function callback(entity, component, value) {
		t.equal(entity, id);
		t.equal(component, "name");
		t.equal(value, "jimmy");
	}
	pool.onRemoveComponent("name", callback);

	pool.removeComponent(id, "name");
});

test("onRemoveComponent with callback isn't called on removing nonexistant component", function(t) {
	t.plan(3);

	var pool = new EntityPool();
	var id = pool.create();
	pool.setComponent(id, "name", "jimmy");
	function callback(entity, component, value) {
		t.equal(entity, id);
		t.equal(component, "name");
		t.equal(value, "jimmy");
	}
	pool.onRemoveComponent("name", callback);

	pool.removeComponent(id, "name");
	pool.removeComponent(id, "name");
});
<|endoftext|>


<commit_before>/**
 * Created by AsherS on 8/24/15.
 */

var _ = require('underscore');
var path = require('path');
var url = require('url');
var httpUtils = require('./utils/http-utils');
var logger = require('./logger/logger');
var m3u8Handler = require('./promise-m3u8');
var flavorDownloader = require('./flavor-downloader');

var EntryDownloader = (function () {

    function EntryDownloader(entryId, persistenceFormat) {
        this.entryId = entryId;
        this.persistanceFormat = persistenceFormat;
        this.flavorsObjects = null;

    }

    var buildM3u8Url = function (masterManifestUrl, flavorUrl) {
        return flavorUrl;    //TODO, here we should handle relative/absolute url in master manifest
    };

    var buildManifestUrl = function() { //TODO, remove
        return "http://cdnapi.kaltura.com/p/931702/sp/93170200/playManifest/entryId/1_oorxcge2/format/applehttp/protocol/http/uiConfId/28428751/a.m3u8?referrer=aHR0cDovL3dlYXRoZXJuYXRpb250di5jb20=&playSessionId=449149e6-b7b1-6862-d8a5-519d3b10d754";
    };

    EntryDownloader.prototype.start = function () {

        var that = this;
        var masterManifestPath = path.join(that.persistanceFormat.getEntryDestPath(that.entryId),"original-playlist.m3u8");

        //get master manifest url
        var manifestUrl = buildManifestUrl();   //TODO function that generates wowza's manifest. master manifest generator does this - just need to expose the function

        httpUtils.downloadFile(manifestUrl, masterManifestPath)

            .then(function parseManifest() {
                return m3u8Handler.parseM3U8(masterManifestPath);
            })
            .then(function startDownloaders(masterManifest) {

                that.flavorsObjects = _.map(masterManifest.items.StreamItem, function(flavorObj){

                    var m3u8Url = buildM3u8Url(manifestUrl, flavorObj.get('uri'));

                    //get playlist name:
                    var parsedUrl = url.parse(m3u8Url);
                    var playlistName = path.basename(parsedUrl.pathname);
                    //TODO, replace that.persistanceFormat.getManifestName() once committed.

                    var bitrate = flavorObj.get('bandwidth');
                    var destPath = that.persistanceFormat.getFlavorDestPath(that.entryId, bitrate);

                    return new flavorDownloader(m3u8Url, destPath, that.entryId, bitrate, playlistName);
                });

                //start the download
                _.forEach(that.flavorsObjects, function (f) {
                    f.start();  //TODO verify success with on-started event?
                });

                //TODO, generate DVR master manifest

            })
            .catch(function(err) {
                throw new Error("Failed to start entry downloader for entry: " + that.entryId + "\n" + err);
            });
    };

    EntryDownloader.prototype.stop = function () {
        logger.info('stopping entry downloader for entry id: ' + this.entryId);
        _.forEach(this.flavorsObjects, function (f) {
            f.stop();
        });
    };

    return EntryDownloader;
})();

module.exports = EntryDownloader;

var persistence = require('./PersistenceFormat')("/Users/AsherS/Downloads/DVR/root");
var downloader = new EntryDownloader("some_entry",persistence);
downloader.start();

setTimeout(function () {
    logger.info('----------------------------------------');
    downloader.stop();
}, 10000);

<commit_msg>add entry downloader template<commit_after>/**
 * Created by AsherS on 8/24/15.
 */

var _ = require('underscore');
var path = require('path');
var url = require('url');
var logger = require('./logger/logger');
var flavorDownloader = require('./flavor-downloader');
var masterGenerator = require('./MasterManifestGenerator');

var EntryDownloader = (function () {

    function EntryDownloader(entryId, hostname, port, applicationName, persistenceFormat) {
        this.entryId = entryId;
        this.persistanceFormat = persistenceFormat;
        this.flavorsObjects = null;

        //TODO, get these parameters from conf file instead - hostname, port, applicationName
        this.masterManifestGenerator = masterGenerator(entryId, hostname, port, applicationName, persistenceFormat.getEntryDestPath(entryId));
    }

    var buildM3u8Url = function (masterManifestUrl, flavorUrl) {
        return flavorUrl;    //TODO, here we should handle relative/absolute url in master manifest
    };

    EntryDownloader.prototype.start = function () {

        var that = this;
        that.masterManifestGenerator.getAllFlavors()

            .then(function startDownloaders(masterManifest) {

                that.flavorsObjects = _.map(masterManifest.items.StreamItem, function(flavorObj){

                    var m3u8Url = buildM3u8Url(manifestUrl, flavorObj.get('uri'));

                    //get playlist name:
                    var parsedUrl = url.parse(m3u8Url);
                    var playlistName = path.basename(parsedUrl.pathname);
                    //TODO, replace that.persistanceFormat.getManifestName() once committed.

                    var bitrate = flavorObj.get('bandwidth');
                    var destPath = that.persistanceFormat.getFlavorDestPath(that.entryId, bitrate);

                    return new flavorDownloader(m3u8Url, destPath, that.entryId, bitrate, playlistName);
                });

                //start the download
                _.forEach(that.flavorsObjects, function (f) {
                    f.start();  //TODO verify success with on-started event?
                });

                //TODO, generate DVR master manifest

            })
            .catch(function(err) {
                throw new Error("Failed to start entry downloader for entry: " + that.entryId + "\n" + err);
            });;
    };

    EntryDownloader.prototype.stop = function () {
        logger.info('stopping entry downloader for entry id: ' + this.entryId);
        _.forEach(this.flavorsObjects, function (f) {
            f.stop();
        });
    };

    return EntryDownloader;
})();

module.exports = EntryDownloader;

//TODO, what should be the hostname?
var persistence = require('./PersistenceFormat')("/Users/AsherS/Downloads/DVR/root");
var downloader = new EntryDownloader("1_oorxcge2", 'kalsegsec-a.akamaihd.net/dc-1/m/ny-live-publish1', 1935, 'kLive',persistence);
downloader.start();

//entryId, hostname, port, applicationName, persistenceFormat
//ttp:\/\/kalsegsec-a.akamaihd.net\/dc-1\/m\/ny-live-publish1\/kLive\/smil:1_oorxcge2_publish.smil\/chunklist_b475136.m3u8
setTimeout(function () {
    logger.info('----------------------------------------');
    downloader.stop();
}, 10000);

<|endoftext|>


<commit_before>var perm = gadgets.nuxeo.isEditable();
var url = top.nxContextPath + "/site/gadgetDocumentAPI/getHtmlContent/";

function launchVideoWidget() {
   var idGadget = gadgets.nuxeo.getGadgetId();
   jQuery("#formUpload").attr("action", gadgets.nuxeo.getFormActionUrl(idGadget));

   setTitle(prefs.getString("vidTitle"));

  loadVideo(idGadget);

  if(!perm)
    jQuery("#perm").remove();

  gadgets.window.adjustHeight();

  jQuery('#show').click(function(){
    jQuery('#show').hide();
    jQuery('#form').show();
    gadgets.window.adjustHeight();
  });

  jQuery('#hide').click(function(){
    jQuery('#form').hide();
    jQuery('#show').show();
    gadgets.window.adjustHeight();
  });

  jQuery('#valid').click(function(){
    prefs.set("vidTitle", gadgets.util.escapeString(jQuery("#title-field").val()),"tmp", ["",Math.random()].join(""));
    jQuery('#formUpload').ajaxSubmit();
  });
};

function loadVideo(id){
  jQuery.ajax({
    type : "GET",
    url :  gadgets.nuxeo.getHtmlActionUrl(id),
    success : function(html) {
      setVideo(html);
    }
    });
};

function setTitle(title){
  var t = "";
  if(_isSet(title))
    t = gadgets.util.unescapeString(title);
  jQuery("#title-field").val(t);
  jQuery("#title").text(t);
};

function _isSet(val) {
  return (jQuery.trim(val) != "" && val != null);
};

function setVideo(balise){
  if(_isSet(balise)){
    jQuery("#video").html(balise);
    jQuery("#baliseVideo").text(balise);
    var dim = gadgets.window.getViewportDimensions();
    var embed = jQuery("embed");
    if(embed.length == 0) embed = jQuery("object");
    var h = (dim.width * embed.height())/jQuery("object").width();
    embed.width(dim.width);
    if(h!=0)
      embed.height(h);
    embed.attr("wmode","transparent");
    embed.attr("type","application/x-shockwave-flash");
  } else {
    jQuery("#video").html("");
    jQuery("#baliseVideo").text("");
  }
  setTimeout(function(){
    gadgets.window.adjustHeight();
  }, 150);
};
<commit_msg>NXP-4791 - Fixed bug when open pop-up on Gadget Video<commit_after>var perm = gadgets.nuxeo.isEditable();
var url = [top.nxContextPath,"/site/gadgetDocumentAPI/getHtmlContent/"].join();

function launchVideoWidget() {
   var idGadget = gadgets.nuxeo.getGadgetId();
   jQuery("#formUpload").attr("action", gadgets.nuxeo.getFormActionUrl(idGadget));

   setTitle(prefs.getString("vidTitle"));

  loadVideo(idGadget);

  if(!perm)
    jQuery("#perm").remove();

  gadgets.window.adjustHeight();

  jQuery('#show').click(function(){
    jQuery('#show').hide();
    jQuery('#form').show();
    gadgets.window.adjustHeight();
  });

  jQuery('#hide').click(function(){
    jQuery('#form').hide();
    jQuery('#show').show();
    gadgets.window.adjustHeight();
  });

  jQuery('#valid').click(function(){
    prefs.set("vidTitle", gadgets.util.escapeString(jQuery("#title-field").val()),"tmp", ["",Math.random()].join(""));
    jQuery('#formUpload').ajaxSubmit();
  });
};

function loadVideo(id){
  jQuery.ajax({
    type : "GET",
    url :  gadgets.nuxeo.getHtmlActionUrl(id),
    success : function(html) {
      setVideo(html);
    }
    });
};

function setTitle(title){
  var t = "";
  if(_isSet(title))
    t = gadgets.util.unescapeString(title);
  jQuery("#title-field").val(t);
  jQuery("#title").text(t);
};

function _isSet(val) {
  return (jQuery.trim(val) != "" && val != null);
};

function setVideo(balise){
  if(_isSet(balise)){
    jQuery("#video").html(balise);
    jQuery("#baliseVideo").text(balise);
    var dim = gadgets.window.getViewportDimensions();
    var embed = jQuery("embed");
    if(embed.length == 0) embed = jQuery("object");
    var h = (dim.width * embed.height())/jQuery("object").width();
    embed.width(dim.width);
    if(h!=0) embed.height(h);
    embed.attr("wmode","transparent");
    embed.attr("type","application/x-shockwave-flash");
    //Hack, if open popup in container
    jQuery("#video").fadeOut("fast",function(){
    	jQuery("#video").fadeIn();
    });

  } else {
    jQuery("#video").html("");
    jQuery("#baliseVideo").text("");
  }
  setTimeout(function(){
    gadgets.window.adjustHeight();
  }, 150);
};
<|endoftext|>


<commit_before>import * as actions from '../../actions';

describe('markers actions', () => {
  it.only('should create an action to provide location details', () => {
    const data = {
      name: "ELWAY'S",
      rating: 4.1,
      vicinity: '1881 Curtis Street, Denver'
    };
    const expectedAction = {
      type: 'DETAIL_LOCATION',
      data
    };
    expect(actions.detailLocation(data)).toEqual(expectedAction);
  });
});
<commit_msg>fix marker test<commit_after>import * as actions from '../../actions';

describe('markers actions', () => {
  it('should have an action that handles a click event', () => {
    const marker = {
      name: "ELWAY'S",
      rating: 4.1,
      vicinity: '1881 Curtis Street, Denver'
    };

    const expectedAction = {
      type: 'HANDLE_MARKER_CLICK',
      marker
    };

    expect(actions.handleMarkerClick(marker)).toEqual(expectedAction);
  });
});
<|endoftext|>


<commit_before>import React from 'react';
import classnames from 'classnames';
import PropTypes from 'prop-types';

const SprkText = ({
  children,
  element,
  variant,
  idString,
  isPageTitle,
  additionalClasses,
  ...other
}) => {

  const classNames = classnames(additionalClasses, {
    'sprk-b-TypeBodyOne': variant === 'bodyOne',
    'sprk-b-TypeBodyTwo': variant === 'bodyTwo',
    'sprk-b-TypeBodyThree': variant === 'bodyThree',
    'sprk-b-TypeBodyFour': variant === 'bodyFour',
  });

  const TagName = element;

  return (
    <TagName
      className={classNames}
      data-id={idString}
      {...other}
    >
      {children}
    </TagName>
  )
};

SprkText.defaultProps = {
  element: 'p',
};

SprkText.propTypes = {
  /**
   * The incoming children.
   */
  children: PropTypes.node,
  /**
   * Determines what element to render.
   */
  element: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.func,
    PropTypes.elementType
  ]),
  /**
   * The text style to render.
   * See [Typography](https://www.sparkdesignsystem.com/using-spark/foundations/typography)
   * for more information on the design styles.
   */
  variant: PropTypes.oneOf([
    'bodyOne',
    'bodyTwo',
    'bodyThree',
    'bodyFour',
  ]),
  /**
   * Assigned to the `data-id` attribute
   * serving as a unique selector for
   * automated tools.
   */
  idString: PropTypes.string,
  /**
   * A space-separated string of classes to add to the
   * outermost container of the component.
   */
  additionalClasses: PropTypes.string,
};

export default SprkText;<commit_msg>react cleanup<commit_after>import React from 'react';
import classnames from 'classnames';
import PropTypes from 'prop-types';

const SprkText = ({
  children,
  element,
  variant,
  idString,
  additionalClasses,
  ...other
}) => {
  const classNames = classnames(additionalClasses, {
    'sprk-b-TypeBodyOne': variant === 'bodyOne',
    'sprk-b-TypeBodyTwo': variant === 'bodyTwo',
    'sprk-b-TypeBodyThree': variant === 'bodyThree',
    'sprk-b-TypeBodyFour': variant === 'bodyFour',
  });

  const TagName = element;

  return (
    <TagName className={classNames} data-id={idString} {...other}>
      {children}
    </TagName>
  );
};

SprkText.defaultProps = {
  element: 'p',
};

SprkText.propTypes = {
  /**
   * The incoming children.
   */
  children: PropTypes.node,
  /**
   * Determines what element to render.
   */
  element: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.func,
    PropTypes.elementType,
  ]),
  /**
   * The text style to render.
   * See [Typography](https://www.sparkdesignsystem.com/using-spark/foundations/typography)
   * for more information on the design styles.
   */
  variant: PropTypes.oneOf(['bodyOne', 'bodyTwo', 'bodyThree', 'bodyFour']),
  /**
   * Assigned to the `data-id` attribute serving as a unique selector for
   * automated tools.
   */
  idString: PropTypes.string,
  /**
   * A space-separated string of classes to add to the outermost container
   * of the component.
   */
  additionalClasses: PropTypes.string,
};

export default SprkText;
<|endoftext|>


<commit_before>// Copyright (c) 2011 Hewlett-Packard Development Company, L.P. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var WebVfx = WebVfx || {};

////////

// canvas - canvas HTML element
WebVfx.Renderer = function (canvas) {
    this.gl = canvas.getContext("experimental-webgl");
    if (!this.gl)
        throw "This browswer does not have WebGL enabled.";
    this.buildQuad();
}

WebVfx.Renderer.prototype.buildQuad = function () {
    var gl = this.gl;

    this.vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER,
                  new Float32Array([ 0, 0, 0, 1, 1, 0, 1, 1 ]),
                  gl.STATIC_DRAW);
}

// shader - Shader to render
// renderTarget - optional RenderTarget, if not specified then render to canvas
WebVfx.Renderer.prototype.render = function (shader, renderTarget) {
    var gl = this.gl;

    if (renderTarget)
        renderTarget.setCurrent(true);

    // Should use gl.drawingBufferWidth/Height but they aren't implemented
    gl.viewport(0, 0, gl.canvas.clientWidth, gl.canvas.clientHeight);

    shader.render();

    if (renderTarget)
        renderTarget.setCurrent(false);
}

////////

WebVfx.RenderTarget = function (renderer) {
    this.renderer = renderer;
    var gl = renderer.gl;
    this.texture = gl.createTexture();
    this.framebuffer = gl.createFramebuffer();
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    // Set parameters to support NPOT textures
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    //XXX should listen for canvas size changes and recreate
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.canvas.width, gl.canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

    gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);

    gl.bindTexture(gl.TEXTURE_2D, null);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
}

WebVfx.RenderTarget.prototype.setCurrent = function (current) {
    var gl = this.renderer.gl;
    gl.bindFramebuffer(gl.FRAMEBUFFER, current ? this.framebuffer : null);
}

WebVfx.RenderTarget.prototype.destroy = function () {
    var gl = this.renderer.gl;
    gl.deleteTexture(this.texture);
    this.texture = null;
    gl.deleteFramebuffer(this.framebuffer);
    this.framebuffer = null;
}

////////

// renderer - Renderer
// shaderSource - fragment shader source code
// uniforms - optional hash mapping uniform name to initial value
WebVfx.Shader = function (renderer, shaderSource, uniforms) {
    this.renderer = renderer;
    var gl = renderer.gl;
    this.program = this.compileProgram(shaderSource);
    this.uniforms = this.extractUniforms();
    // Set default values if specified
    if (uniforms) {
        gl.useProgram(this.program);
        for (var name in uniforms)
            this.uniforms[name].setValue(uniforms[name]);
    }
    this.vertexAttribute = gl.getAttribLocation(this.program, 'vertex');
    gl.vertexAttribPointer(this.vertexAttribute, 2, gl.FLOAT, false, 0, 0);
}

WebVfx.Shader.prototype.render = function () {
    var gl = this.renderer.gl;
    for (var name in this.uniforms)
        this.uniforms[name].bind();
    gl.useProgram(this.program);
    gl.enableVertexAttribArray(this.vertexAttribute);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
    gl.disableVertexAttribArray(this.vertexAttribute);
}

WebVfx.Shader.prototype.destroy = function () {
    var gl = this.renderer.gl;
    for (var name in this.uniforms)
        this.uniforms[name].destroy();
    gl.deleteProgram(this.program);
    this.program = null;
}

// Return the script text from a <script type="x-shader/x-fragment">
// element of the given ID.
WebVfx.Shader.loadShader = function (shaderId) {
    var shaderScript = document.getElementById(shaderId);
    if (!shaderScript || shaderScript.type != "x-shader/x-fragment") {
        throw "Could not find shader script ID " + shaderId +
                    " of type x-shader/x-fragment";
    }
    return shaderScript.text;
}

// Update an existing uniforms value
WebVfx.Shader.prototype.updateUniform = function (name, value) {
    var uniform = this.uniforms[name];
    if (!uniform) {
        console.warn("Invalid uniform name " + name);
        return;
    }
    this.renderer.gl.useProgram(this.program);
    uniform.setValue(value);
}

WebVfx.Shader.VERTEX_SHADER_SOURCE = [
    "attribute vec2 vertex;",
    "varying vec2 texCoord;",
    "void main() {",
    "    texCoord = vertex;",
    "    gl_Position = vec4(vertex * 2.0 - 1.0, 0.0, 1.0);",
    "}"].join("\n");

WebVfx.Shader.prototype.compileProgram = function (shaderSource) {
    var gl = this.renderer.gl;
    var program = gl.createProgram();

    var vs = this.compileSource(gl.VERTEX_SHADER,
                                WebVfx.Shader.VERTEX_SHADER_SOURCE);
    var fs = this.compileSource(gl.FRAGMENT_SHADER, shaderSource);
    gl.attachShader(program, vs);
    gl.attachShader(program, fs);
    gl.linkProgram(program);
    if (!gl.getProgramParameter(program, gl.LINK_STATUS))
        throw 'link error: ' + gl.getProgramInfoLog(program);

    gl.deleteShader(vs);
    gl.deleteShader(fs);

    return program;
}

WebVfx.Shader.prototype.compileSource = function (type, shaderSource) {
    var gl = this.renderer.gl;
    var shader = gl.createShader(type);
    gl.shaderSource(shader, shaderSource);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
        throw 'compile error: ' + gl.getShaderInfoLog(shader);
    return shader;
}

// Extract uniform declarations from program
WebVfx.Shader.prototype.extractUniforms = function () {
    var gl = this.renderer.gl;
    var textureCount = 0;
    var uniforms = {};

    gl.useProgram(this.program);

    var uniformCount = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS);
    for (var u = 0; u < uniformCount; u++) {
        var info = gl.getActiveUniform(this.program, u);
        var location = gl.getUniformLocation(this.program, info.name);

        if (info.type == gl.SAMPLER_2D)
            uniforms[info.name] = new WebVfx.Texture(gl, textureCount++, location);
        else
            uniforms[info.name] = new WebVfx.Uniform(gl, info.type, location);
    }
    return uniforms;
}

////////

// type - uniform type
// location - uniform location
WebVfx.Uniform = function (gl, type, location) {
    this.gl = gl;

    this.uniformLocation = location;

    switch (type) {
    case gl.FLOAT:
        this.uniformFunction = gl.uniform1f;
        break;
    case gl.INT:
    case gl.BOOL:
        this.uniformFunction = gl.uniform1i;
        break;
    case gl.FLOAT_VEC2:
        this.uniformFunction = gl.uniform2fv;
        this.wrapperConstructor = Float32Array;
        break;
    case gl.FLOAT_VEC3:
        this.uniformFunction = gl.uniform3fv;
        this.wrapperConstructor = Float32Array;
        break;
    case gl.FLOAT_VEC4:
        this.uniformFunction = gl.uniform4fv;
        this.wrapperConstructor = Float32Array;
        break;
    case gl.INT_VEC2:
    case gl.BOOL_VEC2:
        this.uniformFunction = gl.uniform2iv;
        this.wrapperConstructor = Int32Array;
        break;
    case gl.INT_VEC3:
    case gl.BOOL_VEC3:
        this.uniformFunction = gl.uniform3iv;
        this.wrapperConstructor = Int32Array;
        break;
    case gl.INT_VEC4:
    case gl.BOOL_VEC4:
        this.uniformFunction = gl.uniform4iv;
        this.wrapperConstructor = Int32Array;
        break;
    default:
        throw 'Unsupported uniform type ' + type;
    }
}

// Set uniform value, can be float or array of floats
WebVfx.Uniform.prototype.setValue = function(value) {
    this.value = value;
    if (this.wrapperConstructor)
        value = new this.wrapperConstructor(value);
    this.uniformFunction.call(this.gl, this.uniformLocation, value);
}

WebVfx.Uniform.prototype.bind = function() {
    // do nothing
}

WebVfx.Uniform.prototype.destroy = function() {
    // do nothing
}

////////

// unit - texture unit, 0-7
// location - uniform location
WebVfx.Texture = function (gl, unit, location) {
    this.gl = gl;
    this.unit = unit;

    gl.uniform1i(location, this.unit);
}

// Value can be a RenderTarget or an image to upload image into a texture.
// The image can have textureOptions which map texParameteri enums to values.
WebVfx.Texture.prototype.setValue = function(image) {
    var gl = this.gl;

    if (image instanceof WebVfx.RenderTarget) {
        this.id = image.texture;
    }
    else {
        if (!this.id) {
            this.id = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, this.id);
            // Set parameters to support NPOT textures
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        }

        if (image.textureOptions) {
            for (var opt in image.textureOptions)
                gl.texParameteri(gl.TEXTURE_2D, opt, image.textureOptions[opt]);
        }
        gl.bindTexture(gl.TEXTURE_2D, this.id);
        // Flip texture vertically so it's not upside down
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    }
}

WebVfx.Texture.prototype.bind = function() {
    var gl = this.gl;
    gl.activeTexture(gl.TEXTURE0 + this.unit);
    gl.bindTexture(gl.TEXTURE_2D, this.id);
}

WebVfx.Texture.prototype.destroy = function() {
    if (this.id) {
        this.gl.deleteTexture(this.id);
        this.id = null;
    }
}
<commit_msg>Add SharedTexture to shader.<commit_after>// Copyright (c) 2011 Hewlett-Packard Development Company, L.P. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var WebVfx = WebVfx || {};

////////

// canvas - canvas HTML element
WebVfx.Renderer = function (canvas) {
    this.gl = canvas.getContext("experimental-webgl");
    if (!this.gl)
        throw "This browswer does not have WebGL enabled.";
    this.buildQuad();
}

WebVfx.Renderer.prototype.buildQuad = function () {
    var gl = this.gl;

    this.vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER,
                  new Float32Array([ 0, 0, 0, 1, 1, 0, 1, 1 ]),
                  gl.STATIC_DRAW);
}

// shader - Shader to render
// renderTarget - optional RenderTarget, if not specified then render to canvas
WebVfx.Renderer.prototype.render = function (shader, renderTarget) {
    var gl = this.gl;

    if (renderTarget)
        renderTarget.setCurrent(true);

    // Should use gl.drawingBufferWidth/Height but they aren't implemented
    gl.viewport(0, 0, gl.canvas.clientWidth, gl.canvas.clientHeight);

    shader.render();

    if (renderTarget)
        renderTarget.setCurrent(false);
}

////////

WebVfx.RenderTarget = function (renderer) {
    this.renderer = renderer;
    var gl = renderer.gl;
    this.texture = gl.createTexture();
    this.framebuffer = gl.createFramebuffer();
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    // Set parameters to support NPOT textures
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    //XXX should listen for canvas size changes and recreate
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.canvas.width, gl.canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

    gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);

    gl.bindTexture(gl.TEXTURE_2D, null);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
}

WebVfx.RenderTarget.prototype.setCurrent = function (current) {
    var gl = this.renderer.gl;
    gl.bindFramebuffer(gl.FRAMEBUFFER, current ? this.framebuffer : null);
}

WebVfx.RenderTarget.prototype.destroy = function () {
    var gl = this.renderer.gl;
    gl.deleteTexture(this.texture);
    this.texture = null;
    gl.deleteFramebuffer(this.framebuffer);
    this.framebuffer = null;
}

////////

// renderer - Renderer
// shaderSource - fragment shader source code
// uniforms - optional hash mapping uniform name to initial value
WebVfx.Shader = function (renderer, shaderSource, uniforms) {
    this.renderer = renderer;
    var gl = renderer.gl;
    this.program = this.compileProgram(shaderSource);
    this.uniforms = this.extractUniforms();
    // Set default values if specified
    if (uniforms) {
        gl.useProgram(this.program);
        for (var name in uniforms)
            this.uniforms[name].setValue(uniforms[name]);
    }
    this.vertexAttribute = gl.getAttribLocation(this.program, 'vertex');
    gl.vertexAttribPointer(this.vertexAttribute, 2, gl.FLOAT, false, 0, 0);
}

WebVfx.Shader.prototype.render = function () {
    var gl = this.renderer.gl;
    for (var name in this.uniforms)
        this.uniforms[name].bind();
    gl.useProgram(this.program);
    gl.enableVertexAttribArray(this.vertexAttribute);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
    gl.disableVertexAttribArray(this.vertexAttribute);
}

WebVfx.Shader.prototype.destroy = function () {
    var gl = this.renderer.gl;
    for (var name in this.uniforms)
        this.uniforms[name].destroy();
    gl.deleteProgram(this.program);
    this.program = null;
}

// Return the script text from a <script type="x-shader/x-fragment">
// element of the given ID.
WebVfx.Shader.loadShader = function (shaderId) {
    var shaderScript = document.getElementById(shaderId);
    if (!shaderScript || shaderScript.type != "x-shader/x-fragment") {
        throw "Could not find shader script ID " + shaderId +
                    " of type x-shader/x-fragment";
    }
    return shaderScript.text;
}

// Update an existing uniforms value
WebVfx.Shader.prototype.updateUniform = function (name, value) {
    var uniform = this.uniforms[name];
    if (!uniform) {
        console.warn("Invalid uniform name " + name);
        return;
    }
    this.renderer.gl.useProgram(this.program);
    uniform.setValue(value);
}

WebVfx.Shader.VERTEX_SHADER_SOURCE = [
    "attribute vec2 vertex;",
    "varying vec2 texCoord;",
    "void main() {",
    "    texCoord = vertex;",
    "    gl_Position = vec4(vertex * 2.0 - 1.0, 0.0, 1.0);",
    "}"].join("\n");

WebVfx.Shader.prototype.compileProgram = function (shaderSource) {
    var gl = this.renderer.gl;
    var program = gl.createProgram();

    var vs = this.compileSource(gl.VERTEX_SHADER,
                                WebVfx.Shader.VERTEX_SHADER_SOURCE);
    var fs = this.compileSource(gl.FRAGMENT_SHADER, shaderSource);
    gl.attachShader(program, vs);
    gl.attachShader(program, fs);
    gl.linkProgram(program);
    if (!gl.getProgramParameter(program, gl.LINK_STATUS))
        throw 'link error: ' + gl.getProgramInfoLog(program);

    gl.deleteShader(vs);
    gl.deleteShader(fs);

    return program;
}

WebVfx.Shader.prototype.compileSource = function (type, shaderSource) {
    var gl = this.renderer.gl;
    var shader = gl.createShader(type);
    gl.shaderSource(shader, shaderSource);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
        throw 'compile error: ' + gl.getShaderInfoLog(shader);
    return shader;
}

// Extract uniform declarations from program
WebVfx.Shader.prototype.extractUniforms = function () {
    var gl = this.renderer.gl;
    var textureCount = 0;
    var uniforms = {};

    gl.useProgram(this.program);

    var uniformCount = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS);
    for (var u = 0; u < uniformCount; u++) {
        var info = gl.getActiveUniform(this.program, u);
        var location = gl.getUniformLocation(this.program, info.name);

        if (info.type == gl.SAMPLER_2D)
            uniforms[info.name] = new WebVfx.Texture(gl, textureCount++, location);
        else
            uniforms[info.name] = new WebVfx.Uniform(gl, info.type, location);
    }
    return uniforms;
}

////////

// type - uniform type
// location - uniform location
WebVfx.Uniform = function (gl, type, location) {
    this.gl = gl;

    this.uniformLocation = location;

    switch (type) {
    case gl.FLOAT:
        this.uniformFunction = gl.uniform1f;
        break;
    case gl.INT:
    case gl.BOOL:
        this.uniformFunction = gl.uniform1i;
        break;
    case gl.FLOAT_VEC2:
        this.uniformFunction = gl.uniform2fv;
        this.wrapperConstructor = Float32Array;
        break;
    case gl.FLOAT_VEC3:
        this.uniformFunction = gl.uniform3fv;
        this.wrapperConstructor = Float32Array;
        break;
    case gl.FLOAT_VEC4:
        this.uniformFunction = gl.uniform4fv;
        this.wrapperConstructor = Float32Array;
        break;
    case gl.INT_VEC2:
    case gl.BOOL_VEC2:
        this.uniformFunction = gl.uniform2iv;
        this.wrapperConstructor = Int32Array;
        break;
    case gl.INT_VEC3:
    case gl.BOOL_VEC3:
        this.uniformFunction = gl.uniform3iv;
        this.wrapperConstructor = Int32Array;
        break;
    case gl.INT_VEC4:
    case gl.BOOL_VEC4:
        this.uniformFunction = gl.uniform4iv;
        this.wrapperConstructor = Int32Array;
        break;
    default:
        throw 'Unsupported uniform type ' + type;
    }
}

// Set uniform value, can be float or array of floats
WebVfx.Uniform.prototype.setValue = function(value) {
    this.value = value;
    if (this.wrapperConstructor)
        value = new this.wrapperConstructor(value);
    this.uniformFunction.call(this.gl, this.uniformLocation, value);
}

WebVfx.Uniform.prototype.bind = function() {
    // do nothing
}

WebVfx.Uniform.prototype.destroy = function() {
    // do nothing
}

////////

// unit - texture unit, 0-7
// location - uniform location
WebVfx.Texture = function (gl, unit, location) {
    this.gl = gl;
    this.unit = unit;

    gl.uniform1i(location, this.unit);
}

// Value can be a RenderTarget, SharedTexture or an image to upload image into a texture.
// The image can have textureOptions which map texParameteri enums to values.
WebVfx.Texture.prototype.setValue = function(image) {
    var gl = this.gl;

    if (image instanceof WebVfx.RenderTarget || image instanceof WebVfx.SharedTexture) {
        this.id = image.texture;
    }
    else {
        if (!this.id) {
            this.id = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, this.id);
            // Set parameters to support NPOT textures
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        }

        if (image.textureOptions) {
            for (var opt in image.textureOptions)
                gl.texParameteri(gl.TEXTURE_2D, opt, image.textureOptions[opt]);
        }
        gl.bindTexture(gl.TEXTURE_2D, this.id);
        // Flip texture vertically so it's not upside down
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    }
}

WebVfx.Texture.prototype.bind = function() {
    if (!this.id)
        return;
    var gl = this.gl;
    gl.activeTexture(gl.TEXTURE0 + this.unit);
    gl.bindTexture(gl.TEXTURE_2D, this.id);
}

WebVfx.Texture.prototype.destroy = function() {
    if (this.id) {
        this.gl.deleteTexture(this.id);
        this.id = null;
    }
}

////////

WebVfx.SharedTexture = function (renderer) {
    this.renderer = renderer;
    var gl = renderer.gl;
    this.texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    // Set parameters to support NPOT textures
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.bindTexture(gl.TEXTURE_2D, null);
}

WebVfx.SharedTexture.prototype.setImage = function(image) {
    var gl = this.renderer.gl;
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    // Flip texture vertically so it's not upside down
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
}<|endoftext|>