<commit_before>// add new event shortcuts
$.each( "touchstart touchmove touchend orientationchange tap taphold swipe swipeleft swiperight scrollstart scrollstop".split( " " ), function( i, name ) {
	$.fn[ name ] = function( fn ) {
		return fn ? this.bind( name, fn ) : this.trigger( name );
	};
	$.attrFn[ name ] = true;
});

var supportTouch = $.support.touch,
	scrollEvent = supportTouch ? "touchmove" : "scroll",
	touchStartEvent = supportTouch ? "touchstart" : "mousedown",
	touchStopEvent = supportTouch ? "touchend" : "mouseup",
	touchMoveEvent = supportTouch ? "touchmove" : "mousemove";

// also handles scrollstop
$.event.special.scrollstart = {
	enabled: true,

	setup: function() {
		var thisObject = this,
			$this = $( thisObject ),
			scrolling,
			timer;

		function trigger( event, state ) {
			scrolling = state;
			var originalType = event.type;
			event.type = scrolling ? "scrollstart" : "scrollstop";
			$.event.handle.call( thisObject, event );
			event.type = originalType;
		}

		// iPhone triggers scroll after a small delay; use touchmove instead
		$this.bind( scrollEvent, function( event ) {
			if ( !$.event.special.scrollstart.enabled ) {
				return;
			}

			if ( !scrolling ) {
				trigger( event, true );
			}

			clearTimeout( timer );
			timer = setTimeout(function() {
				trigger( event, false );
			}, 50 );
		});
	}
};

// also handles taphold
$.event.special.tap = {
	setup: function() {
		var thisObject = this,
			$this = $( thisObject ),
			originalType,
			touching,
			held,
			moved,
			timer;

		$this
			.bind( touchStartEvent, function( event ) {
				held = false;
				moved = false;
				touching = true;

				timer = setTimeout(function() {
					if ( touching && !moved ) {
						held = true;
						originalType = event.type;
						event.type = "taphold";
						$.event.handle.call( thisObject, event );
						event.type = originalType;
					}
				}, 300 );

			})
			.bind( touchMoveEvent, function() {
				moved = true;
			})
			.bind( touchStopEvent, function( event ) {
				clearTimeout( timer );
				touching = false;

				if ( !held && !moved ) {
					originalType = event.type;
					event.type = "tap";
					$.event.handle.call( thisObject, event );
					event.type = originalType;
				}
			});
	}
};

// also handles swipeleft, swiperight
$.event.special.swipe = {
	setup: function() {
		var thisObject = this,
			$this = $( thisObject ),
			start,
			stop;

		$this
			.bind( touchStartEvent, function( event ) {
				var data = event.originalEvent.touches ?
						event.originalEvent.touches[ 0 ] :
						event;
				start = {
					time: (new Date).getTime(),
					coords: [ data.pageX, data.pageY ],
					origin: $( event.target )
				};
			})
			.bind( touchMoveEvent, function( event ) {
				if ( !start ) {
					return;
				}

				var data = event.originalEvent.touches ?
						event.originalEvent.touches[ 0 ] :
						event;
				stop = {
					time: (new Date).getTime(),
					coords: [ data.pageX, data.pageY ]
				};

				// prevent scrolling
				if ( Math.abs( start.coords[0] - stop.coords[0] ) > 10 ) {
					event.preventDefault();
				}
			})
			.bind( touchStopEvent, function( event ) {
				if ( start && stop ) {
					if ( stop.time - start.time < 1000 &&
							Math.abs( start.coords[0] - stop.coords[0]) > 180 &&
							Math.abs( start.coords[1] - stop.coords[1]) < 80 ) {
						start.origin
							.trigger( "swipe" )
							.trigger( start.coords[0] > stop.coords[0] ? "swipeleft" : "swiperight" );
					}
				}
				start = stop = undefined;
			});
	}
};

$.event.special.orientationchange = {
	orientation: function( elem ) {
		return elem.width() / elem.height() < 1.1 ? "portrait" : "landscape";
	},

	setup: function() {
		var thisObject = this,
			$this = $( thisObject ),
			orientation = $.event.special.orientationchange.orientation( $this );

		function handler() {
			var newOrientation = $.event.special.orientationchange.orientation( $this );

			if ( orientation !== newOrientation ) {
				$.event.handle.call( thisObject, "orientationchange", {
					orientation: newOrientation
				} );
				orientation = newOrientation;
			}
		}

		if ( $.support.orientation ) {
			thisObject.addEventListener( "orientationchange", handler, false );
		} else {
			$this.bind( "resize", handler );
		}
	}
};

$.each({
	scrollstop: "scrollstart",
	taphold: "tap",
	swipeleft: "swipe",
	swiperight: "swipe"
}, function( event, sourceEvent ) {
	$.event.special[ event ] = {
		setup: function() {
			$( this ).bind( sourceEvent, $.noop );
		}
	};
});
<commit_msg>Only listen to mousemove/touchmove and mouseup/touchend events after mousedown/touchstart is triggered. Improves performance by not listening to all move events.<commit_after>// add new event shortcuts
$.each( "touchstart touchmove touchend orientationchange tap taphold swipe swipeleft swiperight scrollstart scrollstop".split( " " ), function( i, name ) {
	$.fn[ name ] = function( fn ) {
		return fn ? this.bind( name, fn ) : this.trigger( name );
	};
	$.attrFn[ name ] = true;
});

var supportTouch = $.support.touch,
	scrollEvent = supportTouch ? "touchmove" : "scroll",
	touchStartEvent = supportTouch ? "touchstart" : "mousedown",
	touchStopEvent = supportTouch ? "touchend" : "mouseup",
	touchMoveEvent = supportTouch ? "touchmove" : "mousemove";

// also handles scrollstop
$.event.special.scrollstart = {
	enabled: true,

	setup: function() {
		var thisObject = this,
			$this = $( thisObject ),
			scrolling,
			timer;

		function trigger( event, state ) {
			scrolling = state;
			var originalType = event.type;
			event.type = scrolling ? "scrollstart" : "scrollstop";
			$.event.handle.call( thisObject, event );
			event.type = originalType;
		}

		// iPhone triggers scroll after a small delay; use touchmove instead
		$this.bind( scrollEvent, function( event ) {
			if ( !$.event.special.scrollstart.enabled ) {
				return;
			}

			if ( !scrolling ) {
				trigger( event, true );
			}

			clearTimeout( timer );
			timer = setTimeout(function() {
				trigger( event, false );
			}, 50 );
		});
	}
};

// also handles taphold
$.event.special.tap = {
	setup: function() {
		var thisObject = this,
			$this = $( thisObject );

		$this
			.bind( touchStartEvent, function( event ) {
				var held = false,
					moved = false,
					touching = true,
					originalType,
					timer;

				function moveHandler() {
					moved = true;
				}

				timer = setTimeout(function() {
					if ( touching && !moved ) {
						held = true;
						originalType = event.type;
						event.type = "taphold";
						$.event.handle.call( thisObject, event );
						event.type = originalType;
					}
				}, 300 );

				$this
					.one( touchMoveEvent, moveHandler)
					.one( touchStopEvent, function( event ) {
						$this.unbind( touchMoveEvent, moveHandler );
						clearTimeout( timer );
						touching = false;

						if ( !held && !moved ) {
							originalType = event.type;
							event.type = "tap";
							$.event.handle.call( thisObject, event );
							event.type = originalType;
						}
					});
			});
	}
};

// also handles swipeleft, swiperight
$.event.special.swipe = {
	setup: function() {
		var thisObject = this,
			$this = $( thisObject );

		$this
			.bind( touchStartEvent, function( event ) {
				var data = event.originalEvent.touches ?
						event.originalEvent.touches[ 0 ] :
						event,
					start = {
						time: (new Date).getTime(),
						coords: [ data.pageX, data.pageY ],
						origin: $( event.target )
					},
					stop;

				function moveHandler( event ) {
					if ( !start ) {
						return;
					}

					var data = event.originalEvent.touches ?
							event.originalEvent.touches[ 0 ] :
							event;
					stop = {
							time: (new Date).getTime(),
							coords: [ data.pageX, data.pageY ]
					};

					// prevent scrolling
					if ( Math.abs( start.coords[0] - stop.coords[0] ) > 10 ) {
						event.preventDefault();
					}
				}

				$this
					.bind( touchMoveEvent, moveHandler )
					.one( touchStopEvent, function( event ) {
						$this.unbind( touchMoveEvent, moveHandler );
						if ( start && stop ) {
							if ( stop.time - start.time < 1000 &&
									Math.abs( start.coords[0] - stop.coords[0]) > 180 &&
									Math.abs( start.coords[1] - stop.coords[1]) < 80 ) {
								start.origin
								.trigger( "swipe" )
								.trigger( start.coords[0] > stop.coords[0] ? "swipeleft" : "swiperight" );
							}
						}
						start = stop = undefined;
					});
			});
	}
};

$.event.special.orientationchange = {
	orientation: function( elem ) {
		return elem.width() / elem.height() < 1.1 ? "portrait" : "landscape";
	},

	setup: function() {
		var thisObject = this,
			$this = $( thisObject ),
			orientation = $.event.special.orientationchange.orientation( $this );

		function handler() {
			var newOrientation = $.event.special.orientationchange.orientation( $this );

			if ( orientation !== newOrientation ) {
				$.event.handle.call( thisObject, "orientationchange", {
					orientation: newOrientation
				} );
				orientation = newOrientation;
			}
		}

		if ( $.support.orientation ) {
			thisObject.addEventListener( "orientationchange", handler, false );
		} else {
			$this.bind( "resize", handler );
		}
	}
};

$.each({
	scrollstop: "scrollstart",
	taphold: "tap",
	swipeleft: "swipe",
	swiperight: "swipe"
}, function( event, sourceEvent ) {
	$.event.special[ event ] = {
		setup: function() {
			$( this ).bind( sourceEvent, $.noop );
		}
	};
});
<|endoftext|>


