<commit_before>
define([
     "dojo/_base/declare",
     "dojo/topic",
     "dojo/_base/lang",
     "dojo/aspect",
     "dojo/when",
     "hotplate/hotDojoStores/stores",
     "hotplate/hotDojoComet/messages",
//     'hotplate/hotDojoWidgetHooks/SyncTopic',
//     "hotplate/hotDojoWidgetHooks/SyncSubscriber!hotplate/hotDojoStores/newStore|AppStoreNotify",
     "dojo/domReady!",
   ], function(
   declare
   , topic
   , lang
   , aspect
   , when
   , stores
   , messages
//   , Sync
 ){

  // When a 'resetStores' topic is published, all store's cache is deleted (as it's
  // most likely to be outdated)
  topic.subscribe( 'resetStores', function(){

    // Sets 'configStores' as the hash containing the config stores (they will NOT
    // get initialised)
    var configStores = {};
    if( typeof( vars['hotCoreStoreConfig'] ) === 'object' && typeof( vars['hotCoreStoreConfig'] ) !== null ){
      if( typeof( vars['hotCoreStoreConfig']['configStores'] ) === 'object' && typeof( vars['hotCoreStoreConfig']['configStores'] ) !== null ){
        configStores = vars['hotCoreStoreConfig']['configStores'];
      }
    }

    var allDefinedStores = stores();
    for( var storeName in allDefinedStores ){
      var definedStores = allDefinedStores[ storeName ];

      for( var target in definedStores ){
        var store = definedStores[ target ];
        if( ! configStores[ store.storeName ] ){
          store.memCache.setData( [] );
        }
      }

    };
  });

  topic.subscribe( 'hotplate/hotDojoStores/newStore', function( storeName, store ){

    // CHANGES WITHIN
    //
    // For each "put", "add", "post" and "remove" in the store, publish a message locally
    // about the store being changed
    // Basically, after a put() or a remove(), it will publish a topic (storeRecordUpdate, storeRecordCreate or storeErase )
    // so that other parts of the application will be able to listen up.

    aspect.around( store, 'put', function( put ){

      return function( object, options ){

        return when( put.call( store, object, options ) ).then( function( r ) {
          var eventName;
          var identity = store.idProperty;
          eventName = object[ identity ] ? 'storeRecordUpdate' : 'storeRecordCreate';

          topic.publish( eventName, null, { type: eventName, storeName: storeName, objectId: r[ identity ], object: object }, false );

        } );

      }
    });

    /*
    aspect.around( store, 'add', function( add ){
      return function( object, options ){

        return when( add.call( store, object, options ) ).then( function( r ) {

          var identity = store.idProperty;

          topic.publish('storeRecordCreate', null, { storeName: storeName, storeTarget: storeTarget, objectId: r[identity], object: object }, false }  );

        });
      }
    });*/

    aspect.around( store, 'remove', function( remove ){
      return function( objectId, options ){

        return when( remove.call( store, objectId, options ) ).then( function( r ) {

          topic.publish('storeRecordRemove', null, { type: 'storeRecordRemove', storeName: storeName, objectId: objectId }, false );

        });
      };
    });

  });

  // CHANGES FROM THE OUTSIDE
  //
  // Update local stores according to Comet messages

  topic.subscribe('storeRecordUpdate', function( from, message, remote ){

    // A Comet changed a remote store. Refresh the Something came from a Comet.
    if( remote ){

      var definedStores = stores( message.storeName );
      for( var k in definedStores ){
        var store = definedStores[ k ];

        store.memCache.put( message.object );
        store.notify( message.object, message.object[ store.idProperty ]);
      }

    }
  });

  topic.subscribe('storeRecordCreate', function( from, message, remote ){
    // A Comet changed a remote store. Refresh the Something came from a Comet.
    if( remote ){

     var definedStores = stores( message.storeName );
      for( var k in definedStores ){
        var store = definedStores[ k ];

        store.memCache.put( message.object );
        store.notify( message.object );
      }
    }
  });

  topic.subscribe('storeRecordRemove', function( from, message, remote ){
    // A Comet changed a remote store. Refresh the Something came from a Comet.
    if( remote ){

     var definedStores = stores( message.storeName );
      for( var k in definedStores ){
        var store = definedStores[ k ];
        store.memCache.remove( message.objectId );
        store.notify( undefined, message.objectId );
      }
    }
  });

  // Sync.ready('hotplate/hotDojoStores/newStore');
  return {};

});

<commit_msg>Reworked AppStoreNotify so that it handles in-call methods. Although since it's Observable, it's not really an issue. But still...<commit_after>
define([
     "dojo/_base/declare",
     "dojo/topic",
     "dojo/_base/lang",
     "dojo/aspect",
     "dojo/when",
     "hotplate/hotDojoStores/stores",
     "hotplate/hotDojoComet/messages",
     "dojo/domReady!",
   ], function(
   declare
   , topic
   , lang
   , aspect
   , when
   , stores
   , messages
//   , Sync
 ){

  // TODO: Watch http://stackoverflow.com/questions/20735572/using-aspect-around-but-checking-for-methods-calling-each-other/20738272#20738272

  // When a 'resetStores' topic is published, all store's cache is deleted (as it's
  // most likely to be outdated)
  topic.subscribe( 'resetStores', function(){

    // Sets 'configStores' as the hash containing the config stores (they will NOT
    // get initialised)
    var configStores = {};
    if( typeof( vars['hotCoreStoreConfig'] ) === 'object' && typeof( vars['hotCoreStoreConfig'] ) !== null ){
      if( typeof( vars['hotCoreStoreConfig']['configStores'] ) === 'object' && typeof( vars['hotCoreStoreConfig']['configStores'] ) !== null ){
        configStores = vars['hotCoreStoreConfig']['configStores'];
      }
    }

    var allDefinedStores = stores();
    for( var storeName in allDefinedStores ){
      var definedStores = allDefinedStores[ storeName ];

      for( var target in definedStores ){
        var store = definedStores[ target ];
        if( ! configStores[ store.storeName ] ){
          store.memCache.setData( [] );
        }
      }

    };
  });

  topic.subscribe( 'hotplate/hotDojoStores/newStore', function( storeName, store ){

    var inMethod;

    aspect.around( store, 'put', function( put ){

      return function( object, options ){

        if( inMethod ){
          return put.call( store, object, options );
        } else {

          inMethod = true;

          try {
            var results = put.call( store, object, options );
            when( results ).then( function( r ){
              var eventName;
              var identity = store.idProperty;
              eventName = object[ identity ] ? 'storeRecordUpdate' : 'storeRecordCreate';

              topic.publish( eventName, null, { type: eventName, storeName: storeName, objectId: r[ identity ], object: object }, false );
            });
            return results;
          } finally {
            inMethod = false;
          }

        }

      }
    });

    aspect.around( store, 'add', function( add ){
      return function( object, options ){

        if( inMethod ){
          return add.call( store, object, options );
        } else {

          inMethod = true;

          try {
            var results = add.call( store, object, options );
            when( results ).then(  function( r ){
              var identity = store.idProperty;
              topic.publish('storeRecordCreate', null, { type: 'storeRecordCreate', storeName: storeName, objectId: r[identity], object: object }, false );
            });
            return results;
          } finally {
            inMethod = false;
          }
        }
      }

    });

    aspect.around( store, 'remove', function( remove ){
      return function( objectId, options ){

        if( inMethod ){
          return remove.call( store, objectId, options );
        } else {

          inMethod = true;

          try {
            var results = remove.call( store, objectId, options );
            when( results ).then( function( r ) {
              topic.publish('storeRecordRemove', null, { type: 'storeRecordRemove', storeName: storeName, objectId: objectId }, false );
            });
          } finally {
            inMethod = false
          }

        };
      };
    });

  });

  // CHANGES FROM THE OUTSIDE
  //
  // Update local stores according to Comet messages

  topic.subscribe('storeRecordUpdate', function( from, message, remote ){

    // A Comet changed a remote store. Refresh the Something came from a Comet.
    if( remote ){

      var definedStores = stores( message.storeName );
      for( var k in definedStores ){
        var store = definedStores[ k ];

        store.memCache.put( message.object );
        store.notify( message.object, message.object[ store.idProperty ]);
      }

    }
  });

  topic.subscribe('storeRecordCreate', function( from, message, remote ){
    // A Comet changed a remote store. Refresh the Something came from a Comet.
    if( remote ){

     var definedStores = stores( message.storeName );
      for( var k in definedStores ){
        var store = definedStores[ k ];

        store.memCache.put( message.object );
        store.notify( message.object );
      }
    }
  });

  topic.subscribe('storeRecordRemove', function( from, message, remote ){
    // A Comet changed a remote store. Refresh the Something came from a Comet.
    if( remote ){

     var definedStores = stores( message.storeName );
      for( var k in definedStores ){
        var store = definedStores[ k ];
        store.memCache.remove( message.objectId );
        store.notify( undefined, message.objectId );
      }
    }
  });

  // Sync.ready('hotplate/hotDojoStores/newStore');
  return {};

});

<|endoftext|>


