<commit_before>var activitiesData = {};

var getLang = function ( obj ) {
  var ul = navigator.language || navigator.userLanguage;
  if ( obj[ ul ] !== undefined )  // Same
    return obj[ ul ];

  for ( key in obj )  // Same lang, different country
    if ( obj.hasOwnProperty( key ) )
      if ( key.substr( 0, 2 ) == ul.substr( 0, 2 ) )
        return obj[ key ];

  for ( key in obj )  // Anything
    if ( obj.hasOwnProperty( key ) )
      return obj[ key ];
};

var account = undefined;
var authServer = "http://localhost:5000"
navigator.id.watch({
  onlogin: function ( assertion ) {
    $.post( authServer + "/login", { assertion: assertion } )
      .done( function ( data ) {
		$( "button.login" ).hide()
        account = JSON.parse( data );
        account.code = assertion;
		loadSuggestions();
        commentsSetup( $( ".comments .add" ).data( "bundleId" ) );
      });
  },
  onlogout: function () {
    account = undefined;
  }
});

var suggestServer = "http://localhost:5002/recommend";
var MAX_RECOMMENDED = 10;
var loadSuggestions = function () {
  $.post( suggestServer, { email: account.email } )
    .done( function ( data ) {
      console.log( data );

      $( ".recommended-activities-container" ).show();
      $( ".recommended-activities" ).html( "" );

      for ( i in data ) {
        item = data[ i ];
        if ( i > MAX_RECOMMENDED || item.confidence <= 0)
          return;
        addActivityToList( ".recommended-activities", item.bundleId );
      }
    });
};

var commentsSetupEvents = function () {
  $( ".comments .add" ).click( function () {
    var text = $( ".comments .add-content" ).val();
    var rating = $( ".comments input[name=rating-i]:checked" ).attr( "value" );
    if ( account === undefined ) {
      navigator.id.request()
      return;
    }

    if ( $( ".comments .add" ).data( "bundleId" ) === undefined )
      return

    $.post( authServer + "/comments/post", {
          email: account.email,
          code: account.code,
          content: text,
          bundle_id: $( ".comments .add" ).data( "bundleId" ),
          rating: rating,
    } )
      .done( function ( _ ) {
        commentsSetup($( ".comments .add" ).data( "bundleId" ));
        loadSuggestions()
      });
  });
};