<commit_before>/***********************************************
Jquery Live Preview Plugin:: Created by Alan Phoon (http://www.ampedupdesigns.com)
This notice MUST stay intact for legal use.
***********************************************/
(function($) {
  $.fn.extend({
     livePreview: function(options){

         var defaults = {
             targetWidth : 1000,
             targetHeight: 800,
             viewWidth: 300,
             viewHeight: 200
         }
         var options = $.extend(defaults, options);
         //calculate appropriate scaling based on width.
         var scale_w = (options.viewWidth / options.targetWidth);
         var scale_h = (options.viewHeight / options.targetHeight);
         var scale_f = 1;
         if(typeof options.scale != 'undefined')
             scale_f = options.scale;
         else
         {
             if(scale_w > scale_h)
                 scale_f = scale_w;
             else
                 scale_f = scale_h;
         }
         return this.each(function() {
            var o = options;
            var s = scale_f;
            var obj = $(this);
            var href = $(this).attr("href");
            var pos = $(this).offset();
            var width = $(this).width();
            var leftpos = pos.left + width + 50;
            var toppos = pos.top - (o.viewHeight/2);
            obj.hover(function() {
                //hover on
                $('body').append('

');
                $('#livepreview_dialog').fadeIn(100);
            },
            function() {
                //hover off
                $('#livepreview_dialog').fadeOut(100, function() {
                    $("#livepreview_dialog").remove();
                });

            });

         });
     }

  });

})(jQuery);
<commit_msg>update descript<commit_after>/***********************************************
Jquery Live Preview Plugin:: Created by Alan Phoon (http://www.ampedupdesigns.com)
This notice MUST stay intact for legal use.
***********************************************/
(function($) {
  $.fn.extend({
     livePreview: function(options){
         var defaults = {
             targetWidth : 1000,
             targetHeight: 800,
             viewWidth: 300,
             viewHeight: 200
         }
         var options = $.extend(defaults, options);
         //calculate appropriate scaling based on width.
         var scale_w = (options.viewWidth / options.targetWidth);
         var scale_h = (options.viewHeight / options.targetHeight);
         var scale_f = 1;
         if(typeof options.scale != 'undefined')
             scale_f = options.scale;
         else
         {
             if(scale_w > scale_h)
                 scale_f = scale_w;
             else
                 scale_f = scale_h;
         }
         return this.each(function() {
            var o = options;
            var s = scale_f;
            var obj = $(this);
            var href = $(this).attr("href");
            var pos = $(this).offset();
            var width = $(this).width();
            var leftpos = pos.left + width + 50;
            var toppos = pos.top - (o.viewHeight/2);
            obj.hover(function() {
                //hover on
                $('body').append('

');
                $('#livepreview_dialog').fadeIn(100);
            },
            function() {
                //hover off
                $('#livepreview_dialog').fadeOut(100, function() {
                    $("#livepreview_dialog").remove();
                });
            });
         });
     }
  });
})(jQuery);
<|endoftext|>


<commit_before>(function(  ) {
  var timePickerId = 'mat-timepicker';
  var timePickerHourId = 'mat-timepicker-hour';
  var timePickerMinuteId = 'mat-timepicker-minute';
  var timePickerHourSelectId = 'mat-timepicker-hour-select';
  var timePickerMinuteSelectId = 'mat-timepicker-minute-select';
  var currentInput = null;

  window.onload = function (  ) {
    init( );
  }

  var onSetHourClick = function( event ) {
    setHour( parseInt( event.currentTarget.getAttribute( 'hour' ) ), true );
    switchTimepickerInput( false );
  }

  var setHour = function ( hour, isSelected ) {
    var timepicker = document.getElementById( timePickerId );
    var hourEl = document.getElementById( timePickerHourId );
    hourEl.innerHTML = ( hour < 10 ? '0' : '' ) + hour;
    hourEl.className = isSelected ? 'MatTimePicker-TimeHeader-Selected' : '';
    [].slice.call( timepicker.getElementsByClassName( 'MatTimePicker-WatchHourContainer' ) ).map( function ( element ) {
      element.className = element.className.replace( ' MatTimePicker-HourSelected', '' );
      if( parseInt( element.getAttribute( 'hour' ) ) === hour ) {
        element.className += ' MatTimePicker-HourSelected';
      }
    } );
  }

  var onSetMinuteClick = function ( event ) {
    setMinute( parseInt( event.currentTarget.getAttribute( 'minute' ) ), true );
  }

  var setMinute = function ( minute, isSelected ) {
    var timepicker = document.getElementById( timePickerId );
    var minuteEl = document.getElementById( timePickerMinuteId );
    minuteEl.innerHTML = (  minute < 10 ? '0' : '' ) + minute;
    minuteEl.className = isSelected ? 'MatTimePicker-TimeHeader-Selected' : '';
    [].slice.call( timepicker.getElementsByClassName( 'MatTimePicker-WatchMinuteContainer' ) ).map( function ( element ) {
      element.className = element.className.replace( ' MatTimePicker-HourSelected', '' );
      if( parseInt( element.getAttribute( 'minute' ) ) === minute ) {
        element.className += ' MatTimePicker-HourSelected';
      }
    } );
  }

  var onCancelClick = function ( ) {
    currentInput = null;
    document.getElementById( timePickerId ).style.display = 'none';
  }

  var onOkClick = function ( ) {
    document.getElementById( timePickerId ).style.display = 'none';
    var time = document.getElementById( timePickerHourId ).innerHTML + ':' + document.getElementById( timePickerMinuteId ).innerHTML
    currentInput.value = time;
  }

  var onShowTimepickerClick = function( event ) {
    currentInput = event.currentTarget;
    var hours = minutes = 0;
    try {
      var timeValue = currentInput.getAttribute( 'value' ).split( ':' );
      hours = parseInt( timeValue[ 0 ] );
      minutes = parseInt( timeValue[ 1 ] );
    } catch ( e ) {
      hours = minutes = 0;
    }
    setHour( hours );
    setMinute( minutes );
    switchTimepickerInput( true );
    document.getElementById( timePickerId ).style.display = 'flex';
  }

  var onShowHourTimepickerClick = function ( ) {
    switchTimepickerInput( true );
  }

  var onShowMinuteTimepickerClick = function ( ) {
    switchTimepickerInput( false );
  }

  var switchTimepickerInput = function ( isHour ) {
    document.getElementById( isHour ? timePickerHourId : timePickerMinuteId ).className = 'MatTimePicker-TimeHeader-Selected';
    document.getElementById( timePickerHourSelectId ).style.display = isHour ? 'flex' : 'none';
    document.getElementById( timePickerMinuteSelectId ).style.display = isHour ? 'none' : 'flex';
  }

  var init = function( ) {
    [].slice.call( document.querySelectorAll('[type="mat-timepicker"]') ).map( function( input ) {
      input.addEventListener( 'click', onShowTimepickerClick );
    } );

    var elTimepicker = createElement( 'div', 'MatTimePicker-Clock', timePickerId );
    var elPopup = createElement( 'div', 'MatTimePicker-Popup' );
    elTimepicker.appendChild( elPopup );
    var elHeader = createElement( 'div', 'MatTimePicker-TimeHeader' );
    elPopup.appendChild( elHeader );

    var elHour = createElement( 'span', null, timePickerHourId, '00' );
    elHour.addEventListener( 'click', onShowHourTimepickerClick );
    elHeader.appendChild( elHour );
    var elColon = createElement( 'span', null, null, ':' );
    elHeader.appendChild( elColon );
    var elMinute = createElement( 'span', null, timePickerMinuteId, '00' );
    elMinute.addEventListener( 'click', onShowMinuteTimepickerClick );
    elHeader.appendChild( elMinute );
    var elWatchContainer = createElement( 'div', 'MatTimePicker-WatchContainer' );
    elPopup.appendChild( elWatchContainer );

    var elWatch = createElement( 'div', 'MatTimePicker-Watch' );
    elWatchContainer.appendChild( elWatch );
    var elHourSelect = createElement( 'div', 'MatTimePicker-WatchFace', timePickerHourSelectId );
    elWatch.appendChild( elHourSelect );
    var elMinuteSelect = createElement( 'div', 'MatTimePicker-WatchFace', timePickerMinuteSelectId );
    elMinuteSelect.style.display = 'none';
    elWatch.appendChild( elMinuteSelect );

    var elButtons = createElement( 'div', 'MatTimePicker-Buttons' );
    elWatchContainer.appendChild( elButtons );
    var elButtonCancel = createElement( 'button', 'MatTimePicker-Button', null, 'CANCEL' );
    elButtonCancel.addEventListener( 'click', onCancelClick );
    elButtons.appendChild( elButtonCancel );
    var elButtonOk = createElement( 'button', 'MatTimePicker-Button', null, 'OK' );
    elButtonOk.addEventListener( 'click', onOkClick );
    elButtons.appendChild( elButtonOk );

    initWatchHours( elHourSelect );
    initWatchMinutes( elMinuteSelect );

    document.body.insertBefore( elTimepicker, document.body.children[ 0 ] );
  }

  function initWatchHours( elWatch ) {
    for( var h = 24; h > 0; h-- ) {
      var hourContainer = createElement( 'div', 'MatTimePicker-WatchHourContainer' + ( h > 12 ? ' MatTimePicker-WatchHourPM' : '' ) );
      var rotation = ( -90 + ( 360/12 * h ) );
      hourContainer.style.transform = 'rotate(' + rotation + 'deg)';
      hourContainer.setAttribute( 'hour', h % 24 );
      hourContainer.addEventListener( 'click', onSetHourClick );
      elWatch.appendChild( hourContainer );

      var centerDot = createElement( 'div', 'MatTimePicker-WatchCenterDot' );
      hourContainer.appendChild( centerDot );
      var stick = createElement( 'div', 'MatTimePicker-WatchStick' );
      hourContainer.appendChild( stick );

      var hour = createElement( 'div', 'MatTimePicker-WatchHour' );
      hourContainer.appendChild( hour );
      var hourBg = createElement( 'div', 'MatTimePicker-WatchHourBg' );
      hour.appendChild( hourBg );
      var hourValue = createElement( 'div', 'MatTimePicker-WatchHourValue', null, h % 24 );
      hourValue.style.transform = 'rotate(' + ( rotation * -1 ) + 'deg)';
      hour.appendChild( hourValue );
    }
  }

  function initWatchMinutes( elWatch ) {
    for ( var i = 0; i < 2; i++ ) {
      for( var m = 0; m < 60; m++ ) {
        var minute = m % 60;
        if ( ( i == 0 && m % 5 !== 0 ) || ( i == 1 && m % 5 === 0 ) ) {
          var minuteContainer = createElement( 'div', 'MatTimePicker-WatchMinuteContainer' );
          var rotation = ( -90 + ( 360/60 * m ) );
          minuteContainer.style.transform = 'rotate(' + rotation + 'deg)';
          minuteContainer.setAttribute( 'minute', m );
          minuteContainer.addEventListener( 'click', onSetMinuteClick );
          elWatch.appendChild( minuteContainer );

          var centerDot = createElement( 'div', 'MatTimePicker-WatchCenterDot' );
          minuteContainer.appendChild( centerDot );
          var stick = createElement( 'div', 'MatTimePicker-WatchStick' );
          minuteContainer.appendChild( stick );

          var minute = createElement( 'div', 'MatTimePicker-WatchMinute' );
          minuteContainer.appendChild( minute );
          var minuteBg = createElement( 'div', 'MatTimePicker-WatchHourBg' );
          minute.appendChild( minuteBg );
          if ( m % 5 === 0 ) {
            var minuteValue = createElement( 'div', 'MatTimePicker-WatchHourValue', null, m );
            minuteValue.style.transform = 'rotate(' + ( rotation * -1 ) + 'deg)';
            minute.appendChild( minuteValue );
          }
        }
      }
    }
  }

  function createElement( type, className, id, innerHTML ) {
    var el = document.createElement( type );
    if ( className ) el.className = className;
    if ( id ) el.id = id;
    if ( typeof innerHTML !== 'undefined' ) el.innerHTML = innerHTML;
    return el;
  }
} )( );<commit_msg>set the default time to now<commit_after>(function(  ) {
  var timePickerId = 'mat-timepicker';
  var timePickerHourId = 'mat-timepicker-hour';
  var timePickerMinuteId = 'mat-timepicker-minute';
  var timePickerHourSelectId = 'mat-timepicker-hour-select';
  var timePickerMinuteSelectId = 'mat-timepicker-minute-select';
  var currentInput = null;

  window.onload = function (  ) {
    init( );
  }

  var onSetHourClick = function( event ) {
    setHour( parseInt( event.currentTarget.getAttribute( 'hour' ) ), true );
    switchTimepickerInput( false );
  }

  var setHour = function ( hour, isSelected ) {
    var timepicker = document.getElementById( timePickerId );
    var hourEl = document.getElementById( timePickerHourId );
    hourEl.innerHTML = ( hour < 10 ? '0' : '' ) + hour;
    hourEl.className = isSelected ? 'MatTimePicker-TimeHeader-Selected' : '';
    [].slice.call( timepicker.getElementsByClassName( 'MatTimePicker-WatchHourContainer' ) ).map( function ( element ) {
      element.className = element.className.replace( ' MatTimePicker-HourSelected', '' );
      if( parseInt( element.getAttribute( 'hour' ) ) === hour ) {
        element.className += ' MatTimePicker-HourSelected';
      }
    } );
  }

  var onSetMinuteClick = function ( event ) {
    setMinute( parseInt( event.currentTarget.getAttribute( 'minute' ) ), true );
  }

  var setMinute = function ( minute, isSelected ) {
    var timepicker = document.getElementById( timePickerId );
    var minuteEl = document.getElementById( timePickerMinuteId );
    minuteEl.innerHTML = (  minute < 10 ? '0' : '' ) + minute;
    minuteEl.className = isSelected ? 'MatTimePicker-TimeHeader-Selected' : '';
    [].slice.call( timepicker.getElementsByClassName( 'MatTimePicker-WatchMinuteContainer' ) ).map( function ( element ) {
      element.className = element.className.replace( ' MatTimePicker-HourSelected', '' );
      if( parseInt( element.getAttribute( 'minute' ) ) === minute ) {
        element.className += ' MatTimePicker-HourSelected';
      }
    } );
  }

  var onCancelClick = function ( ) {
    currentInput = null;
    document.getElementById( timePickerId ).style.display = 'none';
  }

  var onOkClick = function ( ) {
    document.getElementById( timePickerId ).style.display = 'none';
    var time = document.getElementById( timePickerHourId ).innerHTML + ':' + document.getElementById( timePickerMinuteId ).innerHTML
    currentInput.value = time;
  }

  var onShowTimepickerClick = function( event ) {
    currentInput = event.currentTarget;
    var hours = minutes = 0;
    try {
      var timeValue = currentInput.getAttribute( 'value' ).split( ':' );
      hours = parseInt( timeValue[ 0 ] );
      minutes = parseInt( timeValue[ 1 ] );
    } catch ( e ) {
      hours = new Date().getHours();
      minutes = new Date().getMinutes();
    }
    setHour( hours );
    setMinute( minutes );
    switchTimepickerInput( true );
    document.getElementById( timePickerId ).style.display = 'flex';
  }

  var onShowHourTimepickerClick = function ( ) {
    switchTimepickerInput( true );
  }

  var onShowMinuteTimepickerClick = function ( ) {
    switchTimepickerInput( false );
  }

  var switchTimepickerInput = function ( isHour ) {
    document.getElementById( isHour ? timePickerHourId : timePickerMinuteId ).className = 'MatTimePicker-TimeHeader-Selected';
    document.getElementById( timePickerHourSelectId ).style.display = isHour ? 'flex' : 'none';
    document.getElementById( timePickerMinuteSelectId ).style.display = isHour ? 'none' : 'flex';
  }

  var init = function( ) {
    [].slice.call( document.querySelectorAll('[type="mat-timepicker"]') ).map( function( input ) {
      input.addEventListener( 'click', onShowTimepickerClick );
    } );

    var elTimepicker = createElement( 'div', 'MatTimePicker-Clock', timePickerId );
    var elPopup = createElement( 'div', 'MatTimePicker-Popup' );
    elTimepicker.appendChild( elPopup );
    var elHeader = createElement( 'div', 'MatTimePicker-TimeHeader' );
    elPopup.appendChild( elHeader );

    var elHour = createElement( 'span', null, timePickerHourId, '00' );
    elHour.addEventListener( 'click', onShowHourTimepickerClick );
    elHeader.appendChild( elHour );
    var elColon = createElement( 'span', null, null, ':' );
    elHeader.appendChild( elColon );
    var elMinute = createElement( 'span', null, timePickerMinuteId, '00' );
    elMinute.addEventListener( 'click', onShowMinuteTimepickerClick );
    elHeader.appendChild( elMinute );
    var elWatchContainer = createElement( 'div', 'MatTimePicker-WatchContainer' );
    elPopup.appendChild( elWatchContainer );

    var elWatch = createElement( 'div', 'MatTimePicker-Watch' );
    elWatchContainer.appendChild( elWatch );
    var elHourSelect = createElement( 'div', 'MatTimePicker-WatchFace', timePickerHourSelectId );
    elWatch.appendChild( elHourSelect );
    var elMinuteSelect = createElement( 'div', 'MatTimePicker-WatchFace', timePickerMinuteSelectId );
    elMinuteSelect.style.display = 'none';
    elWatch.appendChild( elMinuteSelect );

    var elButtons = createElement( 'div', 'MatTimePicker-Buttons' );
    elWatchContainer.appendChild( elButtons );
    var elButtonCancel = createElement( 'button', 'MatTimePicker-Button', null, 'CANCEL' );
    elButtonCancel.addEventListener( 'click', onCancelClick );
    elButtons.appendChild( elButtonCancel );
    var elButtonOk = createElement( 'button', 'MatTimePicker-Button', null, 'OK' );
    elButtonOk.addEventListener( 'click', onOkClick );
    elButtons.appendChild( elButtonOk );

    initWatchHours( elHourSelect );
    initWatchMinutes( elMinuteSelect );

    document.body.insertBefore( elTimepicker, document.body.children[ 0 ] );
  }

  function initWatchHours( elWatch ) {
    for( var h = 24; h > 0; h-- ) {
      var hourContainer = createElement( 'div', 'MatTimePicker-WatchHourContainer' + ( h > 12 ? ' MatTimePicker-WatchHourPM' : '' ) );
      var rotation = ( -90 + ( 360/12 * h ) );
      hourContainer.style.transform = 'rotate(' + rotation + 'deg)';
      hourContainer.setAttribute( 'hour', h % 24 );
      hourContainer.addEventListener( 'click', onSetHourClick );
      elWatch.appendChild( hourContainer );

      var centerDot = createElement( 'div', 'MatTimePicker-WatchCenterDot' );
      hourContainer.appendChild( centerDot );
      var stick = createElement( 'div', 'MatTimePicker-WatchStick' );
      hourContainer.appendChild( stick );

      var hour = createElement( 'div', 'MatTimePicker-WatchHour' );
      hourContainer.appendChild( hour );
      var hourBg = createElement( 'div', 'MatTimePicker-WatchHourBg' );
      hour.appendChild( hourBg );
      var hourValue = createElement( 'div', 'MatTimePicker-WatchHourValue', null, h % 24 );
      hourValue.style.transform = 'rotate(' + ( rotation * -1 ) + 'deg)';
      hour.appendChild( hourValue );
    }
  }

  function initWatchMinutes( elWatch ) {
    for ( var i = 0; i < 2; i++ ) {
      for( var m = 0; m < 60; m++ ) {
        var minute = m % 60;
        if ( ( i == 0 && m % 5 !== 0 ) || ( i == 1 && m % 5 === 0 ) ) {
          var minuteContainer = createElement( 'div', 'MatTimePicker-WatchMinuteContainer' );
          var rotation = ( -90 + ( 360/60 * m ) );
          minuteContainer.style.transform = 'rotate(' + rotation + 'deg)';
          minuteContainer.setAttribute( 'minute', m );
          minuteContainer.addEventListener( 'click', onSetMinuteClick );
          elWatch.appendChild( minuteContainer );

          var centerDot = createElement( 'div', 'MatTimePicker-WatchCenterDot' );
          minuteContainer.appendChild( centerDot );
          var stick = createElement( 'div', 'MatTimePicker-WatchStick' );
          minuteContainer.appendChild( stick );

          var minute = createElement( 'div', 'MatTimePicker-WatchMinute' );
          minuteContainer.appendChild( minute );
          var minuteBg = createElement( 'div', 'MatTimePicker-WatchHourBg' );
          minute.appendChild( minuteBg );
          if ( m % 5 === 0 ) {
            var minuteValue = createElement( 'div', 'MatTimePicker-WatchHourValue', null, m );
            minuteValue.style.transform = 'rotate(' + ( rotation * -1 ) + 'deg)';
            minute.appendChild( minuteValue );
          }
        }
      }
    }
  }

  function createElement( type, className, id, innerHTML ) {
    var el = document.createElement( type );
    if ( className ) el.className = className;
    if ( id ) el.id = id;
    if ( typeof innerHTML !== 'undefined' ) el.innerHTML = innerHTML;
    return el;
  }
} )( );<|endoftext|>


<commit_before>var boom = require('boom')
var braveHapi = require('../brave-hapi')
var braveJoi = require('../brave-joi')
var bson = require('bson')
var crypto = require('crypto')
var currencyCodes = require('currency-codes')
var dns = require('dns')
var Joi = require('joi')
var ledgerPublisher = require('ledger-publisher')
var underscore = require('underscore')

var v1 = {}
var prefix = 'brave-ledger-verification='

/*
   POST /v1/publishers/prune
 */

var pruner = async function (debug, runtime) {
  var results, state, votes
  var voting = runtime.db.get('voting', debug)

  votes = await voting.aggregate([
      { $match: { counts: { $gt: 0 },
                  exclude: false
                }
      },
      { $group: { _id: '$publisher' } },
      { $project: { _id: 1 } }
  ])

  state = { $currentDate: { timestamp: { $type: 'timestamp' } },
            $set: { exclude: true }
          }

  results = []
  votes.forEach(async function (entry) {
    var publisher = entry._id
    var result

    try {
      result = ledgerPublisher.getPublisher('https://' + publisher)
      if (result) return
    } catch (err) {
      return debug('prune', underscore.defaults({ publisher: publisher }, err))
    }

    results.push(publisher)
    await voting.update({ publisher: publisher }, state, { upsert: false, multi: true })
  })

  runtime.notify(debug, { text: 'pruned ' + JSON.stringify(results, null, 2) })
}

v1.prune =
{ handler: function (runtime) {
  return async function (request, reply) {
    var debug = braveHapi.debug(module, request)

    pruner(debug, runtime)
    reply({})
  }
},

  auth:
    { strategy: 'session',
      scope: [ 'ledger' ],
      mode: 'required'
    },

  description: 'Prunes votes corresponding to pruned publishers',
  tags: [ 'api' ],

  validate:
    { query: {} },

  response:
    { schema: Joi.object().length(0) }
}

/*
   GET /v1/publishers/{publisher}/balance
 */

v1.getBalance =
{ handler: function (runtime) {
  return async function (request, reply) {
    var amount, entry, rate, satoshis, summary
    var publisher = request.params.publisher
    var currency = request.query.currency
    var debug = braveHapi.debug(module, request)
    var voting = runtime.db.get('voting', debug)

    summary = await voting.aggregate([
      { $match:
        { satoshis: { $gt: 0 },
          publisher: { $eq: publisher },
          exclude: false
        }
      },
      { $group:
        { _id: '$publisher',
          satoshis: { $sum: '$satoshis' }
        }
      }
    ])
    satoshis = summary.length > 0 ? summary[0].satoshis : 0

    rate = runtime.wallet.rates[currency.toUpperCase()]
    if (rate) {
      entry = currencyCodes.code(currency)
      amount = ((satoshis * rate) / 1e8).toFixed(entry ? entry.digits : 2)
    }
    reply({ amount: amount, currency: currency, satoshis: satoshis })
  }
},

  auth:
    { strategy: 'simple',
      mode: 'required'
    },

  description: 'Gets a verification token for a publisher',
  tags: [ 'api' ],

  validate:
    { params: { publisher: braveJoi.string().publisher().required().description('the publisher identity') },
      query: { currency: braveJoi.string().currencyCode().optional().default('USD').description('the payment currency'),
               access_token: Joi.string().guid().optional() }
    },

  response:
    { schema: Joi.object().keys(
      { amount: Joi.number().min(0).optional().description('the balance in the payment currency'),
        currency: braveJoi.string().currencyCode().optional().default('USD').description('the payment currency'),
        satoshis: Joi.number().integer().min(0).optional().description('the balance in satoshis')
      })
    }
}

/*
   GET /v1/publishers/{publisher}/verifications/{verificationId}
 */

v1.getToken =
{ handler: function (runtime) {
  return async function (request, reply) {
    var entry, state, token
    var publisher = request.params.publisher
    var verificationId = request.params.verificationId
    var debug = braveHapi.debug(module, request)
    var tokens = runtime.db.get('tokens', debug)

    entry = await tokens.findOne({ verificationId: verificationId, publisher: publisher })
    if (entry) return reply({ token: entry.token })

    token = crypto.randomBytes(32).toString('hex')
    state = { $currentDate: { timestamp: { $type: 'timestamp' } },
              $set: { token: token }
            }
    await tokens.update({ verificationId: verificationId, publisher: publisher }, state, { upsert: true })

    reply({ token: token })
  }
},

  auth:
    { strategy: 'simple',
      mode: 'required'
    },

  description: 'Gets a verification token for a publisher',
  tags: [ 'api' ],

  validate:
    { params:
      { publisher: braveJoi.string().publisher().required().description('the publisher identity'),
        verificationId: Joi.string().guid().required().description('identity of the requestor')
      },
      query: { access_token: Joi.string().guid().optional() }
    },

  response:
    { schema: Joi.object().keys({ token: Joi.string().hex().length(64).required().description('verification token') }) }
}

/*
   PUT /v1/publishers/{publisher}/wallet
 */

v1.setWallet =
{ handler: function (runtime) {
  return async function (request, reply) {
    var entry, state
    var publisher = request.params.publisher
    var bitcoinAddress = request.payload.bitcoinAddress
    var verificationId = request.payload.verificationId
    var debug = braveHapi.debug(module, request)
    var publishers = runtime.db.get('publishers', debug)
    var tokens = runtime.db.get('tokens', debug)

    entry = await tokens.findOne({ verificationId: verificationId, publisher: publisher })
    if (!entry) return reply(boom.notFound('no such entry: ' + publisher))

    if (!entry.verified) return reply(boom.badData('not verified: ' + publisher + ' using ' + verificationId))

    state = { $currentDate: { timestamp: { $type: 'timestamp' } },
              $set: { address: bitcoinAddress }
            }
    await publishers.update({ publisher: publisher }, state, { upsert: true })

    reply({})
  }
},

  auth:
    { strategy: 'simple',
      mode: 'required'
    },

  description: 'Sets the bitcoin address for a publisher',
  tags: [ 'api' ],

  validate:
    { params: { publisher: braveJoi.string().publisher().required().description('the publisher identity') },
      query: { access_token: Joi.string().guid().optional() },
      payload: { bitcoinAddress: braveJoi.string().base58().required().description('BTC address'),
                 verificationId: Joi.string().guid().required().description('identity of the requestor')
               }
    },

  response:
    { schema: Joi.object().length(0) }
}

/*
   GET /v1/publishers/{publisher}/verify
 */

var dnsTxtResolver = async function (domain) {
  return new Promise((resolve, reject) => {
    dns.resolveTxt(domain, (err, rrset) => {
      if (err) return reject(err)
      resolve(rrset)
    })
  })
}

var verified = async function (request, reply, runtime, entry, verified, reason) {
  var payload, state
  var indices = underscore.pick(entry, [ 'verificationId', 'publisher' ])
  var debug = braveHapi.debug(module, request)
  var tokens = runtime.db.get('tokens', debug)

  debug('verified', underscore.extend(underscore.clone(indices), { verified: verified, reason: reason }))

  entry.verified = verified
  state = { $currentDate: { timestamp: { $type: 'timestamp' } },
            $set: { verified: entry.verified, reason: reason }
          }
  await tokens.update(indices, state, { upsert: true })

  reason = reason || (verified ? 'ok' : 'unknown')
  payload = underscore.extend(underscore.pick(entry, [ 'verificationId', 'token', 'verified' ]), { status: reason })
  try {
    await braveHapi.wreck.patch(runtime.config.publishers.url + '/v1/publishers/' + encodeURIComponent(entry.publisher) +
                                  '/verifications',
                                { headers: { authorization: 'bearer ' + runtime.config.publishers.access_token },
                                  payload: JSON.stringify(payload)
                                })
  } catch (ex) {
    debug('publishers patch', underscore.extend(indices, { payload: payload, reason: ex.toString() }))
  }
  if (!verified) return

  await runtime.queue.send(debug, 'publisher-report', { publisher: entry.publisher, verified: verified })

  reply({ status: 'success', verificationId: entry.verificationId })
}

v1.verifyToken =
{ handler: function (runtime) {
  return async function (request, reply) {
    var data, entry, entries, i, info, j, matchP, reason, rr, rrset
    var publisher = request.params.publisher
    var debug = braveHapi.debug(module, request)
    var tokens = runtime.db.get('tokens', debug)

    entries = await tokens.find({ publisher: publisher })
    if (entries.length === 0) return reply(boom.notFound('no such publisher: ' + publisher))

    for (i = 0; i < entries.length; i++) {
      entry = entries[i]
      if (entry.verified) return reply({ status: 'success', verificationId: entry.verificationId })
    }

    try { rrset = await dnsTxtResolver(publisher) } catch (ex) {
      reason = ex.toString()
      if (reason.indexOf('ENODATA') === -1) {
        debug('dnsTxtResolver', underscore.extend({ publisher: publisher, reason: reason }))
      }
      rrset = []
    }
    for (i = 0; i < rrset.length; i++) { rrset[i] = rrset[i].join('') }

    var loser = async function (reason) {
      debug('verify', underscore.extend(info, { reason: reason }))
      await verified(request, reply, runtime, entry, false, reason)
    }

    info = { publisher: publisher }
    for (i = 0; i < entries.length; i++) {
      entry = entries[i]
      info.verificationId = entry.verificationId

      for (j = 0; j < rrset.length; j++) {
        rr = rrset[j]
        if (rr.indexOf(prefix) !== 0) continue

        matchP = true
        if (rr.substring(prefix.length) !== entry.token) {
          await loser('TXT RR suffix mismatch ' + prefix + entry.token)
          continue
        }

        return await verified(request, reply, runtime, entry, true, 'TXT RR matches')
      }
      if (!matchP) await loser('no TXT RRs starting with ' + prefix)

      try {
/*
        data = await braveHapi.wreck.get('http://' + publisher + '/.well-known/brave-payments-verification.txt')
        if (data.toString().indexOf(entry.token) !== -1) {
          return await verified(request, reply, runtime, entry, true, 'web file matches')
        }
 */

        try {
          data = await braveHapi.wreck.get('https://' + publisher + '/.well-known/brave-payments-verification.txt',
                                           { rejectUnauthorized: true })
          if (data.toString().indexOf(entry.token) !== -1) {
            return await verified(request, reply, runtime, entry, true, 'web file matches')
          }
        } catch (ex) {
          await loser(ex.toString())
        }
      } catch (ex) {
        await loser(ex.toString())
      }
    }

    return reply({ status: 'failure' })
  }
},

  description: 'Verifies a publisher',
  tags: [ 'api' ],

  validate:
    { params: { publisher: braveJoi.string().publisher().required().description('the publisher identity') } },

  response:
    { schema: Joi.object().keys(
      { status: Joi.string().valid('success', 'failure').required().description('victory is mine!'),
        verificationId: Joi.string().guid().optional().description('identity of the verified requestor')
      })
    }
}

module.exports.notify =
  async function (debug, runtime, publisher, payload) {
// TBD: add some logging here for testing...

    await braveHapi.wreck.post(runtime.config.publishers.url + '/v1/publishers/' + encodeURIComponent(publisher) +
                                 '/notifications',
                               { payload: JSON.stringify(payload) })
  }

module.exports.routes = [
  braveHapi.routes.async().post().path('/v1/publishers/prune').config(v1.prune),
  braveHapi.routes.async().post().path('/v1/publishers/{publisher}/balance').whitelist().config(v1.getBalance),
  braveHapi.routes.async().path('/v1/publishers/{publisher}/verifications/{verificationId}').whitelist().config(v1.getToken),
  braveHapi.routes.async().put().path('/v1/publishers/{publisher}/wallet').whitelist().config(v1.setWallet),
  braveHapi.routes.async().path('/v1/publishers/{publisher}/verify').config(v1.verifyToken)
]

module.exports.initialize = async function (debug, runtime) {
  runtime.db.checkIndices(debug,
  [ { category: runtime.db.get('publishers', debug),
      name: 'publishers',
      property: 'publisher',
      empty: { publisher: '', verified: false, address: '', token: '', timestamp: bson.Timestamp.ZERO },
      unique: [ { publisher: 1 } ],
      others: [ { verified: 1 }, { address: 0 }, { token: 0 }, { timestamp: 1 } ]
    },
    { category: runtime.db.get('tokens', debug),
      name: 'tokens',
      property: 'verificationId_0_publisher',
      empty: { verificationId: '', publisher: '', token: '', verified: false, reason: '', timestamp: bson.Timestamp.ZERO },
      unique: [ { verificationId: 0, publisher: 1 } ],
      others: [ { token: 0 }, { verified: 1 }, { reason: 1 }, { timestamp: 1 } ]
    }
  ])

  await runtime.queue.create('publisher-report')
}
<commit_msg>re-order publisher-report update<commit_after>var boom = require('boom')
var braveHapi = require('../brave-hapi')
var braveJoi = require('../brave-joi')
var bson = require('bson')
var crypto = require('crypto')
var currencyCodes = require('currency-codes')
var dns = require('dns')
var Joi = require('joi')
var ledgerPublisher = require('ledger-publisher')
var underscore = require('underscore')

var v1 = {}
var prefix = 'brave-ledger-verification='

/*
   POST /v1/publishers/prune
 */

var pruner = async function (debug, runtime) {
  var results, state, votes
  var voting = runtime.db.get('voting', debug)

  votes = await voting.aggregate([
      { $match: { counts: { $gt: 0 },
                  exclude: false
                }
      },
      { $group: { _id: '$publisher' } },
      { $project: { _id: 1 } }
  ])

  state = { $currentDate: { timestamp: { $type: 'timestamp' } },
            $set: { exclude: true }
          }

  results = []
  votes.forEach(async function (entry) {
    var publisher = entry._id
    var result

    try {
      result = ledgerPublisher.getPublisher('https://' + publisher)
      if (result) return
    } catch (err) {
      return debug('prune', underscore.defaults({ publisher: publisher }, err))
    }

    results.push(publisher)
    await voting.update({ publisher: publisher }, state, { upsert: false, multi: true })
  })

  runtime.notify(debug, { text: 'pruned ' + JSON.stringify(results, null, 2) })
}

v1.prune =
{ handler: function (runtime) {
  return async function (request, reply) {
    var debug = braveHapi.debug(module, request)

    pruner(debug, runtime)
    reply({})
  }
},

  auth:
    { strategy: 'session',
      scope: [ 'ledger' ],
      mode: 'required'
    },

  description: 'Prunes votes corresponding to pruned publishers',
  tags: [ 'api' ],

  validate:
    { query: {} },

  response:
    { schema: Joi.object().length(0) }
}

/*
   GET /v1/publishers/{publisher}/balance
 */

v1.getBalance =
{ handler: function (runtime) {
  return async function (request, reply) {
    var amount, entry, rate, satoshis, summary
    var publisher = request.params.publisher
    var currency = request.query.currency
    var debug = braveHapi.debug(module, request)
    var voting = runtime.db.get('voting', debug)

    summary = await voting.aggregate([
      { $match:
        { satoshis: { $gt: 0 },
          publisher: { $eq: publisher },
          exclude: false
        }
      },
      { $group:
        { _id: '$publisher',
          satoshis: { $sum: '$satoshis' }
        }
      }
    ])
    satoshis = summary.length > 0 ? summary[0].satoshis : 0

    rate = runtime.wallet.rates[currency.toUpperCase()]
    if (rate) {
      entry = currencyCodes.code(currency)
      amount = ((satoshis * rate) / 1e8).toFixed(entry ? entry.digits : 2)
    }
    reply({ amount: amount, currency: currency, satoshis: satoshis })
  }
},

  auth:
    { strategy: 'simple',
      mode: 'required'
    },

  description: 'Gets a verification token for a publisher',
  tags: [ 'api' ],

  validate:
    { params: { publisher: braveJoi.string().publisher().required().description('the publisher identity') },
      query: { currency: braveJoi.string().currencyCode().optional().default('USD').description('the payment currency'),
               access_token: Joi.string().guid().optional() }
    },

  response:
    { schema: Joi.object().keys(
      { amount: Joi.number().min(0).optional().description('the balance in the payment currency'),
        currency: braveJoi.string().currencyCode().optional().default('USD').description('the payment currency'),
        satoshis: Joi.number().integer().min(0).optional().description('the balance in satoshis')
      })
    }
}

/*
   GET /v1/publishers/{publisher}/verifications/{verificationId}
 */

v1.getToken =
{ handler: function (runtime) {
  return async function (request, reply) {
    var entry, state, token
    var publisher = request.params.publisher
    var verificationId = request.params.verificationId
    var debug = braveHapi.debug(module, request)
    var tokens = runtime.db.get('tokens', debug)

    entry = await tokens.findOne({ verificationId: verificationId, publisher: publisher })
    if (entry) return reply({ token: entry.token })

    token = crypto.randomBytes(32).toString('hex')
    state = { $currentDate: { timestamp: { $type: 'timestamp' } },
              $set: { token: token }
            }
    await tokens.update({ verificationId: verificationId, publisher: publisher }, state, { upsert: true })

    reply({ token: token })
  }
},

  auth:
    { strategy: 'simple',
      mode: 'required'
    },

  description: 'Gets a verification token for a publisher',
  tags: [ 'api' ],

  validate:
    { params:
      { publisher: braveJoi.string().publisher().required().description('the publisher identity'),
        verificationId: Joi.string().guid().required().description('identity of the requestor')
      },
      query: { access_token: Joi.string().guid().optional() }
    },

  response:
    { schema: Joi.object().keys({ token: Joi.string().hex().length(64).required().description('verification token') }) }
}

/*
   PUT /v1/publishers/{publisher}/wallet
 */

v1.setWallet =
{ handler: function (runtime) {
  return async function (request, reply) {
    var entry, state
    var publisher = request.params.publisher
    var bitcoinAddress = request.payload.bitcoinAddress
    var verificationId = request.payload.verificationId
    var debug = braveHapi.debug(module, request)
    var publishers = runtime.db.get('publishers', debug)
    var tokens = runtime.db.get('tokens', debug)

    entry = await tokens.findOne({ verificationId: verificationId, publisher: publisher })
    if (!entry) return reply(boom.notFound('no such entry: ' + publisher))

    if (!entry.verified) return reply(boom.badData('not verified: ' + publisher + ' using ' + verificationId))

    state = { $currentDate: { timestamp: { $type: 'timestamp' } },
              $set: { address: bitcoinAddress }
            }
    await publishers.update({ publisher: publisher }, state, { upsert: true })

    reply({})
  }
},

  auth:
    { strategy: 'simple',
      mode: 'required'
    },

  description: 'Sets the bitcoin address for a publisher',
  tags: [ 'api' ],

  validate:
    { params: { publisher: braveJoi.string().publisher().required().description('the publisher identity') },
      query: { access_token: Joi.string().guid().optional() },
      payload: { bitcoinAddress: braveJoi.string().base58().required().description('BTC address'),
                 verificationId: Joi.string().guid().required().description('identity of the requestor')
               }
    },

  response:
    { schema: Joi.object().length(0) }
}

/*
   GET /v1/publishers/{publisher}/verify
 */

var dnsTxtResolver = async function (domain) {
  return new Promise((resolve, reject) => {
    dns.resolveTxt(domain, (err, rrset) => {
      if (err) return reject(err)
      resolve(rrset)
    })
  })
}

var verified = async function (request, reply, runtime, entry, verified, reason) {
  var payload, state
  var indices = underscore.pick(entry, [ 'verificationId', 'publisher' ])
  var debug = braveHapi.debug(module, request)
  var tokens = runtime.db.get('tokens', debug)

  debug('verified', underscore.extend(underscore.clone(indices), { verified: verified, reason: reason }))

  entry.verified = verified
  state = { $currentDate: { timestamp: { $type: 'timestamp' } },
            $set: { verified: entry.verified, reason: reason }
          }
  await tokens.update(indices, state, { upsert: true })

  await runtime.queue.send(debug, 'publisher-report', { publisher: entry.publisher, verified: verified })

  reason = reason || (verified ? 'ok' : 'unknown')
  payload = underscore.extend(underscore.pick(entry, [ 'verificationId', 'token', 'verified' ]), { status: reason })
  try {
    await braveHapi.wreck.patch(runtime.config.publishers.url + '/v1/publishers/' + encodeURIComponent(entry.publisher) +
                                  '/verifications',
                                { headers: { authorization: 'bearer ' + runtime.config.publishers.access_token },
                                  payload: JSON.stringify(payload)
                                })
  } catch (ex) {
    debug('publishers patch', underscore.extend(indices, { payload: payload, reason: ex.toString() }))
  }
  if (!verified) return

  reply({ status: 'success', verificationId: entry.verificationId })
}

v1.verifyToken =
{ handler: function (runtime) {
  return async function (request, reply) {
    var data, entry, entries, i, info, j, matchP, reason, rr, rrset
    var publisher = request.params.publisher
    var debug = braveHapi.debug(module, request)
    var tokens = runtime.db.get('tokens', debug)

    entries = await tokens.find({ publisher: publisher })
    if (entries.length === 0) return reply(boom.notFound('no such publisher: ' + publisher))

    for (i = 0; i < entries.length; i++) {
      entry = entries[i]
      if (entry.verified) return reply({ status: 'success', verificationId: entry.verificationId })
    }

    try { rrset = await dnsTxtResolver(publisher) } catch (ex) {
      reason = ex.toString()
      if (reason.indexOf('ENODATA') === -1) {
        debug('dnsTxtResolver', underscore.extend({ publisher: publisher, reason: reason }))
      }
      rrset = []
    }
    for (i = 0; i < rrset.length; i++) { rrset[i] = rrset[i].join('') }

    var loser = async function (reason) {
      debug('verify', underscore.extend(info, { reason: reason }))
      await verified(request, reply, runtime, entry, false, reason)
    }

    info = { publisher: publisher }
    for (i = 0; i < entries.length; i++) {
      entry = entries[i]
      info.verificationId = entry.verificationId

      for (j = 0; j < rrset.length; j++) {
        rr = rrset[j]
        if (rr.indexOf(prefix) !== 0) continue

        matchP = true
        if (rr.substring(prefix.length) !== entry.token) {
          await loser('TXT RR suffix mismatch ' + prefix + entry.token)
          continue
        }

        return await verified(request, reply, runtime, entry, true, 'TXT RR matches')
      }
      if (!matchP) await loser('no TXT RRs starting with ' + prefix)

      try {
/*
        data = await braveHapi.wreck.get('http://' + publisher + '/.well-known/brave-payments-verification.txt')
        if (data.toString().indexOf(entry.token) !== -1) {
          return await verified(request, reply, runtime, entry, true, 'web file matches')
        }
 */

        try {
          data = await braveHapi.wreck.get('https://' + publisher + '/.well-known/brave-payments-verification.txt',
                                           { rejectUnauthorized: true })
          if (data.toString().indexOf(entry.token) !== -1) {
            return await verified(request, reply, runtime, entry, true, 'web file matches')
          }
        } catch (ex) {
          await loser(ex.toString())
        }
      } catch (ex) {
        await loser(ex.toString())
      }
    }

    return reply({ status: 'failure' })
  }
},

  description: 'Verifies a publisher',
  tags: [ 'api' ],

  validate:
    { params: { publisher: braveJoi.string().publisher().required().description('the publisher identity') } },

  response:
    { schema: Joi.object().keys(
      { status: Joi.string().valid('success', 'failure').required().description('victory is mine!'),
        verificationId: Joi.string().guid().optional().description('identity of the verified requestor')
      })
    }
}

module.exports.notify =
  async function (debug, runtime, publisher, payload) {
// TBD: add some logging here for testing...

    await braveHapi.wreck.post(runtime.config.publishers.url + '/v1/publishers/' + encodeURIComponent(publisher) +
                                 '/notifications',
                               { payload: JSON.stringify(payload) })
  }

module.exports.routes = [
  braveHapi.routes.async().post().path('/v1/publishers/prune').config(v1.prune),
  braveHapi.routes.async().post().path('/v1/publishers/{publisher}/balance').whitelist().config(v1.getBalance),
  braveHapi.routes.async().path('/v1/publishers/{publisher}/verifications/{verificationId}').whitelist().config(v1.getToken),
  braveHapi.routes.async().put().path('/v1/publishers/{publisher}/wallet').whitelist().config(v1.setWallet),
  braveHapi.routes.async().path('/v1/publishers/{publisher}/verify').config(v1.verifyToken)
]

module.exports.initialize = async function (debug, runtime) {
  runtime.db.checkIndices(debug,
  [ { category: runtime.db.get('publishers', debug),
      name: 'publishers',
      property: 'publisher',
      empty: { publisher: '', verified: false, address: '', token: '', timestamp: bson.Timestamp.ZERO },
      unique: [ { publisher: 1 } ],
      others: [ { verified: 1 }, { address: 0 }, { token: 0 }, { timestamp: 1 } ]
    },
    { category: runtime.db.get('tokens', debug),
      name: 'tokens',
      property: 'verificationId_0_publisher',
      empty: { verificationId: '', publisher: '', token: '', verified: false, reason: '', timestamp: bson.Timestamp.ZERO },
      unique: [ { verificationId: 0, publisher: 1 } ],
      others: [ { token: 0 }, { verified: 1 }, { reason: 1 }, { timestamp: 1 } ]
    }
  ])

  await runtime.queue.create('publisher-report')
}
<|endoftext|>


<commit_before>var io = require('../../lib/socket.io'),
	storage = require('./storage'),
	requests = require('./requests'),
	log = require('./logger').log,
	curry = require('../shared/util').curry

module.exports = {
	start: start
}

/* State
 *******/
var	engine = null,
	store = null,
	debug = true

/* Exported API
 **************/
function start(withEngine, httpServer) {
	engine = withEngine
	storage.setStore(engine.getStore())

	if (!httpServer) {
		httpServer = require('http').createServer(function(){})
		httpServer.listen(8080, '127.0.0.1')
	}
	var socket = io.listen(httpServer)
	socket.on('connection', _handleConnection)
}

/* Handler functions
 *******************/
function _handleConnection(client) {
	log('new connection', client.sessionId)
	client.subscriptionStore = engine.getStore()
	client.on('message', curry(_handleMessage, client))
	client.on('disconnect', curry(_handleDisconnect, client))
}

function _handleMessage(client, message) {
	requests.handleRequest(client, message)
}

function _handleDisconnect(client) {
	log('TODO implement _handleDisconnect', arguments)
}

<commit_msg>Remove unused debug variable<commit_after>var io = require('../../lib/socket.io'),
	storage = require('./storage'),
	requests = require('./requests'),
	log = require('./logger').log,
	curry = require('../shared/util').curry

module.exports = {
	start: start
}

/* State
 *******/
var	engine = null,
	store = null,

/* Exported API
 **************/
function start(withEngine, httpServer) {
	engine = withEngine
	storage.setStore(engine.getStore())

	if (!httpServer) {
		httpServer = require('http').createServer(function(){})
		httpServer.listen(8080, '127.0.0.1')
	}
	var socket = io.listen(httpServer)
	socket.on('connection', _handleConnection)
}

/* Handler functions
 *******************/
function _handleConnection(client) {
	log('new connection', client.sessionId)
	client.subscriptionStore = engine.getStore()
	client.on('message', curry(_handleMessage, client))
	client.on('disconnect', curry(_handleDisconnect, client))
}

function _handleMessage(client, message) {
	requests.handleRequest(client, message)
}

function _handleDisconnect(client) {
	log('TODO implement _handleDisconnect', arguments)
}

<|endoftext|>


<commit_before>/**
 *
 */
function dialogoBonosNaturales() {
    var i;
    var dialogBonosNaturales = $("#dialogBonosNaturales");
    dialogBonosNaturales.empty();
    dialogBonosNaturales.dialog({
        modal: true,
        autoOpen: true,
        draggable: true,
        resizable: true,
        ////show: "puff",
        title: DIAG_ELEGIR_BONOS_NATURALES_TITULO,
        width: ANCHO_DIALOGO,
        height: ALTO_DIALOGO,
        maxHeight: ALTO_DIALOGO,
        closeOnEscape: true,
        buttons: [
            { text: "Ok",
                click: function() {
                    $( this ).dialog( "close" );
                }
            }
        ]
    });

    var divGeneral = $("

");

    for (i = 0; i < 5; i++) {
        var div = $("

");

        var etiqu =  $("

");
        etiqu.addClass(CSS_MUESTRA_INLINE);
        etiqu.append(UI_HABILIDAD_NATURAL + " " + (i+1) + ": ");

        var divNombre = $("

");
        divNombre.attr("id","habilidadNaturalElegida"+i);
        divNombre.addClass(CSS_MUESTRA_INLINE);
        if (personaje_actual.getBonoHabilidadNatural(i,personaje_actual.getNivel()) != -1) {
            var nombreElegido = personaje_actual.getBonoHabilidadNatural(i,personaje_actual.getNivel()).getItem();
            divNombre.append(nombreElegido);
        }
        etiqu.append(divNombre);

        div.append(etiqu);

        var botonBono = boton("medium pretty primary btn",_l(UI_ELEGIR));
        div.append(botonBono);

        botonBono.on("click",{indice: i, nivel: personaje_actual.getNivel()}, elegirHabilidadNatural);

        divGeneral.append(div);
    }

    if (!personaje_actual.hasFlag(FLAG_SIN_BONIFICADOR_NATURAL)) {
        /*bonificador natural físico*/
        var divBonificadoresNaturales = $("

");

        var divFisico = $("

");

        var etiquFisico =  $("

");
        etiquFisico.addClass(CSS_MUESTRA_INLINE);
        etiquFisico.append(UI_BONIFICADOR_NATURAL_FISICO + ": ");

        var divNombreFisico = $("

");
        divNombreFisico.addClass(CSS_MUESTRA_INLINE);
        divNombreFisico.attr("id","bonificadorNaturalElegido"+TIPO_BONIFICADOR_NATURAL_FISICO);

        if (personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_FISICO,1) != "") {
            var nombreElegidoFisico = personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_FISICO,1);
            divNombreFisico.append(nombreElegidoFisico);
        }
        etiquFisico.append(divNombreFisico);
        divFisico.append(etiquFisico);

        var botonFisico = boton("medium pretty primary btn",_l(UI_ELEGIR));
        divFisico.append(botonFisico);
        divBonificadoresNaturales.append(divFisico);

        botonFisico.on("click",{tipo: TIPO_BONIFICADOR_NATURAL_FISICO}, elegirBonificadorNatural);

        /*bonificador natural mental*/
        var divMental = $("

");

        var etiquMental =  $("

");
        etiquMental.addClass(CSS_MUESTRA_INLINE);
        etiquMental.append(UI_BONIFICADOR_NATURAL_MENTAL + ": ");

        var divNombreMental = $("

");
        divNombreMental.addClass(CSS_MUESTRA_INLINE);
        divNombreMental.attr("id","bonificadorNaturalElegido"+TIPO_BONIFICADOR_NATURAL_MENTAL);

        if (personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_MENTAL,1) != "") {
            var nombreElegidoMental = personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_MENTAL,1);
            divNombreMental.append(nombreElegidoMental);
        }
        etiquMental.append(divNombreMental);

        divMental.append(etiquMental);

        var botonMental = boton("medium pretty primary btn",_l(UI_ELEGIR));
        divMental.append(botonMental);

        divBonificadoresNaturales.append(divMental);
        botonMental.on("click",{tipo: TIPO_BONIFICADOR_NATURAL_MENTAL}, elegirBonificadorNatural);

        if (personaje_actual.hasFlag(FLAG_BONO_NATURAL_EXTRA)) {
            /*bonificador natural extra*/
            var divExtra = $("

");

            var etiquExtra =  $("

");
            etiquExtra.addClass(CSS_MUESTRA_INLINE);
            etiquExtra.append(UI_BONIFICADOR_NATURAL_EXTRA + ": ");

            var divNombreExtra = $("

");
            divNombreExtra.addClass(CSS_MUESTRA_INLINE);
            divNombreExtra.attr("id","bonificadorNaturalElegido"+TIPO_BONIFICADOR_NATURAL_EXTRA);

            if (personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_EXTRA,1) != "") {
                var nombreElegidoExtra = personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_EXTRA,1);
                divNombreExtra.append(nombreElegidoExtra);
            }
            etiquExtra.append(divNombreExtra);

            divExtra.append(etiquExtra);

            var botonExtra = boton("medium pretty primary btn",_l(UI_ELEGIR));
            divExtra.append(botonExtra);

            divBonificadoresNaturales.append(divExtra);
            botonExtra.on("click",{tipo: TIPO_BONIFICADOR_NATURAL_EXTRA}, elegirBonificadorNatural);
        }
        divGeneral.append(divBonificadoresNaturales);
    }

    if (personaje_actual.getCategoria().getNombre() == CAT_NOVEL) {
        for (i = 0; i < 5; i++) {
            var divNovel = $("

");

            var etiquNovel =  $("

");
            etiquNovel.addClass(CSS_MUESTRA_INLINE);
            etiquNovel.append(UI_BONO_NOVEL + " " + (i+1) + ": ");

            var divNombreNovel = $("

");
            divNombreNovel.attr("id","habilidadNaturalElegidaNovel"+i);
            divNombreNovel.addClass(CSS_MUESTRA_INLINE);
            if (personaje_actual.getBonoNovel(i,personaje_actual.getNivel()) != "") {
                var nombreElegidoNovel = personaje_actual.getBonoNovel(i,personaje_actual.getNivel());
                divNombreNovel.append(nombreElegidoNovel);
            }
            etiquNovel.append(divNombreNovel);

            divNovel.append(etiquNovel);

            var botonNovel = boton("medium pretty primary btn",_l(UI_ELEGIR));
            botonNovel.css("cursor", "pointer");
            divNovel.append(botonNovel);

            botonNovel.on("click",{indice: i, nivel:personaje_actual.getNivel()}, elegirBonoNovel);

            divGeneral.append(divNovel);
        }
    }

    dialogBonosNaturales.append(divGeneral);
    elegirBonosNaturales();
}

/**
 *
 * @param {string} nombreHabilidad
 * @returns {jQuery}
 */
function muestraBotonMasMenosHabilidad(nombreHabilidad) {
    var div = $("

");
    var divMas = boton("small primary pretty btn",_l("+"));
    var divMenos = boton("small secondary pretty btn",_l("-"));

//    divMas.css("width", "1rem")
  //  divMenos.css("width", "1rem")

    div.append(divMas).append(divMenos);

    divMas.on("click",{nombreHabilidad: nombreHabilidad,unidades: 1}, aumentaHabilidadClick);
    divMenos.on("click",{nombreHabilidad: nombreHabilidad,unidades: -1}, aumentaHabilidadClick);
    return div;
}

function muestraBotonElegirEspecialidad(nombreHabilidad) {
    var div = $("

");
    var divBoton = boton("small info pretty btn",_l("E"));
//    divBoton.css("width", "1rem")
    div.append(divBoton);

    divBoton.on("click",{nombreHabilidad: nombreHabilidad}, eligeEspecialidad);
    return div;
}

/**
 *
 * @param {{principal:function,isDisabled:function}} callback
 * @param {{}} parametro
 * @param {string} [soloFisicasOMentales]
 */
function muestraDialogoElegirOpcionHabilidad(callback,parametro,soloFisicasOMentales) {
    var arrayOpciones =  [];
    var categorias = [];
    var i;
    var j;
    var grupoHabi;
    var habi;

    if (!soloFisicasOMentales) {
        soloFisicasOMentales = "habNatural";
    }

    for (i = 0; i < habilidades_secundarias.length;i++) {
        grupoHabi = habilidades_secundarias[i];
        categorias.push(new OpcionMostrable(_l(habilidades_secundarias_nombres_grupos[i]),habilidades_secundarias_nombres_grupos[i],habilidades_secundarias_nombres_grupos[i]+"_tipo"+soloFisicasOMentales));
        for (j = 0; j < grupoHabi.length; j++) {
            habi = getHabilidad(grupoHabi[j]);
            if ((soloFisicasOMentales == TIPO_BONIFICADOR_NATURAL_EXTRA) || (soloFisicasOMentales == "habNatural") ||
                ((soloFisicasOMentales == TIPO_BONIFICADOR_NATURAL_FISICO) && ((habi.getCaracteristica() == FUE) || (habi.getCaracteristica() == DES) || (habi.getCaracteristica() == AGI) || (habi.getCaracteristica() == CON))) ||
                ((soloFisicasOMentales == TIPO_BONIFICADOR_NATURAL_MENTAL) && ((habi.getCaracteristica() == INT) || (habi.getCaracteristica() == VOL) || (habi.getCaracteristica() == POD) || (habi.getCaracteristica() == PER)))) {
                arrayOpciones.push(new OpcionMostrable(_l(habi.getNombre()),habi.getNombre(),habilidades_secundarias_nombres_grupos[i]+"_tipo"+soloFisicasOMentales));
            }
        }
    }
    muestraDialogoElegirOpciones(arrayOpciones, parametro, {principal: callback.principal, isDisabled: callback.isDisabled}, true, categorias);
}

<commit_msg>Localizar Habilidades view<commit_after>/**
 *
 */
function dialogoBonosNaturales() {
    var i;
    var dialogBonosNaturales = $("#dialogBonosNaturales");
    dialogBonosNaturales.empty();
    dialogBonosNaturales.dialog({
        modal: true,
        autoOpen: true,
        draggable: true,
        resizable: true,
        ////show: "puff",
        title: _l(DIAG_ELEGIR_BONOS_NATURALES_TITULO),
        width: ANCHO_DIALOGO,
        height: ALTO_DIALOGO,
        maxHeight: ALTO_DIALOGO,
        closeOnEscape: true,
        buttons: [
            { text: "Ok",
                click: function() {
                    $( this ).dialog( "close" );
                }
            }
        ]
    });

    var divGeneral = $("

");

    for (i = 0; i < 5; i++) {
        var div = $("

");

        var etiqu =  $("

");
        etiqu.addClass(CSS_MUESTRA_INLINE);
        etiqu.append(_l(UI_HABILIDAD_NATURAL) + " " + (i+1) + ": ");

        var divNombre = $("

");
        divNombre.attr("id","habilidadNaturalElegida"+i);
        divNombre.addClass(CSS_MUESTRA_INLINE);
        if (personaje_actual.getBonoHabilidadNatural(i,personaje_actual.getNivel()) != -1) {
            var nombreElegido = personaje_actual.getBonoHabilidadNatural(i,personaje_actual.getNivel()).getItem();
            divNombre.append(_l(nombreElegido));
        }
        etiqu.append(divNombre);

        div.append(etiqu);

        var botonBono = boton("medium pretty primary btn",_l(UI_ELEGIR));
        div.append(botonBono);

        botonBono.on("click",{indice: i, nivel: personaje_actual.getNivel()}, elegirHabilidadNatural);

        divGeneral.append(div);
    }

    if (!personaje_actual.hasFlag(FLAG_SIN_BONIFICADOR_NATURAL)) {
        /*bonificador natural físico*/
        var divBonificadoresNaturales = $("

");

        var divFisico = $("

");

        var etiquFisico =  $("

");
        etiquFisico.addClass(CSS_MUESTRA_INLINE);
        etiquFisico.append(_l(UI_BONIFICADOR_NATURAL_FISICO) + ": ");

        var divNombreFisico = $("

");
        divNombreFisico.addClass(CSS_MUESTRA_INLINE);
        divNombreFisico.attr("id","bonificadorNaturalElegido"+TIPO_BONIFICADOR_NATURAL_FISICO);

        if (personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_FISICO,1) != "") {
            var nombreElegidoFisico = personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_FISICO,1);
            divNombreFisico.append(_l(nombreElegidoFisico));
        }
        etiquFisico.append(divNombreFisico);
        divFisico.append(etiquFisico);

        var botonFisico = boton("medium pretty primary btn",_l(UI_ELEGIR));
        divFisico.append(botonFisico);
        divBonificadoresNaturales.append(divFisico);

        botonFisico.on("click",{tipo: TIPO_BONIFICADOR_NATURAL_FISICO}, elegirBonificadorNatural);

        /*bonificador natural mental*/
        var divMental = $("

");

        var etiquMental =  $("

");
        etiquMental.addClass(CSS_MUESTRA_INLINE);
        etiquMental.append(_l(UI_BONIFICADOR_NATURAL_MENTAL) + ": ");

        var divNombreMental = $("

");
        divNombreMental.addClass(CSS_MUESTRA_INLINE);
        divNombreMental.attr("id","bonificadorNaturalElegido"+TIPO_BONIFICADOR_NATURAL_MENTAL);

        if (personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_MENTAL,1) != "") {
            var nombreElegidoMental = personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_MENTAL,1);
            divNombreMental.append(_l(nombreElegidoMental));
        }
        etiquMental.append(divNombreMental);

        divMental.append(etiquMental);

        var botonMental = boton("medium pretty primary btn",_l(UI_ELEGIR));
        divMental.append(botonMental);

        divBonificadoresNaturales.append(divMental);
        botonMental.on("click",{tipo: TIPO_BONIFICADOR_NATURAL_MENTAL}, elegirBonificadorNatural);

        if (personaje_actual.hasFlag(FLAG_BONO_NATURAL_EXTRA)) {
            /*bonificador natural extra*/
            var divExtra = $("

");

            var etiquExtra =  $("

");
            etiquExtra.addClass(CSS_MUESTRA_INLINE);
            etiquExtra.append(_l(UI_BONIFICADOR_NATURAL_EXTRA) + ": ");

            var divNombreExtra = $("

");
            divNombreExtra.addClass(CSS_MUESTRA_INLINE);
            divNombreExtra.attr("id","bonificadorNaturalElegido"+TIPO_BONIFICADOR_NATURAL_EXTRA);

            if (personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_EXTRA,1) != "") {
                var nombreElegidoExtra = personaje_actual.getBonificadorNatural(TIPO_BONIFICADOR_NATURAL_EXTRA,1);
                divNombreExtra.append(_l(nombreElegidoExtra));
            }
            etiquExtra.append(divNombreExtra);

            divExtra.append(etiquExtra);

            var botonExtra = boton("medium pretty primary btn",_l(UI_ELEGIR));
            divExtra.append(botonExtra);

            divBonificadoresNaturales.append(divExtra);
            botonExtra.on("click",{tipo: TIPO_BONIFICADOR_NATURAL_EXTRA}, elegirBonificadorNatural);
        }
        divGeneral.append(divBonificadoresNaturales);
    }

    if (personaje_actual.getCategoria().getNombre() == CAT_NOVEL) {
        for (i = 0; i < 5; i++) {
            var divNovel = $("

");

            var etiquNovel =  $("

");
            etiquNovel.addClass(CSS_MUESTRA_INLINE);
            etiquNovel.append(_l(UI_BONO_NOVEL) + " " + (i+1) + ": ");

            var divNombreNovel = $("

");
            divNombreNovel.attr("id","habilidadNaturalElegidaNovel"+i);
            divNombreNovel.addClass(CSS_MUESTRA_INLINE);
            if (personaje_actual.getBonoNovel(i,personaje_actual.getNivel()) != "") {
                var nombreElegidoNovel = personaje_actual.getBonoNovel(i,personaje_actual.getNivel());
                divNombreNovel.append(_l(nombreElegidoNovel));
            }
            etiquNovel.append(divNombreNovel);

            divNovel.append(etiquNovel);

            var botonNovel = boton("medium pretty primary btn",_l(UI_ELEGIR));
            botonNovel.css("cursor", "pointer");
            divNovel.append(botonNovel);

            botonNovel.on("click",{indice: i, nivel:personaje_actual.getNivel()}, elegirBonoNovel);

            divGeneral.append(divNovel);
        }
    }

    dialogBonosNaturales.append(divGeneral);
    elegirBonosNaturales();
}

/**
 *
 * @param {string} nombreHabilidad
 * @returns {jQuery}
 */
function muestraBotonMasMenosHabilidad(nombreHabilidad) {
    var div = $("

");
    var divMas = boton("small primary pretty btn",_l("+"));
    var divMenos = boton("small secondary pretty btn",_l("-"));

//    divMas.css("width", "1rem")
  //  divMenos.css("width", "1rem")

    div.append(divMas).append(divMenos);

    divMas.on("click",{nombreHabilidad: nombreHabilidad,unidades: 1}, aumentaHabilidadClick);
    divMenos.on("click",{nombreHabilidad: nombreHabilidad,unidades: -1}, aumentaHabilidadClick);
    return div;
}

function muestraBotonElegirEspecialidad(nombreHabilidad) {
    var div = $("

");
    var divBoton = boton("small info pretty btn",_l("E"));
//    divBoton.css("width", "1rem")
    div.append(divBoton);

    divBoton.on("click",{nombreHabilidad: nombreHabilidad}, eligeEspecialidad);
    return div;
}

/**
 *
 * @param {{principal:function,isDisabled:function}} callback
 * @param {{}} parametro
 * @param {string} [soloFisicasOMentales]
 */
function muestraDialogoElegirOpcionHabilidad(callback,parametro,soloFisicasOMentales) {
    var arrayOpciones =  [];
    var categorias = [];
    var i;
    var j;
    var grupoHabi;
    var habi;

    if (!soloFisicasOMentales) {
        soloFisicasOMentales = "habNatural";
    }

    for (i = 0; i < habilidades_secundarias.length;i++) {
        grupoHabi = habilidades_secundarias[i];
        categorias.push(new OpcionMostrable(_l(habilidades_secundarias_nombres_grupos[i]),habilidades_secundarias_nombres_grupos[i],habilidades_secundarias_nombres_grupos[i]+"_tipo"+soloFisicasOMentales));
        for (j = 0; j < grupoHabi.length; j++) {
            habi = getHabilidad(grupoHabi[j]);
            if ((soloFisicasOMentales == TIPO_BONIFICADOR_NATURAL_EXTRA) || (soloFisicasOMentales == "habNatural") ||
                ((soloFisicasOMentales == TIPO_BONIFICADOR_NATURAL_FISICO) && ((habi.getCaracteristica() == FUE) || (habi.getCaracteristica() == DES) || (habi.getCaracteristica() == AGI) || (habi.getCaracteristica() == CON))) ||
                ((soloFisicasOMentales == TIPO_BONIFICADOR_NATURAL_MENTAL) && ((habi.getCaracteristica() == INT) || (habi.getCaracteristica() == VOL) || (habi.getCaracteristica() == POD) || (habi.getCaracteristica() == PER)))) {
                arrayOpciones.push(new OpcionMostrable(_l(habi.getNombre()),habi.getNombre(),habilidades_secundarias_nombres_grupos[i]+"_tipo"+soloFisicasOMentales));
            }
        }
    }
    muestraDialogoElegirOpciones(arrayOpciones, parametro, {principal: callback.principal, isDisabled: callback.isDisabled}, true, categorias);
}

<|endoftext|>