<commit_before>/*!
 * Copyright 2014 Apereo Foundation (AF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

define(['jquery', 'oae.core', 'jquery.oembed'], function($, oae) {

    return function(uid, showSettings, widgetData) {

        // Cache the widget container
        var $rootel = $('#' + uid);

        /**
         * Whitelist the supported oEmbed providers
         *
         * @see http://oembed.com
         */
        var oEmbedProviders = {
            'blip': RegExp('blip\\.tv/.+'),
            'dailymotion': RegExp('dailymotion\\.com/.+'),
            'deviantart': RegExp('deviantart.com/.+'),
            'dribble': RegExp('dribbble.com/shots/.+'),
            'flickr': RegExp('flickr\\.com/photos/.+'),
            'hulu': RegExp('hulu\\.com/watch/.*'),
            'ifixit': RegExp('ifixit.com/.+'),
            'imgly': RegExp('img\\.ly/.+'),
            'instagram': RegExp('instagr\\.?am(\\.com)?/.+'),
            'pastebin': RegExp('pastebin\\.com/[\\S]{8}'),
            'pinterest': RegExp('pinterest.com/pin/.+'),
            'prezi': RegExp('prezi.com/.*'),
            'scribd': RegExp('scribd\\.com/.+'),
            'slideshare': RegExp('slideshare\\.net'),
            'soundcloud': RegExp('soundcloud.com/.+'),
            'speakerdeck': RegExp('speakerdeck.com/.+'),
            'ted': RegExp('ted.com/talks/.+'),
            'twitgoocom': RegExp('twitgoo\\.com/.+'),
            'twitpic': RegExp('twitpic.com/.+'),
            'vimeo': RegExp('vimeo\\.com/.+'),
            'youtube': RegExp('youtube\\.com/watch.+v=[\\w-]+&?')
        };

        /**
         * Override the default embed behavior for some of the supported oEmbed providers
         */
        var setUpCustomOEmbedProviders = function() {
            // Dribble
            $.fn.updateOEmbedProvider('dribbble', null, null, null, {
                'templateData' : function(data) {
                    return oae.api.util.template().render($('#linkpreview-image-template', $rootel), {
                        'img': data.image_url,
                        'linkProfile': widgetData
                    });
                }
            });

            // Img.ly
            $.fn.updateOEmbedProvider('img.ly', 'photo', ['img\\.ly/.+'],'//img.ly/show/large/$1', {
                'embedtag': {tag: 'img'}
            });

            // Twitgoo
            $.fn.updateOEmbedProvider('twitgoo.com', 'photo', ['twitgoo\\.com/.+'],'http://twitgoo.com/show/img/$1', {
                embedtag: {tag:'img'}
            });

            // TED, Twitpic
            $.fn.updateOEmbedProvider('opengraph', null, null, null, {
                yql: {
                    xpath: '//meta|//title|//link',
                    from: 'html',
                    datareturn: function(results) {
                        var embed = $('<p/>');
                        if (results['og:url'].match(oEmbedProviders.ted)) {
                            var url = results['og:url'].replace('www.', 'embed.');
                            embed.append(oae.api.util.template().render($('#linkpreview-iframe-template', $rootel), {'link': url}));
                        } else if (results['og:image']) {
                            // If we're looking at TwitPic, get the large picture instead of the thumbnail
                            if (results['og:site_name'] === 'TwitPic') {
                                results['og:image'] = results['og:image'].replace('thumb', 'large');
                            }
                            embed.append(oae.api.util.template().render($('#linkpreview-image-template', $rootel), {
                                'img': results['og:image'],
                                'linkProfile': widgetData
                            }));
                        }
                        return embed;
                    }
                }
            });
        };

        /**
         * In case the current link doesn't match any of the oEmbed providers, we try to embed the link as an iframe.
         * If the preview processor has marked the link as non-embeddable because of cross-domain embedding policies,
         * we try to show the preview image if available. Also, if the link's protocol is http but the user is accessing
         * the server over https, we try to convert the link to https to avoid browser security issues/warnings.
         */
        var renderDefaultPreview = function() {
            var link = widgetData.link;
            var embeddable = widgetData.previews.embeddable;

            // If there is a protocol mismatch, make adjustments
            if ((window.location.protocol === 'https:') && (link.indexOf('http:') === 0)) {
                // If we can convert to https, do so
                if (widgetData.previews.httpsAccessible) {
                    link = link.replace('http:', 'https:');
                // If we can't convert to https, we can't embed
                } else {
                    embeddable = false;
                }
            }
            // We cannot embed the link
            if (embeddable === false) {
                oae.api.util.template().render($('#linkpreview-default-template', $rootel), {'linkProfile': widgetData}, $('#linkpreview-container'), $rootel);
            // Embed the link as an iframe
            } else {
                oae.api.util.template().render($('#linkpreview-iframe-template', $rootel), {'link': link}, $('#linkpreview-container'), $rootel);
            }
        };

        /**
         * Render the link preview using the oEmbed library.
         */
        var renderOEmbedPreview = function() {
            $('#linkpreview-container', $rootel).oembed(widgetData.link, {
                // Delete the arrow that collapses the container
                'includeHandle': false,
                // Place the content into the container instead of creating a new div
                'embedMethod': 'fill'
            });
        };

        /**
         * Decide whether or not to render the link preview using oEmbed or using the standard
         * iFrame embedding method.
         */
        var initPreview = function() {
            // Check the current link against the supported oEmbed providers
            var useOEmbed = false;
            $.each(oEmbedProviders, function(provider, regex) {
                if (regex.test(widgetData.link)) {
                    useOEmbed = true;
                    return false;
                }
            });

            if (useOEmbed) {
                renderOEmbedPreview();
            } else {
                renderDefaultPreview();
            }
        };

        setUpCustomOEmbedProviders();
        initPreview();

    };
});
<commit_msg>Follow up on link embedding<commit_after>/*!
 * Copyright 2014 Apereo Foundation (AF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

define(['jquery', 'oae.core', 'jquery.oembed'], function($, oae) {

    return function(uid, showSettings, widgetData) {

        // Cache the widget container
        var $rootel = $('#' + uid);

        /**
         * Whitelist the supported oEmbed providers
         *
         * @see http://oembed.com
         */
        var oEmbedProviders = {
            'blip': RegExp('blip\\.tv/.+'),
            'dailymotion': RegExp('dailymotion\\.com/.+'),
            'deviantart': RegExp('deviantart.com/.+'),
            'dribble': RegExp('dribbble.com/shots/.+'),
            'flickr': RegExp('flickr\\.com/photos/.+'),
            'hulu': RegExp('hulu\\.com/watch/.*'),
            'ifixit': RegExp('ifixit.com/.+'),
            'imgly': RegExp('img\\.ly/.+'),
            'instagram': RegExp('instagr\\.?am(\\.com)?/.+'),
            'pastebin': RegExp('pastebin\\.com/[\\S]{8}'),
            'pinterest': RegExp('pinterest.com/pin/.+'),
            'prezi': RegExp('prezi.com/.*'),
            'scribd': RegExp('scribd\\.com/.+'),
            'slideshare': RegExp('slideshare\\.net'),
            'soundcloud': RegExp('soundcloud.com/.+'),
            'speakerdeck': RegExp('speakerdeck.com/.+'),
            'ted': RegExp('ted.com/talks/.+'),
            'twitgoocom': RegExp('twitgoo\\.com/.+'),
            'twitpic': RegExp('twitpic.com/.+'),
            'vimeo': RegExp('vimeo\\.com/.+'),
            'youtube': RegExp('youtube\\.com/watch.+v=[\\w-]+&?')
        };

        /**
         * Override the default embed behavior for some of the supported oEmbed providers
         */
        var setUpCustomOEmbedProviders = function() {
            // Dribble
            $.fn.updateOEmbedProvider('dribbble', null, null, null, {
                'templateData' : function(data) {
                    return oae.api.util.template().render($('#linkpreview-image-template', $rootel), {
                        'img': data.image_url,
                        'linkProfile': widgetData
                    });
                }
            });

            // Img.ly
            $.fn.updateOEmbedProvider('img.ly', 'photo', ['img\\.ly/.+'],'//img.ly/show/large/$1', {
                'embedtag': {tag: 'img'}
            });

            // Twitgoo
            $.fn.updateOEmbedProvider('twitgoo.com', 'photo', ['twitgoo\\.com/.+'],'http://twitgoo.com/show/img/$1', {
                embedtag: {tag:'img'}
            });

            // TED, Twitpic
            $.fn.updateOEmbedProvider('opengraph', null, null, null, {
                yql: {
                    xpath: '//meta|//title|//link',
                    from: 'html',
                    datareturn: function(results) {
                        var embed = $('<p/>');
                        if (results['og:url'].match(oEmbedProviders.ted)) {
                            var url = results['og:url'].replace('www.', 'embed.');
                            embed.append(oae.api.util.template().render($('#linkpreview-iframe-template', $rootel), {'link': url}));
                        } else if (results['og:image']) {
                            // If we're looking at TwitPic, get the large picture instead of the thumbnail
                            if (results['og:site_name'] === 'TwitPic') {
                                results['og:image'] = results['og:image'].replace('thumb', 'large');
                            }
                            embed.append(oae.api.util.template().render($('#linkpreview-image-template', $rootel), {
                                'img': results['og:image'],
                                'linkProfile': widgetData
                            }));
                        }
                        return embed;
                    }
                }
            });
        };

        /**
         * In case the current link doesn't match any of the oEmbed providers, we try to embed the link as an iframe.
         * If the preview processor has marked the link as non-embeddable because of cross-domain embedding policies,
         * we try to show the preview image if available. If the link's protocol is `http` but the user is accessing
         * OAE over `https`, the link is converted to `https` if it is accessible over `https` to avoid browser security
         * issues/warnings.
         */
        var renderDefaultPreview = function() {
            var link = widgetData.link;
            var embeddable = widgetData.previews.embeddable;

            // If there is a protocol mismatch, the link is converted to `https` if it is
            // accessible over `https`
            if (window.location.protocol === 'https:' && link.indexOf('http:' === 0)) {
                if (widgetData.previews.httpsAccessible) {
                    link = link.replace('http:', 'https:');
                // If the link is not accessible over `https`, it can't be embedded
                } else {
                    embeddable = false;
                }
            }
            // The link can be embedded as an iFrame
            if (embeddable) {
                oae.api.util.template().render($('#linkpreview-iframe-template', $rootel), {'link': link}, $('#linkpreview-container'), $rootel);
            // The link can not be embedded
            } else {
                oae.api.util.template().render($('#linkpreview-default-template', $rootel), {'linkProfile': widgetData}, $('#linkpreview-container'), $rootel);
            }
        };

        /**
         * Render the link preview using the oEmbed library.
         */
        var renderOEmbedPreview = function() {
            $('#linkpreview-container', $rootel).oembed(widgetData.link, {
                // Delete the arrow that collapses the container
                'includeHandle': false,
                // Place the content into the container instead of creating a new div
                'embedMethod': 'fill'
            });
        };

        /**
         * Decide whether or not to render the link preview using oEmbed or using the standard
         * iFrame embedding method.
         */
        var initPreview = function() {
            // Check the current link against the supported oEmbed providers
            var useOEmbed = false;
            $.each(oEmbedProviders, function(provider, regex) {
                if (regex.test(widgetData.link)) {
                    useOEmbed = true;
                    return false;
                }
            });

            if (useOEmbed) {
                renderOEmbedPreview();
            } else {
                renderDefaultPreview();
            }
        };

        setUpCustomOEmbedProviders();
        initPreview();

    };
});
<|endoftext|>