var commentsSetup = function ( bundleId ) {
  $.post( authServer + "/comments/get/" + bundleId)  // We don't want to GET cached stuff
    .done( function ( strData ) {
    var container = $( ".comments ul" );
    container.html( "" );

    var data = JSON.parse( strData );
    for ( i in data ) {
      var item = data[ i ];
      var ele = $( "
" );

      var img = $( "" );
      img.attr( "src", "http://www.gravatar.com/avatar/" + item.email_hash + "?d=monsterid" );
      ele.append( img );

      var stars = $( "" +
                     "<input disabled type='radio' name='rating' value='1'>" +
                     "<input disabled type='radio' name='rating' value='2'>" +
                     "<input disabled type='radio' name='rating' value='3'>" +
                     "<input disabled type='radio' name='rating' value='4'>" +
                     "<input disabled type='radio' name='rating' value='5'>" );
      $( "input[value=" + item.rating.toString() + "]", stars ).attr( "checked", "" );
      ele.append( stars );

      var text = $( "
" );
      text.html( item.text );
      ele.append( text );

      var report = $( "<button class='report'>Report</button>" );
      report.data( "id", item.id );
      report.click( function () {
        $.post( authServer + "/comments/report", { id: report.data( "id" ) } );
        $( this ).html( "Reported" );
        $( this ).attr( "disabled", "true" );
        $( this ).parent().addClass( "reported" );
      });
      ele.append( report );

      if ( account !== undefined ) {
        if ( md5( account.email ) === item.email_hash ) {
          ele.prependTo( $( ".comments ul" ) );
          return;
        }
      }
      ele.appendTo( $( ".comments ul" ) );
    }
  });

  $( ".comments .add" ).data( "bundleId", bundleId );
};

var focusOnActivity = function ( data, bundleId ) {
  window.location.hash = "!/view/" + bundleId;

  var container = $( ".detail" );
  container.show();

  $( ".title", container ).html( getLang( data.title ) );
  $( ".icon", container ).attr( "src", data.icon );
  $( ".description", container ).html( getLang( data.description ) );
  $( ".whatsnew", container ).html( getLang( data.whats_new ) );
  $( ".minversion", container ).html( data.minSugarVersion );

  $( ".github", container ).hide();
  if ( data.github_url !== undefined ) {
    $( ".github", container ).show();
    $( ".github", container ).attr( "href", "https://www.github.com/" + data.github_url );
  }

  $( ".download", container ).attr( "href", data.xo_url );

  $( ".download-devel", container ).hide();
  if ( data.xo_url_latest ) {
    $( ".download-devel", container ).show();
    $( ".download-devel", container ).attr( "href", data.xo_url_latest );
  }

  $( ".screenshots", container).html( "" );
  for ( i in getLang( data.screenshots ) ) {
    var ele = $( "" );
    var imageSrc = getLang( data.screenshots )[ i ]
    ele.addClass( "screenshot" );
    ele.attr( "src", imageSrc );
    $( ".screenshots", container ).append( ele );
  }

  $( ".by", container).html( "" );
  for ( i in data.by ) {
    var ele = $( "" );
    var person  = data.by[ i ];
    ele.attr( "href", person.page );
    ele.html( person.name );
    $( ".by", container ).append( ele );
  }

  commentsSetup( bundleId );
};

var addActivityToList = function (container, bundleId) {
  var ele = $( "
" );
  var data = activitiesData[ bundleId ];

  var title = $( "
" +  getLang( data.title ) + "
" );
  ele.append( title );

  $( container ).append( ele );

  ele.data( "json", data );
  ele.data( "bundleId", bundleId );
  ele.data( "searchString", getLang( data.title ).toLowerCase() );
  ele.click( function () {
    focusOnActivity( $( this ).data( "json" ), $( this ).data( "bundleId" ) );
  });
}

var setupActivityList = function () {
  for ( var key in activitiesData ) {
    if ( activitiesData.hasOwnProperty( key ) ) {
      addActivityToList( ".activities", key )
    }
  }
};

// FIXME: don't use rawgit! They said bad stuff would happen :(
var dataUrl = "https://rawgit.com/SAMdroid-apps/sugar-activities/master/data.json";
$(document).ready( function () {
  var list = $(".activities");
  var detail = $(".detail");

  $.ajax({
    url: dataUrl
  }).done( function ( data ) {
    activitiesData = data.activities;
    setupActivityList();

    if ( window.location.hash ) {
      var bundleId = window.location.hash.substr( "!/view/".length + 1 );
      var itemData = activitiesData[ bundleId ];
      focusOnActivity( itemData, bundleId );
    }
  });

  var lastQuery = "";
  $( "input.search" ).on( "input", function () {
    term = $( "input.search" ).val().toLowerCase();
    if ( term === "" ) {
      $( ".activities li" ).each( function (index) {
        $( this ).show();
      });
    } else {
      if ( term.indexOf( lastQuery ) === 0 ) {
        // If they just appended to the query the results will be a subset of what is seen now
        var ele = $( ".activities li:visible" );
      } else { var ele = $( ".activities li" ); }
      ele.each( function (index) {
        ( $( this ).data( "searchString" ).indexOf( term ) !== -1 )? $( this ).show() : $( this ).hide();
      });
    }
    lastQuery = term;
  });

  $( "button.login" ).click( function () { navigator.id.request(); } )

  commentsSetupEvents();
});
<commit_msg>Stop missing things from crashing the interface<commit_after>var activitiesData = {};

var getLang = function ( obj ) {
  if ( obj === undefined )
    return ""

  var ul = navigator.language || navigator.userLanguage;
  if ( obj[ ul ] !== undefined )  // Same
    return obj[ ul ];

  for ( key in obj )  // Same lang, different country
    if ( obj.hasOwnProperty( key ) )
      if ( key.substr( 0, 2 ) == ul.substr( 0, 2 ) )
        return obj[ key ];

  for ( key in obj )  // Anything
    if ( obj.hasOwnProperty( key ) )
      return obj[ key ];
};

var account = undefined;
var authServer = "http://localhost:5000"
navigator.id.watch({
  onlogin: function ( assertion ) {
    $.post( authServer + "/login", { assertion: assertion } )
      .done( function ( data ) {
		$( "button.login" ).hide()
        account = JSON.parse( data );
        account.code = assertion;
		loadSuggestions();
        commentsSetup( $( ".comments .add" ).data( "bundleId" ) );
      });
  },
  onlogout: function () {
    account = undefined;
  }
});

var suggestServer = "http://localhost:5002/recommend";
var MAX_RECOMMENDED = 10;
var loadSuggestions = function () {
  $.post( suggestServer, { email: account.email } )
    .done( function ( data ) {
      console.log( data );

      $( ".recommended-activities-container" ).show();
      $( ".recommended-activities" ).html( "" );

      for ( i in data ) {
        item = data[ i ];
        if ( i > MAX_RECOMMENDED || item.confidence <= 0)
          return;
        addActivityToList( ".recommended-activities", item.bundleId );
      }
    });
};

var commentsSetupEvents = function () {
  $( ".comments .add" ).click( function () {
    var text = $( ".comments .add-content" ).val();
    var rating = $( ".comments input[name=rating-i]:checked" ).attr( "value" );
    if ( account === undefined ) {
      navigator.id.request()
      return;
    }

    if ( $( ".comments .add" ).data( "bundleId" ) === undefined )
      return

    $.post( authServer + "/comments/post", {
          email: account.email,
          code: account.code,
          content: text,
          bundle_id: $( ".comments .add" ).data( "bundleId" ),
          rating: rating,
    } )
      .done( function ( _ ) {
        commentsSetup($( ".comments .add" ).data( "bundleId" ));
        loadSuggestions()
      });
  });
};

var commentsSetup = function ( bundleId ) {
  $.post( authServer + "/comments/get/" + bundleId)  // We don't want to GET cached stuff
    .done( function ( strData ) {
    var container = $( ".comments ul" );
    container.html( "" );

    var data = JSON.parse( strData );
    for ( i in data ) {
      var item = data[ i ];
      var ele = $( "
" );

      var img = $( "" );
      img.attr( "src", "http://www.gravatar.com/avatar/" + item.email_hash + "?d=monsterid" );
      ele.append( img );

      var stars = $( "" +
                     "<input disabled type='radio' name='rating' value='1'>" +
                     "<input disabled type='radio' name='rating' value='2'>" +
                     "<input disabled type='radio' name='rating' value='3'>" +
                     "<input disabled type='radio' name='rating' value='4'>" +
                     "<input disabled type='radio' name='rating' value='5'>" );
      $( "input[value=" + item.rating.toString() + "]", stars ).attr( "checked", "" );
      ele.append( stars );

      var text = $( "
" );
      text.html( item.text );
      ele.append( text );

      var report = $( "<button class='report'>Report</button>" );
      report.data( "id", item.id );
      report.click( function () {
        $.post( authServer + "/comments/report", { id: report.data( "id" ) } );
        $( this ).html( "Reported" );
        $( this ).attr( "disabled", "true" );
        $( this ).parent().addClass( "reported" );
      });
      ele.append( report );

      if ( account !== undefined ) {
        if ( md5( account.email ) === item.email_hash ) {
          ele.prependTo( $( ".comments ul" ) );
          return;
        }
      }
      ele.appendTo( $( ".comments ul" ) );
    }
  });

  $( ".comments .add" ).data( "bundleId", bundleId );
};

var focusOnActivity = function ( data, bundleId ) {
  window.location.hash = "!/view/" + bundleId;

  var container = $( ".detail" );
  container.show();

  $( ".title", container ).html( getLang( data.title ) );
  $( ".icon", container ).attr( "src", data.icon );
  $( ".description", container ).html( getLang( data.description ) );
  $( ".whatsnew", container ).html( getLang( data.whats_new ) );
  $( ".minversion", container ).html( data.minSugarVersion );

  $( ".github", container ).hide();
  if ( data.github_url !== undefined ) {
    $( ".github", container ).show();
    $( ".github", container ).attr( "href", "https://www.github.com/" + data.github_url );
  }

  $( ".download", container ).attr( "href", data.xo_url );

  $( ".download-devel", container ).hide();
  if ( data.xo_url_latest ) {
    $( ".download-devel", container ).show();
    $( ".download-devel", container ).attr( "href", data.xo_url_latest );
  }

  $( ".screenshots", container).html( "" );
  for ( i in getLang( data.screenshots ) ) {
    var ele = $( "" );
    var imageSrc = getLang( data.screenshots )[ i ]
    ele.addClass( "screenshot" );
    ele.attr( "src", imageSrc );
    $( ".screenshots", container ).append( ele );
  }

  $( ".by", container).html( "" );
  for ( i in data.by ) {
    var ele = $( "" );
    var person  = data.by[ i ];
    ele.attr( "href", person.page );
    ele.html( person.name );
    $( ".by", container ).append( ele );
  }

  commentsSetup( bundleId );
};

var addActivityToList = function (container, bundleId) {
  var ele = $( "
" );
  var data = activitiesData[ bundleId ];

  var title = $( "
" +  getLang( data.title ) + "
" );
  ele.append( title );

  $( container ).append( ele );

  ele.data( "json", data );
  ele.data( "bundleId", bundleId );
  ele.data( "searchString", getLang( data.title ).toLowerCase() );
  ele.click( function () {
    focusOnActivity( $( this ).data( "json" ), $( this ).data( "bundleId" ) );
  });
}

var setupActivityList = function () {
  for ( var key in activitiesData ) {
    if ( activitiesData.hasOwnProperty( key ) ) {
      addActivityToList( ".activities", key )
    }
  }
};

// FIXME: don't use rawgit! They said bad stuff would happen :(
var dataUrl = "https://rawgit.com/SAMdroid-apps/sugar-activities/master/data.json";
$(document).ready( function () {
  var list = $(".activities");
  var detail = $(".detail");

  $.ajax({
    url: dataUrl
  }).done( function ( data ) {
    activitiesData = data.activities;
    setupActivityList();

    if ( window.location.hash ) {
      var bundleId = window.location.hash.substr( "!/view/".length + 1 );
      var itemData = activitiesData[ bundleId ];
      focusOnActivity( itemData, bundleId );
    }
  });

  var lastQuery = "";
  $( "input.search" ).on( "input", function () {
    term = $( "input.search" ).val().toLowerCase();
    if ( term === "" ) {
      $( ".activities li" ).each( function (index) {
        $( this ).show();
      });
    } else {
      if ( term.indexOf( lastQuery ) === 0 ) {
        // If they just appended to the query the results will be a subset of what is seen now
        var ele = $( ".activities li:visible" );
      } else { var ele = $( ".activities li" ); }
      ele.each( function (index) {
        ( $( this ).data( "searchString" ).indexOf( term ) !== -1 )? $( this ).show() : $( this ).hide();
      });
    }
    lastQuery = term;
  });

  $( "button.login" ).click( function () { navigator.id.request(); } )

  commentsSetupEvents();
});
<|endoftext|>


<commit_before>/**
 * Indicates current section in nav on scroll. Applies an `.is-active`
 * class when the specified `href` reaches the top of the viewport.
 *
 * Triggered by a `.js-scroll-indicator` on a link.
 */

define(function() {
  "use strict";

  var $ = window.jQuery;
  var links = [];

  /**
   * @see _.throttle
   */
  var throttle = function(func, wait, options) {
    var context, args, result;
    var timeout = null;
    var previous = 0;

    options || (options = {});

    var later = function() {
      previous = new Date();
      timeout = null;
      result = func.apply(context, args);
    };

    return function() {
      var now = new Date();
      if (!previous && options.leading === false) previous = now;
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;

      if (remaining <= 0) {
        clearTimeout(timeout);
        timeout = null;
        previous = now;
        result = func.apply(context, args);
      } else if (!timeout && options.trailing !== false) {
        timeout = setTimeout(later, remaining);
      }

      return result;
    };
  };

  /**
   * @see _.sortedIndex
   */
  function sortedIndex(array, value, key) {
    var low = 0,
    high = array ? array.length : low;

    while (low < high) {
      var mid = (low + high) >>> 1; // jshint ignore:line
      (array[mid][key] < value) ? low = mid + 1 : high = mid;
    }

    return low ? low - 1 : low;
  }

  /**
   * Modified binary search. Finds target key, or next lowest if
   * it doesn't exist.
   * @see _.binarySearch
   */
  function binarySearch(array, value) {
    var index = sortedIndex(array, value, "offset");
    return array[index];
  }

  // Registers links and their targets with scroll handler
  function prepareIndicator($link) {
    // Calculate the element's offset from the top of the page while anchored
    var $linkTarget = $( $link.attr("href") );
    if( $linkTarget.length ) {
      // Add jQuery object and offset value to link map
      links.push({ offset: $linkTarget.offset().top, link: $link });
    }
  }

  // Prepare all `.js-scroll-indicator` links on the page.
  function preparePage() {
    links = [];

    $(".js-scroll-indicator").find("a").each(function(index, link) {
      prepareIndicator( $(link) );
    });
  }

  var oldIndicator;
  // Scroll handler: highlights the furthest link the user has passed
  function updateScrollIndicators() {
    var newIndicator = binarySearch(links, $(window).scrollTop() + 40);  // 40px offset
    var newIndicatorParents = newIndicator.link.parentsUntil(".js-scroll-indicator");
    var oldIndicatorParents = $();

    if(oldIndicator && oldIndicator !== newIndicator) {
      oldIndicator.link.removeClass("is-active");
      oldIndicatorParents = oldIndicator.link.parentsUntil(".js-scroll-indicator");
    }

    newIndicator.link.addClass("is-active");
    newIndicatorParents.addClass("is-active");
    oldIndicatorParents.not(newIndicatorParents).removeClass("is-active");

    oldIndicator = newIndicator;
    console.log("WHAWHAWHA");
  }

  // Attach our functions to their respective events.
  $(function() {
    preparePage();

    var throttledScroll = throttle(updateScrollIndicators, 60);

    $(window).on("scroll", throttledScroll);
    $(window).on("resize", preparePage);
  });

});

<commit_msg>Cleanup to scroll indicator from #358 feedback.<commit_after>/**
 * Indicates current section in nav on scroll. Applies an `.is-active`
 * class when the specified `href` reaches the top of the viewport.
 *
 * Triggered by a `.js-scroll-indicator` on a link.
 */

define(function() {
  "use strict";

  var $ = window.jQuery;
  var links = [];

  /**
   * @see _.throttle
   */
  var throttle = function(func, wait, options) {
    var context, args, result;
    var timeout = null;
    var previous = 0;

    options || (options = {});

    var later = function() {
      previous = new Date();
      timeout = null;
      result = func.apply(context, args);
    };

    return function() {
      var now = new Date();
      if (!previous && options.leading === false) previous = now;
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;

      if (remaining <= 0) {
        clearTimeout(timeout);
        timeout = null;
        previous = now;
        result = func.apply(context, args);
      } else if (!timeout && options.trailing !== false) {
        timeout = setTimeout(later, remaining);
      }

      return result;
    };
  };

  /**
   * @see _.sortedIndex
   */
  function sortedIndex(array, value, key) {
    var low = 0,
    high = array ? array.length : low;

    while (low < high) {
      var mid = (low + high) >>> 1; // jshint ignore:line
      (array[mid][key] < value) ? low = mid + 1 : high = mid;
    }

    return low ? low - 1 : low;
  }

  /**
   * Modified binary search. Finds target key, or next lowest if
   * it doesn't exist.
   * @see _.binarySearch
   */
  function binarySearch(array, value) {
    var index = sortedIndex(array, value, "offset");
    return array[index];
  }

  // Registers links and their targets with scroll handler
  function prepareIndicator($link) {
    // Calculate the element's offset from the top of the page while anchored
    var $linkTarget = $( $link.attr("href") );
    if( $linkTarget.length ) {
      // Add jQuery object and offset value to link map
      links.push({ offset: $linkTarget.offset().top, link: $link });
    }
  }

  // Prepare all `.js-scroll-indicator` links on the page.
  function preparePage() {
    links = [];

    $(".js-scroll-indicator").find("a").each(function(index, link) {
      prepareIndicator( $(link) );
    });
  }

  var oldIndicator;
  // Scroll handler: highlights the furthest link the user has passed
  function updateScrollIndicators() {
    var newIndicator = binarySearch(links, $(window).scrollTop() + 40);
    // @NOTE: We use a 40px offset to trigger indicator slightly after scroll position
    // (so that nav switches closer to where a user will likely be reading the text)

    var newIndicatorParents = newIndicator.link.parentsUntil(".js-scroll-indicator");
    var oldIndicatorParents = $();

    if(oldIndicator && oldIndicator !== newIndicator) {
      oldIndicator.link.removeClass("is-active");
      oldIndicatorParents = oldIndicator.link.parentsUntil(".js-scroll-indicator");
    }

    newIndicator.link.addClass("is-active");
    newIndicatorParents.addClass("is-active");
    oldIndicatorParents.not(newIndicatorParents).removeClass("is-active");

    oldIndicator = newIndicator;
  }

  // Attach our functions to their respective events.
  $(function() {
    preparePage();

    var throttledScroll = throttle(updateScrollIndicators, 60);

    $(window).on("scroll", throttledScroll);
    $(window).on("resize", preparePage);
  });

});

<|endoftext|>


<commit_before>/*
 Copyright 2014 OpenMarket Ltd

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

'use strict';

/*
 * Transform an element into an image file input button.
 * Watch to the passed variable change. It will contain the selected HTML5 file object.
 */
angular.module('mFileInput', [])
.directive('mFileInput', function() {
    return {
        restrict: 'A',
        transclude: 'true',
        template: '

<input ng-hide="true" type="file" accept="image/*"/>',
        scope: {
            selectedFile: '=mFileInput'
        },

        link: function(scope, element, attrs, ctrl) {
            element.bind("click", function() {
                element.find("input")[0].click();
                element.find("input").bind("change", function(e) {
                    scope.selectedFile = this.files[0];
                    scope.$apply();
                });
            });

            // Change the mouse icon on mouseover on this element
            element.css("cursor", "pointer");
      }
    };
});<commit_msg>SYWEB-13: disabled "Send image" button if the browser does not support HTML5 file API<commit_after>/*
 Copyright 2014 OpenMarket Ltd

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

'use strict';

/*
 * Transform an element into an image file input button.
 * Watch to the passed variable change. It will contain the selected HTML5 file object.
 */
angular.module('mFileInput', [])
.directive('mFileInput', function() {
    return {
        restrict: 'A',
        transclude: 'true',
        template: '

<input ng-hide="true" type="file" accept="image/*"/>',
        scope: {
            selectedFile: '=mFileInput'
        },

        link: function(scope, element, attrs, ctrl) {

            // Check if HTML5 file selection is supported
            if (window.FileList) {
                element.bind("click", function() {
                    element.find("input")[0].click();
                    element.find("input").bind("change", function(e) {
                        scope.selectedFile = this.files[0];
                        scope.$apply();
                    });
                });
            }
            else {
                setTimeout(function() {
                    element.attr("disabled", true);
                    element.attr("title", "The app uses the HTML5 File API to send files. Your browser does not support it.");
                }, 1);
            }

            // Change the mouse icon on mouseover on this element
            element.css("cursor", "pointer");
      }
    };
});<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////////////////////////////////
function oid() {
    //Get Token Balance
    $("#tokenBal").html(allTokens.balanceTokens.totalEarned.toFixed(2) + " tokens");
    //Load Wallet
    $(".walletToast").remove();
    if (localStorage.getItem('bits-user-name') == null) {
        console.log("Not logged in")
    } else {
        Materialize.toast('Unlock wallet Unlock', null, 'walletToast')
    }
    if (window.location.hash != undefined) {
        //check if hash is oid
        var type = window.location.hash.substr(1);
        // split the hash
        var fields = type.split('=');
        var htpe = fields[0];
        var hval = fields[1];
        if (htpe == "oid") {
            //get the shop and the oder details
            var shop = getBitsWinOpt('s')
            // oid
            $(".otitle").html("");
            $(".otitle").append("Your Order");
            $(".of").html("");
            //var uid = JSON.parseInt(hval)
            var od = getObjectStore('data', 'readwrite').get('bits-user-orders-' + localStorage.getItem("bits-user-name"));
            od.onsuccess = function (event) {
                try {
                    var odData = JSON.parse(event.target.result);
                    for (var ii = 0; ii < odData.length; ++ii) {
                        var xx = odData[ii].items
                        var xid = odData[ii].id
                        //makeOrder(products)
                        // match oid to url id
                        var urloid = getBitsOpt("oid")
                        if (urloid == xid) {
                            makeOrder(JSON.parse(xx), odData[ii].location)
                        } else {
                            console.log("no match")
                        }
                    }
                } catch (err) {}
            };
            od.onerror = function () {};
            //makeOrder(hval)
        } else {
            console.log("we dont know this hash")
        }
    } else {}
}

function unlockWallet() {
    walletFunctions(90).then(function (e) {
        loadGdrive();
        $(".walletToast").remove();
    })
}

function getUserOders(f) {

    doFetch({
        action: 'getAllOrders',
        uid: localStorage.getItem("bits-user-name")
    }).then(function (e) {
        if (e.status == "ok") {
            xx = e.data;
            //var earnedPoints = 0;

            for (var ii in allTokens) {
                allTokens[ii].totalEarned = 0;
            }
            for (var ii in xx) {
                var items = xx[ii].points;
                try {
                    var typeofCoin = JSON.parse(items).coin;
                } catch (err) {
                    console.log(err);
                    continue;
                }
                try {
                    var purchasePoints = JSON.parse(items).purchase;
                    if (purchasePoints == undefined) {
                        var purchasePoints = 0;
                    }
                } catch (err) {
                    console.log('this order does not have any purchase rewards', err);
                    var purchasePoints = 0;
                }
                try {
                    var deliveryPoints = JSON.parse(items).delivery;
                    if (deliveryPoints == undefined) {
                        var deliveryPoints = 0;
                    }
                } catch (err) {
                    console.log('this order does not have any delivery rewards', err);
                    var deliveryPoints = 0;
                }
                try {
                    allTokens[typeofCoin].totalEarned = allTokens[typeofCoin].totalEarned + purchasePoints + deliveryPoints;

                } catch (err) {
                    console.log('this coin had not been included in the rewards since its currently inactive', typeofCoin);
                    continue;
                }

                console.log(typeofCoin, purchasePoints, deliveryPoints);

            };

            var setdb = getObjectStore('data', 'readwrite').put(JSON.stringify(xx), 'bits-user-orders-' + localStorage.getItem("bits-user-name"));
            setdb.onsuccess = function () {
                oid();
            }
            setTimeout(function () {
                updateEarnedTokens(f)
            }, 1500);

        } else {
            swal("Cancelled", "an error occcured", "error");
        }
    })

}
// 		var gtod = localStorage.getItem('bits-user-orders-'+localStorage.getItem("bits-user-name"));
//
function updateEarnedTokens(f) {

    $('.coinlist').html('');
    var at = allTokens['allContracts'];

    var i = 0;
    var tCe = 0;
    tBal = 0;

    for(var i in at) {
if(!(location.origin+'/').includes(allTokens[allTokens['allContracts'][at[i]]].webpage)){
   continue;
   }
try{
        var rate = allTokens[at[i]].rate;
        var coinName = allTokens[at[i]].name;
        //if i have 1000 kobos
        //var koboBalance = 1000;
        //		console.log((rate*e.data.baseEx*koboBalance).toFixed(2)+' KES');
        var koboRate = Math.floor(rate * baseX);
        var qq = rate * baseX;
        var xx = qq.toFixed(2);
        var coinId = at[i];
        var tA = allTokens[coinId].totalEarned + (allTokens[coinId].balance / Math.pow(10, allTokens[coinId].decimals));
        if (tA > 0) {
            //only display the coin if the user has a balance
            $('.coinlist').append('

' + coinName + '')
            $('.coin-' + coinId + '-bal').html('').append(tA.toFixed(5));

        }
        $('.coin-' + coinId + '-xrate').html('').append('1 ' + coinName + ' = ' + xx + ' ' + baseCd);
        tBal = tBal + (tA * allTokens[coinId].rate * baseX);
    }catch(e){
        console.log(e)
    }
        i++;
    }

    $('.balance-coins').html('').append(numberify(tBal,2) + ' ' + baseCd);
}

//Check Bal Interval
var checkBal = window.setInterval(function () {
    if ($("#checkBal")[0].innerHTML == "") {
        updateEarnedTokens()
    } else {
        clearInterval(checkBal);
    }
}, 7000);
<commit_msg>Update bits-oder-functions.js<commit_after>////////////////////////////////////////////////////////////////////////////////////////////////////////////
function oid() {
    //Get Token Balance
    $("#tokenBal").html(allTokens.balanceTokens.totalEarned.toFixed(2) + " tokens");
    //Load Wallet
    $(".walletToast").remove();
    if (localStorage.getItem('bits-user-name') == null) {
        console.log("Not logged in")
    } else {
        Materialize.toast('Unlock wallet Unlock', null, 'walletToast')
    }
    if (window.location.hash != undefined) {
        //check if hash is oid
        var type = window.location.hash.substr(1);
        // split the hash
        var fields = type.split('=');
        var htpe = fields[0];
        var hval = fields[1];
        if (htpe == "oid") {
            //get the shop and the oder details
            var shop = getBitsWinOpt('s')
            // oid
            $(".otitle").html("");
            $(".otitle").append("Your Order");
            $(".of").html("");
            //var uid = JSON.parseInt(hval)
            var od = getObjectStore('data', 'readwrite').get('bits-user-orders-' + localStorage.getItem("bits-user-name"));
            od.onsuccess = function (event) {
                try {
                    var odData = JSON.parse(event.target.result);
                    for (var ii = 0; ii < odData.length; ++ii) {
                        var xx = odData[ii].items
                        var xid = odData[ii].id
                        //makeOrder(products)
                        // match oid to url id
                        var urloid = getBitsOpt("oid")
                        if (urloid == xid) {
                            makeOrder(JSON.parse(xx), odData[ii].location)
                        } else {
                            console.log("no match")
                        }
                    }
                } catch (err) {}
            };
            od.onerror = function () {};
            //makeOrder(hval)
        } else {
            console.log("we dont know this hash")
        }
    } else {}
}

function unlockWallet() {
    walletFunctions(90).then(function (e) {
        loadGdrive();
        $(".walletToast").remove();
    })
}

function getUserOders(f) {

    doFetch({
        action: 'getAllOrders',
        uid: localStorage.getItem("bits-user-name")
    }).then(function (e) {
        if (e.status == "ok") {
            xx = e.data;
            //var earnedPoints = 0;

            for (var ii in allTokens) {
                allTokens[ii].totalEarned = 0;
            }
            for (var ii in xx) {
                var items = xx[ii].points;
                try {
                    var typeofCoin = JSON.parse(items).coin;
                } catch (err) {
                    console.log(err);
                    continue;
                }
                try {
                    var purchasePoints = JSON.parse(items).purchase;
                    if (purchasePoints == undefined) {
                        var purchasePoints = 0;
                    }
                } catch (err) {
                    console.log('this order does not have any purchase rewards', err);
                    var purchasePoints = 0;
                }
                try {
                    var deliveryPoints = JSON.parse(items).delivery;
                    if (deliveryPoints == undefined) {
                        var deliveryPoints = 0;
                    }
                } catch (err) {
                    console.log('this order does not have any delivery rewards', err);
                    var deliveryPoints = 0;
                }
                try {
                    allTokens[typeofCoin].totalEarned = allTokens[typeofCoin].totalEarned + purchasePoints + deliveryPoints;

                } catch (err) {
                    console.log('this coin had not been included in the rewards since its currently inactive', typeofCoin);
                    continue;
                }

                console.log(typeofCoin, purchasePoints, deliveryPoints);

            };

            var setdb = getObjectStore('data', 'readwrite').put(JSON.stringify(xx), 'bits-user-orders-' + localStorage.getItem("bits-user-name"));
            setdb.onsuccess = function () {
                oid();
            }
            setTimeout(function () {
                updateEarnedTokens(f)
            }, 1500);

        } else {
            swal("Cancelled", "an error occcured", "error");
        }
    })

}
// 		var gtod = localStorage.getItem('bits-user-orders-'+localStorage.getItem("bits-user-name"));
//
function updateEarnedTokens(f) {

    $('.coinlist').html('');
    var at = allTokens['allContracts'];

    var i = 0;
    var tCe = 0;
    tBal = 0;

    for(var i in at) {
if(!(location.origin+'/').includes(allTokens[at[i]].webpage)){
   continue;
   }
try{
        var rate = allTokens[at[i]].rate;
        var coinName = allTokens[at[i]].name;
        //if i have 1000 kobos
        //var koboBalance = 1000;
        //		console.log((rate*e.data.baseEx*koboBalance).toFixed(2)+' KES');
        var koboRate = Math.floor(rate * baseX);
        var qq = rate * baseX;
        var xx = qq.toFixed(2);
        var coinId = at[i];
        var tA = allTokens[coinId].totalEarned + (allTokens[coinId].balance / Math.pow(10, allTokens[coinId].decimals));
        if (tA > 0) {
            //only display the coin if the user has a balance
            $('.coinlist').append('

' + coinName + '')
            $('.coin-' + coinId + '-bal').html('').append(tA.toFixed(5));

        }
        $('.coin-' + coinId + '-xrate').html('').append('1 ' + coinName + ' = ' + xx + ' ' + baseCd);
        tBal = tBal + (tA * allTokens[coinId].rate * baseX);
    }catch(e){
        console.log(e)
    }
        i++;
    }

    $('.balance-coins').html('').append(numberify(tBal,2) + ' ' + baseCd);
}

//Check Bal Interval
var checkBal = window.setInterval(function () {
    if ($("#checkBal")[0].innerHTML == "") {
        updateEarnedTokens()
    } else {
        clearInterval(checkBal);
    }
}, 7000);
<|endoftext|>


<commit_before>const https = require('follow-redirects').https
const fs = require('fs');
const util = require('util');
const readline = require('readline');
const stream = require('stream');

const url = "http://www.shl.se/calendar/66/show/shl.ics";
let icalData = false;
let lastFetch = false;

const download = function(url, cb) {
    let fetch = true;

    if (icalData) {
        const now = new Date().getTime() / 1000;
        const diff = now - 3600;

        if (diff < lastFetch ) {
            fetch = false;
        };
    };

    if (!fetch) {
        cb(null);
    } else {
        const request = https.get(url, function(response) {
            let bufferData = [];

            response.on( 'data', ( chunk ) => {
                bufferData.push( chunk );
            });

            response.on('end', () => {
                icalData = Buffer.concat( bufferData );
                lastFetch = new Date().getTime() / 1000;
                cb(null);
            });
        }).on('error', function(err) {
            if (cb) {
                cb(err);

                return false;
            }
        });
    };
};

const calendar = (f,cb) => {
    const filter = [].concat(f);
    const re_array = [];
    const newline = "\r\n";
    let return_object = `BEGIN:VCALENDAR${ newline }PRODID:-//Google Inc//Google Calendar//EN${ newline }VERSION:2.0${ newline }CALSCALE:GREGORIAN${ newline }X-WR-TIMEZONE:Europe/Stockholm${ newline }`;
    let calendarName = 'SHL';
    let calendarDesc = 'Spelschema för SHL';

    filter.forEach(function(team) {
        if (team === "BIF") {
            re_array.push("Brynäs IF");
        } else if ( team === "DIF" ) {
            re_array.push("Djurgården");
        } else if ( team === "FHC" ) {
            re_array.push("Frölunda HC");
        } else if ( team === "FBK" ) {
            re_array.push("Färjestad BK");
        } else if ( team === "HV71" ) {
            re_array.push("HV71");
        } else if ( team === "KHK" ) {
            re_array.push("Karlskrona HK");
        } else if ( team === "LIF" ) {
            re_array.push("Leksands IF");
        } else if ( team === "LHC" ) {
            re_array.push("Linköping HC");
        } else if ( team === "LHF" ) {
            re_array.push("Luleå Hockey");
        } else if ( team === "MIF" ) {
            re_array.push("Malmö Redhawks");
        } else if ( team === "RBK" ) {
            re_array.push("Rögle BK");
        } else if ( team === "SKE"  || team === "SAIK") {
            re_array.push("Skellefteå AIK");
        } else if ( team === "VLH" ) {
            re_array.push("Växjö Lakers");
        } else if ( team === "ÖRE" ) {
            re_array.push("Örebro Hockey");
        };
    });

    if( filter.length === 1 ){
        calendarName = re_array[ 0 ];
        calendarDesc = `Spelschema för ${ re_array[ 0 ] }`;
    }

    return_object = `${ return_object }X-WR-CALNAME:${ calendarName }${ newline }`;
    return_object = `${ return_object }X-WR-CALDESC:${ calendarDesc }${ newline }`;

    const global_re = re_array.join("|");

    download(url, (err) => {
        if (err) {
            cb(err);

            return false;
        }

        let readStream = new stream.PassThrough();
        readStream.end( icalData );

        const lineReader = readline.createInterface({
            input: readStream
        });

        let in_event = false;
        let event_data = [];
        let print_event = false;

        lineReader.on('line', (line) => {
            if (line.match("^BEGIN:VEVENT")) {
                in_event = true;
                event_data = [];
            }

            if (in_event) {
                event_data.push(line);
            }

            if (line.match("^END:VEVENT")) {
                print_event = false;
                in_event = false;

                event_data.forEach(function(entry) {
                    re = /^SUMMARY/;
                    if (entry.match(re) && entry.match(global_re)) {
                        print_event = true;
                    };
                });

                if (print_event) {
                    event_data.forEach(function(entry) {
                        return_object += entry + newline;
                    });
                };
            };
        });

        lineReader.on('close', () => {
            return_object = `${ return_object }END:VCALENDAR`;

            cb(null, return_object);
        });

        lineReader.on('error', ( error ) => {
            cb(error);
        });
    });
};

module.exports = calendar;
<commit_msg>SHL isn't secure.<commit_after>const http = require('http');

const fs = require('fs');
const util = require('util');
const readline = require('readline');
const stream = require('stream');

const url = "http://www.shl.se/calendar/66/show/shl.ics";
let icalData = false;
let lastFetch = false;

const download = function(url, cb) {
    let fetch = true;

    if (icalData) {
        const now = new Date().getTime() / 1000;
        const diff = now - 3600;

        if (diff < lastFetch ) {
            fetch = false;
        };
    };

    if (!fetch) {
        cb(null);
    } else {
        const request = http.get(url, function(response) {
            let bufferData = [];

            response.on( 'data', ( chunk ) => {
                bufferData.push( chunk );
            });

            response.on('end', () => {
                icalData = Buffer.concat( bufferData );
                lastFetch = new Date().getTime() / 1000;
                cb(null);
            });
        }).on('error', function(err) {
            if (cb) {
                cb(err);

                return false;
            }
        });
    };
};

const calendar = (f,cb) => {
    const filter = [].concat(f);
    const re_array = [];
    const newline = "\r\n";
    let return_object = `BEGIN:VCALENDAR${ newline }PRODID:-//Google Inc//Google Calendar//EN${ newline }VERSION:2.0${ newline }CALSCALE:GREGORIAN${ newline }X-WR-TIMEZONE:Europe/Stockholm${ newline }`;
    let calendarName = 'SHL';
    let calendarDesc = 'Spelschema för SHL';

    filter.forEach(function(team) {
        if (team === "BIF") {
            re_array.push("Brynäs IF");
        } else if ( team === "DIF" ) {
            re_array.push("Djurgården");
        } else if ( team === "FHC" ) {
            re_array.push("Frölunda HC");
        } else if ( team === "FBK" ) {
            re_array.push("Färjestad BK");
        } else if ( team === "HV71" ) {
            re_array.push("HV71");
        } else if ( team === "KHK" ) {
            re_array.push("Karlskrona HK");
        } else if ( team === "LIF" ) {
            re_array.push("Leksands IF");
        } else if ( team === "LHC" ) {
            re_array.push("Linköping HC");
        } else if ( team === "LHF" ) {
            re_array.push("Luleå Hockey");
        } else if ( team === "MIF" ) {
            re_array.push("Malmö Redhawks");
        } else if ( team === "RBK" ) {
            re_array.push("Rögle BK");
        } else if ( team === "SKE"  || team === "SAIK") {
            re_array.push("Skellefteå AIK");
        } else if ( team === "VLH" ) {
            re_array.push("Växjö Lakers");
        } else if ( team === "ÖRE" ) {
            re_array.push("Örebro Hockey");
        };
    });

    if( filter.length === 1 ){
        calendarName = re_array[ 0 ];
        calendarDesc = `Spelschema för ${ re_array[ 0 ] }`;
    }

    return_object = `${ return_object }X-WR-CALNAME:${ calendarName }${ newline }`;
    return_object = `${ return_object }X-WR-CALDESC:${ calendarDesc }${ newline }`;

    const global_re = re_array.join("|");

    download(url, (err) => {
        if (err) {
            cb(err);

            return false;
        }

        let readStream = new stream.PassThrough();
        readStream.end( icalData );

        const lineReader = readline.createInterface({
            input: readStream
        });

        let in_event = false;
        let event_data = [];
        let print_event = false;

        lineReader.on('line', (line) => {
            if (line.match("^BEGIN:VEVENT")) {
                in_event = true;
                event_data = [];
            }

            if (in_event) {
                event_data.push(line);
            }

            if (line.match("^END:VEVENT")) {
                print_event = false;
                in_event = false;

                event_data.forEach(function(entry) {
                    re = /^SUMMARY/;
                    if (entry.match(re) && entry.match(global_re)) {
                        print_event = true;
                    };
                });

                if (print_event) {
                    event_data.forEach(function(entry) {
                        return_object += entry + newline;
                    });
                };
            };
        });

        lineReader.on('close', () => {
            return_object = `${ return_object }END:VCALENDAR`;

            cb(null, return_object);
        });

        lineReader.on('error', ( error ) => {
            cb(error);
        });
    });
};

module.exports = calendar;
<|endoftext|>


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

/**
 * A segment represents a specific curve with a start and end.
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */

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

  var kite = require( 'KITE/kite' );

  var inherit = require( 'PHET_CORE/inherit' );
  var Events = require( 'AXON/Events' );
  var DotUtil = require( 'DOT/Util' ); // eslint-disable-line require-statement-match
  var Bounds2 = require( 'DOT/Bounds2' );

  /**
   * Will contain (for segments):
   * properties (backed by ES5 getters, created usually lazily):
   * start        - start point of this segment
   * end          - end point of this segment
   * startTangent - the tangent vector (normalized) to the segment at the start, pointing in the direction of motion (from start to end)
   * endTangent   - the tangent vector (normalized) to the segment at the end, pointing in the direction of motion (from start to end)
   * bounds       - the bounding box for the segment
   *
   * methods:
   * positionAt( t )          - returns the position parametrically, with 0 <= t <= 1. this does NOT guarantee a constant magnitude tangent... don't feel like adding elliptical functions yet!
   * tangentAt( t )           - returns the non-normalized tangent (dx/dt, dy/dt) parametrically, with 0 <= t <= 1.
   * curvatureAt( t )         - returns the signed curvature (positive for visual clockwise - mathematical counterclockwise)
   * subdivided( t )          - returns an array with 2 sub-segments, split at the parametric t value.
   * getSVGPathFragment()     - returns a string containing the SVG path. assumes that the start point is already provided, so anything that calls this needs to put the M calls first
   * strokeLeft( lineWidth )  - returns an array of segments that will draw an offset curve on the logical left side
   * strokeRight( lineWidth ) - returns an array of segments that will draw an offset curve on the logical right side
   * windingIntersection      - returns the winding number for intersection with a ray
   * getInteriorExtremaTs     - returns a list of t values where dx/dt or dy/dt is 0 where 0 < t < 1. subdividing on these will result in monotonic segments
   *
   * writeToContext( context ) - draws the segment to the 2D Canvas context, assuming the context's current location is already at the start point
   * transformed( matrix )     - returns a new segment that represents this segment after transformation by the matrix
   *
   * @constructor
   */
  function Segment() {
    Events.call( this );
  }

  kite.register( 'Segment', Segment );

  /**
   * Returns itself
   * @param {Vector2} x
   * @returns {Vector2}
   */
  var identityFunction = function identityFunction( x ) { return x; };

  inherit( Events, Segment, {
    /**
     * Will return true if the start/end tangents are purely vertical or horizontal. If all of the segments of a shape
     * have this property, then the only line joins will be a multiple of pi/2 (90 degrees), and so all of the types of
     * line joins will have the same bounds. This means that the stroked bounds will just be a pure dilation of the
     * regular bounds, by lineWidth / 2.
     * @public
     *
     * @returns {boolean}
     */
    areStrokedBoundsDilated: function() {
      var epsilon = 0.0000001;

      // If the derivative at the start/end are pointing in a cardinal direction (north/south/east/west), then the
      // endpoints won't trigger non-dilated bounds, and the interior of the curve will not contribute.
      return Math.abs( this.startTangent.x * this.startTangent.y ) < epsilon && Math.abs( this.endTangent.x * this.endTangent.y ) < epsilon;
    },

    /**
     *  // TODO: override everywhere so this isn't necessary (it's not particularly efficient!)
     * @param {Matrix3} matrix
     * @returns {Bounds2}
     */
    getBoundsWithTransform: function( matrix ) {
      var transformedSegment = this.transformed( matrix );
      return transformedSegment.getBounds();
    },

    /**
     *
     * @param {Array.<number>} tList - list of sorted t values from 0 <= t <= 1
     * @returns {Array}
     */
    subdivisions: function( tList ) {
      // this could be solved by recursion, but we don't plan on the JS engine doing tail-call optimization
      var self = this;
      var result = [];
      for ( var i = 0; i < tList.length; i++ ) {
        // assume binary subdivision
        var t = tList[ i ];
        var arr = self.subdivided( t );
        assert && assert( arr.length === 2 );
        result.push( arr[ 0 ] );
        self = arr[ 1 ];

        // scale up the remaining t values
        for ( var j = i + 1; j < tList.length; j++ ) {
          tList[ j ] = DotUtil.linear( t, 1, 0, 1, tList[ j ] );
        }
      }
      result.push( self );
      return result;
    },

    // return an array of segments from breaking this segment into monotone pieces
    subdividedIntoMonotone: function() {
      return this.subdivisions( this.getInteriorExtremaTs() );
    },

    /**
     *
     * @param {object} [options] -           with the following options provided:
     *  - minLevels:                       how many levels to force subdivisions
     *  - maxLevels:                       prevent subdivision past this level
     *  - distanceEpsilon (optional null): controls level of subdivision by attempting to ensure a maximum (squared) deviation from the curve
     *  - curveEpsilon (optional null):    controls level of subdivision by attempting to ensure a maximum curvature change between segments
     *  - pointMap (optional):             function( Vector2 ) : Vector2, represents a (usually non-linear) transformation applied
     *  - methodName (optional):           if the method name is found on the segment, it is called with the expected signature function( options ) : Array[Segment]
     *                                     instead of using our brute-force logic
     * @param {number} [minLevels] -   how many levels to force subdivisions
     * @param {number} [maxLevels] -   prevent subdivision past this level
     * @param {Array.<Segment>} [segments]
     * @param {Vector2} [start]
     * @param {Vector2} [end]
     * @returns {Array.<Line>}
     */
    toPiecewiseLinearSegments: function( options, minLevels, maxLevels, segments, start, end ) {
      // for the first call, initialize min/max levels from our options
      minLevels = minLevels === undefined ? options.minLevels : minLevels;
      maxLevels = maxLevels === undefined ? options.maxLevels : maxLevels;
      segments = segments || [];
      var pointMap = options.pointMap || identityFunction;

      // points mapped by the (possibly-nonlinear) pointMap.
      start = start || pointMap( this.start );
      end = end || pointMap( this.end );
      var middle = pointMap( this.positionAt( 0.5 ) );

      assert && assert( minLevels <= maxLevels );
      assert && assert( options.distanceEpsilon === null || typeof options.distanceEpsilon === 'number' );
      assert && assert( options.curveEpsilon === null || typeof options.curveEpsilon === 'number' );
      assert && assert( !pointMap || typeof pointMap === 'function' );

      // i.e. we will have finished = maxLevels === 0 || ( minLevels <= 0 && epsilonConstraints ), just didn't want to one-line it
      var finished = maxLevels === 0; // bail out once we reach our maximum number of subdivision levels
      if ( !finished && minLevels <= 0 ) { // force subdivision if minLevels hasn't been reached
        // flatness criterion: A=start, B=end, C=midpoint, d0=distance from AB, d1=||B-A||, subdivide if d0/d1 > sqrt(epsilon)
        finished = ( options.curveEpsilon === null || ( DotUtil.distToSegmentSquared( middle, start, end ) / start.distanceSquared( end ) < options.curveEpsilon ) ) &&
                   // deviation criterion
                   ( options.distanceEpsilon === null || ( DotUtil.distToSegmentSquared( middle, start, end ) < options.distanceEpsilon ) );
      }

      if ( finished ) {
        segments.push( new kite.Line( start, end ) );
      }
      else {
        var subdividedSegments = this.subdivided( 0.5 );
        subdividedSegments[ 0 ].toPiecewiseLinearSegments( options, minLevels - 1, maxLevels - 1, segments, start, middle );
        subdividedSegments[ 1 ].toPiecewiseLinearSegments( options, minLevels - 1, maxLevels - 1, segments, middle, end );
      }
      return segments;
    }
  } );

  /**
   * Adds getter/setter function pairs and ES5 pairs, e.g. addInvalidatingGetterSetter( Arc, 'radius' ) would add:
   * - segment.getRadius()
   * - segment.setRadius( value )
   * - segment.radius // getter and setter
   *
   * It assumes the following is the internal name: '_' + name
   *
   * @param {Function} type - Should be the constructor of the type. We will modify its prototype
   * @param {string} name - Name of the attribute
   */
  Segment.addInvalidatingGetterSetter = function( type, name ) {
    var internalName = '_' + name;
    var capitalizedName = name.charAt( 0 ).toUpperCase() + name.slice( 1 );
    var getterName = 'get' + capitalizedName;
    var setterName = 'set' + capitalizedName;

    // e.g. getRadius()
    type.prototype[ getterName ] = function() {
      return this[ internalName ];
    };

    // e.g. setRadius( value )
    type.prototype[ setterName ] = function( value ) {
      if ( this[ internalName ] !== value ) {
        this[ internalName ] = value;
        this.invalidate();
      }
      return this; // allow chaining
    };

    Object.defineProperty( type.prototype, name, {
      set: type.prototype[ setterName ],
      get: type.prototype[ getterName ]
    } );
  };

  /**
   * list of { segment: ..., t: ..., closestPoint: ..., distanceSquared: ... } (since there can be duplicates), threshold is used for subdivision,
   * where it will exit if all of the segments are shorter than the threshold
   *  TODO: solve segments to determine this analytically!
   * @param {Array.<Segment>} segments
   * @param {Vector2} point
   * @param {number} threshold
   * @returns {Array.<Object>}
   */
  Segment.closestToPoint = function( segments, point, threshold ) {
    var thresholdSquared = threshold * threshold;
    var items = [];
    var bestList = [];
    var bestDistanceSquared = Number.POSITIVE_INFINITY;
    var thresholdOk = false;

    _.each( segments, function( segment ) {
      // if we have an explicit computation for this segment, use it
      if ( segment.explicitClosestToPoint ) {
        var infos = segment.explicitClosestToPoint( point );
        _.each( infos, function( info ) {
          if ( info.distanceSquared < bestDistanceSquared ) {
            bestList = [ info ];
            bestDistanceSquared = info.distanceSquared;
          }
          else if ( info.distanceSquared === bestDistanceSquared ) {
            bestList.push( info );
          }
        } );
      }
      else {
        // otherwise, we will split based on monotonicity, so we can subdivide
        // separate, so we can map the subdivided segments
        var ts = [ 0 ].concat( segment.getInteriorExtremaTs() ).concat( [ 1 ] );
        for ( var i = 0; i < ts.length - 1; i++ ) {
          var ta = ts[ i ];
          var tb = ts[ i + 1 ];
          var pa = segment.positionAt( ta );
          var pb = segment.positionAt( tb );
          var bounds = Bounds2.point( pa ).addPoint( pb );
          var minDistanceSquared = bounds.minimumDistanceToPointSquared( point );
          if ( minDistanceSquared <= bestDistanceSquared ) {
            var maxDistanceSquared = bounds.maximumDistanceToPointSquared( point );
            if ( maxDistanceSquared < bestDistanceSquared ) {
              bestDistanceSquared = maxDistanceSquared;
              bestList = []; // clear it
            }
            items.push( {
              ta: ta,
              tb: tb,
              pa: pa,
              pb: pb,
              segment: segment,
              bounds: bounds,
              min: minDistanceSquared,
              max: maxDistanceSquared
            } );
          }
        }
      }
    } );

    while ( items.length && !thresholdOk ) {
      var curItems = items;
      items = [];

      // whether all of the segments processed are shorter than the threshold
      thresholdOk = true;

      _.each( curItems, function( item ) {
        if ( item.minDistanceSquared > bestDistanceSquared ) {
          return; // drop this item
        }
        if ( thresholdOk && item.pa.distanceSquared( item.pb ) > thresholdSquared ) {
          thresholdOk = false;
        }
        var tmid = ( item.ta + item.tb ) / 2;
        var pmid = item.segment.positionAt( tmid );
        var boundsA = Bounds2.point( item.pa ).addPoint( pmid );
        var boundsB = Bounds2.point( item.pb ).addPoint( pmid );
        var minA = boundsA.minimumDistanceToPointSquared( point );
        var minB = boundsB.minimumDistanceToPointSquared( point );
        if ( minA <= bestDistanceSquared ) {
          var maxA = boundsA.maximumDistanceToPointSquared( point );
          if ( maxA < bestDistanceSquared ) {
            bestDistanceSquared = maxA;
            bestList = []; // clear it
          }
          items.push( {
            ta: item.ta,
            tb: tmid,
            pa: item.pa,
            pb: pmid,
            segment: item.segment,
            bounds: boundsA,
            min: minA,
            max: maxA
          } );
        }
        if ( minB <= bestDistanceSquared ) {
          var maxB = boundsB.maximumDistanceToPointSquared( point );
          if ( maxB < bestDistanceSquared ) {
            bestDistanceSquared = maxB;
            bestList = []; // clear it
          }
          items.push( {
            ta: tmid,
            tb: item.tb,
            pa: pmid,
            pb: item.pb,
            segment: item.segment,
            bounds: boundsB,
            min: minB,
            max: maxB
          } );
        }
      } );
    }

    // if there are any closest regions, they are within the threshold, so we will add them all
    _.each( items, function( item ) {
      var t = ( item.ta + item.tb ) / 2;
      var closestPoint = item.segment.positionAt( t );
      bestList.push( {
        segment: item.segment,
        t: t,
        closestPoint: closestPoint,
        distanceSquared: point.distanceSquared( closestPoint )
      } );
    } );

    return bestList;
  };

  return Segment;
} );
<commit_msg>Use var self = this; see https://github.com/phetsims/scenery/issues/563<commit_after>// Copyright 2013-2015, University of Colorado Boulder

/**
 * A segment represents a specific curve with a start and end.
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */

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

  var kite = require( 'KITE/kite' );

  var inherit = require( 'PHET_CORE/inherit' );
  var Events = require( 'AXON/Events' );
  var DotUtil = require( 'DOT/Util' ); // eslint-disable-line require-statement-match
  var Bounds2 = require( 'DOT/Bounds2' );

  /**
   * Will contain (for segments):
   * properties (backed by ES5 getters, created usually lazily):
   * start        - start point of this segment
   * end          - end point of this segment
   * startTangent - the tangent vector (normalized) to the segment at the start, pointing in the direction of motion (from start to end)
   * endTangent   - the tangent vector (normalized) to the segment at the end, pointing in the direction of motion (from start to end)
   * bounds       - the bounding box for the segment
   *
   * methods:
   * positionAt( t )          - returns the position parametrically, with 0 <= t <= 1. this does NOT guarantee a constant magnitude tangent... don't feel like adding elliptical functions yet!
   * tangentAt( t )           - returns the non-normalized tangent (dx/dt, dy/dt) parametrically, with 0 <= t <= 1.
   * curvatureAt( t )         - returns the signed curvature (positive for visual clockwise - mathematical counterclockwise)
   * subdivided( t )          - returns an array with 2 sub-segments, split at the parametric t value.
   * getSVGPathFragment()     - returns a string containing the SVG path. assumes that the start point is already provided, so anything that calls this needs to put the M calls first
   * strokeLeft( lineWidth )  - returns an array of segments that will draw an offset curve on the logical left side
   * strokeRight( lineWidth ) - returns an array of segments that will draw an offset curve on the logical right side
   * windingIntersection      - returns the winding number for intersection with a ray
   * getInteriorExtremaTs     - returns a list of t values where dx/dt or dy/dt is 0 where 0 < t < 1. subdividing on these will result in monotonic segments
   *
   * writeToContext( context ) - draws the segment to the 2D Canvas context, assuming the context's current location is already at the start point
   * transformed( matrix )     - returns a new segment that represents this segment after transformation by the matrix
   *
   * @constructor
   */
  function Segment() {
    Events.call( this );
  }

  kite.register( 'Segment', Segment );

  /**
   * Returns itself
   * @param {Vector2} x
   * @returns {Vector2}
   */
  var identityFunction = function identityFunction( x ) { return x; };

  inherit( Events, Segment, {
    /**
     * Will return true if the start/end tangents are purely vertical or horizontal. If all of the segments of a shape
     * have this property, then the only line joins will be a multiple of pi/2 (90 degrees), and so all of the types of
     * line joins will have the same bounds. This means that the stroked bounds will just be a pure dilation of the
     * regular bounds, by lineWidth / 2.
     * @public
     *
     * @returns {boolean}
     */
    areStrokedBoundsDilated: function() {
      var epsilon = 0.0000001;

      // If the derivative at the start/end are pointing in a cardinal direction (north/south/east/west), then the
      // endpoints won't trigger non-dilated bounds, and the interior of the curve will not contribute.
      return Math.abs( this.startTangent.x * this.startTangent.y ) < epsilon && Math.abs( this.endTangent.x * this.endTangent.y ) < epsilon;
    },

    /**
     *  // TODO: override everywhere so this isn't necessary (it's not particularly efficient!)
     * @param {Matrix3} matrix
     * @returns {Bounds2}
     */
    getBoundsWithTransform: function( matrix ) {
      var transformedSegment = this.transformed( matrix );
      return transformedSegment.getBounds();
    },

    /**
     *
     * @param {Array.<number>} tList - list of sorted t values from 0 <= t <= 1
     * @returns {Array}
     */
    subdivisions: function( tList ) {
      // this could be solved by recursion, but we don't plan on the JS engine doing tail-call optimization
      var right = this; // eslint-disable-line consistent-this
      var result = [];
      for ( var i = 0; i < tList.length; i++ ) {
        // assume binary subdivision
        var t = tList[ i ];
        var arr = right.subdivided( t );
        assert && assert( arr.length === 2 );
        result.push( arr[ 0 ] );
        right = arr[ 1 ];

        // scale up the remaining t values
        for ( var j = i + 1; j < tList.length; j++ ) {
          tList[ j ] = DotUtil.linear( t, 1, 0, 1, tList[ j ] );
        }
      }
      result.push( right );
      return result;
    },

    // return an array of segments from breaking this segment into monotone pieces
    subdividedIntoMonotone: function() {
      return this.subdivisions( this.getInteriorExtremaTs() );
    },

    /**
     *
     * @param {object} [options] -           with the following options provided:
     *  - minLevels:                       how many levels to force subdivisions
     *  - maxLevels:                       prevent subdivision past this level
     *  - distanceEpsilon (optional null): controls level of subdivision by attempting to ensure a maximum (squared) deviation from the curve
     *  - curveEpsilon (optional null):    controls level of subdivision by attempting to ensure a maximum curvature change between segments
     *  - pointMap (optional):             function( Vector2 ) : Vector2, represents a (usually non-linear) transformation applied
     *  - methodName (optional):           if the method name is found on the segment, it is called with the expected signature function( options ) : Array[Segment]
     *                                     instead of using our brute-force logic
     * @param {number} [minLevels] -   how many levels to force subdivisions
     * @param {number} [maxLevels] -   prevent subdivision past this level
     * @param {Array.<Segment>} [segments]
     * @param {Vector2} [start]
     * @param {Vector2} [end]
     * @returns {Array.<Line>}
     */
    toPiecewiseLinearSegments: function( options, minLevels, maxLevels, segments, start, end ) {
      // for the first call, initialize min/max levels from our options
      minLevels = minLevels === undefined ? options.minLevels : minLevels;
      maxLevels = maxLevels === undefined ? options.maxLevels : maxLevels;
      segments = segments || [];
      var pointMap = options.pointMap || identityFunction;

      // points mapped by the (possibly-nonlinear) pointMap.
      start = start || pointMap( this.start );
      end = end || pointMap( this.end );
      var middle = pointMap( this.positionAt( 0.5 ) );

      assert && assert( minLevels <= maxLevels );
      assert && assert( options.distanceEpsilon === null || typeof options.distanceEpsilon === 'number' );
      assert && assert( options.curveEpsilon === null || typeof options.curveEpsilon === 'number' );
      assert && assert( !pointMap || typeof pointMap === 'function' );

      // i.e. we will have finished = maxLevels === 0 || ( minLevels <= 0 && epsilonConstraints ), just didn't want to one-line it
      var finished = maxLevels === 0; // bail out once we reach our maximum number of subdivision levels
      if ( !finished && minLevels <= 0 ) { // force subdivision if minLevels hasn't been reached
        // flatness criterion: A=start, B=end, C=midpoint, d0=distance from AB, d1=||B-A||, subdivide if d0/d1 > sqrt(epsilon)
        finished = ( options.curveEpsilon === null || ( DotUtil.distToSegmentSquared( middle, start, end ) / start.distanceSquared( end ) < options.curveEpsilon ) ) &&
                   // deviation criterion
                   ( options.distanceEpsilon === null || ( DotUtil.distToSegmentSquared( middle, start, end ) < options.distanceEpsilon ) );
      }

      if ( finished ) {
        segments.push( new kite.Line( start, end ) );
      }
      else {
        var subdividedSegments = this.subdivided( 0.5 );
        subdividedSegments[ 0 ].toPiecewiseLinearSegments( options, minLevels - 1, maxLevels - 1, segments, start, middle );
        subdividedSegments[ 1 ].toPiecewiseLinearSegments( options, minLevels - 1, maxLevels - 1, segments, middle, end );
      }
      return segments;
    }
  } );

  /**
   * Adds getter/setter function pairs and ES5 pairs, e.g. addInvalidatingGetterSetter( Arc, 'radius' ) would add:
   * - segment.getRadius()
   * - segment.setRadius( value )
   * - segment.radius // getter and setter
   *
   * It assumes the following is the internal name: '_' + name
   *
   * @param {Function} type - Should be the constructor of the type. We will modify its prototype
   * @param {string} name - Name of the attribute
   */
  Segment.addInvalidatingGetterSetter = function( type, name ) {
    var internalName = '_' + name;
    var capitalizedName = name.charAt( 0 ).toUpperCase() + name.slice( 1 );
    var getterName = 'get' + capitalizedName;
    var setterName = 'set' + capitalizedName;

    // e.g. getRadius()
    type.prototype[ getterName ] = function() {
      return this[ internalName ];
    };

    // e.g. setRadius( value )
    type.prototype[ setterName ] = function( value ) {
      if ( this[ internalName ] !== value ) {
        this[ internalName ] = value;
        this.invalidate();
      }
      return this; // allow chaining
    };

    Object.defineProperty( type.prototype, name, {
      set: type.prototype[ setterName ],
      get: type.prototype[ getterName ]
    } );
  };

  /**
   * list of { segment: ..., t: ..., closestPoint: ..., distanceSquared: ... } (since there can be duplicates), threshold is used for subdivision,
   * where it will exit if all of the segments are shorter than the threshold
   *  TODO: solve segments to determine this analytically!
   * @param {Array.<Segment>} segments
   * @param {Vector2} point
   * @param {number} threshold
   * @returns {Array.<Object>}
   */
  Segment.closestToPoint = function( segments, point, threshold ) {
    var thresholdSquared = threshold * threshold;
    var items = [];
    var bestList = [];
    var bestDistanceSquared = Number.POSITIVE_INFINITY;
    var thresholdOk = false;

    _.each( segments, function( segment ) {
      // if we have an explicit computation for this segment, use it
      if ( segment.explicitClosestToPoint ) {
        var infos = segment.explicitClosestToPoint( point );
        _.each( infos, function( info ) {
          if ( info.distanceSquared < bestDistanceSquared ) {
            bestList = [ info ];
            bestDistanceSquared = info.distanceSquared;
          }
          else if ( info.distanceSquared === bestDistanceSquared ) {
            bestList.push( info );
          }
        } );
      }
      else {
        // otherwise, we will split based on monotonicity, so we can subdivide
        // separate, so we can map the subdivided segments
        var ts = [ 0 ].concat( segment.getInteriorExtremaTs() ).concat( [ 1 ] );
        for ( var i = 0; i < ts.length - 1; i++ ) {
          var ta = ts[ i ];
          var tb = ts[ i + 1 ];
          var pa = segment.positionAt( ta );
          var pb = segment.positionAt( tb );
          var bounds = Bounds2.point( pa ).addPoint( pb );
          var minDistanceSquared = bounds.minimumDistanceToPointSquared( point );
          if ( minDistanceSquared <= bestDistanceSquared ) {
            var maxDistanceSquared = bounds.maximumDistanceToPointSquared( point );
            if ( maxDistanceSquared < bestDistanceSquared ) {
              bestDistanceSquared = maxDistanceSquared;
              bestList = []; // clear it
            }
            items.push( {
              ta: ta,
              tb: tb,
              pa: pa,
              pb: pb,
              segment: segment,
              bounds: bounds,
              min: minDistanceSquared,
              max: maxDistanceSquared
            } );
          }
        }
      }
    } );

    while ( items.length && !thresholdOk ) {
      var curItems = items;
      items = [];

      // whether all of the segments processed are shorter than the threshold
      thresholdOk = true;

      _.each( curItems, function( item ) {
        if ( item.minDistanceSquared > bestDistanceSquared ) {
          return; // drop this item
        }
        if ( thresholdOk && item.pa.distanceSquared( item.pb ) > thresholdSquared ) {
          thresholdOk = false;
        }
        var tmid = ( item.ta + item.tb ) / 2;
        var pmid = item.segment.positionAt( tmid );
        var boundsA = Bounds2.point( item.pa ).addPoint( pmid );
        var boundsB = Bounds2.point( item.pb ).addPoint( pmid );
        var minA = boundsA.minimumDistanceToPointSquared( point );
        var minB = boundsB.minimumDistanceToPointSquared( point );
        if ( minA <= bestDistanceSquared ) {
          var maxA = boundsA.maximumDistanceToPointSquared( point );
          if ( maxA < bestDistanceSquared ) {
            bestDistanceSquared = maxA;
            bestList = []; // clear it
          }
          items.push( {
            ta: item.ta,
            tb: tmid,
            pa: item.pa,
            pb: pmid,
            segment: item.segment,
            bounds: boundsA,
            min: minA,
            max: maxA
          } );
        }
        if ( minB <= bestDistanceSquared ) {
          var maxB = boundsB.maximumDistanceToPointSquared( point );
          if ( maxB < bestDistanceSquared ) {
            bestDistanceSquared = maxB;
            bestList = []; // clear it
          }
          items.push( {
            ta: tmid,
            tb: item.tb,
            pa: pmid,
            pb: item.pb,
            segment: item.segment,
            bounds: boundsB,
            min: minB,
            max: maxB
          } );
        }
      } );
    }

    // if there are any closest regions, they are within the threshold, so we will add them all
    _.each( items, function( item ) {
      var t = ( item.ta + item.tb ) / 2;
      var closestPoint = item.segment.positionAt( t );
      bestList.push( {
        segment: item.segment,
        t: t,
        closestPoint: closestPoint,
        distanceSquared: point.distanceSquared( closestPoint )
      } );
    } );

    return bestList;
  };

  return Segment;
} );
<|endoftext|>


<commit_before>define(['js/core/EventDispatcher','js/lib/parser','js/core/Binding', 'underscore'], function(EventDispatcher,Parser, Binding, _){

    function findTransformFunction(path, scope) {
        var pathElement = path[0];
        if (pathElement.type == Binding.TYPE_FNC) {
            scope = scope.getScopeForFncName(pathElement.name);
        } else {
            scope = scope.getScopeForKey(pathElement.name);
        }

        var nScope = scope;
        while (nScope && path.length > 0) {
            pathElement = path.shift();
            if (pathElement.type == Binding.TYPE_FNC) {
                return nScope[pathElement.name];
            } else if (pathElement.type == Binding.TYPE_VAR) {
                nScope = nScope.get(pathElement.name);
            }
        }

        return false;
    }

    var bindingCache = {},
        idCounter = 0,
        cacheCounter = 0;

    function pathToString(path){
        if(path instanceof Array){
            var el = [];
            for(var i = 0; i < path.length; i++){
                if(path[i].type === Binding.TYPE_VAR){
                    el.push(path[i].name);
                } else if(path[i].type === Binding.TYPE_FNC){
                    el.push(path[i].name + "(" + (idCounter++) + ")");
                }
            }

            return el.join(".");
        } else {
            return path;
        }
    }

    return EventDispatcher.inherit('js.core.BindingCreator',{

        /***
         *
         * @param bindingDef
         * @param targetScope
         * @param {String|Function} attrKey key where to bind, or callback function
         * @param context
         * @return {*}
         */
        create: function(bindingDef, targetScope, attrKey, context){
            var path = bindingDef.path;
            var pathElement = path[0];

            var scope;
            var searchScope = targetScope;
            if (pathElement.type != Binding.TYPE_FNC && attrKey == pathElement.name) {
                searchScope = searchScope.$parentScope;
            }

            if (pathElement.type == Binding.TYPE_FNC) {
                scope = searchScope.getScopeForFncName(pathElement.name);
            } else {
                scope = searchScope.getScopeForKey(pathElement.name);
            }

            if(scope){
                if (bindingDef.type !== "static") {
                    var cb;
                    if (_.isFunction(attrKey)) {
                        cb = attrKey;
                    }

                    var twoWay = (bindingDef.type == Binding.TYPE_TWOWAY),
                        cacheId;

                    if(!cb && !twoWay){
                        cacheId = pathToString(bindingDef.path) + scope.$cid;
                        if(bindingCache[cacheId]){
                            console.log(cacheCounter++);
                            bindingCache[cacheId].addTarget(targetScope,attrKey);
                            return bindingCache[cacheId];
                        }
                    }

                    var options = {
                        scope: scope,
                        path: path,
                        parent: bindingDef.parent,
                        target: targetScope,
                        twoWay: twoWay,
                        context: context,
                        bindingCreator: this
                    };

                    if (twoWay) {
                        if (bindingDef.transform) {
                            var transformFnc = findTransformFunction(bindingDef.transform, searchScope);
                            if (transformFnc) {
                                options.transform = transformFnc;
                            }
                        }

                        if (bindingDef.transformBack) {
                            var transformBackFnc = findTransformFunction(bindingDef.transformBack, searchScope);
                            if (transformBackFnc) {
                                options.transformBack = transformBackFnc;
                            }
                        }
                    }

                    if (cb) {
                        options['callback'] = cb;
                    } else {
                        options['targetKey'] = attrKey;
                    }

                    var binding = new Binding(options);
                    if(!twoWay && !(cb)){
                        binding.bind('destroy', function(){
                            delete bindingCache[cacheId];
                        });
                        bindingCache[cacheId] = binding
                    }

                    return binding;

                } else {
                    return scope.get(bindingDef.path);
                }
            }else{
                throw new Error("Couldn't find scope for " + pathElement.name);
            }

        },

        /***
         *
         * @param text
         * @param scope
         * @param attrKey
         * @param [bindingDefinitions]
         * @return {*}
         */
        evaluate: function (text, scope, attrKey, bindingDefinitions) {
            if (!_.isString(text)) {
                return text;
            }

            bindingDefinitions = bindingDefinitions || this.parse(text);

            var binding,
                bindings = [];

            for (var i = 0; i < bindingDefinitions.length; i++) {
                var bindingDef = bindingDefinitions[i];
                if (bindingDef.length) {
                    bindingDefinitions[i] = bindingDef;
                } else {
                    try {
                        binding = this.create(bindingDef, scope, attrKey, bindingDefinitions);
                    } catch (e) {
                        throw new Error("Create binding for '" + text + "'. " + e.message);
                    }

                    if (binding instanceof Binding) {
                        bindings.push(binding);
                        scope.$bindings[attrKey] = scope.$bindings[attrKey] || [];
                        scope.$bindings[attrKey].push(binding);
                    }
                    bindingDefinitions[i] = binding;
                }

            }

            if (bindings.length > 0) {
                return bindings[0].getContextValue();
            } else if (bindingDefinitions.length > 0) {
                if (bindingDefinitions.length === 1) {
                    return bindingDefinitions[0];
                }
                return Binding.contextToString(bindingDefinitions);
            } else {
                return text;
            }

        },

        parse: function(text) {
            if (_.isString(text)) {
                return Parser.parse(text, "text");
            }
        },

        parsePath: function(text){
            return Parser.parse(text, "path");
        },
        containsBindingDefinition: function(bindingDefinitions) {

            if (bindingDefinitions) {
                for (var i = 0; i < bindingDefinitions.length; i++) {
                    if (bindingDefinitions[i] instanceof Object) {
                        return true;
                    }
                }
            }

            return false;
        }
    });

});<commit_msg>removed console.log<commit_after>define(['js/core/EventDispatcher','js/lib/parser','js/core/Binding', 'underscore'], function(EventDispatcher,Parser, Binding, _){

    function findTransformFunction(path, scope) {
        var pathElement = path[0];
        if (pathElement.type == Binding.TYPE_FNC) {
            scope = scope.getScopeForFncName(pathElement.name);
        } else {
            scope = scope.getScopeForKey(pathElement.name);
        }

        var nScope = scope;
        while (nScope && path.length > 0) {
            pathElement = path.shift();
            if (pathElement.type == Binding.TYPE_FNC) {
                return nScope[pathElement.name];
            } else if (pathElement.type == Binding.TYPE_VAR) {
                nScope = nScope.get(pathElement.name);
            }
        }

        return false;
    }

    var bindingCache = {},
        idCounter = 0,
        cacheCounter = 0;

    function pathToString(path){
        if(path instanceof Array){
            var el = [];
            for(var i = 0; i < path.length; i++){
                if(path[i].type === Binding.TYPE_VAR){
                    el.push(path[i].name);
                } else if(path[i].type === Binding.TYPE_FNC){
                    el.push(path[i].name + "(" + (idCounter++) + ")");
                }
            }

            return el.join(".");
        } else {
            return path;
        }
    }

    return EventDispatcher.inherit('js.core.BindingCreator',{

        /***
         *
         * @param bindingDef
         * @param targetScope
         * @param {String|Function} attrKey key where to bind, or callback function
         * @param context
         * @return {*}
         */
        create: function(bindingDef, targetScope, attrKey, context){
            var path = bindingDef.path;
            var pathElement = path[0];

            var scope;
            var searchScope = targetScope;
            if (pathElement.type != Binding.TYPE_FNC && attrKey == pathElement.name) {
                searchScope = searchScope.$parentScope;
            }

            if (pathElement.type == Binding.TYPE_FNC) {
                scope = searchScope.getScopeForFncName(pathElement.name);
            } else {
                scope = searchScope.getScopeForKey(pathElement.name);
            }

            if(scope){
                if (bindingDef.type !== "static") {
                    var cb;
                    if (_.isFunction(attrKey)) {
                        cb = attrKey;
                    }

                    var twoWay = (bindingDef.type == Binding.TYPE_TWOWAY),
                        cacheId;

                    if(!cb && !twoWay){
                        cacheId = pathToString(bindingDef.path) + scope.$cid;
                        if(bindingCache[cacheId]){
                            bindingCache[cacheId].addTarget(targetScope,attrKey);
                            return bindingCache[cacheId];
                        }
                    }

                    var options = {
                        scope: scope,
                        path: path,
                        parent: bindingDef.parent,
                        target: targetScope,
                        twoWay: twoWay,
                        context: context,
                        bindingCreator: this
                    };

                    if (twoWay) {
                        if (bindingDef.transform) {
                            var transformFnc = findTransformFunction(bindingDef.transform, searchScope);
                            if (transformFnc) {
                                options.transform = transformFnc;
                            }
                        }

                        if (bindingDef.transformBack) {
                            var transformBackFnc = findTransformFunction(bindingDef.transformBack, searchScope);
                            if (transformBackFnc) {
                                options.transformBack = transformBackFnc;
                            }
                        }
                    }

                    if (cb) {
                        options['callback'] = cb;
                    } else {
                        options['targetKey'] = attrKey;
                    }

                    var binding = new Binding(options);
                    if(!twoWay && !(cb)){
                        binding.bind('destroy', function(){
                            delete bindingCache[cacheId];
                        });
                        bindingCache[cacheId] = binding
                    }

                    return binding;

                } else {
                    return scope.get(bindingDef.path);
                }
            }else{
                throw new Error("Couldn't find scope for " + pathElement.name);
            }

        },

        /***
         *
         * @param text
         * @param scope
         * @param attrKey
         * @param [bindingDefinitions]
         * @return {*}
         */
        evaluate: function (text, scope, attrKey, bindingDefinitions) {
            if (!_.isString(text)) {
                return text;
            }

            bindingDefinitions = bindingDefinitions || this.parse(text);

            var binding,
                bindings = [];

            for (var i = 0; i < bindingDefinitions.length; i++) {
                var bindingDef = bindingDefinitions[i];
                if (bindingDef.length) {
                    bindingDefinitions[i] = bindingDef;
                } else {
                    try {
                        binding = this.create(bindingDef, scope, attrKey, bindingDefinitions);
                    } catch (e) {
                        throw new Error("Create binding for '" + text + "'. " + e.message);
                    }

                    if (binding instanceof Binding) {
                        bindings.push(binding);
                        scope.$bindings[attrKey] = scope.$bindings[attrKey] || [];
                        scope.$bindings[attrKey].push(binding);
                    }
                    bindingDefinitions[i] = binding;
                }

            }

            if (bindings.length > 0) {
                return bindings[0].getContextValue();
            } else if (bindingDefinitions.length > 0) {
                if (bindingDefinitions.length === 1) {
                    return bindingDefinitions[0];
                }
                return Binding.contextToString(bindingDefinitions);
            } else {
                return text;
            }

        },

        parse: function(text) {
            if (_.isString(text)) {
                return Parser.parse(text, "text");
            }
        },

        parsePath: function(text){
            return Parser.parse(text, "path");
        },
        containsBindingDefinition: function(bindingDefinitions) {

            if (bindingDefinitions) {
                for (var i = 0; i < bindingDefinitions.length; i++) {
                    if (bindingDefinitions[i] instanceof Object) {
                        return true;
                    }
                }
            }

            return false;
        }
    });

});<|endoftext|>


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

	var CoapClient = require('./CoapClient');
    CoapClient.command();
})();
<commit_msg>Locale data added to calender.js<commit_after>(function(){
	'use strict';

	function showComponents(locale){
		console.log("\n");
		Object.keys(locale).map(function(key){
			console.log(key + " : " + locale[key]);
			if (key === "RightNow"){
				console.log("----------------------------------");
			}
		});
		console.log("-------------------------------------\n");
	}

	var moment = require('moment');

	function getLocaleData(){
		var now = moment();

		var locale = {
			RightNow: now.format('llll'),
			year: now.year(),
			month: now.month(),
			day: now.day(),
			hour: now.hour(),
			minute: now.minute(),
			second: now.second()
		};
		return locale;
	}

	setInterval(function(){
		showComponents(getLocaleData());
	}, 1000);

	//var CoapClient = require('./CoapClient');
    //CoapClient.command();
})();
<|endoftext|>


<commit_before>angular.module('rapidchat')
.factory('Keyring', function($log, db, $q) {

  function KeyRing(prefix) {

    if(typeof openpgp === 'undefined')
      throw new TypeError("Openpgp is not loaded")

    if(typeof Dexie === 'undefined')
      throw new TypeError("Dexie is not loaded")

    prefix = prefix || 'openpgp-'
  }

  //@todo pub keys / users from a channel
  KeyRing.prototype.getPublicKeysFromChannel = function(channel) {
    var ids = []
    var defer = $q.defer()

    db.channelKeys.where('channel').anyOf(channel)
    .each(function(uk) {
      ids.push(uk.keyId)
    })
    .then(function() {
      return db.publicKeys.where(':id').anyOf(ids).toArray()
    })
    .then(function(jsonKeys) {
      var keys = []

      for(var i in jsonKeys) {
        keys.push(openpgp.key.readArmored(jsonKeys[i].key).keys[0])
      }

      defer.resolve(keys)
    })
    .catch(function(error) {
      return defer.reject(error)
    })

    return defer.promise
  }

  KeyRing.prototype.getKeysById = function(keyId) {
    var keys = {public: null, private: null}
    var defer = $q.defer()

    db.publicKeys.where(':id').equals(keyId).first()
    .then(function(publicKey) {
      keys.public = openpgp.key.readArmored(publicKey.key).keys[0]

      return db.privateKeys.where(':id').equals(keyId).first()
    })
    .then(function(privateKey) {
      keys.private = openpgp.key.readArmored(privateKey.key).keys[0]

      return defer.resolve(keys)
    })
    .catch(function(error) {
      return defer.reject(error)
    })

    return defer.promise
  }

  KeyRing.prototype.store = function(type) {
    var self = this

    if(!~['public', 'private'].indexOf(type))
      throw new TypeError("Type can be one of public, private")

    return function(key, userId) {
      var keyId = key.primaryKey.getKeyId().toHex()
      return db[type+'Keys'].add({
        key: key.armor(),
        dateAdded: Date.now(),
        id: keyId
      }).then(function() {
        return db.userKeys.add({keyId: keyId, userId: userId})
      })
    }
  }

  KeyRing.prototype.storeChannel = function(channel) {
    var self = this

    return function(key) {
      var keyId = key.primaryKey.getKeyId().toHex()
      return db.publicKeys.add({
        key: key.armor(),
        dateAdded: Date.now(),
        id: keyId
      }).then(function() {
        return db.channelKeys.add({keyId: keyId, channel: channel})
      })
    }
  }

  return new KeyRing()
})
<commit_msg>fix(Keyring): Reject if no public keys to send to<commit_after>angular.module('rapidchat')
.factory('Keyring', function($log, db, $q) {

  function KeyRing(prefix) {

    if(typeof openpgp === 'undefined')
      throw new TypeError("Openpgp is not loaded")

    if(typeof Dexie === 'undefined')
      throw new TypeError("Dexie is not loaded")

    prefix = prefix || 'openpgp-'
  }

  //@todo pub keys / users from a channel
  KeyRing.prototype.getPublicKeysFromChannel = function(channel) {
    var ids = []
    var defer = $q.defer()

    db.channelKeys.where('channel').anyOf(channel)
    .each(function(uk) {
      ids.push(uk.keyId)
    })
    .then(function() {
      if(!ids || ids.length === 0)
        return defer.reject('No public keys for channel ' + channel)

      return db.publicKeys.where(':id').anyOf(ids).toArray()
    })
    .then(function(jsonKeys) {
      var keys = []

      for(var i in jsonKeys) {
        keys.push(openpgp.key.readArmored(jsonKeys[i].key).keys[0])
      }

      defer.resolve(keys)
    })
    .catch(function(error) {
      return defer.reject(error)
    })

    return defer.promise
  }

  KeyRing.prototype.getKeysById = function(keyId) {
    var keys = {public: null, private: null}
    var defer = $q.defer()

    db.publicKeys.where(':id').equals(keyId).first()
    .then(function(publicKey) {
      keys.public = openpgp.key.readArmored(publicKey.key).keys[0]

      return db.privateKeys.where(':id').equals(keyId).first()
    })
    .then(function(privateKey) {
      keys.private = openpgp.key.readArmored(privateKey.key).keys[0]

      return defer.resolve(keys)
    })
    .catch(function(error) {
      return defer.reject(error)
    })

    return defer.promise
  }

  KeyRing.prototype.store = function(type) {
    var self = this

    if(!~['public', 'private'].indexOf(type))
      throw new TypeError("Type can be one of public, private")

    return function(key, userId) {
      var keyId = key.primaryKey.getKeyId().toHex()
      return db[type+'Keys'].add({
        key: key.armor(),
        dateAdded: Date.now(),
        id: keyId
      }).then(function() {
        return db.userKeys.add({keyId: keyId, userId: userId})
      })
    }
  }

  KeyRing.prototype.storeChannel = function(channel) {
    var self = this

    return function(key) {
      var keyId = key.primaryKey.getKeyId().toHex()
      return db.publicKeys.add({
        key: key.armor(),
        dateAdded: Date.now(),
        id: keyId
      }).then(function() {
        return db.channelKeys.add({keyId: keyId, channel: channel})
      })
    }
  }

  return new KeyRing()
})
<|endoftext|>