<commit_before>/*  Copyright (c) 2011 The ORMMA.org project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

(function() {

   var ormmaview = window.ormmaview = {};

   /****************************************************/
   /********** PROPERTIES OF THE ORMMA BRIDGE **********/
   /****************************************************/

   /** Expand Properties */
   var expandProperties = {
        useBackground:false,
        backgroundColor:0xffffff,
        backgroundOpacity:1.0,
        isModal:false
    };

   /** The set of listeners for ORMMA Native Bridge Events */
   var listeners = { };

   /** Holds the current dimension values */
   dimensions : {};

   /** A Queue of Calls to the Native SDK that still need execution */
   var nativeCallQueue = [ ];

   /** Identifies if a native call is currently in progress */
   var nativeCallInFlight = false;

   /** timer for identifying iframes */
   var timer;
   var totalTime;

   /**********************************************/
   /************* JAVA ENTRY POINTS **************/
   /**********************************************/

   /**
    * Called by the JAVA SDK when an asset has been fully cached.
    *
    * @returns string, "OK"
    */
   ormmaview.fireAssetReadyEvent = function( alias, URL ) {
      var handlers = listeners["assetReady"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
            handlers[i]( alias, URL );
         }
      }

      return "OK";
   };

   /**
    * Called by the JAVA SDK when an asset has been removed from the
	* cache at the request of the creative.
    *
    * @returns string, "OK"
    */
   ormmaview.fireAssetRemovedEvent = function( alias ) {
      var handlers = listeners["assetRemoved"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
            handlers[i]( alias );
         }
      }

      return "OK";
   };

 	ormmaview.logHTML = function(){
 		ORMMADisplayControllerBridge.logHTML(document.documentElement.innerHTML);

 	};

   /**
    * Called by the JAVA SDK when an asset has been automatically
	* removed from the cache for reasons outside the control of the creative.
    *
    * @returns string, "OK"
    */
   ormmaview.fireAssetRetiredEvent = function( alias ) {
      var handlers = listeners["assetRetired"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
            handlers[i]( alias );
         }
      }

      return "OK";
   };

   /**
	* Called by the JAVA SDK when various state properties have changed.
    *
    * @returns string, "OK"
	*/
   ormmaview.fireChangeEvent = function( properties ) {
      var handlers = listeners["change"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
		    handlers[i]( properties );
         }
      }

      return "OK";
   };

   /**
    * Called by the JAVA SDK when an error has occured.
    *
    * @returns string, "OK"
    */
   ormmaview.fireErrorEvent = function( message, action ) {
      var handlers = listeners["error"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
            handlers[i]( message, action );
         }
      }

      return "OK";
   };

   /**
    * Called by the JAVA SDK when the user shakes the device.
    *
    * @returns string, "OK"
    */
   ormmaview.fireShakeEvent = function() {
      var handlers = listeners["shake"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
            handlers[i]();
         }
      }

      return "OK";
   };

   /**
    *
    */
   ormmaview.showAlert = function( message ) {
      ORMMAUtilityControllerBridge.showAlert( message );
   };

   /*********************************************/
   /********** INTERNALLY USED METHODS **********/
   /*********************************************/

   /**
    *
    */
   ormmaview.zeroPad = function( number ) {
      var text = "";
      if ( number < 10 ) {
         text += "0";
      }
	  text += number;
      return text;
   }

   /***************************************************************************/
   /********** LEVEL 0 (not part of spec, but required by public API **********/
   /***************************************************************************/

   /**
    *
    */
   ormmaview.activate = function( event ) {
   		 ORMMAUtilityControllerBridge.activate(event);
   };

   /**
    *
    */
   ormmaview.addEventListener = function( event, listener ) {
      var handlers = listeners[event];
	  if ( handlers == null ) {
		 // no handlers defined yet, set it up
         listeners[event] = [];
         handlers = listeners[event];
      }

      // see if the listener is already present
	  for ( var handler in handlers ) {
	     if ( listener == handler ) {
		    // listener already present, nothing to do
			return;
		}
	  }

      // not present yet, go ahead and add it
      handlers.push( listener );
   };

   /**
    *
    */
   ormmaview.deactivate = function( event ) {
      ORMMAUtilityControllerBridge.deactivate(event);
   };

   /**
    *
    */
   ormmaview.removeEventListener = function( event, listener ) {
	  var handlers = listeners[event];
	  if ( handlers != null ) {
         handlers.remove( listener );
	  }
   };

   /*****************************/
   /********** LEVEL 1 **********/
   /*****************************/

   /**
    *
    */
   ormmaview.close = function() {
   try {
   	  ORMMADisplayControllerBridge.close();
	  } catch ( e ) {
	     ormmaview.showAlert( "close: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.expand = function( dimensions, URL ) {
	  try {
		 this.dimensions = dimensions;
		 ORMMADisplayControllerBridge.expand(ormmaview.stringify(dimensions), URL, ormmaview.stringify(expandProperties));
	  } catch ( e ) {
	     ormmaview.showAlert( "executeNativeExpand: " + e + ", dimensions = " + dimensions  + ", URL = " + URL + ", expandProperties = " + expandProperties);
	  }
   };

   /**
    *
    */
   ormmaview.hide = function() {
   try {
	  ORMMADisplayControllerBridge.hide();
	  } catch ( e ) {
	     ormmaview.showAlert( "hide: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.open = function( URL, controls ) {
	  // the navigation parameter is an array, break it into its parts
	  var back = false;
	  var forward = false;
	  var refresh = false;
	  if ( controls == null ) {
		 back = true;
		 forward = true;
		 refresh = true;
	  }
	  else {
		 for ( var i = 0; i < controls.length; i++ ) {
			if ( ( controls[i] == "none" ) && ( i > 0 ) ) {
			   // error
			   self.fireErrorEvent( "none must be the only navigation element present.", "open" );
			   return;
			}
			else if ( controls[i] == "all" ) {
			   if ( i > 0 ) {
				   // error
				   self.fireErrorEvent( "none must be the only navigation element present.", "open" );
				   return;
				}

				// ok
				back = true;
				forward = true;
				refresh = true;
			}
			else if ( controls[i] == "back" ) {
				back = true;
			}
			else if ( controls[i] == "forward" ) {
				forward = true;
			}
			else if ( controls[i] == "refresh" ) {
				refresh = true;
			}
	     }
	  }

	 try{
	  ORMMADisplayControllerBridge.open(URL, back, forward, refresh);
   		} catch ( e ) {
	     ormmaview.showAlert( "open: " + e );
	  }

   };

   /**
   *
   */
  ormmaview.openMap = function( POI, fullscreen ) {
      try{
    	  ORMMADisplayControllerBridge.openMap(POI, fullscreen);
      } catch ( e ) {
	     ormmaview.showAlert( "openMap: " + e );
	  }
  };

  /**
  *
  */
  ormmaview.playAudio = function( URL, properties ) {

	var autoPlay = true, controls = true, loop = false, inline = false,
	    startStyle = 'normal', stopStyle = 'normal';

    if ( properties != null ) {

        if ( ( typeof properties.autoplay != "undefined" ) && ( properties.autoplay != null ) ) {
            autoPlay = true;
        }

        if ( ( typeof properties.controls != "undefined" ) && ( properties.controls != null ) ) {
        	controls = true;
        }

        if ( ( typeof properties.loop != "undefined" ) && ( properties.loop != null ) ) {
        	loop = true;
        }

        if ( ( typeof properties.inline != "undefined" ) && ( properties.inline != null ) ) {
        	inline = true;
        }

        //TODO check valid values...

        if ( ( typeof properties.startStyle != "undefined" ) && ( properties.startStyle != null ) ) {
             startStyle = properties.startStyle;
        }

        if ( ( typeof properties.stopStyle != "undefined" ) && ( properties.stopStyle != null ) ) {
            stopStyle = properties.stopStyle;
        }
    }

    try{
  	  ORMMADisplayControllerBridge.playAudio(URL, autoPlay, controls, loop, inline, startStyle, stopStyle);
    }
    catch ( e ) {
	     ormmaview.showAlert( "playAudio: " + e );
	}
 };

  /**
   *
   */
  ormmaview.playVideo = function( URL, properties ) {
	 var audioMuted = false, autoPlay = true, controls = true, loop = false, inline = [-1, -1, -1, -1],
	    startStyle = 'normal', stopStyle = 'normal';
     if ( properties != null ) {

         if ( ( typeof properties.audio != "undefined" ) && ( properties.audio != null ) ) {
             audioMuted = true;
         }

         if ( ( typeof properties.autoplay != "undefined" ) && ( properties.autoplay != null ) ) {
             autoPlay = true;
         }

         if ( ( typeof properties.controls != "undefined" ) && ( properties.controls != null ) ) {
         	controls = true;
         }

         if ( ( typeof properties.loop != "undefined" ) && ( properties.loop != null ) ) {
         	loop = true;
         }

         if ( ( typeof properties.inline != "undefined" ) && ( properties.inline != null ) ) {
        	 inline = new Array(4);

        	 inline[0] = properties.inline.top;
        	 inline[1] = properties.inline.left;

             if ( ( typeof properties.width != "undefined" ) && ( properties.width != null ) ) {
            	 inline[2] =  properties.width;
             }
             else{
                 //TODO ERROR
             }

             if ( ( typeof properties.height != "undefined" ) && ( properties.height != null ) ) {
            	 inline[3] =  properties.height;
             }
             else{
                 //TODO ERROR
             }
         }

         if ( ( typeof properties.startStyle != "undefined" ) && ( properties.startStyle != null ) ) {
             startStyle = properties.startStyle;
         }

         if ( ( typeof properties.stopStyle != "undefined" ) && ( properties.stopStyle != null ) ) {
            stopStyle = properties.stopStyle;
         }
     }

     try{
     	  ORMMADisplayControllerBridge.playVideo(URL, audioMuted, autoPlay, controls, loop, inline, startStyle, stopStyle);
       }
       catch ( e ) {
   	     ormmaview.showAlert( "playVideo: " + e );
   	}

  };

   /**
    *
    */
   ormmaview.resize = function( width, height ) {
   try {
	  ORMMADisplayControllerBridge.resize(width, height);
	  } catch ( e ) {
	     ormmaview.showAlert( "resize: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.setExpandProperties = function( properties ) {
	  expandProperties = properties;
   };

   /**
    *
    */
   ormmaview.show = function() {
   try{
	  ORMMADisplayControllerBridge.show();
	  } catch ( e ) {
	     ormmaview.showAlert( "show: " + e );
	  }
   };

   /*****************************/
   /********** LEVEL 2 **********/
   /*****************************/

   /**
    *
    */
   ormmaview.createEvent = function( date, title, body ) {
      	var msecs=(date.getTime()-date.getMilliseconds());

		try {
		ORMMAUtilityControllerBridge.createEvent(msecs.toString(), title, body);
		} catch ( e ) {
	     ormmaview.showAlert( "createEvent: " + e );
	  }

   };

   /**
    *
    */
   ormmaview.makeCall = function( phoneNumber ) {
   try {
	  ORMMAUtilityControllerBridge.makeCall(phoneNumber);
	  } catch ( e ) {
	     ormmaview.showAlert( "makeCall: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.sendMail = function( recipient, subject, body ) {
   try {
	  ORMMAUtilityControllerBridge.sendMail(recipient, subject, body);
	  } catch ( e ) {
	     ormmaview.showAlert( "sendMail: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.sendSMS = function( recipient, body ) {
   try {
	  ORMMAUtilityControllerBridge.sendSMS(recipient, body);
	  } catch ( e ) {
	     ormmaview.showAlert( "sendSMS: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.setShakeProperties = function( properties ) {
   };

   /*****************************/
   /********** LEVEL 3 **********/
   /*****************************/

   /**
    *
    */
   ormmaview.addAsset = function( URL, alias ) {

   };
   /**
    *
    */
   ormmaview.request = function( URI, display ) {

   };
   /**
    *
    */
   ormmaview.removeAsset = function( alias ) {
   };

   ormmaview.stringify = function(args) {
    if (typeof JSON === "undefined") {
        var s = "";
        var len = args.length;
        var i;
        if (typeof len == "undefined"){
        	return ormmaview.stringifyArg(args);
        }
        for (i = 0; i < args.length; i++) {
            if (i > 0) {
                s = s + ",";
            }
            s = s + ormmaview.stringifyArg(args[i]);
        }
        s = s + "]";
        return s;
    } else {
        return JSON.stringify(args);
    }
};

	ormmaview.stringifyArg = function(arg) {
        var s, type, start, name, nameType, a;
            type = typeof arg;
            s = "";
            if ((type === "number") || (type === "boolean")) {
                s = s + args;
            } else if (arg instanceof Array) {
                s = s + "[" + arg + "]";
            } else if (arg instanceof Object) {
                start = true;
                s = s + '{';
                for (name in arg) {
                    if (arg[name] !== null) {
                        if (!start) {
                            s = s + ',';
                        }
                        s = s + '"' + name + '":';
                        nameType = typeof arg[name];
                        if ((nameType === "number") || (nameType === "boolean")) {
                            s = s + arg[name];
                        } else if ((typeof arg[name]) === 'function') {
                            // don't copy the functions
                            s = s + '""';
                        } else if (arg[name] instanceof Object) {
                            s = s + this.stringify(args[i][name]);
                        } else {
                            s = s + '"' + arg[name] + '"';
                        }
                        start = false;
                    }
                }
                s = s + '}';
            } else {
                a = arg.replace(/\\/g, '\\\\');
                a = a.replace(/"/g, '\\"');
                s = s + '"' + a + '"';
            }
        ormmaview.showAlert("json:"+ s);
		return s;
	}

   })();
<commit_msg>argument default values for playaudio and video were wrong<commit_after>/*  Copyright (c) 2011 The ORMMA.org project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

(function() {

   var ormmaview = window.ormmaview = {};

   /****************************************************/
   /********** PROPERTIES OF THE ORMMA BRIDGE **********/
   /****************************************************/

   /** Expand Properties */
   var expandProperties = {
        useBackground:false,
        backgroundColor:0xffffff,
        backgroundOpacity:1.0,
        isModal:false
    };

   /** The set of listeners for ORMMA Native Bridge Events */
   var listeners = { };

   /** Holds the current dimension values */
   dimensions : {};

   /** A Queue of Calls to the Native SDK that still need execution */
   var nativeCallQueue = [ ];

   /** Identifies if a native call is currently in progress */
   var nativeCallInFlight = false;

   /** timer for identifying iframes */
   var timer;
   var totalTime;

   /**********************************************/
   /************* JAVA ENTRY POINTS **************/
   /**********************************************/

   /**
    * Called by the JAVA SDK when an asset has been fully cached.
    *
    * @returns string, "OK"
    */
   ormmaview.fireAssetReadyEvent = function( alias, URL ) {
      var handlers = listeners["assetReady"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
            handlers[i]( alias, URL );
         }
      }

      return "OK";
   };

   /**
    * Called by the JAVA SDK when an asset has been removed from the
	* cache at the request of the creative.
    *
    * @returns string, "OK"
    */
   ormmaview.fireAssetRemovedEvent = function( alias ) {
      var handlers = listeners["assetRemoved"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
            handlers[i]( alias );
         }
      }

      return "OK";
   };

 	ormmaview.logHTML = function(){
 		ORMMADisplayControllerBridge.logHTML(document.documentElement.innerHTML);

 	};

   /**
    * Called by the JAVA SDK when an asset has been automatically
	* removed from the cache for reasons outside the control of the creative.
    *
    * @returns string, "OK"
    */
   ormmaview.fireAssetRetiredEvent = function( alias ) {
      var handlers = listeners["assetRetired"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
            handlers[i]( alias );
         }
      }

      return "OK";
   };

   /**
	* Called by the JAVA SDK when various state properties have changed.
    *
    * @returns string, "OK"
	*/
   ormmaview.fireChangeEvent = function( properties ) {
      var handlers = listeners["change"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
		    handlers[i]( properties );
         }
      }

      return "OK";
   };

   /**
    * Called by the JAVA SDK when an error has occured.
    *
    * @returns string, "OK"
    */
   ormmaview.fireErrorEvent = function( message, action ) {
      var handlers = listeners["error"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
            handlers[i]( message, action );
         }
      }

      return "OK";
   };

   /**
    * Called by the JAVA SDK when the user shakes the device.
    *
    * @returns string, "OK"
    */
   ormmaview.fireShakeEvent = function() {
      var handlers = listeners["shake"];
      if ( handlers != null ) {
         for ( var i = 0; i < handlers.length; i++ ) {
            handlers[i]();
         }
      }

      return "OK";
   };

   /**
    *
    */
   ormmaview.showAlert = function( message ) {
      ORMMAUtilityControllerBridge.showAlert( message );
   };

   /*********************************************/
   /********** INTERNALLY USED METHODS **********/
   /*********************************************/

   /**
    *
    */
   ormmaview.zeroPad = function( number ) {
      var text = "";
      if ( number < 10 ) {
         text += "0";
      }
	  text += number;
      return text;
   }

   /***************************************************************************/
   /********** LEVEL 0 (not part of spec, but required by public API **********/
   /***************************************************************************/

   /**
    *
    */
   ormmaview.activate = function( event ) {
   		 ORMMAUtilityControllerBridge.activate(event);
   };

   /**
    *
    */
   ormmaview.addEventListener = function( event, listener ) {
      var handlers = listeners[event];
	  if ( handlers == null ) {
		 // no handlers defined yet, set it up
         listeners[event] = [];
         handlers = listeners[event];
      }

      // see if the listener is already present
	  for ( var handler in handlers ) {
	     if ( listener == handler ) {
		    // listener already present, nothing to do
			return;
		}
	  }

      // not present yet, go ahead and add it
      handlers.push( listener );
   };

   /**
    *
    */
   ormmaview.deactivate = function( event ) {
      ORMMAUtilityControllerBridge.deactivate(event);
   };

   /**
    *
    */
   ormmaview.removeEventListener = function( event, listener ) {
	  var handlers = listeners[event];
	  if ( handlers != null ) {
         handlers.remove( listener );
	  }
   };

   /*****************************/
   /********** LEVEL 1 **********/
   /*****************************/

   /**
    *
    */
   ormmaview.close = function() {
   try {
   	  ORMMADisplayControllerBridge.close();
	  } catch ( e ) {
	     ormmaview.showAlert( "close: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.expand = function( dimensions, URL ) {
	  try {
		 this.dimensions = dimensions;
		 ORMMADisplayControllerBridge.expand(ormmaview.stringify(dimensions), URL, ormmaview.stringify(expandProperties));
	  } catch ( e ) {
	     ormmaview.showAlert( "executeNativeExpand: " + e + ", dimensions = " + dimensions  + ", URL = " + URL + ", expandProperties = " + expandProperties);
	  }
   };

   /**
    *
    */
   ormmaview.hide = function() {
   try {
	  ORMMADisplayControllerBridge.hide();
	  } catch ( e ) {
	     ormmaview.showAlert( "hide: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.open = function( URL, controls ) {
	  // the navigation parameter is an array, break it into its parts
	  var back = false;
	  var forward = false;
	  var refresh = false;
	  if ( controls == null ) {
		 back = true;
		 forward = true;
		 refresh = true;
	  }
	  else {
		 for ( var i = 0; i < controls.length; i++ ) {
			if ( ( controls[i] == "none" ) && ( i > 0 ) ) {
			   // error
			   self.fireErrorEvent( "none must be the only navigation element present.", "open" );
			   return;
			}
			else if ( controls[i] == "all" ) {
			   if ( i > 0 ) {
				   // error
				   self.fireErrorEvent( "none must be the only navigation element present.", "open" );
				   return;
				}

				// ok
				back = true;
				forward = true;
				refresh = true;
			}
			else if ( controls[i] == "back" ) {
				back = true;
			}
			else if ( controls[i] == "forward" ) {
				forward = true;
			}
			else if ( controls[i] == "refresh" ) {
				refresh = true;
			}
	     }
	  }

	 try{
	  ORMMADisplayControllerBridge.open(URL, back, forward, refresh);
   		} catch ( e ) {
	     ormmaview.showAlert( "open: " + e );
	  }

   };

   /**
   *
   */
  ormmaview.openMap = function( POI, fullscreen ) {
      try{
    	  ORMMADisplayControllerBridge.openMap(POI, fullscreen);
      } catch ( e ) {
	     ormmaview.showAlert( "openMap: " + e );
	  }
  };

  /**
  *
  */
  ormmaview.playAudio = function( URL, properties ) {

	var autoPlay = false, controls = false, loop = false, inline = false,
	    startStyle = 'normal', stopStyle = 'normal';

    if ( properties != null ) {

        if ( ( typeof properties.autoplay != "undefined" ) && ( properties.autoplay != null ) ) {
            autoPlay = true;
        }

        if ( ( typeof properties.controls != "undefined" ) && ( properties.controls != null ) ) {
        	controls = true;
        }

        if ( ( typeof properties.loop != "undefined" ) && ( properties.loop != null ) ) {
        	loop = true;
        }

        if ( ( typeof properties.inline != "undefined" ) && ( properties.inline != null ) ) {
        	inline = true;
        }

        //TODO check valid values...

        if ( ( typeof properties.startStyle != "undefined" ) && ( properties.startStyle != null ) ) {
             startStyle = properties.startStyle;
        }

        if ( ( typeof properties.stopStyle != "undefined" ) && ( properties.stopStyle != null ) ) {
            stopStyle = properties.stopStyle;
        }
    }

    try{
  	  ORMMADisplayControllerBridge.playAudio(URL, autoPlay, controls, loop, inline, startStyle, stopStyle);
    }
    catch ( e ) {
	     ormmaview.showAlert( "playAudio: " + e );
	}
 };

  /**
   *
   */
  ormmaview.playVideo = function( URL, properties ) {
	 var audioMuted = false, autoPlay = false, controls = false, loop = false, inline = [-1, -1, -1, -1],
	    startStyle = 'normal', stopStyle = 'normal';
     if ( properties != null ) {

         if ( ( typeof properties.audio != "undefined" ) && ( properties.audio != null ) ) {
             audioMuted = true;
         }

         if ( ( typeof properties.autoplay != "undefined" ) && ( properties.autoplay != null ) ) {
             autoPlay = true;
         }

         if ( ( typeof properties.controls != "undefined" ) && ( properties.controls != null ) ) {
         	controls = true;
         }

         if ( ( typeof properties.loop != "undefined" ) && ( properties.loop != null ) ) {
         	loop = true;
         }

         if ( ( typeof properties.inline != "undefined" ) && ( properties.inline != null ) ) {
        	 inline = new Array(4);

        	 inline[0] = properties.inline.top;
        	 inline[1] = properties.inline.left;

             if ( ( typeof properties.width != "undefined" ) && ( properties.width != null ) ) {
            	 inline[2] =  properties.width;
             }
             else{
                 //TODO ERROR
             }

             if ( ( typeof properties.height != "undefined" ) && ( properties.height != null ) ) {
            	 inline[3] =  properties.height;
             }
             else{
                 //TODO ERROR
             }
         }

         if ( ( typeof properties.startStyle != "undefined" ) && ( properties.startStyle != null ) ) {
             startStyle = properties.startStyle;
         }

         if ( ( typeof properties.stopStyle != "undefined" ) && ( properties.stopStyle != null ) ) {
            stopStyle = properties.stopStyle;
         }
     }

     try{
     	  ORMMADisplayControllerBridge.playVideo(URL, audioMuted, autoPlay, controls, loop, inline, startStyle, stopStyle);
       }
       catch ( e ) {
   	     ormmaview.showAlert( "playVideo: " + e );
   	}

  };

   /**
    *
    */
   ormmaview.resize = function( width, height ) {
   try {
	  ORMMADisplayControllerBridge.resize(width, height);
	  } catch ( e ) {
	     ormmaview.showAlert( "resize: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.setExpandProperties = function( properties ) {
	  expandProperties = properties;
   };

   /**
    *
    */
   ormmaview.show = function() {
   try{
	  ORMMADisplayControllerBridge.show();
	  } catch ( e ) {
	     ormmaview.showAlert( "show: " + e );
	  }
   };

   /*****************************/
   /********** LEVEL 2 **********/
   /*****************************/

   /**
    *
    */
   ormmaview.createEvent = function( date, title, body ) {
      	var msecs=(date.getTime()-date.getMilliseconds());

		try {
		ORMMAUtilityControllerBridge.createEvent(msecs.toString(), title, body);
		} catch ( e ) {
	     ormmaview.showAlert( "createEvent: " + e );
	  }

   };

   /**
    *
    */
   ormmaview.makeCall = function( phoneNumber ) {
   try {
	  ORMMAUtilityControllerBridge.makeCall(phoneNumber);
	  } catch ( e ) {
	     ormmaview.showAlert( "makeCall: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.sendMail = function( recipient, subject, body ) {
   try {
	  ORMMAUtilityControllerBridge.sendMail(recipient, subject, body);
	  } catch ( e ) {
	     ormmaview.showAlert( "sendMail: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.sendSMS = function( recipient, body ) {
   try {
	  ORMMAUtilityControllerBridge.sendSMS(recipient, body);
	  } catch ( e ) {
	     ormmaview.showAlert( "sendSMS: " + e );
	  }
   };

   /**
    *
    */
   ormmaview.setShakeProperties = function( properties ) {
   };

   /*****************************/
   /********** LEVEL 3 **********/
   /*****************************/

   /**
    *
    */
   ormmaview.addAsset = function( URL, alias ) {

   };
   /**
    *
    */
   ormmaview.request = function( URI, display ) {

   };
   /**
    *
    */
   ormmaview.removeAsset = function( alias ) {
   };

   ormmaview.stringify = function(args) {
    if (typeof JSON === "undefined") {
        var s = "";
        var len = args.length;
        var i;
        if (typeof len == "undefined"){
        	return ormmaview.stringifyArg(args);
        }
        for (i = 0; i < args.length; i++) {
            if (i > 0) {
                s = s + ",";
            }
            s = s + ormmaview.stringifyArg(args[i]);
        }
        s = s + "]";
        return s;
    } else {
        return JSON.stringify(args);
    }
};

	ormmaview.stringifyArg = function(arg) {
        var s, type, start, name, nameType, a;
            type = typeof arg;
            s = "";
            if ((type === "number") || (type === "boolean")) {
                s = s + args;
            } else if (arg instanceof Array) {
                s = s + "[" + arg + "]";
            } else if (arg instanceof Object) {
                start = true;
                s = s + '{';
                for (name in arg) {
                    if (arg[name] !== null) {
                        if (!start) {
                            s = s + ',';
                        }
                        s = s + '"' + name + '":';
                        nameType = typeof arg[name];
                        if ((nameType === "number") || (nameType === "boolean")) {
                            s = s + arg[name];
                        } else if ((typeof arg[name]) === 'function') {
                            // don't copy the functions
                            s = s + '""';
                        } else if (arg[name] instanceof Object) {
                            s = s + this.stringify(args[i][name]);
                        } else {
                            s = s + '"' + arg[name] + '"';
                        }
                        start = false;
                    }
                }
                s = s + '}';
            } else {
                a = arg.replace(/\\/g, '\\\\');
                a = a.replace(/"/g, '\\"');
                s = s + '"' + a + '"';
            }
        ormmaview.showAlert("json:"+ s);
		return s;
	}

   })();
<|endoftext|>


<commit_before>javascript: (function () {
  var member = ['Rplus', 'whalesingswee', 'amazingandyyy', 'Clementtang', 'erwaiyang', 'noootown', 'ryrocks'];
  var allowedReactions = ['+1', 'thinking_face', 'tada'];

  var weight = {
    likes: 1,      /* 互動基數 */
    comments: 1.5, /* 鼓勵討論 */
    shares: 2,     /* 鼓勵擴散 */
    vote: 3        /* 些微調整 */
  };

  var comments = [].slice.call(document.querySelectorAll('.timeline-comment-wrapper'));

  var targetComments = comments.filter((comment) => {
    var firstTd = comment.querySelector('tbody td');
    return !!firstTd && /^\# \d+/.test(firstTd.textContent);
  });

  var emojisData = targetComments.map((t) => {
    var reactionBtn = [].slice.call(t.querySelectorAll('.comment-reactions-options .reaction-summary-item'));

    var avatarBoxStyle = document.getElementById('customAvatarBoxStyle');
    if (!avatarBoxStyle) {
      var style = document.createElement('style');
      style.id = 'customAvatarBoxStyle';
      style.innerHTML = '.customAvatarBox img {width: 20px; height: 20px; vertical-align: top; margin-left: 3px; border-radius: 3px;}';
      document.head.appendChild(style);
    }

    return reactionBtn.map((btn) => {
      var who = btn.getAttribute('aria-label').split(' reacted with')[0].replace(/,| and/g, '').split(/\s+/);

      var avatarBox = document.createElement('span');
      avatarBox.className = 'customAvatarBox';
      avatarBox.innerHTML = who.map((uid) => `<img src="https://github.com/${uid}.png">`).join('');
      btn.appendChild(avatarBox);

      return {
        reaction: btn.value.split(/\s+/)[0],
        who: who
      };
    });
  });

  var sumTable = emojisData.map((emojis, idx) => {
    var voteData = {};
    var _id = targetComments[idx].querySelector('.comment-body a').href.replace('https://fb.com/', '');

    console.log(idx, `https://fb.com/${_id}`);

    var tds = [].slice.call(targetComments[idx].querySelectorAll('tbody td'));
    var tdsData = tds.map((td) => {
      return td.textContent;
    });

    [voteData.order, voteData.likes, voteData.comments, voteData.shares] = tdsData;

    voteData.vote = 0;

    emojis.forEach((emoji) => {
      if (allowedReactions.indexOf(emoji.reaction) === -1) { return; }

      var reaction = emoji.reaction;
      var people = emoji.who;

      people.forEach((t) => {
        voteData[t] = reaction;
      });
    });

    Object.keys(voteData).forEach((i) => {
      if (!member.includes(i)) { return; }

      switch (voteData[i]) {
        case '+1':
          voteData.vote += 1;
          break;

        case 'thinking_face':
          voteData.vote -= 1;
          break;

        case 'tada':
          if (i === member[0]) {
            console.log('tada');
            voteData.vote -= 500;
          }
          break;
      }
    });

    voteData.calcSum = voteData.likes * weight.likes + voteData.comments * weight.comments + voteData.shares * weight.shares + voteData.vote * weight.vote;

    voteData.postId = _id;

    return voteData;
  });

  window.sumTable = sumTable;

  console.table(sumTable);
  console.log('copy(sumTable)');
})();
<commit_msg>修正 sumTable 未依最終統計結果排序的錯誤<commit_after>javascript: (function () {
  var member = ['Rplus', 'whalesingswee', 'amazingandyyy', 'Clementtang', 'erwaiyang', 'noootown', 'ryrocks'];
  var allowedReactions = ['+1', 'thinking_face', 'tada'];

  var weight = {
    likes: 1,      /* 互動基數 */
    comments: 1.5, /* 鼓勵討論 */
    shares: 2,     /* 鼓勵擴散 */
    vote: 3        /* 些微調整 */
  };

  var comments = [].slice.call(document.querySelectorAll('.timeline-comment-wrapper'));

  var targetComments = comments.filter((comment) => {
    var firstTd = comment.querySelector('tbody td');
    return !!firstTd && /^\# \d+/.test(firstTd.textContent);
  });

  var emojisData = targetComments.map((t) => {
    var reactionBtn = [].slice.call(t.querySelectorAll('.comment-reactions-options .reaction-summary-item'));

    var avatarBoxStyle = document.getElementById('customAvatarBoxStyle');
    if (!avatarBoxStyle) {
      var style = document.createElement('style');
      style.id = 'customAvatarBoxStyle';
      style.innerHTML = '.customAvatarBox img {width: 20px; height: 20px; vertical-align: top; margin-left: 3px; border-radius: 3px;}';
      document.head.appendChild(style);
    }

    return reactionBtn.map((btn) => {
      var who = btn.getAttribute('aria-label').split(' reacted with')[0].replace(/,| and/g, '').split(/\s+/);

      var avatarBox = document.createElement('span');
      avatarBox.className = 'customAvatarBox';
      avatarBox.innerHTML = who.map((uid) => `<img src="https://github.com/${uid}.png">`).join('');
      btn.appendChild(avatarBox);

      return {
        reaction: btn.value.split(/\s+/)[0],
        who: who
      };
    });
  });

  var sumTable = emojisData.map((emojis, idx) => {
    var voteData = {};
    var _id = targetComments[idx].querySelector('.comment-body a').href.replace('https://fb.com/', '');

    console.log(idx, `https://fb.com/${_id}`);

    var tds = [].slice.call(targetComments[idx].querySelectorAll('tbody td'));
    var tdsData = tds.map((td) => {
      return td.textContent;
    });

    [voteData.order, voteData.likes, voteData.comments, voteData.shares] = tdsData;

    voteData.vote = 0;

    emojis.forEach((emoji) => {
      if (allowedReactions.indexOf(emoji.reaction) === -1) { return; }

      var reaction = emoji.reaction;
      var people = emoji.who;

      people.forEach((t) => {
        voteData[t] = reaction;
      });
    });

    Object.keys(voteData).forEach((i) => {
      if (!member.includes(i)) { return; }

      switch (voteData[i]) {
        case '+1':
          voteData.vote += 1;
          break;

        case 'thinking_face':
          voteData.vote -= 1;
          break;

        case 'tada':
          if (i === member[0]) {
            console.log('tada');
            voteData.vote -= 500;
          }
          break;
      }
    });

    voteData.calcSum = voteData.likes * weight.likes + voteData.comments * weight.comments + voteData.shares * weight.shares + voteData.vote * weight.vote;

    voteData.postId = _id;

    return voteData;
  });

  window.sumTable = sumTable;

  window.top10 = sumTable.sort((a, b) => {
    return b.calcSum - a.calcSum;
  });

  console.table(window.top10);
  console.log('copy(top10)');
})();
<|endoftext|>


<commit_before>function game(){
	let tree = new Tree(new Board([0,0,0,0,0,0,0,0,0], 1), 100)

	let clickable = true
	let cross_marks = [] // Gamestate: List of positions where crosses are
	let circle_marks = [] // Gamestate: List of positions where circles are
	let scale = 100
	let bc1 = 'hsl(0,0%,20%)'
	let width = 2
	// Draw the Game Board on the Canvas
	let div = document.getElementById("gameCanvas")
	let canvas = document.createElementNS("http://www.w3.org/2000/svg", 'svg')
	canvas.setAttribute('style', 'width: 40%; float: right; margin: 0% 5% 5% 5%;')
    div.appendChild(canvas)
    canvas.setAttribute('viewBox', '0 0 ' + scale + ' ' + scale + ' ')
	let textele = document.createElementNS('http://www.w3.org/2000/svg','text')
    let textnode = document.createTextNode("Make a move!")
    textele.setAttribute('x', '50%')
    textele.setAttribute('y', '50%')
    textele.setAttribute('alignment-baseline', 'middle')
    textele.setAttribute('text-anchor', 'middle')
    textele.setAttribute('id', 'wintext')

	function draw_line(x1, y1, x2, y2) {
		let l1 = document.createElementNS("http://www.w3.org/2000/svg", 'line')
		canvas.appendChild(l1)
		l1.setAttribute('x1', x1)
		l1.setAttribute('y1', y1)
		l1.setAttribute('x2', x2)
		l1.setAttribute('y2', y2)
		l1.setAttribute('stroke', bc1)
		l1.setAttribute('stroke-width', width)
		l1.setAttribute('stroke-linecap' , 'round')
	}

	async function reset() {
		return new Promise(async (resolve) => {
			textnode.nodeValue = (tree.board.gameState == 2 ? "X Wins" : "Draw")
			await sleep(2000)
			tree = new Tree(new Board([0,0,0,0,0,0,0,0,0], 1), 100)
			for(let i = 0; i < 9; i++) {
				cross_marks[i].setAttribute('class','')
				circle_marks[i].setAttribute('class','')
			}
			textnode.nodeValue = ""
			clickable = true
			resolve('reset');
		})
	}

	// Loop over each of the moves unless the game ends early
	for(let i = 0; i < 9; i++) {
		let button = document.createElementNS("http://www.w3.org/2000/svg", 'rect')
		canvas.appendChild(button)
		button.setAttribute('x', i%3*scale/3)
		button.setAttribute('y', Math.floor(i/3)*scale/3)
		button.setAttribute('width', scale/3)
		button.setAttribute('height', scale/3)
		button.setAttribute('stroke', 'none')
		button.setAttribute('fill', 'hsl(60,5%,95%)')
		button.setAttribute('style', 'cursor:pointer;')
		// Initialize Circle and Cross Objects
		let circle = document.createElementNS("http://www.w3.org/2000/svg", 'path')
		canvas.appendChild(circle)
		let r = scale/8
		let place = "M " + (i%3*scale/3 + scale/6) + ", " + ((Math.floor(i/3)*scale/3) + (scale/6)) + " m " + (-1*r) + ", 0 a "+r+", "+r+" 0 1, 0 "+ ( 2 * r) + ", 0 a "+r+", "+r+" 0 1,0 " + ( -2 * r) + ",0"
		circle.setAttribute('d', place)
		circle.setAttribute('fill', 'none')
		circle.setAttribute('stroke', 'hsl(120, 50%, 50%)')
		circle.setAttribute('style', 'stroke-dasharray: 1000; stroke-dashoffset: 1000;  pointer-events: none;')
		circle.setAttribute('stroke-width', width)
		circle_marks.push(circle)
		let cross = document.createElementNS("http://www.w3.org/2000/svg", 'path')
		canvas.appendChild(cross)
		let off = 14
		place = "M " + (i%3*scale/3 + scale/off) + ", " + (Math.floor(i/3)*scale/3 + scale/off) +" L " + ((i%3*scale/3) + scale/3 - scale/off) + ", " + (Math.floor(i/3)*scale/3 + scale/3 - scale/off)+" M " + (i%3*scale/3 + scale/3 - scale/off)+ " " + (Math.floor(i/3)*scale/3 + scale/off) +" L " + (i%3*scale/3 + scale/off) + " " + (Math.floor(i/3)*scale/3 + scale/3 - scale/off)
		cross.setAttribute('d', place)
		cross.setAttribute('stroke', 'hsl(0, 50%, 50%)')
		cross.setAttribute('style', 'stroke-dasharray: 1000; stroke-dashoffset: 1000;  pointer-events: none;')
		cross.setAttribute('stroke-width', width)
		cross_marks.push(cross)
		// The Click Event Listener on the board
		button.onclick = async ()=> {
			if (tree.board.tiles[i] != 0 || clickable == false) {
				return;
			}
			clickable = false;
			textnode.nodeValue = "";
			let count = 0;
			for(let j = 0; j < i; j++) {
				if (tree.board.tiles[j] == 0) {
					count++;
				}
			}
			circle.setAttribute('class','gameapp')
			tree = tree.children[count];
			if(tree.board.gameState != 0) {
				await reset()
				return
			}
			let move = tree.best(); // Call to find the optimal move

			let location = 0
			count = -1;
			for(let j = 0; j < 9; j++) {
				if (tree.board.tiles[j] == 0)
					count++;
				if(count == move) {
					location = j;
					break
				}
			}
			await sleep(1000)
			cross_marks[location].setAttribute('class','gameapp')
			tree = tree.children[move];
			// Reset the board for the next game
			if(tree.board.gameState != 0) {
				await reset()
			}
			clickable = true
		}
	}

	draw_line(scale/3, width/2, scale/3, scale-width/2)
	draw_line(scale/3*2, width/2, scale/3*2, scale-width/2)
	draw_line(width/2, scale/3, scale-width/2, scale/3)
	draw_line(width/2, scale/3*2, scale-width/2, scale/3*2)
	textele.appendChild(textnode)
	canvas.appendChild(textele)
}

<commit_msg>attempt at #168 (#169)<commit_after>function game(){
	let tree = new Tree(new Board([0,0,0,0,0,0,0,0,0], 1), 100)

	let clickable = true
	let cross_marks = [] // Gamestate: List of positions where crosses are
	let circle_marks = [] // Gamestate: List of positions where circles are
	let scale = 100
	let bc1 = 'hsl(0,0%,20%)'
	let width = 2
	// Draw the Game Board on the Canvas
	let div = document.getElementById("gameCanvas")
	let canvas = document.createElementNS("http://www.w3.org/2000/svg", 'svg')
	canvas.setAttribute('style', 'width: 40%; float: right; margin: 0% 5% 5% 5%;')
    div.appendChild(canvas)
    canvas.setAttribute('viewBox', '0 0 ' + scale + ' ' + scale + ' ')
	let textele = document.createElementNS('http://www.w3.org/2000/svg','text')
    let textnode = document.createTextNode("Make a move!")
    textele.setAttribute('x', '50%')
    textele.setAttribute('y', '50%')
    textele.setAttribute('alignment-baseline', 'middle')
    textele.setAttribute('text-anchor', 'middle')
    textele.setAttribute('id', 'wintext')

	function draw_line(x1, y1, x2, y2) {
		let l1 = document.createElementNS("http://www.w3.org/2000/svg", 'line')
		canvas.appendChild(l1)
		l1.setAttribute('x1', x1)
		l1.setAttribute('y1', y1)
		l1.setAttribute('x2', x2)
		l1.setAttribute('y2', y2)
		l1.setAttribute('stroke', bc1)
		l1.setAttribute('stroke-width', width)
		l1.setAttribute('stroke-linecap' , 'round')
	}

	async function reset() {
		return new Promise(async (resolve) => {
			textnode.nodeValue = (tree.board.gameState == 2 ? "X Wins" : tree.board.gameState == 1 ? "O wins" : "Draw")
			await sleep(2000)
			tree = new Tree(new Board([0,0,0,0,0,0,0,0,0], 1), 100)
			for(let i = 0; i < 9; i++) {
				cross_marks[i].setAttribute('class','')
				circle_marks[i].setAttribute('class','')
			}
			textnode.nodeValue = ""
			clickable = true
			resolve('reset');
		})
	}

	// Loop over each of the moves unless the game ends early
	for(let i = 0; i < 9; i++) {
		let button = document.createElementNS("http://www.w3.org/2000/svg", 'rect')
		canvas.appendChild(button)
		button.setAttribute('x', i%3*scale/3)
		button.setAttribute('y', Math.floor(i/3)*scale/3)
		button.setAttribute('width', scale/3)
		button.setAttribute('height', scale/3)
		button.setAttribute('stroke', 'none')
		button.setAttribute('fill', 'hsl(60,5%,95%)')
		button.setAttribute('style', 'cursor:pointer;')
		// Initialize Circle and Cross Objects
		let circle = document.createElementNS("http://www.w3.org/2000/svg", 'path')
		canvas.appendChild(circle)
		let r = scale/8
		let place = "M " + (i%3*scale/3 + scale/6) + ", " + ((Math.floor(i/3)*scale/3) + (scale/6)) + " m " + (-1*r) + ", 0 a "+r+", "+r+" 0 1, 0 "+ ( 2 * r) + ", 0 a "+r+", "+r+" 0 1,0 " + ( -2 * r) + ",0"
		circle.setAttribute('d', place)
		circle.setAttribute('fill', 'none')
		circle.setAttribute('stroke', 'hsl(120, 50%, 50%)')
		circle.setAttribute('style', 'stroke-dasharray: 1000; stroke-dashoffset: 1000;  pointer-events: none;')
		circle.setAttribute('stroke-width', width)
		circle_marks.push(circle)
		let cross = document.createElementNS("http://www.w3.org/2000/svg", 'path')
		canvas.appendChild(cross)
		let off = 14
		place = "M " + (i%3*scale/3 + scale/off) + ", " + (Math.floor(i/3)*scale/3 + scale/off) +" L " + ((i%3*scale/3) + scale/3 - scale/off) + ", " + (Math.floor(i/3)*scale/3 + scale/3 - scale/off)+" M " + (i%3*scale/3 + scale/3 - scale/off)+ " " + (Math.floor(i/3)*scale/3 + scale/off) +" L " + (i%3*scale/3 + scale/off) + " " + (Math.floor(i/3)*scale/3 + scale/3 - scale/off)
		cross.setAttribute('d', place)
		cross.setAttribute('stroke', 'hsl(0, 50%, 50%)')
		cross.setAttribute('style', 'stroke-dasharray: 1000; stroke-dashoffset: 1000;  pointer-events: none;')
		cross.setAttribute('stroke-width', width)
		cross_marks.push(cross)
		// The Click Event Listener on the board
		button.onclick = async ()=> {
			if (tree.board.tiles[i] != 0 || clickable == false) {
				return;
			}
			clickable = false;
			textnode.nodeValue = "";
			let count = 0;
			for(let j = 0; j < i; j++) {
				if (tree.board.tiles[j] == 0) {
					count++;
				}
			}
			circle.setAttribute('class','gameapp')
			tree = tree.children[count];
			if(tree.board.gameState != 0) {
				await reset()
				return
			}
			let move = tree.best(); // Call to find the optimal move

			let location = 0
			count = -1;
			for(let j = 0; j < 9; j++) {
				if (tree.board.tiles[j] == 0)
					count++;
				if(count == move) {
					location = j;
					break
				}
			}
			await sleep(1000)
			cross_marks[location].setAttribute('class','gameapp')
			tree = tree.children[move];
			// Reset the board for the next game
			if(tree.board.gameState != 0) {
				await reset()
			}
			clickable = true
		}
	}

	draw_line(scale/3, width/2, scale/3, scale-width/2)
	draw_line(scale/3*2, width/2, scale/3*2, scale-width/2)
	draw_line(width/2, scale/3, scale-width/2, scale/3)
	draw_line(width/2, scale/3*2, scale-width/2, scale/3*2)
	textele.appendChild(textnode)
	canvas.appendChild(textele)
}

<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies
 */

var utils = require('lazy-cache')(require);
var fn = require;

require = utils;
require('mixin-deep', 'merge');
require('through2', 'through');
require = fn;

/**
 * Expose `utils`
 */

module.exports = utils;
<commit_msg>move debug function to utils<commit_after>'use strict';

/**
 * Module dependencies
 */

var utils = require('lazy-cache')(require);
var fn = require;

require = utils;
require('mixin-deep', 'merge');
require('through2', 'through');
require = fn;

utils.debug = require('debug')('base:assemble:assemble-render-file');

/**
 * Expose `utils`
 */

module.exports = utils;
<|endoftext|>


<commit_before>exports = module.exports = {
    getXmlFileNameFromClip: function(clip) {
        return clip.playlist_id + "-" + clip.id + ".xml";
    },

    getPlaylistIdFromXmlFileName: function(filename) {
        var aux = filename.split("-");
        if ( aux.length > 0 ) {
            filename = aux[0];
		}
		return filename;
    },

    getClipIdFromXmlFileName: function(filename) {
        var aux = filename.split("-");
        if ( aux.length > 1 ) {
            aux = aux[1];
            filename = aux.substring(0, aux.length - 5);
        }
        return filename;
    },

    getTimeLengthFromFrames: function(frames, fps) {
        var seconds = parseFloat(frames) / parseFloat(fps);
        var minutes = 0;
        if (seconds > 60) {
            minutes = parseInt(seconds / 60);
            seconds = parseInt (seconds - (minutes * 60));
        }
        var hours = 0;
        if (minutes > 60) {
            hours = parseInt(hours / 60);
            minutes = parseInt(minutes - (hours * 60));
        }
        return "." + hours + ":" + minutes + ":" + seconds;
    },

    getCurrentPosFromClip: function(actualFrame, totalFrames) {
        return parseFloat(actualFrame / totalFrames);
    }
};<commit_msg>Migrating mosto functions to util<commit_after>var moment = require('moment');

exports = module.exports = {
    getXmlFileNameFromClip: function(clip) {
        return clip.playlist_id + "-" + clip.id + ".xml";
    },

    getPlaylistIdFromXmlFileName: function(filename) {
        var aux = filename.split("-");
        if ( aux.length > 0 ) {
            filename = aux[0];
		}
		return filename;
    },

    getClipIdFromXmlFileName: function(filename) {
        var aux = filename.split("-");
        if ( aux.length > 1 ) {
            aux = aux[1];
            filename = aux.substring(0, aux.length - 5);
        }
        return filename;
    },

    getTimeLengthFromFrames: function(frames, fps) {
        var seconds = parseFloat(frames) / parseFloat(fps);
        var minutes = 0;
        if (seconds > 60) {
            minutes = parseInt(seconds / 60);
            seconds = parseInt (seconds - (minutes * 60));
        }
        var hours = 0;
        if (minutes > 60) {
            hours = parseInt(hours / 60);
            minutes = parseInt(minutes - (hours * 60));
        }
        return "." + hours + ":" + minutes + ":" + seconds;
    },

    getCurrentPosFromClip: function(actualFrame, totalFrames) {
        return parseFloat(actualFrame / totalFrames);
    },

    convertFramesToSeconds: function ( frames, fps ) {
        return frames/fps;
    },

    convertLengthToMilliseconds: function ( frames ) {
        var m = moment( frames, "HH:mm:ss.SS");
        return m.hours()*60*60*1000 + m.minutes()*60*1000 + m.seconds()*1000 + m.milliseconds();
    },

    convertFramesToMilliseconds: function ( frames, fps ) {
		if (fps+""=="NaN" || fps==undefined || fps===false || fps==0) {
            var m = moment( frames, "HH:mm:ss.SS");
            return m.hours()*60*60*1000 + m.minutes()*60*1000 + m.seconds()*1000 + m.milliseconds();
 		}
        return frames * 1000.0 / (1.0 * fps);
    },

    convertUnixToDate:  function ( unix_timestamp ) {
        //var date = new Date(unix_timestamp*1000);
        var date = new moment(unix_timestamp);
        return date.format("hh:mm:ss");
    },

    convertDateToUnix:  function ( date_timestamp ) {
        var date = new moment(date_timestamp);
        return date.unix();
    }
};
<|endoftext|>


<commit_before>class _PrerenderData {
  constructor(options) {
    this.initialPrefs = options.initialPrefs;
    this.initialSections = options.initialSections;
    this._setValidation(options.validation);
  }

  get validation() {
    return this._validation;
  }

  set validation(value) {
    this._setValidation(value);
  }

  get invalidatingPrefs() {
    return this._invalidatingPrefs;
  }

    // This is needed so we can use it in the constructor
  _setValidation(value = []) {
    this._validation = value;
    this._invalidatingPrefs = value.reduce((result, next) => {
      if (typeof next === "string") {
        result.push(next);
        return result;
      } else if (next && next.oneOf) {
        return result.concat(next.oneOf);
      } else if (next && next.indexedDB) {
        return result.concat(next.indexedDB);
      } else if (next && next.jsonPrefs) {
        return result.concat(next.jsonPrefs);
      }
      throw new Error("Your validation configuration is not properly configured");
    }, []);
  }

  _isPrefEnabled(prefObj) {
    try {
      let data = JSON.parse(prefObj);
      return data && data.enabled;
    } catch (e) {
      return null;
    }
  }

  arePrefsValid(getPref, indexedDBPrefs) {
    for (const prefs of this.validation) {
      // {oneOf: ["foo", "bar"]}
      if (prefs && prefs.oneOf && !prefs.oneOf.some(name => getPref(name) === this.initialPrefs[name])) {
        return false;

        // {indexedDB: ["foo", "bar"]}
      } else if (indexedDBPrefs && prefs && prefs.indexedDB) {
        const anyModifiedPrefs = prefs.indexedDB.some(prefName => indexedDBPrefs.some(pref => pref && pref[prefName]));
        if (anyModifiedPrefs) {
          return false;
        }
        // {jsonPrefs: ["foo", "bar"]}
      } else if (prefs && prefs.jsonPrefs) {
        const isPrefModified =
          prefs.jsonPrefs.some(name => this._isPrefEnabled(getPref(name)) !== this.initialPrefs[name].enabled);
        if (isPrefModified) {
          return false;
        }
        // "foo"
      } else if (getPref(prefs) !== this.initialPrefs[prefs]) {
        return false;
      }
    }
    return true;
  }
}

this.PrerenderData = new _PrerenderData({
  initialPrefs: {
    "migrationExpired": true,
    "feeds.topsites": true,
    "showSearch": true,
    "topSitesRows": 1,
    "feeds.section.topstories": true,
    "feeds.section.highlights": true,
    "sectionOrder": "topsites,topstories,highlights",
    "collapsed": false,
    "discoverystream.config": {"enabled": false},
  },
  // Prefs listed as invalidating will prevent the prerendered version
  // of AS from being used if their value is something other than what is listed
  // here. This is required because some preferences cause the page layout to be
  // too different for the prerendered version to be used. Unfortunately, this
  // will result in users who have modified some of their preferences not being
  // able to get the benefits of prerendering.
  validation: [
    "feeds.topsites",
    "showSearch",
    "topSitesRows",
    "sectionOrder",
    // This means if either of these are set to their default values,
    // prerendering can be used.
    {oneOf: ["feeds.section.topstories", "feeds.section.highlights"]},
    // If any component has the following preference set to `true` it will
    // invalidate the prerendered version.
    {indexedDB: ["collapsed"]},
    // For below prefs, parse value to check enabled property. If enabled property
    // differs from initial prefs enabled value, prerendering cannot be used
    {jsonPrefs: ["discoverystream.config"]},
  ],
  initialSections: [
    {
      enabled: true,
      icon: "pocket",
      id: "topstories",
      order: 1,
      title: {id: "header_recommended_by", values: {provider: "Pocket"}},
    },
    {
      enabled: true,
      id: "highlights",
      icon: "highlights",
      order: 2,
      title: {id: "header_highlights"},
    },
  ],
});

this._PrerenderData = _PrerenderData;
const EXPORTED_SYMBOLS = ["PrerenderData", "_PrerenderData"];
<commit_msg>Port Bug 1523703 - Pref on Pocket Newtab experience in Nightly for EN and CA (#4770)<commit_after>class _PrerenderData {
  constructor(options) {
    this.initialPrefs = options.initialPrefs;
    this.initialSections = options.initialSections;
    this._setValidation(options.validation);
  }

  get validation() {
    return this._validation;
  }

  set validation(value) {
    this._setValidation(value);
  }

  get invalidatingPrefs() {
    return this._invalidatingPrefs;
  }

    // This is needed so we can use it in the constructor
  _setValidation(value = []) {
    this._validation = value;
    this._invalidatingPrefs = value.reduce((result, next) => {
      if (typeof next === "string") {
        result.push(next);
        return result;
      } else if (next && next.oneOf) {
        return result.concat(next.oneOf);
      } else if (next && next.indexedDB) {
        return result.concat(next.indexedDB);
      } else if (next && next.jsonPrefs) {
        return result.concat(next.jsonPrefs);
      }
      throw new Error("Your validation configuration is not properly configured");
    }, []);
  }

  _isPrefEnabled(prefObj) {
    try {
      let data = JSON.parse(prefObj);
      return (data && data.enabled) ? true : false;
    } catch (e) {
      return false;
    }
  }

  arePrefsValid(getPref, indexedDBPrefs) {
    for (const prefs of this.validation) {
      // {oneOf: ["foo", "bar"]}
      if (prefs && prefs.oneOf && !prefs.oneOf.some(name => getPref(name) === this.initialPrefs[name])) {
        return false;

        // {indexedDB: ["foo", "bar"]}
      } else if (indexedDBPrefs && prefs && prefs.indexedDB) {
        const anyModifiedPrefs = prefs.indexedDB.some(prefName => indexedDBPrefs.some(pref => pref && pref[prefName]));
        if (anyModifiedPrefs) {
          return false;
        }
        // {jsonPrefs: ["foo", "bar"]}
      } else if (prefs && prefs.jsonPrefs) {
        const isPrefModified =
          prefs.jsonPrefs.some(name => this._isPrefEnabled(getPref(name)) !== this.initialPrefs[name].enabled);
        if (isPrefModified) {
          return false;
        }
        // "foo"
      } else if (getPref(prefs) !== this.initialPrefs[prefs]) {
        return false;
      }
    }
    return true;
  }
}

this.PrerenderData = new _PrerenderData({
  initialPrefs: {
    "migrationExpired": true,
    "feeds.topsites": true,
    "showSearch": true,
    "topSitesRows": 1,
    "feeds.section.topstories": true,
    "feeds.section.highlights": true,
    "sectionOrder": "topsites,topstories,highlights",
    "collapsed": false,
    "discoverystream.config": {"enabled": false},
  },
  // Prefs listed as invalidating will prevent the prerendered version
  // of AS from being used if their value is something other than what is listed
  // here. This is required because some preferences cause the page layout to be
  // too different for the prerendered version to be used. Unfortunately, this
  // will result in users who have modified some of their preferences not being
  // able to get the benefits of prerendering.
  validation: [
    "feeds.topsites",
    "showSearch",
    "topSitesRows",
    "sectionOrder",
    // This means if either of these are set to their default values,
    // prerendering can be used.
    {oneOf: ["feeds.section.topstories", "feeds.section.highlights"]},
    // If any component has the following preference set to `true` it will
    // invalidate the prerendered version.
    {indexedDB: ["collapsed"]},
    // For below prefs, parse value to check enabled property. If enabled property
    // differs from initial prefs enabled value, prerendering cannot be used
    {jsonPrefs: ["discoverystream.config"]},
  ],
  initialSections: [
    {
      enabled: true,
      icon: "pocket",
      id: "topstories",
      order: 1,
      title: {id: "header_recommended_by", values: {provider: "Pocket"}},
    },
    {
      enabled: true,
      id: "highlights",
      icon: "highlights",
      order: 2,
      title: {id: "header_highlights"},
    },
  ],
});

this._PrerenderData = _PrerenderData;
const EXPORTED_SYMBOLS = ["PrerenderData", "_PrerenderData"];
<|endoftext|>


<commit_before>/**
 *  Utils
 *  Util functions for Mono modules.
 *
 * */
var Utils = module.exports = {};

/**
 *  Find value
 *  Finds a value in parent (object) using the dot notation passed in dotNot.
 *
 *  Example:
 *
 *      Utils.findValue ({
 *          a: {
 *              b: 1
 *          }
 *      }, "a.b") === 1 // true
 * */
Utils.findValue = function (parent, dotNot) {

    if (!dotNot || !dotNot) return undefined;

    var splits = dotNot.split(".")
      , value
      ;

    for (var i = 0; i < splits.length; ++i) {
        value = parent[splits[i]];
        if (value === undefined) return undefined;
        if (typeof value === "object") parent = value;
    }

    return value;
};

/**
 *  Find function
 *  Finds a function in parent (object) using the dot notation passed in dotNot.
 *
 *  Example:
 *
 *      typeof Utils.findFunction ({
 *          a: {
 *              b: function () {}
 *          }
 *      }, "a.b") === "function" // true
 * */
Utils.findFunction = function (parent, dotNot) {

    var func = Utils.findValue (parent, dotNot);

    if (typeof func !== "function") {
        return undefined;
    }

    return func;
};

/**
 *  Converts an object to a flat one
 *
 *  Example
 *
 *      Utils.flattenObject ({
 *          a: {
 *              b: 1
 *          }
 *      }); // { "a.b": 1 }
 *
 * */
Utils.flattenObject = function (obj) {

    var result = {};

    for (var key in obj) {
        if (!obj.hasOwnProperty(key)) continue;

        if (typeof obj[key] === 'object' && !(obj[key] instanceof Array)) {
            var flat = Utils.flattenObject (obj[key]);
            for (var x in flat) {
                if (!flat.hasOwnProperty(x)) {
                     continue;
                }

                result[key + '.' + x] = flat[x];
            }
        } else {
            result[key] = obj[key];
        }
    }
    return result;
};

/**
 *  Converts a flat object to an unflatten one
 *
 *  Example
 *
 *      Utils.flattenObject ({
 *          "a.b": 1
 *      }); // { a: { b: 1 } }
 *
 * */
Utils.unflattenObject = function (flat) {

    var result = {}
      , parentObj = result
      ;

    var keys = Object.keys(flat);
    for (var i = 0; i < keys.length; ++i) {

        var key = keys[i]
          , subkeys = key.split('.')
          , last = subkeys.pop()
          ;

        for (var ii = 0; ii < subkeys.length; ++ii) {
            var subkey = subkeys[ii];
            parentObj[subkey] = typeof parentObj[subkey] === 'undefined' ? {} : parentObj[subkey];
            parentObj = parentObj[subkey];
        }

        parentObj[last] = flat[key];
        parentObj = result;
    }

    return result;
};

/**
 *  cloneObject
 *
 *  Example
 *
 *      var cloned = Utils.cloneObject ({
 *          "hello": "world"
 *      });
 *
 * */
Utils.cloneObject = function cloneObject(item, deepClone) {
    if (!deepClone) {
        var c = function () {};
        c.prototype = Object(item);
        return new c();
    }

    if (!item) { return item; } // null, undefined values check

    var types = [ Number, String, Boolean ],
        result;

    // normalizing primitives if someone did new String('aaa'), or new Number('444');
    types.forEach(function(type) {
        if (item instanceof type) {
            result = type( item );
        }
    });

    if (typeof result == "undefined") {
        if (Object.prototype.toString.call( item ) === "[object Array]") {
            result = [];
            item.forEach(function(child, index, array) {
                result[index] = cloneObject( child );
            });
        } else if (typeof item == "object") {
            // testing that this is DOM
            if (item.nodeType && typeof item.cloneNode == "function") {
                var result = item.cloneNode( true );
            } else if (!item.prototype) { // check that this is a literal
                if (item instanceof Date) {
                    result = new Date(item);
                } else {
                    // it is an object literal
                    result = {};
                    for (var i in item) {
                        result[i] = cloneObject( item[i] );
                    }
                }
            } else {
                // depending what you would like here,
                // just keep the reference, or create new object
                if (false && item.constructor) {
                    // would not advice to do that, reason? Read below
                    result = new item.constructor();
                } else {
                    result = item;
                }
            }
        } else {
            result = item;
        }
    }

    return result;
};
<commit_msg>Minor enchantments<commit_after>/**
 *  Utils
 *  Util functions for Mono modules.
 *
 * */
var Utils = module.exports = {};

/**
 *  Find value
 *  Finds a value in parent (object) using the dot notation passed in dotNot.
 *
 *  Example:
 *
 *      Utils.findValue ({
 *          a: {
 *              b: 1
 *          }
 *      }, "a.b") === 1 // true
 * */
Utils.findValue = function (parent, dotNot) {

    if (!dotNot || !dotNot) return undefined;

    var splits = dotNot.split(".")
      , value
      ;

    for (var i = 0; i < splits.length; ++i) {
        value = parent[splits[i]];
        if (value === undefined) return undefined;
        if (typeof value === "object") parent = value;
    }

    return value;
};

/**
 *  Find function
 *  Finds a function in parent (object) using the dot notation passed in dotNot.
 *
 *  Example:
 *
 *      typeof Utils.findFunction ({
 *          a: {
 *              b: function () {}
 *          }
 *      }, "a.b") === "function" // true
 * */
Utils.findFunction = function (parent, dotNot) {

    var func = Utils.findValue (parent, dotNot);

    if (typeof func !== "function") {
        return undefined;
    }

    return func;
};

/**
 *  Converts an object to a flat one
 *
 *  Example
 *
 *      Utils.flattenObject ({
 *          a: {
 *              b: 1
 *          }
 *      }); // { "a.b": 1 }
 *
 * */
Utils.flattenObject = function (obj) {

    var result = {};

    for (var key in obj) {
        if (!obj.hasOwnProperty(key)) continue;

        if (typeof obj[key] === 'object' && !(obj[key] instanceof Array)) {
            var flat = Utils.flattenObject (obj[key]);
            for (var x in flat) {
                if (!flat.hasOwnProperty(x)) {
                     continue;
                }

                result[key + '.' + x] = flat[x];
            }
        } else {
            result[key] = obj[key];
        }
    }
    return result;
};

/**
 *  Converts a flat object to an unflatten one
 *
 *  Example
 *
 *      Utils.flattenObject ({
 *          "a.b": 1
 *      }); // { a: { b: 1 } }
 *
 * */
Utils.unflattenObject = function (flat) {

    var result = {}
      , parentObj = result
      ;

    var keys = Object.keys(flat);
    for (var i = 0; i < keys.length; ++i) {

        var key = keys[i]
          , subkeys = key.split('.')
          , last = subkeys.pop()
          ;

        for (var ii = 0; ii < subkeys.length; ++ii) {
            var subkey = subkeys[ii];
            parentObj[subkey] = typeof parentObj[subkey] === 'undefined' ? {} : parentObj[subkey];
            parentObj = parentObj[subkey];
        }

        parentObj[last] = flat[key];
        parentObj = result;
    }

    return result;
};

/**
 *  cloneObject
 *
 *  Example
 *
 *      var cloned = Utils.cloneObject ({
 *          "hello": "world"
 *      });
 *
 * */
Utils.cloneObject = function (item, deepClone) {
    if (!deepClone) {
        var c = function () {};
        c.prototype = Object(item);
        return new c();
    }

    if (!item) { return item; } // null, undefined values check

    var types = [Number, String, Boolean];
    var result;

    // normalizing primitives if someone did new String('aaa'), or new Number('444');
    types.forEach(function(type) {
        if (item instanceof type) {
            result = type( item );
        }
    });

    if (typeof result == "undefined") {
        if (Object.prototype.toString.call( item ) === "[object Array]") {
            result = [];
            item.forEach(function(child, index, array) {
                result[index] = Utils.cloneObject(child, true);
            });
        } else if (typeof item == "object") {
            // testing that this is DOM
            if (item.nodeType && typeof item.cloneNode == "function") {
                var result = item.cloneNode(true)
            } else if (!item.prototype) { // check that this is a literal
                if (item instanceof Date) {
                    result = new Date(item);
                } else {
                    // it is an object literal
                    result = {};
                    for (var i in item) {
                        result[i] = Utils.cloneObject(item[i], true);
                    }
                }
            } else {
                // depending what you would like here,
                // just keep the reference, or create new object
                if (false && item.constructor) {
                    // would not advice to do that, reason? Read below
                    result = new item.constructor();
                } else {
                    result = item;
                }
            }
        } else {
            result = item;
        }
    }

    return result;
};
<|endoftext|>


<commit_before>//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

const async = require('async');

// ----------------------------------------------------------------------------
// Returns an integer, random, between low and high (exclusive) - [low, high)
// ----------------------------------------------------------------------------
exports.randomInteger = function (low, high) {
  return Math.floor(Math.random() * (high - low) + low);
};

// ----------------------------------------------------------------------------
// Session utility: Store the referral URL, if present, and redirect to a new
// location.
// ----------------------------------------------------------------------------
exports.storeReferrer = function storeReferrer(req, res, redirect, optionalReason) {
  const eventDetails = {
    method: 'storeReferrer',
    reason: optionalReason || 'unknown reason',
  };
  if (req.session && req.headers && req.headers.referer && req.session.referer !== undefined && !req.headers.referer.includes('/signout')) {
    req.session.referer = req.headers.referer;
    eventDetails.referer = req.headers.referer;
  }
  if (redirect) {
    eventDetails.redirect = redirect;
    if (req.insights) {
      req.insights.trackEvent('RedirectWithReferrer', eventDetails);
    }
    res.redirect(redirect);
  }
};

// ----------------------------------------------------------------------------
// Session utility: store the original URL
// ----------------------------------------------------------------------------
exports.storeOriginalUrlAsReferrer = function storeOriginalUrl(req, res, redirect, optionalReason) {
  storeOriginalUrlAsVariable(req, res, 'referer', redirect, optionalReason);
};

exports.redirectToReferrer = function redirectToReferrer(req, res, url, optionalReason) {
  url = url || '/';
  const alternateUrl = popSessionVariable(req, res, 'referer');
  const eventDetails = {
    method: 'redirectToReferrer',
    reason: optionalReason || 'unknown reason',
  };
  if (req.insights) {
    req.insights.trackEvent('RedirectToReferrer', eventDetails);
  }
  res.redirect(alternateUrl || url);
};

function storeOriginalUrlAsVariable(req, res, variable, redirect, optionalReason) {
  const eventDetails = {
    method: 'storeOriginalUrlAsVariable',
    variable: variable,
    redirect: redirect,
    reason: optionalReason || 'unknown reason',
  };
  if (req.session && req.originalUrl) {
    req.session[variable] = req.originalUrl;
  }
  if (redirect) {
    if (req.insights) {
      req.insights.trackEvent('RedirectFromOriginalUrl', eventDetails);
    }
    res.redirect(redirect);
  }
}

exports.storeOriginalUrlAsVariable = storeOriginalUrlAsVariable;

function popSessionVariable(req, res, variableName) {
  if (req.session && req.session[variableName] !== undefined) {
    const url = req.session[variableName];
    delete req.session[variableName];
    return url;
  }
}

exports.popSessionVariable = popSessionVariable;

// ----------------------------------------------------------------------------
// Provide our own error wrapper and message for an underlying thrown error.
// Useful for the user-presentable version.
// ----------------------------------------------------------------------------
exports.wrapError = function (error, message, userIntendedMessage) {
  var err = new Error(message);
  err.innerError = error;
  if (error && error.stack) {
    err.stack = error.stack;
  }
  if (userIntendedMessage === true) {
    err.skipLog = true;
  }
  return err;
};

// ----------------------------------------------------------------------------
// A destructive removal function for an object. Removes a single key.
// ----------------------------------------------------------------------------
exports.stealValue = function steal(obj, key) {
  if (obj[key] !== undefined) {
    var val = obj[key];
    delete obj[key];
    return val;
  }
};

// ----------------------------------------------------------------------------
// Given a list of string values, check a string, using a case-insensitive
// comparison.
// ----------------------------------------------------------------------------
exports.inListInsensitive = function inListInsensitive(list, value) {
  value = value.toLowerCase();
  for (var i = 0; i < list.length; i++) {
    if (list[i].toLowerCase() === value) {
      return true;
    }
  }
  return false;
};

// ----------------------------------------------------------------------------
// Given a list of lowercase values, check whether a value is present.
// ----------------------------------------------------------------------------
exports.isInListAnycaseInLowercaseList = function isInListAnycaseInLowercaseList(list, value) {
  value = value.toLowerCase();
  for (var i = 0; i < list.length; i++) {
    if (list[i] === value) {
      return true;
    }
  }
  return false;
};

// ----------------------------------------------------------------------------
// Given an array of things that have an `id` property, return a hash indexed
// by that ID.
// ----------------------------------------------------------------------------
exports.arrayToHashById = function arrayToHashById(inputArray) {
  var hash = {};
  if (inputArray && inputArray.length) {
    for (var i = 0; i < inputArray.length; i++) {
      if (inputArray[i] && inputArray[i].id) {
        hash[inputArray[i].id] = inputArray[i];
      }
    }
  }
  return hash;
};

// ----------------------------------------------------------------------------
// Obfuscate a string value, optionally leaving a few characters visible.
// ----------------------------------------------------------------------------
exports.obfuscate = function obfuscate(value, lastCharactersShowCount) {
  if (value === undefined || value === null || value.length === undefined) {
    return value;
  }
  var length = value.length;
  lastCharactersShowCount = lastCharactersShowCount || 0;
  lastCharactersShowCount = Math.min(Math.round(lastCharactersShowCount), length - 1);
  var obfuscated = '';
  for (var i = 0; i < length - lastCharactersShowCount; i++) {
    obfuscated += '*';
  }
  for (var j = length - lastCharactersShowCount; j < length; j++) {
    obfuscated += value[j];
  }
  return obfuscated;
};

// ----------------------------------------------------------------------------
// A very basic breadcrumb stack that ties in to an Express request object.
// ----------------------------------------------------------------------------
exports.addBreadcrumb = function (req, breadcrumbTitle, optionalBreadcrumbLink) {
  if (req === undefined || req.baseUrl === undefined) {
    throw new Error('addBreadcrumb: did you forget to provide a request object instance?');
  }
  if (!optionalBreadcrumbLink && optionalBreadcrumbLink !== false) {
    optionalBreadcrumbLink = req.baseUrl;
  }
  if (!optionalBreadcrumbLink && optionalBreadcrumbLink !== false) {
    optionalBreadcrumbLink = '/';
  }
  var breadcrumbs = req.breadcrumbs;
  if (breadcrumbs === undefined) {
    breadcrumbs = [];
  }
  breadcrumbs.push({
    title: breadcrumbTitle,
    url: optionalBreadcrumbLink,
  });
  req.breadcrumbs = breadcrumbs;
};

exports.stackSafeCallback = function stackSafeCallback(callback, err, item, extraItem) {
  // Works around RangeError: Maximum call stack size exceeded.
  async.setImmediate(() => {
    callback(err, item, extraItem);
  });
};

exports.createSafeCallbackNoParams = function createSafeCallbackNoParams(cb) {
  return () => {
    exports.stackSafeCallback(cb);
  };
};
<commit_msg>Updating utility code<commit_after>//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

const async = require('async');

// ----------------------------------------------------------------------------
// Returns an integer, random, between low and high (exclusive) - [low, high)
// ----------------------------------------------------------------------------
exports.randomInteger = function (low, high) {
  return Math.floor(Math.random() * (high - low) + low);
};

// ----------------------------------------------------------------------------
// Session utility: Store the referral URL, if present, and redirect to a new
// location.
// ----------------------------------------------------------------------------
exports.storeReferrer = function storeReferrer(req, res, redirect, optionalReason) {
  const eventDetails = {
    method: 'storeReferrer',
    reason: optionalReason || 'unknown reason',
  };
  if (req.session && req.headers && req.headers.referer && req.session.referer !== undefined && !req.headers.referer.includes('/signout')) {
    req.session.referer = req.headers.referer;
    eventDetails.referer = req.headers.referer;
  }
  if (redirect) {
    eventDetails.redirect = redirect;
    if (req.insights) {
      req.insights.trackEvent({ name: 'RedirectWithReferrer', properties: eventDetails });
    }
    res.redirect(redirect);
  }
};

// ----------------------------------------------------------------------------
// Session utility: store the original URL
// ----------------------------------------------------------------------------
exports.storeOriginalUrlAsReferrer = function storeOriginalUrl(req, res, redirect, optionalReason) {
  storeOriginalUrlAsVariable(req, res, 'referer', redirect, optionalReason);
};

exports.redirectToReferrer = function redirectToReferrer(req, res, url, optionalReason) {
  url = url || '/';
  const alternateUrl = popSessionVariable(req, res, 'referer');
  const eventDetails = {
    method: 'redirectToReferrer',
    reason: optionalReason || 'unknown reason',
  };
  if (req.insights) {
    req.insights.trackEvent({ name: 'RedirectToReferrer', properties: eventDetails });
  }
  res.redirect(alternateUrl || url);
};

function storeOriginalUrlAsVariable(req, res, variable, redirect, optionalReason) {
  const eventDetails = {
    method: 'storeOriginalUrlAsVariable',
    variable: variable,
    redirect: redirect,
    reason: optionalReason || 'unknown reason',
  };
  if (req.session && req.originalUrl) {
    req.session[variable] = req.originalUrl;
  }
  if (redirect) {
    if (req.insights) {
      req.insights.trackEvent({ name: 'RedirectFromOriginalUrl', properties: eventDetails });
    }
    res.redirect(redirect);
  }
}

exports.storeOriginalUrlAsVariable = storeOriginalUrlAsVariable;

function popSessionVariable(req, res, variableName) {
  if (req.session && req.session[variableName] !== undefined) {
    const url = req.session[variableName];
    delete req.session[variableName];
    return url;
  }
}

exports.popSessionVariable = popSessionVariable;

// ----------------------------------------------------------------------------
// Provide our own error wrapper and message for an underlying thrown error.
// Useful for the user-presentable version.
// ----------------------------------------------------------------------------
exports.wrapError = function (error, message, userIntendedMessage) {
  var err = new Error(message);
  err.innerError = error;
  if (error && error.stack) {
    err.stack = error.stack;
  }
  if (userIntendedMessage === true) {
    err.skipLog = true;
  }
  return err;
};

// ----------------------------------------------------------------------------
// A destructive removal function for an object. Removes a single key.
// ----------------------------------------------------------------------------
exports.stealValue = function steal(obj, key) {
  if (obj[key] !== undefined) {
    var val = obj[key];
    delete obj[key];
    return val;
  }
};

// ----------------------------------------------------------------------------
// Given a list of string values, check a string, using a case-insensitive
// comparison.
// ----------------------------------------------------------------------------
exports.inListInsensitive = function inListInsensitive(list, value) {
  value = value.toLowerCase();
  for (var i = 0; i < list.length; i++) {
    if (list[i].toLowerCase() === value) {
      return true;
    }
  }
  return false;
};

// ----------------------------------------------------------------------------
// Given a list of lowercase values, check whether a value is present.
// ----------------------------------------------------------------------------
exports.isInListAnycaseInLowercaseList = function isInListAnycaseInLowercaseList(list, value) {
  value = value.toLowerCase();
  for (var i = 0; i < list.length; i++) {
    if (list[i] === value) {
      return true;
    }
  }
  return false;
};

// ----------------------------------------------------------------------------
// Given an array of things that have an `id` property, return a hash indexed
// by that ID.
// ----------------------------------------------------------------------------
exports.arrayToHashById = function arrayToHashById(inputArray) {
  var hash = {};
  if (inputArray && inputArray.length) {
    for (var i = 0; i < inputArray.length; i++) {
      if (inputArray[i] && inputArray[i].id) {
        hash[inputArray[i].id] = inputArray[i];
      }
    }
  }
  return hash;
};

// ----------------------------------------------------------------------------
// Obfuscate a string value, optionally leaving a few characters visible.
// ----------------------------------------------------------------------------
exports.obfuscate = function obfuscate(value, lastCharactersShowCount) {
  if (value === undefined || value === null || value.length === undefined) {
    return value;
  }
  var length = value.length;
  lastCharactersShowCount = lastCharactersShowCount || 0;
  lastCharactersShowCount = Math.min(Math.round(lastCharactersShowCount), length - 1);
  var obfuscated = '';
  for (var i = 0; i < length - lastCharactersShowCount; i++) {
    obfuscated += '*';
  }
  for (var j = length - lastCharactersShowCount; j < length; j++) {
    obfuscated += value[j];
  }
  return obfuscated;
};

// ----------------------------------------------------------------------------
// A very basic breadcrumb stack that ties in to an Express request object.
// ----------------------------------------------------------------------------
exports.addBreadcrumb = function (req, breadcrumbTitle, optionalBreadcrumbLink) {
  if (req === undefined || req.baseUrl === undefined) {
    throw new Error('addBreadcrumb: did you forget to provide a request object instance?');
  }
  if (!optionalBreadcrumbLink && optionalBreadcrumbLink !== false) {
    optionalBreadcrumbLink = req.baseUrl;
  }
  if (!optionalBreadcrumbLink && optionalBreadcrumbLink !== false) {
    optionalBreadcrumbLink = '/';
  }
  var breadcrumbs = req.breadcrumbs;
  if (breadcrumbs === undefined) {
    breadcrumbs = [];
  }
  breadcrumbs.push({
    title: breadcrumbTitle,
    url: optionalBreadcrumbLink,
  });
  req.breadcrumbs = breadcrumbs;
};

exports.stackSafeCallback = function stackSafeCallback(callback, err, item, extraItem) {
  // Works around RangeError: Maximum call stack size exceeded.
  async.setImmediate(() => {
    callback(err, item, extraItem);
  });
};

exports.createSafeCallbackNoParams = function createSafeCallbackNoParams(cb) {
  return () => {
    exports.stackSafeCallback(cb);
  };
};
<|endoftext|>