<commit_before>// Copyright 2002-2014, University of Colorado Boulder

/**
 * Demonstration of misc scenery-phet UI components
 *
 * @author Sam Reid
 * @author Chris Malley
 */
define( function( require ) {
  'use strict';

  // modules
  var Bounds2 = require( 'DOT/Bounds2' );
  var Dimension2 = require( 'DOT/Dimension2' );
  var EyeDropperNode = require( 'SCENERY_PHET/EyeDropperNode' );
  var FaucetNode = require( 'SCENERY_PHET/FaucetNode' );
  var HSlider = require( 'SUN/HSlider' );
  var inherit = require( 'PHET_CORE/inherit' );
  var MeasuringTape = require( 'SCENERY_PHET/MeasuringTape' );
  var Node = require( 'SCENERY/nodes/Node' );
  var Property = require( 'AXON/Property' );
  var ResetAllButton = require( 'SCENERY_PHET/buttons/ResetAllButton' );
  var ScreenView = require( 'JOIST/ScreenView' );
  var StarNode = require( 'SCENERY_PHET/StarNode' );
  var ThermometerNode = require( 'SCENERY_PHET/ThermometerNode' );
  var Vector2 = require( 'DOT/Vector2' );

  function ComponentsView() {

    ScreenView.call( this, { renderer: 'svg', layoutBounds: new Bounds2( 0, 0, 768, 504 ) } );

    // thermometer
    var temperatureProperty = new Property( 50 );
    var thermometer = new ThermometerNode( 0, 100, temperatureProperty, {
      fluidSphereSpacing: 6,
      fluidRectSpacing: 6,
      right: this.layoutBounds.right - 100,
      bottom: this.layoutBounds.bottom - 20
    } );
    this.addChild( thermometer );
    var temperatureSlider = new HSlider( temperatureProperty, { min: 0, max: 100 }, {
      thumbSize: new Dimension2( 15, 30 ),
      thumbFillHighlighted: 'red',
      thumbFillEnabled: 'rgb(158,35,32)'
    } );
    temperatureSlider.rotation = -Math.PI / 2;
    temperatureSlider.right = thermometer.left - 10;
    temperatureSlider.centerY = thermometer.centerY;
    this.addChild( temperatureSlider );

    // measuring tape
    var measuringTapeScaleProperty = new Property( 0.5 );
    var measuringTapeUnitsProperty = new Property( { name: 'meters', multiplier: 1 } );
    var measuringTape = new MeasuringTape( measuringTapeUnitsProperty, new Property( true ), {
      textColor: 'black',
      unrolledTapeDistance: 100,
      dragBounds: this.layoutBounds,
      scaleProperty: measuringTapeScaleProperty,
      basePositionProperty: new Property( new Vector2( 100, 100 ) )
    } );
    this.addChild( measuringTape );
    var measuringTapeScaleSlider = new HSlider( measuringTapeScaleProperty, { min: 0.5, max: 2 }, {
      thumbSize: new Dimension2( 15, 30 ),
      left: 50,
      top: measuringTape.bottom + 20
    } );
    this.addChild( measuringTapeScaleSlider );

    /*
     * Fill up a star by creating new StarNodes dynamically.
     * Shouldn't be a problem for sims since stars are relatively static.
     * Stars should be rewritten if they need to support smooth dynamic filling (may require mutable kite paths).
     */
    var starNodeContainer = new Node( {
      children: [new StarNode()],
      top: 20,
      right: this.layoutBounds.right - 20
    } );
    this.addChild( starNodeContainer );
    var starValueProperty = new Property( 1 );
    var starSlider = new HSlider( starValueProperty, { min: 0, max: 1 }, {
      thumbSize: new Dimension2( 15, 30 ),
      thumbFillHighlighted: 'yellow',
      thumbFillEnabled: 'rgb(220,220,0)',
      thumbCenterLineStroke: 'black',
      right: starNodeContainer.right,
      top: starNodeContainer.bottom + 5
    } );
    this.addChild( starSlider );
    starValueProperty.link( function( value ) {
      starNodeContainer.children = [ new StarNode( { value: value } ) ];
    } );

    // faucet
    var fluidRateProperty = new Property( 5 );
    var faucetNode = new FaucetNode( 10, fluidRateProperty, new Property( true ), {
      left: 10,
      bottom: this.layoutBounds.bottom - 10
    } );
    this.addChild( faucetNode );

    // eye dropper
    var dropperNode = new EyeDropperNode( {
      fluidColor: 'purple',
      scale: 0.75,
      centerX: this.layoutBounds.centerX,
      top: 10
    });
    this.addChild( dropperNode );

    // Reset All button
    var resetAllButton = new ResetAllButton( {
      listener: function() {
        temperatureProperty.reset();
        measuringTapeScaleProperty.reset();
        measuringTape.reset();
        starValueProperty.reset();
        fluidRateProperty.reset();
      },
      radius: 22,
      right: this.layoutBounds.right - 10,
      bottom: this.layoutBounds.bottom - 10
    } );
    this.addChild( resetAllButton );
  }

  return inherit( ScreenView, ComponentsView );
} );<commit_msg>#71 add console output to EyeDropperNode demo<commit_after>// Copyright 2002-2014, University of Colorado Boulder

/**
 * Demonstration of misc scenery-phet UI components
 *
 * @author Sam Reid
 * @author Chris Malley
 */
define( function( require ) {
  'use strict';

  // modules
  var Bounds2 = require( 'DOT/Bounds2' );
  var Dimension2 = require( 'DOT/Dimension2' );
  var EyeDropperNode = require( 'SCENERY_PHET/EyeDropperNode' );
  var FaucetNode = require( 'SCENERY_PHET/FaucetNode' );
  var HSlider = require( 'SUN/HSlider' );
  var inherit = require( 'PHET_CORE/inherit' );
  var MeasuringTape = require( 'SCENERY_PHET/MeasuringTape' );
  var Node = require( 'SCENERY/nodes/Node' );
  var Property = require( 'AXON/Property' );
  var ResetAllButton = require( 'SCENERY_PHET/buttons/ResetAllButton' );
  var ScreenView = require( 'JOIST/ScreenView' );
  var StarNode = require( 'SCENERY_PHET/StarNode' );
  var ThermometerNode = require( 'SCENERY_PHET/ThermometerNode' );
  var Vector2 = require( 'DOT/Vector2' );

  function ComponentsView() {

    ScreenView.call( this, { renderer: 'svg', layoutBounds: new Bounds2( 0, 0, 768, 504 ) } );

    // thermometer
    var temperatureProperty = new Property( 50 );
    var thermometer = new ThermometerNode( 0, 100, temperatureProperty, {
      fluidSphereSpacing: 6,
      fluidRectSpacing: 6,
      right: this.layoutBounds.right - 100,
      bottom: this.layoutBounds.bottom - 20
    } );
    this.addChild( thermometer );
    var temperatureSlider = new HSlider( temperatureProperty, { min: 0, max: 100 }, {
      thumbSize: new Dimension2( 15, 30 ),
      thumbFillHighlighted: 'red',
      thumbFillEnabled: 'rgb(158,35,32)'
    } );
    temperatureSlider.rotation = -Math.PI / 2;
    temperatureSlider.right = thermometer.left - 10;
    temperatureSlider.centerY = thermometer.centerY;
    this.addChild( temperatureSlider );

    // measuring tape
    var measuringTapeScaleProperty = new Property( 0.5 );
    var measuringTapeUnitsProperty = new Property( { name: 'meters', multiplier: 1 } );
    var measuringTape = new MeasuringTape( measuringTapeUnitsProperty, new Property( true ), {
      textColor: 'black',
      unrolledTapeDistance: 100,
      dragBounds: this.layoutBounds,
      scaleProperty: measuringTapeScaleProperty,
      basePositionProperty: new Property( new Vector2( 100, 100 ) )
    } );
    this.addChild( measuringTape );
    var measuringTapeScaleSlider = new HSlider( measuringTapeScaleProperty, { min: 0.5, max: 2 }, {
      thumbSize: new Dimension2( 15, 30 ),
      left: 50,
      top: measuringTape.bottom + 20
    } );
    this.addChild( measuringTapeScaleSlider );

    /*
     * Fill up a star by creating new StarNodes dynamically.
     * Shouldn't be a problem for sims since stars are relatively static.
     * Stars should be rewritten if they need to support smooth dynamic filling (may require mutable kite paths).
     */
    var starNodeContainer = new Node( {
      children: [new StarNode()],
      top: 20,
      right: this.layoutBounds.right - 20
    } );
    this.addChild( starNodeContainer );
    var starValueProperty = new Property( 1 );
    var starSlider = new HSlider( starValueProperty, { min: 0, max: 1 }, {
      thumbSize: new Dimension2( 15, 30 ),
      thumbFillHighlighted: 'yellow',
      thumbFillEnabled: 'rgb(220,220,0)',
      thumbCenterLineStroke: 'black',
      right: starNodeContainer.right,
      top: starNodeContainer.bottom + 5
    } );
    this.addChild( starSlider );
    starValueProperty.link( function( value ) {
      starNodeContainer.children = [ new StarNode( { value: value } ) ];
    } );

    // faucet
    var fluidRateProperty = new Property( 5 );
    var faucetNode = new FaucetNode( 10, fluidRateProperty, new Property( true ), {
      left: 10,
      bottom: this.layoutBounds.bottom - 10
    } );
    this.addChild( faucetNode );

    // eye dropper
    var dropperNode = new EyeDropperNode( {
      fluidColor: 'purple',
      scale: 0.75,
      centerX: this.layoutBounds.centerX,
      top: 10
    });
    this.addChild( dropperNode );
    dropperNode.onProperty.lazyLink( function( on ) {
        console.log( 'dropper ' + ( on ? 'on' : 'off' ) );
    } );

    // Reset All button
    var resetAllButton = new ResetAllButton( {
      listener: function() {
        temperatureProperty.reset();
        measuringTapeScaleProperty.reset();
        measuringTape.reset();
        starValueProperty.reset();
        fluidRateProperty.reset();
      },
      radius: 22,
      right: this.layoutBounds.right - 10,
      bottom: this.layoutBounds.bottom - 10
    } );
    this.addChild( resetAllButton );
  }

  return inherit( ScreenView, ComponentsView );
} );<|endoftext|>


<commit_before>/**
 * Author: Damian Szymczuk
 * Website: http://dszymczuk.pl
 * Version: 0.2
 * GitHub: https://github.com/dszymczuk/JSONEventCalendar
 */

(function( $ ) {
    $.fn.JSONEventCalendar = function(events,options) {

        var settings = $.extend($.fn.JSONEventCalendar.settings, options );

        var initMoment = moment();
        initMoment.locale(settings.lang);

        var names = {
            monthNames: initMoment._locale._months,
            dayNames: initMoment._locale._weekdays,
            dayNamesShort: initMoment._locale._weekdaysShort,
            dayNamesMin: initMoment._locale._weekdaysMin
        };

        return this.each( function() {
            var that = $(this);
            var year = moment().get('year');
            var month = moment().get('month');

            that.html(_drawCalendar({
                formatTitle: settings.formatTitle,
                lang: settings.lang
                ,year: year
                ,month: month
            }));
            _refreshDayHeight(that);

            /*------------*\
               NEXT MONTH
            \*------------*/
            that.on('click','.ds-next-month',function(){
                if(month > 10)
                {
                    month = 0;
                    year++;
                }
                else
                    month++;

                that.html(_drawCalendar({
                    formatTitle: settings.formatTitle,
                    lang: settings.lang
                    ,year: year
                    ,month: month
                }));
                _refreshDayHeight(that);
            });

            /*------------*\
               PREV MONTH
            \*------------*/
            that.on('click','.ds-prev-month',function(){
                if(month < 1)
                {
                    month=11;
                    year--;
                }
                else
                    month--;

                that.html(_drawCalendar({
                    formatTitle: settings.formatTitle,
                    lang: settings.lang
                    ,year: year
                    ,month: month
                }));
                _refreshDayHeight(that);
            });

            /*-------------*\
               EVENT CLICK
            \*-------------*/
            that.on('click','.ds-event',function(){
                var elem = $(this);
                var id = elem[0].id;

                var event =  _.find(events, function(e) {
                    return e.id == id;
                });
                $(".ds-calendar").append(_drawModalEvent(event));
            });

            /*-------------*\
               CLOSE MODAL
            \*-------------*/
            that.on('click','.ds-event-modal .close-button',function(){
                $(".ds-event-modal").remove();
            });

        });

        /**
         * Refresh height of element to equal size
         *
         * @param element
         * @private
         */
        function _refreshDayHeight(element) {
            var maxHeight = 0;
            element.find('.ds-events').each(function(){
                var that = $(this);
                if(that.height() > maxHeight)
                    maxHeight = that.height();
            }).each(function(){
                var that = $(this);
                that.css('height',maxHeight + "px");
            });
        }

        function _drawCalendar(options) {
            var year, month;
            var mom = moment();
            if(options.hasOwnProperty('year'))
                year = options.year;
            else
                year = mom.get('year');

            if(options.hasOwnProperty('month'))
                month = options.month;
            else
                month = mom.get('month');

            mom.set('year',year);
            mom.set('month',month);
            mom.locale(settings.lang);

            var before = {
                month: month,
                year: year
            };
            before.month--;

            /*---------------------------*\
                CALCUALTE BEFORE MONTH
            \*---------------------------*/
            if(month < 0)
            {
                before.month=11;
                before.year--;
            }

            var calendar = '
';

            //header
            calendar += '
';
            calendar += '
';
            calendar += '
<
';
            calendar += '
'+mom.format(settings.formatTitle)+'
';
            calendar += '
>
';
            calendar += '
';
            calendar += '
';

            // name of days
            calendar += '
';

            var offset = settings.startFrom;

            calendar += '
'+names.dayNames[offset]+'
';
            for(var i = 1 + offset ; i < 7 + offset ; i++)
                calendar += '
'+names.dayNames[i%7]+'
';

            calendar += '
';

            /*-----------*\
                MONTH -1
            \*-----------*/
            var daysBefore = monthDays(before.year,before.month);
            var calcBefore = _calcBefore(year,month);
            daysBefore = daysBefore - calcBefore+1;

            for(var b = 0 ; b < calcBefore ; b++)
            {
                calendar += drawDay(daysBefore+b,'before');
            }

            /*-----------------*\
                CUREENT MONTH
            \*-----------------*/
            var currDaysInMonth = monthDays(year,month);
            for(var c = 1 ; c <= currDaysInMonth ; c++)
            {
                calendar += drawDay(c,'current',true);
            }

            /*------------*\
                MONTH +1
            \*------------*/
            var nextMonth = 0;
            var cA = _calcAfter(year,month);
            if(cA !== 1)
            {
                for(var a = 0 ; a <= 7-cA ; a++)
                {
                    nextMonth++;
                    calendar += drawDay(nextMonth,'after');
                }
            }

            //to have 6 rows in calendar
            //@todo to think
//            if(cA !== 2 && cA !== 0)
//            {
//                for(var a = 0 ; a < 7 ; a++)
//                {
//                    nextMonth++;
//                    calendar += drawDay(nextMonth,'extra-after');
//                }
//            }

            calendar += '';
            calendar += '';
            calendar += '';
            calendar += '';
            calendar += '';

            calendar += '
';
            return calendar;

            function drawDay(day,elementClass,drawEvents){
                drawEvents = typeof drawEvents !== 'undefined' ? drawEvents : false;

                if(typeof elementClass === 'undefined')
                    elementClass = '';
                var dD = '';
                dD += '
';
                dD += '
'+day+'
';
                dD += '
';

                if(drawEvents)
                {
                    var events = _getEvents(day,month,year);
                    for(var e = 0 ; e < events.length ; e++)
                    {
                        dD += '
'+events[e].title+'
';
                    }

                }

                dD += '
';
                dD += '
';
                return dD;
            }

            function _calcBefore(year,month){
                var f = firstDayPosition(year,month,0)-1;

                if(f < 0)
                    return 6;
                else
                    return f;
            }

            function _calcAfter(year,month){
                month++;
                return firstDayPosition(year,month,0);
            }

            function _getEvents(day,month,year){
                return _.filter(sampleEvents, function (sE) {
                    return moment(new Date(year, month, day)) < new Date(sE.date)
                        && new Date(sE.date) < moment(new Date(year, month, day)).add(1, 'd');
                });
            }

            function monthDays(year,month) {
                month++;
                var d = new Date(year,month, 0);
                return d.getDate();
            }

            function firstDayPosition(year,month,offset) {
                var mom = moment();
                mom.set('year',year);
                mom.set('month',month);
                mom.date(1);
                return mom.day()+offset;
            }
        }

        function _drawModalEvent(event){
            var eventDetails = "";
            eventDetails += '
';
            eventDetails += '
';

            if(typeof  event.color !== "undefined")
                eventDetails += '
';
            else
                eventDetails += '
';

            eventDetails += '
'+event.title+'
';
            eventDetails += '
'+moment(event.date).locale(settings.lang).format(settings.formatEvent)+'
';
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += '
'+settings.typeText+' '+event.type+'
';
            eventDetails += '
'+event.description+'
';
            eventDetails += '
';
            eventDetails += ''+event.url+'';
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += settings.closeText;
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += '
';
            return eventDetails;
        }
    }
}( jQuery ));

$.fn.JSONEventCalendar.settings = {
    lang: "pl",
//    format: "DD-MM-YYYY",
    formatTitle: "MMMM YYYY",
    formatEvent: "DD MMMM YYYY",
    startFrom: 1, //0 - Sunday, 1 - Monday etc.
    eventsInDay: 3,
    closeText: 'close',
    typeText: 'Type:'
};

var data = [];<commit_msg>offset before done<commit_after>/**
 * Author: Damian Szymczuk
 * Website: http://dszymczuk.pl
 * Version: 0.2
 * GitHub: https://github.com/dszymczuk/JSONEventCalendar
 */

(function( $ ) {
    $.fn.JSONEventCalendar = function(events,options) {

        var settings = $.extend($.fn.JSONEventCalendar.settings, options );

        var initMoment = moment();
        initMoment.locale(settings.lang);

        var names = {
            monthNames: initMoment._locale._months,
            dayNames: initMoment._locale._weekdays,
            dayNamesShort: initMoment._locale._weekdaysShort,
            dayNamesMin: initMoment._locale._weekdaysMin
        };

        return this.each( function() {
            var that = $(this);
            var year = moment().get('year');
            var month = moment().get('month');

            that.html(_drawCalendar({
                formatTitle: settings.formatTitle,
                lang: settings.lang
                ,year: year
                ,month: month
            }));
            _refreshDayHeight(that);

            /*------------*\
               NEXT MONTH
            \*------------*/
            that.on('click','.ds-next-month',function(){
                if(month > 10)
                {
                    month = 0;
                    year++;
                }
                else
                    month++;

                that.html(_drawCalendar({
                    formatTitle: settings.formatTitle,
                    lang: settings.lang
                    ,year: year
                    ,month: month
                }));
                _refreshDayHeight(that);
            });

            /*------------*\
               PREV MONTH
            \*------------*/
            that.on('click','.ds-prev-month',function(){
                if(month < 1)
                {
                    month=11;
                    year--;
                }
                else
                    month--;

                that.html(_drawCalendar({
                    formatTitle: settings.formatTitle,
                    lang: settings.lang
                    ,year: year
                    ,month: month
                }));
                _refreshDayHeight(that);
            });

            /*-------------*\
               EVENT CLICK
            \*-------------*/
            that.on('click','.ds-event',function(){
                var elem = $(this);
                var id = elem[0].id;

                var event =  _.find(events, function(e) {
                    return e.id == id;
                });
                $(".ds-calendar").append(_drawModalEvent(event));
            });

            /*-------------*\
               CLOSE MODAL
            \*-------------*/
            that.on('click','.ds-event-modal .close-button',function(){
                $(".ds-event-modal").remove();
            });

        });

        /**
         * Refresh height of element to equal size
         *
         * @param element
         * @private
         */
        function _refreshDayHeight(element) {
            var maxHeight = 0;
            element.find('.ds-events').each(function(){
                var that = $(this);
                if(that.height() > maxHeight)
                    maxHeight = that.height();
            }).each(function(){
                var that = $(this);
                that.css('height',maxHeight + "px");
            });
        }

        function _drawCalendar(options) {
            var year, month;
            var mom = moment();
            if(options.hasOwnProperty('year'))
                year = options.year;
            else
                year = mom.get('year');

            if(options.hasOwnProperty('month'))
                month = options.month;
            else
                month = mom.get('month');

            mom.set('year',year);
            mom.set('month',month);
            mom.locale(settings.lang);

            var before = {
                month: month,
                year: year
            };
            before.month--;

            /*---------------------------*\
                CALCUALTE BEFORE MONTH
            \*---------------------------*/
            if(month < 0)
            {
                before.month=11;
                before.year--;
            }

            var calendar = '
';

            //header
            calendar += '
';
            calendar += '
';
            calendar += '
<
';
            calendar += '
'+mom.format(settings.formatTitle)+'
';
            calendar += '
>
';
            calendar += '
';
            calendar += '
';

            // name of days
            calendar += '
';

            var offset = settings.startFrom;

            calendar += '
'+names.dayNames[offset]+'
';
            for(var i = 1 + offset ; i < 7 + offset ; i++)
                calendar += '
'+names.dayNames[i%7]+'
';

            calendar += '
';

            /*-----------*\
                MONTH -1
            \*-----------*/
            var daysBefore = monthDays(before.year,before.month);
            var calcBefore = _calcBefore(year,month) + 7 - offset +1;
            daysBefore = daysBefore - calcBefore+1;

            if(calcBefore >= 7)
                calcBefore = calcBefore - 7;

            for(var b = 0 ; b < calcBefore ; b++)
            {
                calendar += drawDay(daysBefore+b,'before');
            }

            /*-----------------*\
                CUREENT MONTH
            \*-----------------*/
            var currDaysInMonth = monthDays(year,month);
            for(var c = 1 ; c <= currDaysInMonth ; c++)
            {
                calendar += drawDay(c,'current',true);
            }

            /*------------*\
                MONTH +1
            \*------------*/
            var nextMonth = 0;
            var cA = _calcAfter(year,month);
            if(cA !== 1)
            {
                for(var a = 0 ; a <= 7-cA ; a++)
                {
                    nextMonth++;
                    calendar += drawDay(nextMonth,'after');
                }
            }

            //to have 6 rows in calendar
            //@todo to think
//            if(cA !== 2 && cA !== 0)
//            {
//                for(var a = 0 ; a < 7 ; a++)
//                {
//                    nextMonth++;
//                    calendar += drawDay(nextMonth,'extra-after');
//                }
//            }

            calendar += '';
            calendar += '';
            calendar += '';
            calendar += '';
            calendar += '';

            calendar += '
';
            return calendar;

            function drawDay(day,elementClass,drawEvents){
                drawEvents = typeof drawEvents !== 'undefined' ? drawEvents : false;

                if(typeof elementClass === 'undefined')
                    elementClass = '';
                var dD = '';
                dD += '
';
                dD += '
'+day+'
';
                dD += '
';

                if(drawEvents)
                {
                    var events = _getEvents(day,month,year);
                    for(var e = 0 ; e < events.length ; e++)
                    {
                        dD += '
'+events[e].title+'
';
                    }

                }

                dD += '
';
                dD += '
';
                return dD;
            }

            function _calcBefore(year,month){
                var f = firstDayPosition(year,month,0)-1;

                if(f < 0)
                    return 6;
                else
                    return f;
            }

            function _calcAfter(year,month){
                month++;
                return firstDayPosition(year,month,0);
            }

            function _getEvents(day,month,year){
                return _.filter(sampleEvents, function (sE) {
                    return moment(new Date(year, month, day)) < new Date(sE.date)
                        && new Date(sE.date) < moment(new Date(year, month, day)).add(1, 'd');
                });
            }

            function monthDays(year,month) {
                month++;
                var d = new Date(year,month, 0);
                return d.getDate();
            }

            function firstDayPosition(year,month,offset) {
                var mom = moment();
                mom.set('year',year);
                mom.set('month',month);
                mom.date(1);
                return mom.day()+offset;
            }
        }

        function _drawModalEvent(event){
            var eventDetails = "";
            eventDetails += '
';
            eventDetails += '
';

            if(typeof  event.color !== "undefined")
                eventDetails += '
';
            else
                eventDetails += '
';

            eventDetails += '
'+event.title+'
';
            eventDetails += '
'+moment(event.date).locale(settings.lang).format(settings.formatEvent)+'
';
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += '
'+settings.typeText+' '+event.type+'
';
            eventDetails += '
'+event.description+'
';
            eventDetails += '
';
            eventDetails += ''+event.url+'';
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += settings.closeText;
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += '
';
            eventDetails += '
';
            return eventDetails;
        }
    }
}( jQuery ));

$.fn.JSONEventCalendar.settings = {
    lang: "pl",
//    format: "DD-MM-YYYY",
    formatTitle: "MMMM YYYY",
    formatEvent: "DD MMMM YYYY",
    startFrom: 3, //0 - Sunday, 1 - Monday etc.
    eventsInDay: 3,
    closeText: 'close',
    typeText: 'Type:'
};

var data = [];<|endoftext|>


<commit_before>CLASS({
  package: 'foam.graphics',
  name: 'Gauge',

  extendsModel: 'foam.graphics.CView',

  properties: [
    {
      name: 'label',
      help: 'The label to appear on the meter.',
    },
    {
      model_: 'FloatProperty',
      name: 'data',
      defaultValue: 1
    },
    {
      model_: 'FloatProperty',
      name:  'maxValue',
      label: 'Max. Value',
      help: 'Maximum Value.',
      defaultValue: 10
    },
    {
      name: 'width',
      defaultValue: 280
    },
    {
      name: 'height',
      defaultValue: 180
    }
  ],

  methods: {
    /*
    toHTML: function() {
      this.canvasView = Canvas.create({background:'rgba(0,0,0,0)',width:this.width+4, height:this.height+4});
      this.canvasView.addChild(this);
      return this.canvasView.toHTML();
    },
    */

    /*
    link: function(powerInfo) {
      Events.follow(powerInfo.propertyValue('watts'), this.propertyValue('value'));
    },
    */

    rotateToValue: function(x, y, value) {
      var c = this.canvas;
      var a = value / this.maxValue * (3.0*Math.PI/5.0)-1.5*Math.PI/5.0;

      c.save();

      c.translate(x,y);
      c.rotate(a);
      c.translate(-x,-y);
    },

    paintSelf: function() {
      var c = this.canvas;

      var width  = this.width - 4;
      var height = this.height - 4;
      var r = height-30;
      var x = width/2+1;
      var y = height-8;

      c.shadowOffsetX = 0;
      c.shadowOffsetY = 0;
      c.shadowBlur = 0;

      c.fillStyle = "black";
      c.fillRect(0,0,width+10,height+10);
      c.fillStyle = "white";
      c.fillRect(2,2,width,height);

      c.strokeStyle = 'black';
      c.lineWidth = 2;
      c.beginPath();
      c.arc(x, y, r, -Math.PI/5.0, -4.0*Math.PI/5.0, true);
      c.stroke();

      c.fillStyle = 'black';
      c.textAlign = 'center';
      c.font = '16pt sans-serif';
      c.fillText(this.label, x, y-30,60);

      this.rotateToValue(x,y,this.data);

      c.lineWidth = 1;
      c.shadowOffsetX = 2;
      c.shadowOffsetY = 2;
      c.shadowBlur = 1;
      c.shadowColor = "gray";

      c.beginPath();
      c.moveTo(width/2+3, height-10);
      c.lineTo(width/2+3, height+5-r);
      c.stroke();

      c.fillStyle='white';
      c.fillRect(width/2+3, height-10, 1, -r+15);
      c.strokeStyle = 'red';
      c.beginPath();
      c.moveTo(width/2+3, height+5-r);
      c.lineTo(width/2+3, height-20-r);
      c.stroke();
      c.fillStyle='white';
      c.fillRect(width/2+3, height+5-r, 1, -30);
      c.restore();

      for ( var i = 0 ; i <= this.maxValue ; i++ ) {
        this.rotateToValue(x,y,i);

        c.fillStyle = 'black';
        c.textAlign = 'center';
        c.font = "10pt sans-serif";
        c.fillText(i, x, y-r-5);

        c.beginPath();
        c.moveTo(x, y-r);
        c.lineTo(x, y-r-4);
        c.stroke();

        c.restore();
      }

      for ( var i = 0 ; i < this.maxValue ; i++ ) {
        this.rotateToValue(x,y,i+0.5);

        c.lineWidth = 1;
        c.beginPath();
        c.moveTo(x, y-r);
        c.lineTo(x, y-r-3);
        c.stroke();

        c.restore();
      }
    }
  }
});
<commit_msg>Add missing @license headers<commit_after>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

CLASS({
  package: 'foam.graphics',
  name: 'Gauge',

  extendsModel: 'foam.graphics.CView',

  properties: [
    {
      name: 'label',
      help: 'The label to appear on the meter.',
    },
    {
      model_: 'FloatProperty',
      name: 'data',
      defaultValue: 1
    },
    {
      model_: 'FloatProperty',
      name:  'maxValue',
      label: 'Max. Value',
      help: 'Maximum Value.',
      defaultValue: 10
    },
    {
      name: 'width',
      defaultValue: 280
    },
    {
      name: 'height',
      defaultValue: 180
    }
  ],

  methods: {
    /*
    toHTML: function() {
      this.canvasView = Canvas.create({background:'rgba(0,0,0,0)',width:this.width+4, height:this.height+4});
      this.canvasView.addChild(this);
      return this.canvasView.toHTML();
    },
    */

    /*
    link: function(powerInfo) {
      Events.follow(powerInfo.propertyValue('watts'), this.propertyValue('value'));
    },
    */

    rotateToValue: function(x, y, value) {
      var c = this.canvas;
      var a = value / this.maxValue * (3.0*Math.PI/5.0)-1.5*Math.PI/5.0;

      c.save();

      c.translate(x,y);
      c.rotate(a);
      c.translate(-x,-y);
    },

    paintSelf: function() {
      var c = this.canvas;

      var width  = this.width - 4;
      var height = this.height - 4;
      var r = height-30;
      var x = width/2+1;
      var y = height-8;

      c.shadowOffsetX = 0;
      c.shadowOffsetY = 0;
      c.shadowBlur = 0;

      c.fillStyle = "black";
      c.fillRect(0,0,width+10,height+10);
      c.fillStyle = "white";
      c.fillRect(2,2,width,height);

      c.strokeStyle = 'black';
      c.lineWidth = 2;
      c.beginPath();
      c.arc(x, y, r, -Math.PI/5.0, -4.0*Math.PI/5.0, true);
      c.stroke();

      c.fillStyle = 'black';
      c.textAlign = 'center';
      c.font = '16pt sans-serif';
      c.fillText(this.label, x, y-30,60);

      this.rotateToValue(x,y,this.data);

      c.lineWidth = 1;
      c.shadowOffsetX = 2;
      c.shadowOffsetY = 2;
      c.shadowBlur = 1;
      c.shadowColor = "gray";

      c.beginPath();
      c.moveTo(width/2+3, height-10);
      c.lineTo(width/2+3, height+5-r);
      c.stroke();

      c.fillStyle='white';
      c.fillRect(width/2+3, height-10, 1, -r+15);
      c.strokeStyle = 'red';
      c.beginPath();
      c.moveTo(width/2+3, height+5-r);
      c.lineTo(width/2+3, height-20-r);
      c.stroke();
      c.fillStyle='white';
      c.fillRect(width/2+3, height+5-r, 1, -30);
      c.restore();

      for ( var i = 0 ; i <= this.maxValue ; i++ ) {
        this.rotateToValue(x,y,i);

        c.fillStyle = 'black';
        c.textAlign = 'center';
        c.font = "10pt sans-serif";
        c.fillText(i, x, y-r-5);

        c.beginPath();
        c.moveTo(x, y-r);
        c.lineTo(x, y-r-4);
        c.stroke();

        c.restore();
      }

      for ( var i = 0 ; i < this.maxValue ; i++ ) {
        this.rotateToValue(x,y,i+0.5);

        c.lineWidth = 1;
        c.beginPath();
        c.moveTo(x, y-r);
        c.lineTo(x, y-r-3);
        c.stroke();

        c.restore();
      }
    }
  }
});
<|endoftext|>


<commit_before>/**
 * Add event to `.child_num_input` for clone `#child_ageClone` on change
 * to create as many inputs as is the number of children
 *
 * @dependencies [w-alert]
 *
 * @param  form  The form on that it work `.children_age_form`
 * @param  childNum  The number of children, for create it age inputs
 *
 * <form>.children_age_form
 * <input>.child_num_input
 *
#child_ageClone
 *
 * --- and ---
 *
 * <form class="... children_age_form"> ...
 * <input type="number" class="form-control child_num_input" min="0" max="5" name="num_children">
 *
 *  --- and ---
 *
 *

 *

 *               <input type="number" placeholder="0" class="form-control" name="age_children[]" value="1" max="17" min="0" disabled/>
 *
 *           Children 1
 *

 *

 *
 *  --- and ---
 *
 *  $php
 *      $children_number = $_POST['num_children']); // 3
 *      $children_age = implode(', ', $_POST['age_children']); // 3, 6, 7
 *  $endphp
 *
 * max children: default 5 (configurable by max attribute)
 * @todo: keep values of yet inserted children ages (w-cookie)
 * @type {any}
 */
function addAges(form, childNum) {
    $("[id^='child_age_']", form).remove(); // first remove all
    childNum = parseInt(childNum);

    // if counter are equal 0 - do nothing
    if (childNum == 0) {
        return false;
    }

    // set {max_children}
    var max_children = parseInt($('.child_num_input', form).attr('max'));
    if (typeof max_children == 'undefined') {
        max_children = 5;
    }
    // over {max_children} are invalid
    if (childNum > max_children) {
        if (typeof withAlert == 'function') {
            withAlert('No more then ' + max_children + ' childs / Non più di ' + max_children + ' bambini', 'warning', {hidetime: 7000});
        } else {
            alert('No more then ' + max_children + ' childs / Non più di ' + max_children + ' bambini', 'warning');
        }
        $('.child_num_input', form).val(max_children);

        childNum = max_children;
    }

    for (var _cN = 1; _cN <= childNum; _cN++) {
        if (_cN > max_children) {
            $('.child_num_input', form).val(max_children);
            return false;
        }
        var childClone = $('#child_ageClone', form).clone();

        // change params
        childClone.attr('id', 'child_age_' + _cN);
        childClone.find('.jq_child_num').text(_cN);
        // input // you can also change `name` attributeetc. ex: .attr('name', 'Camera_1_EtaBambino_' + _cN)
        childClone.find('input')
            .prop("disabled", false)
            .removeProp('disabled')
            .attr('data-binded', childClone.find('input').attr('data-binded') + _cN + ' input');

        // attach and show
        $('#child_ageClone', form).after(childClone);
        childClone.show();

        form.css('padding-bottom', '10px');
    }
}
$(".children_age_form").each(function () {
    var form = $(this);

    // add event trigger for form
    form.on('keyup change', '.child_num_input', function () {
        addAges(form, $('.child_num_input', form).val()); // loop and add age inputs
    });

    // init childNum counter
    addAges(form, $('.child_num_input', form).val());
});
<commit_msg>Added data-attr-name, removed the 10px margin bottom<commit_after>/**
 * Add event to `.child_num_input` for clone `#child_ageClone` on change
 * to create as many inputs as is the number of children
 *
 * @dependencies [w-alert]
 *
 * @param  form  The form on that it work `.children_age_form`
 * @param  childNum  The number of children, for create it age inputs
 *
 * <form>.children_age_form
 * <input>.child_num_input
 *
#child_ageClone
 *
 * --- and ---
 *
 * <form class="children_age_form">
 * <input type="number" class="form-control child_num_input" min="0" max="5" name="num_children">
 *
 *  --- and ---
 *
 *

 *

 *             <input type="number" placeholder="0" class="form-control" name="age_children[]" value="1" max="17" min="0" disabled/>
 *
 *             Children 1
 *

 *

 *
 *  --- and ---
 *
 *  $php
 *      $children_number = $_POST['num_children']); // 3
 *      $children_age = implode(', ', $_POST['age_children']); // 3, 6, 7
 *  $endphp
 *
 * max children: default 5 (configurable by max attribute)
 * @todo: keep values of yet inserted children ages (w-cookie)
 * @type {any}
 */
function addAges(form, childNum) {
    $("[id^='child_age_']", form).remove(); // first remove all
    childNum = parseInt(childNum);

    // if counter are equal 0 - do nothing
    if (childNum == 0) {
        return false;
    }

    // set {max_children}
    var max_children = parseInt($('.child_num_input', form).attr('max'));
    if (typeof max_children == 'undefined') {
        max_children = 5;
    }
    // over {max_children} are invalid
    if (childNum > max_children) {
        if (typeof withAlert == 'function') {
            withAlert('No more then ' + max_children + ' childs / Non più di ' + max_children + ' bambini', 'warning', {hidetime: 7000});
        } else {
            alert('No more then ' + max_children + ' childs / Non più di ' + max_children + ' bambini', 'warning');
        }
        $('.child_num_input', form).val(max_children);

        childNum = max_children;
    }

    for (var _cN = 1; _cN <= childNum; _cN++) {
        if (_cN > max_children) {
            $('.child_num_input', form).val(max_children);
            return false;
        }
        var childClone = $('#child_ageClone', form).clone();

        // change params
        childClone.attr('id', 'child_age_' + _cN);
        childClone.find('.jq_child_num').text(_cN);
        // input
        childClone.find('input')
            .prop("disabled", false)
            .removeProp('disabled')
            .attr('data-binded', childClone.find('input').attr('data-binded') + _cN + ' input');
        // `data-attr-name` you can also change other attributes ex: .attr('placeholder', 'Eta Bambino_' + _cN)
        if (childClone.attr('data-attr-name').length) {
            childClone.find('input').attr('name', childClone.attr('data-attr-name') + _cN);
        }

        // attach and show
        $('#child_ageClone', form).after(childClone);
        childClone.show();
    }
}
$(".children_age_form").each(function () {
    var form = $(this);

    // add event trigger for form
    form.on('keyup change', '.child_num_input', function () {
        addAges(form, $('.child_num_input', form).val()); // loop and add age inputs
    });

    // init childNum counter
    addAges(form, $('.child_num_input', form).val());
});
<|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
         {
             console.log('calculate');
             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 notes<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>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Popup windows.
//>>label: Popups

define( [ "jquery",
	"jquery.mobile.widget",
	"jquery.mobile.navigation",
	"../external/requirejs/depend!./jquery.mobile.hashchange[jquery]" ], function( $ ) {
//>>excludeEnd("jqmBuildExclude");
(function( $, undefined ) {

	$.widget( "mobile.popup", $.mobile.widget, {
		options: {
			theme: null,
			overlayTheme: null,
			shadow: true,
			corners: true,
			fade: true,
			transition: $.mobile.defaultDialogTransition,
			initSelector: ":jqmData(role='popup')"
		},

		_create: function() {
			var ui = {
					screen: "#ui-popup-screen",
					container: "#ui-popup-container"
				},
				proto = $(
					"
" +
					"

" +
					"

" +
					"
"
				),
				thisPage = this.element.closest( ":jqmData(role='page')" ),
				self = this;

			if ( thisPage.length === 0 ) {
				thisPage = $( "body" );
			}

			// Assign the relevant parts of the proto
			for ( var key in ui ) {
				ui[ key ] = proto.find( ui[ key ] ).removeAttr( "id" );
			}

			// Apply the proto
			thisPage.append( ui.screen );
			ui.container.insertAfter( ui.screen );
			ui.container.append( this.element );

			// Define instance variables
			$.extend( this, {
				_ui: ui,
				_isOpen: false
			} );

			$.each( this.options, function( key ) {
				// Cause initial options to be applied by their handler by temporarily setting the option to undefined
				// - the handler then sets it to the initial value
				var value = self.options[ key ];

				self.options[ key ] = undefined;
				self._setOption( key, value, true );
			} );

			ui.screen.bind( "vclick", function( e ) {
				self.close();
			} );
		},

		_realSetTheme: function( dst, theme ) {
			var classes = ( dst.attr( "class" ) || "").split( " " ),
				alreadyAdded = true,
				currentTheme = null,
				matches;

			theme = String( theme );
			while ( classes.length > 0 ) {
				currentTheme = classes.pop();
				matches = currentTheme.match( /^ui-body-([a-z])$/ );
				if ( matches && matches.length > 1 ) {
					currentTheme = matches[ 1 ];
					break;
				} else {
					currentTheme = null;
				}
			}

			if ( theme !== currentTheme ) {
				dst.removeClass( "ui-body-" + currentTheme );
				if ( theme !== null ) {
					dst.addClass( "ui-body-" + theme );
				}
			}
		},

		_setTheme: function( value ) {
			this._realSetTheme( this.element, value );
			this.options.theme = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "theme", value );
		},

		_setOverlayTheme: function( value ) {
			this._realSetTheme( this._ui.container, value );
			// The screen must always have some kind of background for fade to work, so, if the theme is being unset,
			// set the background to "a".
			this._realSetTheme( this._ui.screen, (value === "" ? "a" : value) );
			this.options.overlayTheme = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "overlay-theme", value );
		},

		_setShadow: function( value ) {
			this._ui.container[value ? "addClass" : "removeClass"]( "ui-overlay-shadow" );
			this.options.shadow = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "shadow", value );
		},

		_setCorners: function( value ) {
			this._ui.container[value ? "addClass" : "removeClass"]( "ui-corner-all" );
			this.options.corners = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "corners", value );
		},

		_setFade: function( value ) {
			this.options.fade = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "fade", value );
		},

		_setTransition: function( value ) {
			this._ui.container.removeClass( this.options.transition || "" );
			if ( value && value !== "none" ) {
				this._ui.container.addClass( value );
			}
			this.options.transition = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "transition", value );
		},

		_setOption: function( key, value ) {
			var setter = "_set" + key.replace( /^[a-z]/, function(c) {
				return c.toUpperCase();
			} );

			if ( this[setter] !== undefined ) {
				this[setter]( value );
			} else {
				$.mobile.widget.prototype._setOption.apply( this, arguments );
			}
		},

		_placementCoords: function( x, y ) {
			// Try and center the overlay over the given coordinates
			var ret,
				menuHeight = this._ui.container.outerHeight( true ),
				menuWidth = this._ui.container.outerWidth( true ),
				scrollTop = $( window ).scrollTop(),
				screenHeight = $( window ).height(),
				screenWidth = $( window ).width(),
				halfheight = menuHeight / 2,
				maxwidth = parseFloat( this._ui.container.css( "max-width" ) ),
				roomtop = y - scrollTop,
				roombot = scrollTop + screenHeight - y,
				newtop, newleft;

			if ( roomtop > menuHeight / 2 && roombot > menuHeight / 2 ) {
				newtop = y - halfheight;
			} else {
				// 30px tolerance off the edges
				newtop = roomtop > roombot ? scrollTop + screenHeight - menuHeight - 30 : scrollTop + 30;
			}

			// If the menuwidth is smaller than the screen center is
			if ( menuWidth < maxwidth ) {
				newleft = ( screenWidth - menuWidth ) / 2;
			} else {
				//otherwise insure a >= 30px offset from the left
				newleft = x - menuWidth / 2;

				// 10px tolerance off the edges
				if ( newleft < 10 ) {
					newleft = 10;
				} else if ( ( newleft + menuWidth ) > screenWidth ) {
					newleft = screenWidth - menuWidth - 10;
				}
			}

			return { x: newleft, y: newtop };
		},

		_bindHashChange: function() {
			var self = this;
			$( window ).one( "hashchange.popup", function() {
				self.close( true );
			} );
		},

		_unbindHashChange: function() {
			$( window ).unbind( "hashchange.popup" );
		},

		open: function( x, y ) {
			if ( !this._isOpen ) {
				var self = this,
					onAnimationComplete = function() {
						self._ui.screen.height( $( document ).height() );
					},
					coords = this._placementCoords(
							(undefined === x ? window.innerWidth / 2 : x),
							(undefined === y ? window.innerHeight / 2 : y) );

				this._ui.screen
						.height( $( document ).height() )
						.removeClass( "ui-screen-hidden" );

				if ( this.options.fade ) {
					this._ui.screen.animate( {opacity: 0.5}, "fast" );
				}

				this._ui.container
					.removeClass( "ui-selectmenu-hidden" )
					.css( {
						left: coords.x,
						top: coords.y
					} );

				if ( this.options.transition && this.options.transition !== "none" ) {
					this._ui.container
						.addClass( "in" )
						.animationComplete( onAnimationComplete );
				} else {
					onAnimationComplete();
				}

				// listen for hashchange that will occur when we set it to null dialog hash
				$( window ).one( "hashchange", function() {
					self._bindHashChange();
				} );

				// set hash to non-linkable dialog url
				$.mobile.path.set( ( ( $.mobile.activePage != $.mobile.firstPage) ? $.mobile.urlHistory.getActive().url : "" ) + "&ui-state=dialog" );

				this._isOpen = true;
			}
		},

		close: function( fromHash ) {
			if ( this._isOpen ) {
				var self = this,
					onAnimationComplete = function() {
						self._ui.container
							.removeClass( "reverse out" )
							.addClass( "ui-selectmenu-hidden" )
							.removeAttr( "style" );
					},
					hideScreen = function() {
						self._ui.screen.addClass( "ui-screen-hidden" );
						self._isOpen = false;
						self.element.trigger( "closed" );
						self._ui.screen.removeAttr( "style" );
					};

				if ( this.options.transition && this.options.transition !== "none" ) {
					this._ui.container
						.removeClass( "in" )
						.addClass( "reverse out" )
						.animationComplete( onAnimationComplete );
				} else {
					onAnimationComplete();
				}

				if ( this.options.fade ) {
					this._ui.screen.animate( {opacity: 0.0}, "fast", hideScreen );
				} else {
					hideScreen();
				}

				// unbind listener that comes with opening popup
				this._unbindHashChange();

				// if the close event did not come from an internal hash listener, reset URL back
				if ( !fromHash ) {
					window.history.back();
				}
			}
		}
	} );

	$.mobile.popup.bindPopupToButton = function( btn, popup ) {
		if ( btn.length === 0 || popup.length === 0 ) return;

		var btnVClickHandler = function( e ) {
			// When /this/ button causes a popup, align the popup's theme with that of the button, unless the popup has a theme pre-set
			if ( !popup.jqmData( "overlay-theme-set" ) ) {
				popup.popup( "option", "overlayTheme", btn.jqmData( "theme" ) );
			}
			popup.popup( "open",
					btn.offset().left + btn.outerWidth() / 2,
					btn.offset().top + btn.outerHeight() / 2 );

			// Swallow event, because it might end up getting picked up by the popup window's screen handler, which
			// will in turn cause the popup window to close - Thanks Sasha!
			if ( e.stopPropagation ) {
				e.stopPropagation();
			}
			if ( e.preventDefault ) {
				e.preventDefault();
			}
		};

		// If the popup has a theme set, prevent it from being clobbered by the associated button
		if ( (popup.popup( "option", "overlayTheme" ) || "").match( /[a-z]/ ) ) {
			popup.jqmData( "overlay-theme-set", true );
		}

		btn.attr( {
			"aria-haspopup": true,
			"aria-owns": btn.attr( "href" )
		} )
			.removeAttr( "href" )
			.bind( "vclick", btnVClickHandler );
	};

	$( document ).bind( "pagecreate create", function( e )  {
		$( $.mobile.popup.prototype.options.initSelector, e.target )
				.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
				.popup();

		$( "a[href^='#']:jqmData(rel='popup')", e.target ).each( function() {
			$.mobile.popup.bindPopupToButton( $( this ), $( $( this ).attr( "href" ) ) );
		} );
	} );

})( jQuery );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
} );
//>>excludeEnd("jqmBuildExclude");
<commit_msg>Kill the vclick event on the overlay to just dismiss the popup and do nothing else<commit_after>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Popup windows.
//>>label: Popups

define( [ "jquery",
	"jquery.mobile.widget",
	"jquery.mobile.navigation",
	"../external/requirejs/depend!./jquery.mobile.hashchange[jquery]" ], function( $ ) {
//>>excludeEnd("jqmBuildExclude");
(function( $, undefined ) {

	$.widget( "mobile.popup", $.mobile.widget, {
		options: {
			theme: null,
			overlayTheme: null,
			shadow: true,
			corners: true,
			fade: true,
			transition: $.mobile.defaultDialogTransition,
			initSelector: ":jqmData(role='popup')"
		},

		_create: function() {
			var ui = {
					screen: "#ui-popup-screen",
					container: "#ui-popup-container"
				},
				proto = $(
					"
" +
					"

" +
					"

" +
					"
"
				),
				thisPage = this.element.closest( ":jqmData(role='page')" ),
				self = this;

			if ( thisPage.length === 0 ) {
				thisPage = $( "body" );
			}

			// Assign the relevant parts of the proto
			for ( var key in ui ) {
				ui[ key ] = proto.find( ui[ key ] ).removeAttr( "id" );
			}

			// Apply the proto
			thisPage.append( ui.screen );
			ui.container.insertAfter( ui.screen );
			ui.container.append( this.element );

			// Define instance variables
			$.extend( this, {
				_ui: ui,
				_isOpen: false
			} );

			$.each( this.options, function( key ) {
				// Cause initial options to be applied by their handler by temporarily setting the option to undefined
				// - the handler then sets it to the initial value
				var value = self.options[ key ];

				self.options[ key ] = undefined;
				self._setOption( key, value, true );
			} );

			ui.screen.bind( "vclick", function( e ) {
				e.preventDefault();
				e.stopImmediatePropagation();
				self.close();
			} );
		},

		_realSetTheme: function( dst, theme ) {
			var classes = ( dst.attr( "class" ) || "").split( " " ),
				alreadyAdded = true,
				currentTheme = null,
				matches;

			theme = String( theme );
			while ( classes.length > 0 ) {
				currentTheme = classes.pop();
				matches = currentTheme.match( /^ui-body-([a-z])$/ );
				if ( matches && matches.length > 1 ) {
					currentTheme = matches[ 1 ];
					break;
				} else {
					currentTheme = null;
				}
			}

			if ( theme !== currentTheme ) {
				dst.removeClass( "ui-body-" + currentTheme );
				if ( theme !== null ) {
					dst.addClass( "ui-body-" + theme );
				}
			}
		},

		_setTheme: function( value ) {
			this._realSetTheme( this.element, value );
			this.options.theme = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "theme", value );
		},

		_setOverlayTheme: function( value ) {
			this._realSetTheme( this._ui.container, value );
			// The screen must always have some kind of background for fade to work, so, if the theme is being unset,
			// set the background to "a".
			this._realSetTheme( this._ui.screen, (value === "" ? "a" : value) );
			this.options.overlayTheme = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "overlay-theme", value );
		},

		_setShadow: function( value ) {
			this._ui.container[value ? "addClass" : "removeClass"]( "ui-overlay-shadow" );
			this.options.shadow = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "shadow", value );
		},

		_setCorners: function( value ) {
			this._ui.container[value ? "addClass" : "removeClass"]( "ui-corner-all" );
			this.options.corners = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "corners", value );
		},

		_setFade: function( value ) {
			this.options.fade = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "fade", value );
		},

		_setTransition: function( value ) {
			this._ui.container.removeClass( this.options.transition || "" );
			if ( value && value !== "none" ) {
				this._ui.container.addClass( value );
			}
			this.options.transition = value;
			this.element.attr( "data-" + ( $.mobile.ns || "" ) + "transition", value );
		},

		_setOption: function( key, value ) {
			var setter = "_set" + key.replace( /^[a-z]/, function(c) {
				return c.toUpperCase();
			} );

			if ( this[setter] !== undefined ) {
				this[setter]( value );
			} else {
				$.mobile.widget.prototype._setOption.apply( this, arguments );
			}
		},

		_placementCoords: function( x, y ) {
			// Try and center the overlay over the given coordinates
			var ret,
				menuHeight = this._ui.container.outerHeight( true ),
				menuWidth = this._ui.container.outerWidth( true ),
				scrollTop = $( window ).scrollTop(),
				screenHeight = $( window ).height(),
				screenWidth = $( window ).width(),
				halfheight = menuHeight / 2,
				maxwidth = parseFloat( this._ui.container.css( "max-width" ) ),
				roomtop = y - scrollTop,
				roombot = scrollTop + screenHeight - y,
				newtop, newleft;

			if ( roomtop > menuHeight / 2 && roombot > menuHeight / 2 ) {
				newtop = y - halfheight;
			} else {
				// 30px tolerance off the edges
				newtop = roomtop > roombot ? scrollTop + screenHeight - menuHeight - 30 : scrollTop + 30;
			}

			// If the menuwidth is smaller than the screen center is
			if ( menuWidth < maxwidth ) {
				newleft = ( screenWidth - menuWidth ) / 2;
			} else {
				//otherwise insure a >= 30px offset from the left
				newleft = x - menuWidth / 2;

				// 10px tolerance off the edges
				if ( newleft < 10 ) {
					newleft = 10;
				} else if ( ( newleft + menuWidth ) > screenWidth ) {
					newleft = screenWidth - menuWidth - 10;
				}
			}

			return { x: newleft, y: newtop };
		},

		_bindHashChange: function() {
			var self = this;
			$( window ).one( "hashchange.popup", function() {
				self.close( true );
			} );
		},

		_unbindHashChange: function() {
			$( window ).unbind( "hashchange.popup" );
		},

		open: function( x, y ) {
			if ( !this._isOpen ) {
				var self = this,
					onAnimationComplete = function() {
						self._ui.screen.height( $( document ).height() );
					},
					coords = this._placementCoords(
							(undefined === x ? window.innerWidth / 2 : x),
							(undefined === y ? window.innerHeight / 2 : y) );

				this._ui.screen
						.height( $( document ).height() )
						.removeClass( "ui-screen-hidden" );

				if ( this.options.fade ) {
					this._ui.screen.animate( {opacity: 0.5}, "fast" );
				}

				this._ui.container
					.removeClass( "ui-selectmenu-hidden" )
					.css( {
						left: coords.x,
						top: coords.y
					} );

				if ( this.options.transition && this.options.transition !== "none" ) {
					this._ui.container
						.addClass( "in" )
						.animationComplete( onAnimationComplete );
				} else {
					onAnimationComplete();
				}

				// listen for hashchange that will occur when we set it to null dialog hash
				$( window ).one( "hashchange", function() {
					self._bindHashChange();
				} );

				// set hash to non-linkable dialog url
				$.mobile.path.set( ( ( $.mobile.activePage != $.mobile.firstPage) ? $.mobile.urlHistory.getActive().url : "" ) + "&ui-state=dialog" );

				this._isOpen = true;
			}
		},

		close: function( fromHash ) {
			if ( this._isOpen ) {
				var self = this,
					onAnimationComplete = function() {
						self._ui.container
							.removeClass( "reverse out" )
							.addClass( "ui-selectmenu-hidden" )
							.removeAttr( "style" );
					},
					hideScreen = function() {
						self._ui.screen.addClass( "ui-screen-hidden" );
						self._isOpen = false;
						self.element.trigger( "closed" );
						self._ui.screen.removeAttr( "style" );
					};

				if ( this.options.transition && this.options.transition !== "none" ) {
					this._ui.container
						.removeClass( "in" )
						.addClass( "reverse out" )
						.animationComplete( onAnimationComplete );
				} else {
					onAnimationComplete();
				}

				if ( this.options.fade ) {
					this._ui.screen.animate( {opacity: 0.0}, "fast", hideScreen );
				} else {
					hideScreen();
				}

				// unbind listener that comes with opening popup
				this._unbindHashChange();

				// if the close event did not come from an internal hash listener, reset URL back
				if ( !fromHash ) {
					window.history.back();
				}
			}
		}
	} );

	$.mobile.popup.bindPopupToButton = function( btn, popup ) {
		if ( btn.length === 0 || popup.length === 0 ) return;

		var btnVClickHandler = function( e ) {
			// When /this/ button causes a popup, align the popup's theme with that of the button, unless the popup has a theme pre-set
			if ( !popup.jqmData( "overlay-theme-set" ) ) {
				popup.popup( "option", "overlayTheme", btn.jqmData( "theme" ) );
			}
			popup.popup( "open",
					btn.offset().left + btn.outerWidth() / 2,
					btn.offset().top + btn.outerHeight() / 2 );

			// Swallow event, because it might end up getting picked up by the popup window's screen handler, which
			// will in turn cause the popup window to close - Thanks Sasha!
			if ( e.stopPropagation ) {
				e.stopPropagation();
			}
			if ( e.preventDefault ) {
				e.preventDefault();
			}
		};

		// If the popup has a theme set, prevent it from being clobbered by the associated button
		if ( (popup.popup( "option", "overlayTheme" ) || "").match( /[a-z]/ ) ) {
			popup.jqmData( "overlay-theme-set", true );
		}

		btn.attr( {
			"aria-haspopup": true,
			"aria-owns": btn.attr( "href" )
		} )
			.removeAttr( "href" )
			.bind( "vclick", btnVClickHandler );
	};

	$( document ).bind( "pagecreate create", function( e )  {
		$( $.mobile.popup.prototype.options.initSelector, e.target )
				.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
				.popup();

		$( "a[href^='#']:jqmData(rel='popup')", e.target ).each( function() {
			$.mobile.popup.bindPopupToButton( $( this ), $( $( this ).attr( "href" ) ) );
		} );
	} );

})( jQuery );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
} );
//>>excludeEnd("jqmBuildExclude");
<|endoftext|>