<commit_before>/**
* A simple authentication api for consuming KS from kaltura authenticated api provider
*/
(function(kWidget){ "use strict"
	if( !kWidget ){
		return ;
	}

	var kAuthentication = function(){
		this.init();
	}
	kAuthentication.prototype = {
		// callbacks to auth object events go here:
		authCallbackList : [],

		// Store the latest user data response
		userData: null,

		init: function(){
			var _this = this;
			// setup vars:
			this.authPageUrl = kWidget.getPath() + 'auth/authPage.php';
			this.authOrgin = kWidget.getPath().split('/').slice(0,3).join('/');

			// Await postMessage response:
			if( !window.addEventListener ){
				kWidget.log( "kWidget.auth, requires postMessage browser support" );
				return ;
			}
			window.addEventListener( "message", function( event ){
				kWidget.log( "kWidget.auth: message: " + event.data );
				// check for correct event origin:
				if( event.origin != _this.authOrgin ){
					// error origin mismatch
					return ;
				}
				if( event.data ){
					_this.userData = JSON.parse( event.data );
					for( var i=0; i < _this.authCallbackList.length; i++ ){
						_this.authCallbackList[i]( _this.userData );
					}
				}
			}, false );
			// Add the communication iframe ( will seed message response if already authenticated )
			// added once document is ready ( all auth checks are async )
			$(document).ready(function(){
				$('body').append(
					$( '<iframe style="width:1px;height:1px;border:none;" id="kwidget_auth_iframe">' )
					.attr('src', _this.authPageUrl )
					.load( function(){
						// TODO populate target from kWidget config:
						$(this)[0].contentWindow.postMessage( 'kaltura-auth-check',  '*');
					})
				)
			});
		},
		addAuthCallback: function( callback ) {
			// Check if we are already authenticated:
			if( this.userData ){
				callback( this.userData );
			}
			// Still add the callback for updates ( such as logout or domain deny )
			this.authCallbackList.push( callback );
		},
		getWidget: function( targetId, callback ){
			var _this = this;
			var loginText = "Login to Kaltura";
			var denyDomainText = "Domain Not Allowed";
			var $userIcon = $('<div>')
			.addClass( 'kaltura-user-icon' )
			.css({
				'display': 'inline',
				'float': 'left',
				'margin-right': 5,
				'width': 33,
				'height': 24,
				'background-image': 'url(\'' + kWidget.getPath() + 'auth/kaltura-user-icon-gray.png\')',
				'background-repeat':'no-repeat',
				'background-position':'bottom left'
			});

			$('#' + targetId ).append(
				$( '<a>' )
				.addClass('btn')
				.append(
					$userIcon,
					$('<span>')
					.text( loginText )
				).click( function(){
					var authPage = (window.open( _this.authPageUrl +'?ui=1' ,
							'kalturaauth',
							 "menubar=no,location=yes,resizable=no,scrollbars=no,status=no" +
							 "left=50,top=100,width=400,height=250"
					));
				})
			);
			this.addAuthCallback( function( userData ){
				if( userData.code ){
					var $icon =$('#' + targetId ).find('a div');
					var grayIconUrl = 'url(\'' + kWidget.getPath() + 'auth/kaltura-user-icon-gray.png\')';
					if( grayIconUrl != $icon.css('background-image') ){
						$icon.css({
							'background-image': grayIconUrl
						});
					}
					if( userData.code == 'LOGIN' ){
						if( $('#' + targetId ).find('a span').text() != loginText ){
							$('#' + targetId ).find('a span').text( loginText );
						}
					}
					if(  userData.code == 'DOMAIN_DENY'){
						if( $('#' + targetId ).find('a span').text() != denyDomainText ){
							$('#' + targetId ).find('a span').text( denyDomainText );
						}
					}
					// error check:
					return ;
				}
				// check for data:
				// update the icon to "kaltura light"
				$('#' + targetId ).find('a').empty()
				.append(
					$userIcon.css({
						'background-image': 'url(\'' + kWidget.getPath() + 'auth/kaltura-user-icon.png\')'
					}),
					$('<span>').text( userData.fullName )
				);
				callback( userData );
			})
		}
	}

	// export the auth object into kWidget.auth:
	kWidget.auth = new kAuthentication();

})( window.kWidget );<commit_msg>kWidget.auth: turn off auth log<commit_after>/**
* A simple authentication api for consuming KS from kaltura authenticated api provider
*/
(function(kWidget){ "use strict"
	if( !kWidget ){
		return ;
	}

	var kAuthentication = function(){
		this.init();
	}
	kAuthentication.prototype = {
		// callbacks to auth object events go here:
		authCallbackList : [],

		// Store the latest user data response
		userData: null,

		init: function(){
			var _this = this;
			// setup vars:
			this.authPageUrl = kWidget.getPath() + 'auth/authPage.php';
			this.authOrgin = kWidget.getPath().split('/').slice(0,3).join('/');

			// Await postMessage response:
			if( !window.addEventListener ){
				kWidget.log( "kWidget.auth, requires postMessage browser support" );
				return ;
			}
			window.addEventListener( "message", function( event ){
				//kWidget.log( "kWidget.auth: message: " + event.data );
				// check for correct event origin:
				if( event.origin != _this.authOrgin ){
					// error origin mismatch
					return ;
				}
				if( event.data ){
					_this.userData = JSON.parse( event.data );
					for( var i=0; i < _this.authCallbackList.length; i++ ){
						_this.authCallbackList[i]( _this.userData );
					}
				}
			}, false );
			// Add the communication iframe ( will seed message response if already authenticated )
			// added once document is ready ( all auth checks are async )
			$(document).ready(function(){
				$('body').append(
					$( '<iframe style="width:1px;height:1px;border:none;" id="kwidget_auth_iframe">' )
					.attr('src', _this.authPageUrl )
					.load( function(){
						// TODO populate target from kWidget config:
						$(this)[0].contentWindow.postMessage( 'kaltura-auth-check',  '*');
					})
				)
			});
		},
		addAuthCallback: function( callback ) {
			// Check if we are already authenticated:
			if( this.userData ){
				callback( this.userData );
			}
			// Still add the callback for updates ( such as logout or domain deny )
			this.authCallbackList.push( callback );
		},
		getWidget: function( targetId, callback ){
			var _this = this;
			var loginText = "Login to Kaltura";
			var denyDomainText = "Domain Not Allowed";
			var $userIcon = $('<div>')
			.addClass( 'kaltura-user-icon' )
			.css({
				'display': 'inline',
				'float': 'left',
				'margin-right': 5,
				'width': 33,
				'height': 24,
				'background-image': 'url(\'' + kWidget.getPath() + 'auth/kaltura-user-icon-gray.png\')',
				'background-repeat':'no-repeat',
				'background-position':'bottom left'
			});

			$('#' + targetId ).append(
				$( '<a>' )
				.addClass('btn')
				.append(
					$userIcon,
					$('<span>')
					.text( loginText )
				).click( function(){
					var authPage = (window.open( _this.authPageUrl +'?ui=1' ,
							'kalturaauth',
							 "menubar=no,location=yes,resizable=no,scrollbars=no,status=no" +
							 "left=50,top=100,width=400,height=250"
					));
				})
			);
			this.addAuthCallback( function( userData ){
				if( userData.code ){
					var $icon =$('#' + targetId ).find('a div');
					var grayIconUrl = 'url(\'' + kWidget.getPath() + 'auth/kaltura-user-icon-gray.png\')';
					if( grayIconUrl != $icon.css('background-image') ){
						$icon.css({
							'background-image': grayIconUrl
						});
					}
					if( userData.code == 'LOGIN' ){
						if( $('#' + targetId ).find('a span').text() != loginText ){
							$('#' + targetId ).find('a span').text( loginText );
						}
					}
					if(  userData.code == 'DOMAIN_DENY'){
						if( $('#' + targetId ).find('a span').text() != denyDomainText ){
							$('#' + targetId ).find('a span').text( denyDomainText );
						}
					}
					// error check:
					return ;
				}
				// check for data:
				// update the icon to "kaltura light"
				$('#' + targetId ).find('a').empty()
				.append(
					$userIcon.css({
						'background-image': 'url(\'' + kWidget.getPath() + 'auth/kaltura-user-icon.png\')'
					}),
					$('<span>').text( userData.fullName )
				);
				callback( userData );
			})
		}
	}

	// export the auth object into kWidget.auth:
	kWidget.auth = new kAuthentication();

})( window.kWidget );<|endoftext|>


<commit_before><commit_msg>Improved menu structure<commit_after><|endoftext|>


<commit_before>/**
 * @class WebRtcContent
 *
 * @param {String} ws_uri: URI of the server WebSocket endpoint. Alternatively,
 *   it can be used a WebSocket or DataChannel object.
 */
function WebRtcContent(url, options)
{
  var self = this;

  // Initialize options and object status
  options = options || {};

  $.jsonRPC.setup({endPoint: url});

  var sessionId = null;
  var pollingTimeout = null;

  // Error dispatcher functions

  /**
   * Common function to dispatch the error to the user application
   *
   * @param {Error} error: error object to be dispatched
   */
  function onerror(error)
  {
    if(self.onerror)
       self.onerror(error);
  };

  /**
   * Adaptor from jsonRPC errors to standard Javascript Error objects
   *
   * @param response: jsonRPC error object
   */
  function onerror_jsonrpc(response)
  {
    onerror(new Error(response.error || response));
  };

  // Create the PeerConnection object
  var pc = new RTCPeerConnection(
  {
    iceServers: [{url: 'stun:'+'stun.l.google.com:19302'}]
  });

  // Add the local stream if defined
  if(options.stream)
    pc.addStream(options.stream);

  // Dispatch 'close' event if signaling gets closed
  pc.addEventListener('signalingState', function(event)
  {
    if(pc.signalingState == "close"
    && self.onclose)
       self.onclose(new Event('close'));
  });

  // RPC calls

  // Start

  var mediaConstraints =
  {
    'mandatory':
    {
      'OfferToReceiveAudio': true,
      'OfferToReceiveVideo': true
    }
  };

  pc.createOffer(function(offer)
  {
    // Set the peer local description
    pc.setLocalDescription(offer,
    function()
    {
      console.info("LocalDescription correctly set");
    },
    onerror);
  },
  onerror,
  mediaConstraints);

  pc.onicecandidate = function(event)
  {
    if(event.candidate)
      return;

    var params =
    {
      sdp: pc.localDescription.sdp
    };

    /**
     * Callback when connection is succesful
     *
     * @param {Object} response: JsonRPC response
     */
    function success(response)
    {
      var result = response.result;

      sessionId = result.sessionId;

      pc.setRemoteDescription(new RTCSessionDescription(
      {
        type: 'answer',
        sdp: result.sdp
      }),
      function()
      {
        // Init MediaEvents polling
        pollMediaEvents();

        // Notify to the user about the new stream
        if(self.onopen)
        {
          var streams = pc.getRemoteStreams();

          if(streams && streams[0])
          {
            var event = new Event('open');
                event.stream = streams[0];

            self.onopen(event);
          }
          else
            onerror(new Error("No streams are available"));
        }
      },
      onerror);
    }

    $.jsonRPC.request('start',
    {
      params:  params,
      success: success,
      error:   onerror_jsonrpc
    });
  };

  /**
   * Terminate the connection with the WebRTC media server
   */
  this.terminate = function()
  {
    // Stop polling
    clearTimeout(pollingTimeout);
    pollingTimeout = 'stopped';

    var params =
    {
      sessionId: sessionId
    };

    $.jsonRPC.request('terminate',
    {
      params: params,
      success: function(response)
      {
        if(self.onclose)
           self.onclose(new Event('close'));
      },
      error: onerror_jsonrpc
    });
  };

  // Pool

  /**
   * Pool for events dispatched on the server pipeline
   */
  function pollMediaEvents()
  {
    var timeout = 5*1000;  // Request events each 5 seconds

    var params =
    {
      sessionId: sessionId
    };

    $.jsonRPC.request('poll',
    {
      params: params,
      success: function(response)
      {
        var result = response.result;

        if(result.events)
          for(var i=0, data; data=result.events[i]; i++)
            if(self.onMediaEvent)
            {
              var event = new Event('MediaEvent');
                  event.data = data;

              self.onMediaEvent(event);
            }

        if(pollingTimeout != 'stopped')
           pollingTimeout = setTimeout(pollMediaEvents, timeout);
      },
      error: function(event)
      {
        onerror_jsonrpc(event);

        if(pollingTimeout != 'stopped')
           pollingTimeout = setTimeout(pollMediaEvents, timeout);
      }
    });
  }

  // Mediacontrol

  /**
   * Start a new media communication
   *
   * @param {String} mediaId: identifier of the media communication
   * @param {Object} options: configuration options
   *   {Enum(null, 'send', 'recv', 'sendrecv')} audio: audio stream mode
   *   {Enum(null, 'send', 'recv', 'sendrecv')} video: video stream mode
   * @param {Function(Error, Media)} callback: continuation function
   */
/*  this.startMedia = function(mediaId, options, callback)
  {
    // Adjust arguments if options is not defined
    if(typeof options == 'function')
    {
      callback = options;
      options = undefined;
    }

    options = options || {};

    // We can't disable both audio and video on a stream, raise error
    if(options.audio == null
    && options.video == null)
    {
      callback(new Error("No audio or video medias are defined"));
      return
    }
*/
    /**
     * Decode the mode of the streams
     */
/*    function decodeMode(type, mode)
    {
      var result = {};

      switch(mode)
      {
        case undefined:  // If not defined, set send & receive by default
        case 'sendrecv':
          result.local = true;
          result.remote = true;
        break;

        case 'send':
          result.local = true;
          result.remote = false;
        break;

        case 'recv':
          result.local = false;
          result.remote = true;
        break;

        default:
          callback(new Error("Invalid "+type+" media mode"));
          return
      }

      return result;
    }

    // Audio media
    var audio = decodeMode("audio", options.audio);
    if(!audio) return;

    // Video media
    var video = decodeMode("video", options.video);
    if(!video) return;
*/
    /**
     * Send an offer with the current and new streams and constraints
     */
/*
    // Mode set to send local audio and/or video stream
    if(audio.local || video.local)
      navigator.getUserMedia({'audio': audio.local, 'video': video.local},
      function(stream)
      {
        pc.addStream(stream);
        sendOffer();
      },
      onerror)

    // Mode set to only receive a stream, not send it
    else
      sendOffer();
  }*/
}
<commit_msg>Setting event callback as property to work on Firefox v23<commit_after>/**
 * @class WebRtcContent
 *
 * @param {String} ws_uri: URI of the server WebSocket endpoint. Alternatively,
 *   it can be used a WebSocket or DataChannel object.
 */
function WebRtcContent(url, options)
{
  var self = this;

  // Initialize options and object status
  options = options || {};

  $.jsonRPC.setup({endPoint: url});

  var sessionId = null;
  var pollingTimeout = null;

  // Error dispatcher functions

  /**
   * Common function to dispatch the error to the user application
   *
   * @param {Error} error: error object to be dispatched
   */
  function onerror(error)
  {
    if(self.onerror)
       self.onerror(error);
  };

  /**
   * Adaptor from jsonRPC errors to standard Javascript Error objects
   *
   * @param response: jsonRPC error object
   */
  function onerror_jsonrpc(response)
  {
    onerror(new Error(response.error || response));
  };

  // Create the PeerConnection object
  var pc = new RTCPeerConnection(
  {
    iceServers: [{url: 'stun:'+'stun.l.google.com:19302'}]
  });

  // Add the local stream if defined
  if(options.stream)
    pc.addStream(options.stream);

  // Dispatch 'close' event if signaling gets closed
  pc.onsignalingstatechange = function(event)
  {
    if(pc.signalingState == "close"
    && self.onclose)
       self.onclose(new Event('close'));
  };

  // RPC calls

  // Start

  var mediaConstraints =
  {
    'mandatory':
    {
      'OfferToReceiveAudio': true,
      'OfferToReceiveVideo': true
    }
  };

  pc.createOffer(function(offer)
  {
    // Set the peer local description
    pc.setLocalDescription(offer,
    function()
    {
      console.info("LocalDescription correctly set");
    },
    onerror);
  },
  onerror,
  mediaConstraints);

  pc.onicecandidate = function(event)
  {
    if(event.candidate)
      return;

    var params =
    {
      sdp: pc.localDescription.sdp
    };

    /**
     * Callback when connection is succesful
     *
     * @param {Object} response: JsonRPC response
     */
    function success(response)
    {
      var result = response.result;

      sessionId = result.sessionId;

      pc.setRemoteDescription(new RTCSessionDescription(
      {
        type: 'answer',
        sdp: result.sdp
      }),
      function()
      {
        // Init MediaEvents polling
        pollMediaEvents();

        // Notify to the user about the new stream
        if(self.onopen)
        {
          var streams = pc.getRemoteStreams();

          if(streams && streams[0])
          {
            var event = new Event('open');
                event.stream = streams[0];

            self.onopen(event);
          }
          else
            onerror(new Error("No streams are available"));
        }
      },
      onerror);
    }

    $.jsonRPC.request('start',
    {
      params:  params,
      success: success,
      error:   onerror_jsonrpc
    });
  };

  /**
   * Terminate the connection with the WebRTC media server
   */
  this.terminate = function()
  {
    // Stop polling
    clearTimeout(pollingTimeout);
    pollingTimeout = 'stopped';

    var params =
    {
      sessionId: sessionId
    };

    $.jsonRPC.request('terminate',
    {
      params: params,
      success: function(response)
      {
        if(self.onclose)
           self.onclose(new Event('close'));
      },
      error: onerror_jsonrpc
    });
  };

  // Pool

  /**
   * Pool for events dispatched on the server pipeline
   */
  function pollMediaEvents()
  {
    var timeout = 5*1000;  // Request events each 5 seconds

    var params =
    {
      sessionId: sessionId
    };

    $.jsonRPC.request('poll',
    {
      params: params,
      success: function(response)
      {
        var result = response.result;

        if(result.events)
          for(var i=0, data; data=result.events[i]; i++)
            if(self.onMediaEvent)
            {
              var event = new Event('MediaEvent');
                  event.data = data;

              self.onMediaEvent(event);
            }

        if(pollingTimeout != 'stopped')
           pollingTimeout = setTimeout(pollMediaEvents, timeout);
      },
      error: function(event)
      {
        onerror_jsonrpc(event);

        if(pollingTimeout != 'stopped')
           pollingTimeout = setTimeout(pollMediaEvents, timeout);
      }
    });
  }

  // Mediacontrol

  /**
   * Start a new media communication
   *
   * @param {String} mediaId: identifier of the media communication
   * @param {Object} options: configuration options
   *   {Enum(null, 'send', 'recv', 'sendrecv')} audio: audio stream mode
   *   {Enum(null, 'send', 'recv', 'sendrecv')} video: video stream mode
   * @param {Function(Error, Media)} callback: continuation function
   */
/*  this.startMedia = function(mediaId, options, callback)
  {
    // Adjust arguments if options is not defined
    if(typeof options == 'function')
    {
      callback = options;
      options = undefined;
    }

    options = options || {};

    // We can't disable both audio and video on a stream, raise error
    if(options.audio == null
    && options.video == null)
    {
      callback(new Error("No audio or video medias are defined"));
      return
    }
*/
    /**
     * Decode the mode of the streams
     */
/*    function decodeMode(type, mode)
    {
      var result = {};

      switch(mode)
      {
        case undefined:  // If not defined, set send & receive by default
        case 'sendrecv':
          result.local = true;
          result.remote = true;
        break;

        case 'send':
          result.local = true;
          result.remote = false;
        break;

        case 'recv':
          result.local = false;
          result.remote = true;
        break;

        default:
          callback(new Error("Invalid "+type+" media mode"));
          return
      }

      return result;
    }

    // Audio media
    var audio = decodeMode("audio", options.audio);
    if(!audio) return;

    // Video media
    var video = decodeMode("video", options.video);
    if(!video) return;
*/
    /**
     * Send an offer with the current and new streams and constraints
     */
/*
    // Mode set to send local audio and/or video stream
    if(audio.local || video.local)
      navigator.getUserMedia({'audio': audio.local, 'video': video.local},
      function(stream)
      {
        pc.addStream(stream);
        sendOffer();
      },
      onerror)

    // Mode set to only receive a stream, not send it
    else
      sendOffer();
  }*/
}
<|endoftext|>


<commit_before><commit_msg>ajax post ArrayBuffer Blob<commit_after><|endoftext|>


<commit_before><commit_msg>Update locations by keeping track of current vehicles on map<commit_after><|endoftext|>


<commit_before><commit_msg>Change to a redirect to solve path issues<commit_after><|endoftext|>


<commit_before><commit_msg>fixed copying a root panel on the page of a Wizard, it pasts below the copied panel<commit_after><|endoftext|>


<commit_before><commit_msg>Solved some file params bugs<commit_after><|endoftext|>


<commit_before>const fs = require('fs')
const path = require('path')
const LRU = require('lru-cache')
const express = require('express')
const cookieParser = require('cookie-parser')
const favicon = require('serve-favicon')
const compression = require('compression')
const microcache = require('route-cache')
const resolve = file => path.resolve(__dirname, file)
const { createBundleRenderer } = require('vue-server-renderer')
const redirects = require('./router/301.json')

const isProd = process.env.NODE_ENV === 'production'
const useMicroCache = process.env.MICRO_CACHE !== 'false'
const serverInfo =
  `express/${require('express/package.json').version} ` +
  `vue-server-renderer/${require('vue-server-renderer/package.json').version}`

const availableLanguages = require('./i18n/languages').map(lang => lang.locale)

const app = express()

// const template = fs.readFileSync(resolve('./assets/index.template.html'), 'utf-8')

function createRenderer (bundle, options) {
  // https://github.com/vuejs/vue/blob/dev/packages/vue-server-renderer/README.md#why-use-bundlerenderer
  return createBundleRenderer(bundle, Object.assign(options, {
    // for component caching
    cache: LRU({
      max: 1000,
      maxAge: 1000 * 60 * 15
    }),
    // this is only needed when vue-server-renderer is npm-linked
    basedir: resolve('./public'),
    // recommended for performance
    runInNewContext: false
  }))
}

let renderer
let readyPromise
const templatePath = resolve('./assets/index.template.html')
if (isProd) {
  // In production: create server renderer using template and built server bundle.
  // The server bundle is generated by vue-ssr-webpack-plugin.
  const template = fs.readFileSync(templatePath, 'utf-8')
  const bundle = require('./public/vue-ssr-server-bundle.json')
  // The client manifests are optional, but it allows the renderer
  // to automatically infer preload/prefetch links and directly add <script>
  // tags for any async chunks used during render, avoiding waterfall requests.
  const clientManifest = require('./public/vue-ssr-client-manifest.json')
  renderer = createRenderer(bundle, {
    template,
    clientManifest
  })
} else {
  // In development: setup the dev server with watch and hot-reload,
  // and create a new renderer on bundle / index template update.
  readyPromise = require('./build/setup-dev-server')(
    app,
    templatePath,
    (bundle, options) => {
      renderer = createRenderer(bundle, options)
    }
  )
}

const serve = (path, cache) => express.static(resolve(path), {
  maxAge: cache && isProd ? 1000 * 60 * 60 * 24 * 30 : 0
})

app.use(cookieParser())
app.use(compression({ threshold: 0 }))
app.use(favicon('./static/favicon.ico'))
app.use('/static/manifest.json', serve('./manifest.json', true))
app.use('/static', serve('./static', true))
app.use('/public', serve('./public', true))
app.use('/static/robots.txt', serve('./robots.txt'))
app.use('/releases', serve('./releases'))
app.use('/themes', serve('./themes'))
app.get('/releases/:release', (req, res) => {
  res.setHeader('Content-Type', 'text/html')
  res.sendFile(resolve(`./releases/${req.params.release}`))
})

app.get('/sitemap.xml', (req, res) => {
  res.setHeader('Content-Type', 'text/xml')
  res.sendFile(resolve('./static/sitemap.xml'))
})

// 301 redirect for changed routes
Object.keys(redirects).forEach(k => {
  app.get(k, (req, res) => res.redirect(301, redirects[k]))
})

// since this app has no user-specific content, every page is micro-cacheable.
// if your app involves user-specific content, you need to implement custom
// logic to determine whether a request is cacheable based on its url and
// headers.
// 10-minute microcache.
// https://www.nginx.com/blog/benefits-of-microcaching-nginx/
const isStore = req => !!req.params && !!req.params[1] && req.params[1].includes('store')
app.use(microcache.cacheSeconds(10 * 60 * 1000, req => useMicroCache && !isStore(req) && req.originalUrl))

function render (req, res) {
  const s = Date.now()

  res.setHeader('Content-Type', 'text/html')
  res.setHeader('Server', serverInfo)
  res.cookie('currentLanguage', req.params[0], {
    maxAge: 1000 * 60 * 60 * 24 * 7 // 7 days
  })

  const handleError = err => {
    if (err.url) {
      res.redirect(err.url)
    } else if (err.code === 404) {
      res.status(404).send('404 | Page Not Found')
    } else {
      // Render Error Page or Redirect
      res.status(500).send('500 | Internal Server Error')
      console.error(`error during render : ${req.url}`)
      console.error(err.stack)
    }
  }

  const context = {
    title: 'Vuetify', // default title
    url: req.url,
    lang: req.params[0],
    res,
    hreflangs: availableLanguages.reduce((acc, lang) => {
      return acc + `<link rel="alternate" hreflang="${lang}" href="https://${req.hostname}/${lang}${req.params[1]}" />`
    }, '')
  }
  renderer.renderToString(context, (err, html) => {
    if (err) {
      return handleError(err)
    }
    res.end(html)
    if (!isProd) {
      console.log(`whole request: ${Date.now() - s}ms`)
    }
  })
}

const languageRegex = /^\/([a-z]{2,3}|[a-z]{2,3}-[a-zA-Z]{4}|[a-z]{2,3}-[A-Z]{2,3})(\/.*)?$/

app.get(languageRegex, isProd ? render : (req, res) => {
  readyPromise.then(() => render(req, res))
})

// 302 redirect for no language
app.get('*', (req, res) => {
  let lang = req.cookies.currentLanguage || req.acceptsLanguages(availableLanguages) || 'en'
  if (!languageRegex.test('/' + lang)) lang = 'en'
  res.redirect(302, `/${lang}${req.path}`)
})

const port = process.env.PORT || 8095
app.listen(port, '0.0.0.0', () => {
  console.log(`server started at 0.0.0.0:${port}`)
})
<commit_msg>fix: only cache succesful requests<commit_after>const fs = require('fs')
const path = require('path')
const LRU = require('lru-cache')
const express = require('express')
const cookieParser = require('cookie-parser')
const favicon = require('serve-favicon')
const compression = require('compression')
const microcache = require('route-cache')
const resolve = file => path.resolve(__dirname, file)
const { createBundleRenderer } = require('vue-server-renderer')
const redirects = require('./router/301.json')

const isProd = process.env.NODE_ENV === 'production'
const useMicroCache = process.env.MICRO_CACHE !== 'false'
const serverInfo =
  `express/${require('express/package.json').version} ` +
  `vue-server-renderer/${require('vue-server-renderer/package.json').version}`

const availableLanguages = require('./i18n/languages').map(lang => lang.locale)

const app = express()

// const template = fs.readFileSync(resolve('./assets/index.template.html'), 'utf-8')

function createRenderer (bundle, options) {
  // https://github.com/vuejs/vue/blob/dev/packages/vue-server-renderer/README.md#why-use-bundlerenderer
  return createBundleRenderer(bundle, Object.assign(options, {
    // for component caching
    cache: LRU({
      max: 1000,
      maxAge: 1000 * 60 * 15
    }),
    // this is only needed when vue-server-renderer is npm-linked
    basedir: resolve('./public'),
    // recommended for performance
    runInNewContext: false
  }))
}

let renderer
let readyPromise
const templatePath = resolve('./assets/index.template.html')
if (isProd) {
  // In production: create server renderer using template and built server bundle.
  // The server bundle is generated by vue-ssr-webpack-plugin.
  const template = fs.readFileSync(templatePath, 'utf-8')
  const bundle = require('./public/vue-ssr-server-bundle.json')
  // The client manifests are optional, but it allows the renderer
  // to automatically infer preload/prefetch links and directly add <script>
  // tags for any async chunks used during render, avoiding waterfall requests.
  const clientManifest = require('./public/vue-ssr-client-manifest.json')
  renderer = createRenderer(bundle, {
    template,
    clientManifest
  })
} else {
  // In development: setup the dev server with watch and hot-reload,
  // and create a new renderer on bundle / index template update.
  readyPromise = require('./build/setup-dev-server')(
    app,
    templatePath,
    (bundle, options) => {
      renderer = createRenderer(bundle, options)
    }
  )
}

const serve = (path, cache) => express.static(resolve(path), {
  maxAge: cache && isProd ? 1000 * 60 * 60 * 24 * 30 : 0
})

app.use(cookieParser())
app.use(compression({ threshold: 0 }))
app.use(favicon('./static/favicon.ico'))
app.use('/static/manifest.json', serve('./manifest.json', true))
app.use('/static', serve('./static', true))
app.use('/public', serve('./public', true))
app.use('/static/robots.txt', serve('./robots.txt'))
app.use('/releases', serve('./releases'))
app.use('/themes', serve('./themes'))
app.get('/releases/:release', (req, res) => {
  res.setHeader('Content-Type', 'text/html')
  res.sendFile(resolve(`./releases/${req.params.release}`))
})

app.get('/sitemap.xml', (req, res) => {
  res.setHeader('Content-Type', 'text/xml')
  res.sendFile(resolve('./static/sitemap.xml'))
})

// 301 redirect for changed routes
Object.keys(redirects).forEach(k => {
  app.get(k, (req, res) => res.redirect(301, redirects[k]))
})

// since this app has no user-specific content, every page is micro-cacheable.
// if your app involves user-specific content, you need to implement custom
// logic to determine whether a request is cacheable based on its url and
// headers.
// 10-minute microcache.
// https://www.nginx.com/blog/benefits-of-microcaching-nginx/
const isStore = req => !!req.params && !!req.params[1] && req.params[1].includes('store')
const cacheMiddleware = microcache.cacheSeconds(10 * 60, req => useMicroCache && !isStore(req) && req.originalUrl)

function render (req, res) {
  const s = Date.now()

  res.setHeader('Content-Type', 'text/html')
  res.setHeader('Server', serverInfo)
  res.cookie('currentLanguage', req.params[0], {
    maxAge: 1000 * 60 * 60 * 24 * 7 // 7 days
  })

  const handleError = err => {
    if (err.url) {
      res.redirect(err.url)
    } else if (err.code === 404) {
      res.status(404).send('404 | Page Not Found')
    } else {
      // Render Error Page or Redirect
      res.status(500).send('500 | Internal Server Error')
      console.error(`error during render : ${req.url}`)
      console.error(err.stack)
    }
  }

  const context = {
    title: 'Vuetify', // default title
    url: req.url,
    lang: req.params[0],
    res,
    hreflangs: availableLanguages.reduce((acc, lang) => {
      return acc + `<link rel="alternate" hreflang="${lang}" href="https://${req.hostname}/${lang}${req.params[1]}" />`
    }, '')
  }
  renderer.renderToString(context, (err, html) => {
    if (err) {
      return handleError(err)
    }
    res.end(html)
    if (!isProd) {
      console.log(`whole request: ${Date.now() - s}ms`)
    }
  })
}

const languageRegex = /^\/([a-z]{2,3}|[a-z]{2,3}-[a-zA-Z]{4}|[a-z]{2,3}-[A-Z]{2,3})(\/.*)?$/

app.get(languageRegex, isProd ? render : (req, res) => {
  readyPromise.then(() => render(req, res))
}, cacheMiddleware)

// 302 redirect for no language
app.get('*', (req, res) => {
  let lang = req.cookies.currentLanguage || req.acceptsLanguages(availableLanguages) || 'en'
  if (!languageRegex.test('/' + lang)) lang = 'en'
  res.redirect(302, `/${lang}${req.path}`)
})

const port = process.env.PORT || 8095
app.listen(port, '0.0.0.0', () => {
  console.log(`server started at 0.0.0.0:${port}`)
})
<|endoftext|>


<commit_before>/*
 * Namespace: lb.core.Sandbox
 * Sandbox for Modules of Legal Box Web Application
 *
 * A new instance of Sandbox gets attributed to each User Interface Module
 * and Data Model Module. It acts as a proxy to the methods of the Application
 * Core.
 *
 * Author:
 * Eric Bréchemier <legalbox@eric.brechemier.name>
 *
 * Copyright:
 * Legal Box (c) 2010, All Rights Reserved
 *
 * Version:
 * 2010-05-04
 */
/*requires lb.base.dom.js */
/*requires lb.base.string.js */
/*requires lb.base.log.js */
/*requires lb.core.js */
/*requires lb.core.events.publisher.js */
/*requires lb.core.events.Subscriber.js */
/*jslint nomen:false, white:false, onevar:false, plusplus:false */
/*global lb */
// preserve the module, if already loaded
lb.core.Sandbox = lb.core.Sandbox || function (id){
  // Function: new Sandbox(id): Sandbox
  // Constructor of a new Sandbox.
  //
  // Parameters:
  //   id - string, the identifier of the module, which is also the id of the
  //        root HTML element for this module. If the element does not exist in
  //        the document, it will get created on the first call to getBox().
  //
  // Returns:
  //   object, the new instance of lb.core.Sandbox

  // Define aliases
  var dom = lb.base.dom,
      trim = lb.base.string.trim,
      log = lb.base.log.print,
      publisher = lb.core.events.publisher,
      Subscriber = lb.core.events.Subscriber,

  // Private fields

  // DOM element, the root of the box, carrying the module identifier.
  // Used only withing getBox(), to avoid multiple lookups of the same element.
  // Initialized on first call to getBox().
      box;

  function getId(localId){
    // Function: getId(localId): string
    // Get the identifier of the module, when optional parameter is omitted.
    // With optional parameter, get the full identifier corresponding to the
    // given local identifier.
    //
    // Parameter:
    //  localId - string, optional local identifier
    //
    // Returns:
    //   string, the identifier of the module, as provided in constructor,
    //   or the full identifier corresponding to given local identifier.
    //
    // Note:
    //   The full identifier is made of the module identifier, followed by the
    //   separator '.', followed by the local identifier.

    if (localId) {
      return id+'.'+localId;
    } else {
      return id;
    }
  }

  function getBox(){
    // Function: getBox(): DOM element
    // Get the root HTML element for this module
    //
    // Returns:
    //   DOM element, the HTML element corresponding to the module id
    //
    // Note:
    //   In case no HTML element is found in the document with the module id,
    //   a new div element is created with this id and inserted last in the
    //   document body, and this new element is returned.

    if (box) {
      return box;
    }
    box = dom.$(id);
    if (!box){
      log('Warning: no element "'+id+
          '" found in box. Will be created at end of body.');
      box = dom.element('div',{'id': id});
      document.body.appendChild(box);
    }
    return box;
  }

  function isInBox(element){
    // Function: isInBox(element): boolean
    // Check whether the given element is in the box.
    //
    // Parameter:
    //   element - DOM element, an element
    //
    // Returns:
    //   true if the element is a descendant of or the root of the box itself
    //   false otherwise

    // Warning: element attribute hides element() function.

    var ancestor = element;
    while (ancestor) {
      // box must be found in ancestors or self
      if ( ancestor === getBox() ) {
        return true;
      }
      ancestor = ancestor.parentNode;
    }
    return false;
  }

  function subscribe(filter,callback){
    // Function: subscribe(filter,callback)
    // Create a new event subscription, triggering the callback only for events
    // matching the provided filter.
    //
    // A new instance of Event Subscriber (lb.core.events.Subscriber) is
    // created and added to the Event publisher (lb.core.events.publisher).
    //
    // Parameters:
    //   filter - object, the event filter.
    //           This object is similar to event objects. Any included property
    //           will be used as a filter to restrict events part of the
    //           subscription. For example:
    //           * {} is a subscription to all events (no filter)
    //           * {name: 'foo'} is a subscription to all events named 'foo'
    //           * {name: 'foo', id:42} filters on name==='foo' and id===42
    //   callback - function, the associated callback function

    publisher.addSubscriber( new Subscriber(filter,callback) );
  }

  function trim(string){
    // Function: trim(string): string
    // Remove leading and trailing whitespace from a string.
    //
    // Parameter:
    //   string - string, the string to trim
    //
    // Returns:
    //   string, a copy of the string with no whitespace at start and end

    return trim(string);
  }

  function $(localId){
    // Function: $(localId): DOM element
    // Get the element of the box with given local identifier
    //
    // Parameter:
    //   localId - string, the local identifier of the element, without prefix.
    //             See getId() for details.
    //
    // Returns:
    //   * DOM element, the element from the box with corresponding localId
    //   * null if no element is found in the box with the localId
    //
    // Notes:
    //   This method calls getBox() internally to check that a found element
    //   is a descendant of the box element. This may create the box element
    //   if not already present in the document.
    //
    //   Since the provided localId is converted to a full identifier using
    //   getId(), a call to $() without argument will return the root element
    //   of the box, in the same way as getBox().

    var element = dom.$( getId(localId) );
    if ( isInBox(element) ){
      return element;
    }
    log('Warning: element "'+getId(localId)+'" not part of box "'+id+'"');
    return null;
  }

  function element(name,attributes){
    // Function: element(name,attributes,childNodes): DOM element
    // Create a new DOM element
    // e.g.
    // element('a',{href:'#here',title:'Here'},'Click here')
    // will create a new DOM element
    // Click here
    //
    // Parameters:
    //   name - string, the name of the element
    //   attributes - object, optional arguments as a set of named properties
    //   childNodes - array or list of arguments, the optional child nodes.
    //                Text nodes may be represented simply as strings.
    //
    // Returns:
    //   DOM element, the newly created DOM element

    return dom.element.apply(this,arguments);
  }

  function getClasses(element){
    // Function: getClasses(element): object
    // Get the CSS classes of given DOM element
    //
    // Parameter:
    //   element - DOM element, an element of the box
    //
    // Returns:
    //   object, a hash of CSS classes, with a boolean property set to true
    //   for each of the CSS class names found on element.
    //
    // Note:
    //   an empty object is returned when the element is out of the box.

    // Warning: element parameter hides element() function
    if ( !isInBox(element) ){
      log('Warning: cannot get CSS classes of element "'+element+
          '" outside of box "'+id+'"');
      return {};
    }

    return dom.getClasses(element);
  }

  function addClass(element,name){
    // Function: addClass(element,name)
    // Append a CSS class to a DOM element part of the box
    //
    // Parameters:
    //   element - DOM element, an element of the box
    //   name - string, a CSS class name
    //
    // Note:
    //   Nothing happens if element is out of the box.

    // Warning: element parameter hides element() function
    if ( !isInBox(element) ){
      log('Warning: cannot add CSS class to element "'+element+
          '" outside of box "'+id+'"');
      return;
    }

    dom.addClass(element,name);
  }

  function removeClass(element,name){
    // Function: removeClass(element,name)
    // Remove a CSS class from a DOM element part of the box
    //
    // Parameters:
    //   element - DOM element, an element of the box
    //   name - string, a CSS class name
    //
    // Note:
    //   Nothing happens if element is out of the box.

    // Warning: element parameter hides element() function
    if ( !isInBox(element) ){
      log('Warning: cannot remove CSS class from element "'+element+
          '" outside of box "'+id+'"');
      return;
    }

    dom.removeClass(element,name);
  }

  function addListener(element,type,listener,useCapture){
    // Function: addListener(element, type, listener, useCapture)
    // Register a new listener for a type of event on a DOM element of the box
    //
    // Parameters:
    //   element - Element, a DOM element
    //   type - string, the name of an event (without 'on') e.g. 'click'
    //   listener - function, a function to call when the event is dispatched.
    //   useCapture - boolean, whether the callback is set for capture phase.
    //                Optional: defaults to false.
    //
    // Note:
    //   Nothing happens when element is out of the box.

    // Warning: element parameter hides element() function
    if ( !isInBox(element) ){
      log('Warning: cannot add listener to element "'+element+
          '" outside of box "'+id+'"');
      return;
    }

    dom.addListener(element,type,listener,useCapture);
  }

  function removeListener(element,type,listener,useCapture){
    // Function: removeListener(element, type, listener, useCapture)
    // Unregister a listener for a type of event on a DOM element of the box
    //
    // Parameters:
    //   element - Element, a DOM element
    //   type - string, the name of an event (without 'on') e.g. 'click'
    //   listener - function, a function to call when the event is dispatched.
    //   useCapture - boolean, whether the callback is set for capture phase.
    //                Optional: defaults to false.
    //
    // Note:
    //   Nothing happens when element is out of the box.

    // Warning: element parameter hides element() function
    if ( !isInBox(element) ){
      log('Warning: cannot remove listener from element "'+element+
          '" outside of box "'+id+'"');
      return;
    }

    dom.removeListener(element,type,listener,useCapture);
  }

  return { // Public methods
    getId: getId,
    getBox: getBox,
    isInBox: isInBox,
    subscribe: subscribe,
    trim: trim,
    $: $,
    element: element,
    getClasses: getClasses,
    addClass: addClass,
    removeClass: removeClass,
    addListener: addListener,
    removeListener: removeListener
  };
};
<commit_msg>Minor fixes based on JSLint and documentation output<commit_after>/*
 * Namespace: lb.core.Sandbox
 * Sandbox for Modules of Legal Box Web Application
 *
 * A new instance of Sandbox gets attributed to each User Interface Module
 * and Data Model Module. It acts as a proxy to the methods of the Application
 * Core.
 *
 * Author:
 * Eric Bréchemier <legalbox@eric.brechemier.name>
 *
 * Copyright:
 * Legal Box (c) 2010, All Rights Reserved
 *
 * Version:
 * 2010-05-04
 */
/*requires lb.base.dom.js */
/*requires lb.base.string.js */
/*requires lb.base.log.js */
/*requires lb.core.js */
/*requires lb.core.events.publisher.js */
/*requires lb.core.events.Subscriber.js */
/*jslint nomen:false, white:false, onevar:false, plusplus:false */
/*global lb, document */
// preserve the module, if already loaded
lb.core.Sandbox = lb.core.Sandbox || function (id){
  // Function: new Sandbox(id): Sandbox
  // Constructor of a new Sandbox.
  //
  // Parameters:
  //   id - string, the identifier of the module, which is also the id of the
  //        root HTML element for this module. If the element does not exist in
  //        the document, it will get created on the first call to getBox().
  //
  // Returns:
  //   object, the new instance of lb.core.Sandbox

  // Define aliases
  var dom = lb.base.dom,
      gTrim = lb.base.string.trim,
      log = lb.base.log.print,
      publisher = lb.core.events.publisher,
      Subscriber = lb.core.events.Subscriber,

  // Private fields

  // DOM element, the root of the box, carrying the module identifier.
  // Used only withing getBox(), to avoid multiple lookups of the same element.
  // Initialized on first call to getBox().
      box;

  function getId(localId){
    // Function: getId(localId): string
    // Get the identifier of the module, when optional parameter is omitted.
    // With optional parameter, get the full identifier corresponding to the
    // given local identifier.
    //
    // Parameter:
    //  localId - string, optional local identifier
    //
    // Returns:
    //   string, the identifier of the module, as provided in constructor,
    //   or the full identifier corresponding to given local identifier.
    //
    // Note:
    //   The full identifier is made of the module identifier, followed by the
    //   separator '.', followed by the local identifier.

    if (localId) {
      return id+'.'+localId;
    } else {
      return id;
    }
  }

  function getBox(){
    // Function: getBox(): DOM element
    // Get the root HTML element for this module
    //
    // Returns:
    //   DOM element, the HTML element corresponding to the module id
    //
    // Note:
    //   In case no HTML element is found in the document with the module id,
    //   a new div element is created with this id and inserted last in the
    //   document body, and this new element is returned.

    if (box) {
      return box;
    }
    box = dom.$(id);
    if (!box){
      log('Warning: no element "'+id+
          '" found in box. Will be created at end of body.');
      box = dom.element('div',{'id': id});
      document.body.appendChild(box);
    }
    return box;
  }

  function isInBox(element){
    // Function: isInBox(element): boolean
    // Check whether the given element is in the box.
    //
    // Parameter:
    //   element - DOM element, an element
    //
    // Returns:
    //   true if the element is a descendant of or the root of the box itself
    //   false otherwise

    // Warning: element attribute hides element() function.

    var ancestor = element;
    while (ancestor) {
      // box must be found in ancestors or self
      if ( ancestor === getBox() ) {
        return true;
      }
      ancestor = ancestor.parentNode;
    }
    return false;
  }

  function subscribe(filter,callback){
    // Function: subscribe(filter,callback)
    // Create a new event subscription, triggering the callback only for events
    // matching the provided filter.
    //
    // A new instance of Event Subscriber (lb.core.events.Subscriber) is
    // created and added to the Event publisher (lb.core.events.publisher).
    //
    // Parameters:
    //   filter - object, the event filter.
    //           This object is similar to event objects. Any included property
    //           will be used as a filter to restrict events part of the
    //           subscription. For example:
    //           * {} is a subscription to all events (no filter)
    //           * {name: 'foo'} is a subscription to all events named 'foo'
    //           * {name: 'foo', id:42} filters on name==='foo' and id===42
    //   callback - function, the associated callback function

    publisher.addSubscriber( new Subscriber(filter,callback) );
  }

  function trim(string){
    // Function: trim(string): string
    // Remove leading and trailing whitespace from a string.
    //
    // Parameter:
    //   string - string, the string to trim
    //
    // Returns:
    //   string, a copy of the string with no whitespace at start and end

    //
    return gTrim(string);
  }

  function $(localId){
    // Function: $(localId): DOM element
    // Get the element of the box with given local identifier
    //
    // Parameter:
    //   localId - string, the local identifier of the element, without prefix.
    //             See getId() for details.
    //
    // Returns:
    //   * DOM element, the element from the box with corresponding localId
    //   * null if no element is found in the box with the localId
    //
    // Notes:
    //   This method calls getBox() internally to check that a found element
    //   is a descendant of the box element. This may create the box element
    //   if not already present in the document.
    //
    //   Since the provided localId is converted to a full identifier using
    //   getId(), a call to $() without argument will return the root element
    //   of the box, in the same way as getBox().

    //
    var element = dom.$( getId(localId) );
    if ( isInBox(element) ){
      return element;
    }
    log('Warning: element "'+getId(localId)+'" not part of box "'+id+'"');
    return null;
  }

  function element(name,attributes){
    // Function: element(name,attributes,childNodes): DOM element
    // Create a new DOM element
    // e.g.
    // element('a',{href:'#here',title:'Here'},'Click here')
    // will create a new DOM element
    // Click here
    //
    // Parameters:
    //   name - string, the name of the element
    //   attributes - object, optional arguments as a set of named properties
    //   childNodes - array or list of arguments, the optional child nodes.
    //                Text nodes may be represented simply as strings.
    //
    // Returns:
    //   DOM element, the newly created DOM element

    //
    return dom.element.apply(this,arguments);
  }

  function getClasses(element){
    // Function: getClasses(element): object
    // Get the CSS classes of given DOM element
    //
    // Parameter:
    //   element - DOM element, an element of the box
    //
    // Returns:
    //   object, a hash of CSS classes, with a boolean property set to true
    //   for each of the CSS class names found on element.
    //
    // Note:
    //   an empty object is returned when the element is out of the box.

    // Warning: element parameter hides element() function
    if ( !isInBox(element) ){
      log('Warning: cannot get CSS classes of element "'+element+
          '" outside of box "'+id+'"');
      return {};
    }

    return dom.getClasses(element);
  }

  function addClass(element,name){
    // Function: addClass(element,name)
    // Append a CSS class to a DOM element part of the box
    //
    // Parameters:
    //   element - DOM element, an element of the box
    //   name - string, a CSS class name
    //
    // Note:
    //   Nothing happens if element is out of the box.

    // Warning: element parameter hides element() function
    if ( !isInBox(element) ){
      log('Warning: cannot add CSS class to element "'+element+
          '" outside of box "'+id+'"');
      return;
    }

    dom.addClass(element,name);
  }

  function removeClass(element,name){
    // Function: removeClass(element,name)
    // Remove a CSS class from a DOM element part of the box
    //
    // Parameters:
    //   element - DOM element, an element of the box
    //   name - string, a CSS class name
    //
    // Note:
    //   Nothing happens if element is out of the box.

    // Warning: element parameter hides element() function
    if ( !isInBox(element) ){
      log('Warning: cannot remove CSS class from element "'+element+
          '" outside of box "'+id+'"');
      return;
    }

    dom.removeClass(element,name);
  }

  function addListener(element,type,listener,useCapture){
    // Function: addListener(element, type, listener, useCapture)
    // Register a new listener for a type of event on a DOM element of the box
    //
    // Parameters:
    //   element - Element, a DOM element
    //   type - string, the name of an event (without 'on') e.g. 'click'
    //   listener - function, a function to call when the event is dispatched.
    //   useCapture - boolean, whether the callback is set for capture phase.
    //                Optional: defaults to false.
    //
    // Note:
    //   Nothing happens when element is out of the box.

    // Warning: element parameter hides element() function
    if ( !isInBox(element) ){
      log('Warning: cannot add listener to element "'+element+
          '" outside of box "'+id+'"');
      return;
    }

    dom.addListener(element,type,listener,useCapture);
  }

  function removeListener(element,type,listener,useCapture){
    // Function: removeListener(element, type, listener, useCapture)
    // Unregister a listener for a type of event on a DOM element of the box
    //
    // Parameters:
    //   element - Element, a DOM element
    //   type - string, the name of an event (without 'on') e.g. 'click'
    //   listener - function, a function to call when the event is dispatched.
    //   useCapture - boolean, whether the callback is set for capture phase.
    //                Optional: defaults to false.
    //
    // Note:
    //   Nothing happens when element is out of the box.

    // Warning: element parameter hides element() function
    if ( !isInBox(element) ){
      log('Warning: cannot remove listener from element "'+element+
          '" outside of box "'+id+'"');
      return;
    }

    dom.removeListener(element,type,listener,useCapture);
  }

  return { // Public methods
    getId: getId,
    getBox: getBox,
    isInBox: isInBox,
    subscribe: subscribe,
    trim: trim,
    $: $,
    element: element,
    getClasses: getClasses,
    addClass: addClass,
    removeClass: removeClass,
    addListener: addListener,
    removeListener: removeListener
  };
};
<|endoftext|>


<commit_before><commit_msg>tweaking tab drag anims<commit_after><|endoftext|>


<commit_before>const fs = require('fs')
const path = require('path')
const LRU = require('lru-cache')
const express = require('express')
const cookieParser = require('cookie-parser')
const favicon = require('serve-favicon')
const compression = require('compression')
const microcache = require('route-cache')
const resolve = file => path.resolve(__dirname, file)
const { createBundleRenderer } = require('vue-server-renderer')
const redirects = require('./router/301.json')

const isProd = process.env.NODE_ENV === 'production'
const useMicroCache = process.env.MICRO_CACHE !== 'false'
const serverInfo =
  `express/${require('express/package.json').version} ` +
  `vue-server-renderer/${require('vue-server-renderer/package.json').version}`

const availableLanguages = require('./i18n/languages').map(lang => lang.locale)

const app = express()

// const template = fs.readFileSync(resolve('./assets/index.template.html'), 'utf-8')

function createRenderer (bundle, options) {
  // https://github.com/vuejs/vue/blob/dev/packages/vue-server-renderer/README.md#why-use-bundlerenderer
  return createBundleRenderer(bundle, Object.assign(options, {
    // for component caching
    cache: LRU({
      max: 1000,
      maxAge: 1000 * 60 * 15
    }),
    // this is only needed when vue-server-renderer is npm-linked
    basedir: resolve('./public'),
    // recommended for performance
    runInNewContext: false
  }))
}

let renderer
let readyPromise
const templatePath = resolve('./assets/index.template.html')
if (isProd) {
  // In production: create server renderer using template and built server bundle.
  // The server bundle is generated by vue-ssr-webpack-plugin.
  const template = fs.readFileSync(templatePath, 'utf-8')
  const bundle = require('./public/vue-ssr-server-bundle.json')
  // The client manifests are optional, but it allows the renderer
  // to automatically infer preload/prefetch links and directly add <script>
  // tags for any async chunks used during render, avoiding waterfall requests.
  const clientManifest = require('./public/vue-ssr-client-manifest.json')
  renderer = createRenderer(bundle, {
    template,
    clientManifest
  })
} else {
  // In development: setup the dev server with watch and hot-reload,
  // and create a new renderer on bundle / index template update.
  readyPromise = require('./build/setup-dev-server')(
    app,
    templatePath,
    (bundle, options) => {
      renderer = createRenderer(bundle, options)
    }
  )
}

const serve = (path, cache) => express.static(resolve(path), {
  maxAge: cache && isProd ? 1000 * 60 * 60 * 24 * 30 : 0
})

app.use(cookieParser())
app.use(compression({ threshold: 0 }))
app.use(favicon('./static/favicon.ico'))
app.use('/example-source', serve('./examples', true)) // TODO: This should be a regex to serve anything with an extension
app.use('/static/manifest.json', serve('./manifest.json', true))
app.use('/static', serve('./static', true))
app.use('/public', serve('./public', true))
app.use('/static/robots.txt', serve('./robots.txt'))
app.use('/releases', serve('./releases'))
app.use('/themes', serve('./themes'))
app.get('/releases/:release', (req, res) => {
  res.setHeader('Content-Type', 'text/html')
  res.sendFile(resolve(`./releases/${req.params.release}`))
})

app.get('/sitemap.xml', (req, res) => {
  res.setHeader('Content-Type', 'text/xml')
  res.sendFile(resolve('./static/sitemap.xml'))
})

// 301 redirect for changed routes
Object.keys(redirects).forEach(k => {
  app.get(k, (req, res) => res.redirect(301, redirects[k]))
})

// since this app has no user-specific content, every page is micro-cacheable.
// if your app involves user-specific content, you need to implement custom
// logic to determine whether a request is cacheable based on its url and
// headers.
// 1-second microcache.
// https://www.nginx.com/blog/benefits-of-microcaching-nginx/
app.use(microcache.cacheSeconds(1, req => useMicroCache && req.originalUrl))

function render (req, res) {
  const s = Date.now()

  res.setHeader('Content-Type', 'text/html')
  res.setHeader('Server', serverInfo)
  res.cookie('currentLanguage', req.params[0], {
    maxAge: 1000 * 60 * 60 * 24 * 7 // 7 days
  })

  const handleError = err => {
    if (err.url) {
      res.redirect(err.url)
    } else if (err.code === 404) {
      res.status(404).send('404 | Page Not Found')
    } else {
      // Render Error Page or Redirect
      res.status(500).send('500 | Internal Server Error')
      console.error(`error during render : ${req.url}`)
      console.error(err.stack)
    }
  }

  const context = {
    title: 'Vuetify', // default title
    url: req.url,
    lang: req.params[0],
    res,
    hreflangs: availableLanguages.reduce((acc, lang) => {
      return acc + `<link rel="alternate" hreflang="${lang}" href="https://${req.hostname}/${lang}${req.params[1]}" />`
    }, '')
  }
  renderer.renderToString(context, (err, html) => {
    if (err) {
      return handleError(err)
    }
    res.end(html)
    if (!isProd) {
      console.log(`whole request: ${Date.now() - s}ms`)
    }
  })
}

const languageRegex = /^\/([a-z]{2,3}|[a-z]{2,3}-[a-zA-Z]{4}|[a-z]{2,3}-[A-Z]{2,3})(\/.*)?$/

app.get(languageRegex, isProd ? render : (req, res) => {
  readyPromise.then(() => render(req, res))
})

// 302 redirect for no language
app.get('*', (req, res) => {
  let lang = req.cookies.currentLanguage || req.acceptsLanguages(availableLanguages) || 'en'
  if (!languageRegex.test('/' + lang)) lang = 'en'
  res.redirect(302, `/${lang}${req.path}`)
})

const port = process.env.PORT || 8095
app.listen(port, '0.0.0.0', () => {
  console.log(`server started at 0.0.0.0:${port}`)
})
<commit_msg>increase page cache time to 10 minutes<commit_after>const fs = require('fs')
const path = require('path')
const LRU = require('lru-cache')
const express = require('express')
const cookieParser = require('cookie-parser')
const favicon = require('serve-favicon')
const compression = require('compression')
const microcache = require('route-cache')
const resolve = file => path.resolve(__dirname, file)
const { createBundleRenderer } = require('vue-server-renderer')
const redirects = require('./router/301.json')

const isProd = process.env.NODE_ENV === 'production'
const useMicroCache = process.env.MICRO_CACHE !== 'false'
const serverInfo =
  `express/${require('express/package.json').version} ` +
  `vue-server-renderer/${require('vue-server-renderer/package.json').version}`

const availableLanguages = require('./i18n/languages').map(lang => lang.locale)

const app = express()

// const template = fs.readFileSync(resolve('./assets/index.template.html'), 'utf-8')

function createRenderer (bundle, options) {
  // https://github.com/vuejs/vue/blob/dev/packages/vue-server-renderer/README.md#why-use-bundlerenderer
  return createBundleRenderer(bundle, Object.assign(options, {
    // for component caching
    cache: LRU({
      max: 1000,
      maxAge: 1000 * 60 * 15
    }),
    // this is only needed when vue-server-renderer is npm-linked
    basedir: resolve('./public'),
    // recommended for performance
    runInNewContext: false
  }))
}

let renderer
let readyPromise
const templatePath = resolve('./assets/index.template.html')
if (isProd) {
  // In production: create server renderer using template and built server bundle.
  // The server bundle is generated by vue-ssr-webpack-plugin.
  const template = fs.readFileSync(templatePath, 'utf-8')
  const bundle = require('./public/vue-ssr-server-bundle.json')
  // The client manifests are optional, but it allows the renderer
  // to automatically infer preload/prefetch links and directly add <script>
  // tags for any async chunks used during render, avoiding waterfall requests.
  const clientManifest = require('./public/vue-ssr-client-manifest.json')
  renderer = createRenderer(bundle, {
    template,
    clientManifest
  })
} else {
  // In development: setup the dev server with watch and hot-reload,
  // and create a new renderer on bundle / index template update.
  readyPromise = require('./build/setup-dev-server')(
    app,
    templatePath,
    (bundle, options) => {
      renderer = createRenderer(bundle, options)
    }
  )
}

const serve = (path, cache) => express.static(resolve(path), {
  maxAge: cache && isProd ? 1000 * 60 * 60 * 24 * 30 : 0
})

app.use(cookieParser())
app.use(compression({ threshold: 0 }))
app.use(favicon('./static/favicon.ico'))
app.use('/example-source', serve('./examples', true)) // TODO: This should be a regex to serve anything with an extension
app.use('/static/manifest.json', serve('./manifest.json', true))
app.use('/static', serve('./static', true))
app.use('/public', serve('./public', true))
app.use('/static/robots.txt', serve('./robots.txt'))
app.use('/releases', serve('./releases'))
app.use('/themes', serve('./themes'))
app.get('/releases/:release', (req, res) => {
  res.setHeader('Content-Type', 'text/html')
  res.sendFile(resolve(`./releases/${req.params.release}`))
})

app.get('/sitemap.xml', (req, res) => {
  res.setHeader('Content-Type', 'text/xml')
  res.sendFile(resolve('./static/sitemap.xml'))
})

// 301 redirect for changed routes
Object.keys(redirects).forEach(k => {
  app.get(k, (req, res) => res.redirect(301, redirects[k]))
})

// since this app has no user-specific content, every page is micro-cacheable.
// if your app involves user-specific content, you need to implement custom
// logic to determine whether a request is cacheable based on its url and
// headers.
// 10-minute microcache.
// https://www.nginx.com/blog/benefits-of-microcaching-nginx/
const isStore = req => !!req.params && !!req.params[1] && req.params[1].includes('store')
app.use(microcache.cacheSeconds(10 * 60 * 1000, req => useMicroCache && !isStore(req) && req.originalUrl))

function render (req, res) {
  const s = Date.now()

  res.setHeader('Content-Type', 'text/html')
  res.setHeader('Server', serverInfo)
  res.cookie('currentLanguage', req.params[0], {
    maxAge: 1000 * 60 * 60 * 24 * 7 // 7 days
  })

  const handleError = err => {
    if (err.url) {
      res.redirect(err.url)
    } else if (err.code === 404) {
      res.status(404).send('404 | Page Not Found')
    } else {
      // Render Error Page or Redirect
      res.status(500).send('500 | Internal Server Error')
      console.error(`error during render : ${req.url}`)
      console.error(err.stack)
    }
  }

  const context = {
    title: 'Vuetify', // default title
    url: req.url,
    lang: req.params[0],
    res,
    hreflangs: availableLanguages.reduce((acc, lang) => {
      return acc + `<link rel="alternate" hreflang="${lang}" href="https://${req.hostname}/${lang}${req.params[1]}" />`
    }, '')
  }
  renderer.renderToString(context, (err, html) => {
    if (err) {
      return handleError(err)
    }
    res.end(html)
    if (!isProd) {
      console.log(`whole request: ${Date.now() - s}ms`)
    }
  })
}

const languageRegex = /^\/([a-z]{2,3}|[a-z]{2,3}-[a-zA-Z]{4}|[a-z]{2,3}-[A-Z]{2,3})(\/.*)?$/

app.get(languageRegex, isProd ? render : (req, res) => {
  readyPromise.then(() => render(req, res))
})

// 302 redirect for no language
app.get('*', (req, res) => {
  let lang = req.cookies.currentLanguage || req.acceptsLanguages(availableLanguages) || 'en'
  if (!languageRegex.test('/' + lang)) lang = 'en'
  res.redirect(302, `/${lang}${req.path}`)
})

const port = process.env.PORT || 8095
app.listen(port, '0.0.0.0', () => {
  console.log(`server started at 0.0.0.0:${port}`)
})
<|endoftext|>


<commit_before>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _Arc = require('./shapes/Arc');

Object.defineProperty(exports, 'Arc', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_Arc).default;
  }
});

var _Pie = require('./shapes/Pie');

Object.defineProperty(exports, 'Pie', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_Pie).default;
  }
});

var _Line = require('./shapes/Line');

Object.defineProperty(exports, 'Line', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_Line).default;
  }
});

var _LinePath = require('./shapes/LinePath');

Object.defineProperty(exports, 'LinePath', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_LinePath).default;
  }
});

var _LineRadial = require('./shapes/LineRadial');

Object.defineProperty(exports, 'LineRadial', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_LineRadial).default;
  }
});

var _LinkHorizontal = require('./shapes/LinkHorizontal');

Object.defineProperty(exports, 'LinkHorizontal', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_LinkHorizontal).default;
  }
});

var _LinkVertical = require('./shapes/LinkVertical');

Object.defineProperty(exports, 'LinkVertical', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_LinkVertical).default;
  }
});

var _LinkRadial = require('./shapes/LinkRadial');

Object.defineProperty(exports, 'LinkRadial', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_LinkRadial).default;
  }
});

var _Area = require('./shapes/Area');

Object.defineProperty(exports, 'Area', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_Area).default;
  }
});

var _AreaClosed = require('./shapes/AreaClosed');

Object.defineProperty(exports, 'AreaClosed', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_AreaClosed).default;
  }
});

var _AreaStack = require('./shapes/AreaStack');

Object.defineProperty(exports, 'AreaStack', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_AreaStack).default;
  }
});

var _Bar = require('./shapes/Bar');

Object.defineProperty(exports, 'Bar', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_Bar).default;
  }
});

var _BarGroup = require('./shapes/BarGroup');

Object.defineProperty(exports, 'BarGroup', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_BarGroup).default;
  }
});

var _BarStack = require('./shapes/BarStack');

Object.defineProperty(exports, 'BarStack', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_BarStack).default;
  }
});

var _Stack = require('./shapes/Stack');

Object.defineProperty(exports, 'Stack', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_Stack).default;
  }
});

var _callOrValue = require('./util/callOrValue');

Object.defineProperty(exports, 'callOrValue', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_callOrValue).default;
  }
});

var _stackOffset = require('./util/stackOffset');

Object.defineProperty(exports, 'stackOffset', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_stackOffset).default;
  }
});
Object.defineProperty(exports, 'STACK_OFFSETS', {
  enumerable: true,
  get: function get() {
    return _stackOffset.STACK_OFFSETS;
  }
});
Object.defineProperty(exports, 'STACK_OFFSET_NAMES', {
  enumerable: true,
  get: function get() {
    return _stackOffset.STACK_OFFSET_NAMES;
  }
});

var _stackOrder = require('./util/stackOrder');

Object.defineProperty(exports, 'stackOrder', {
  enumerable: true,
  get: function get() {
    return _interopRequireDefault(_stackOrder).default;
  }
});
Object.defineProperty(exports, 'STACK_ORDERS', {
  enumerable: true,
  get: function get() {
    return _stackOrder.STACK_ORDERS;
  }
});
Object.defineProperty(exports, 'STACK_ORDER_NAMES', {
  enumerable: true,
  get: function get() {
    return _stackOrder.STACK_ORDER_NAMES;
  }
});

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }<commit_msg>[shape] git rm build<commit_after><|endoftext|>


<commit_before>/**
 * @license
 * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */
var _       = require('lodash');
var request = require('request');

var browsers = require('./browsers');
var sauce    = require('./sauce');

/** WCT plugin that enables support for remote browsers via Sauce Labs. */
module.exports = function(wct, pluginOptions) {

  // The capabilities objects for browsers to run. We don't know the tunnel id
  // until `prepare`, so we've gotta hang onto them.
  var eachCapabilities = [];

  wct.hook('configure', function(done) {
    if (!pluginOptions.browsers || pluginOptions.browsers.length === 0) return done();

    expandOptions(pluginOptions);

    browsers.expand(pluginOptions, function(error, expanded) {
      if (error) return done(error);
      wct.emit('log:debug', 'Using sauce browsers:', expanded);
      // We are careful to append these to the configuration object, even though
      // we don't know the tunnel id yet. This allows WCT to give a useful error
      // if no browsers were configured.
      var activeBrowsers = wct.options.activeBrowsers;
      activeBrowsers.push.apply(activeBrowsers, expanded);
      // But we still need to inject the sauce tunnel ID once we know it.
      eachCapabilities = expanded;

      done();
    });
  });

  wct.hook('prepare', function(done) {
    // Don't bother spinning up the tunnel if we don't have any browsers talking
    // over it.
    if (eachCapabilities.length === 0) return done();

    // Is there already an active sauce tunnel?
    if (pluginOptions.tunnelId) {
      _injectTunnelId(eachCapabilities, pluginOptions.tunnelId);
      return done();
    }

    // Let anyone know, and give them a chance to modify the options prior to
    // booting up the Sauce Connect tunnel.
    wct.emitHook('prepare:sauce-tunnel', function(error) {
      if (error) return done(error);
      sauce.startTunnel(pluginOptions, wct, function(error, tunnelId) {
        if (error) return done(error);
        _injectTunnelId(eachCapabilities, tunnelId);
        done();
      });
    });
  });

  wct.on('browser-end', function(def, error, stats, sessionId) {
    if (eachCapabilities.length === 0) return done();

    // Send the pass/fail info to sauce-labs if we are testing remotely.
    var username  = wct.options.plugins.sauce.username;
    var accessKey = wct.options.plugins.sauce.accessKey;
    request.put({
      url:  'https://saucelabs.com/rest/v1/' + encodeURIComponent(username) + '/jobs/' + encodeURIComponent(sessionId),
      auth: {user: username, pass: accessKey},
      json: true,
      body: {
        passed: (stats.failing > 0),
      },
    });
  });

};

function expandOptions(options) {
  _.defaults(options, {
    username:  process.env.SAUCE_USERNAME,
    accessKey: process.env.SAUCE_ACCESS_KEY,
    tunnelId:  process.env.SAUCE_TUNNEL_ID,
  });
}

/**
 * @param {!Array<!Object>} eachCapabilities
 * @param {string} tunnelId
 */
function _injectTunnelId(eachCapabilities, tunnelId) {
  eachCapabilities.forEach(function(browser) {
    browser['tunnel-identifier'] = tunnelId;
  });
}

// Hacks for the wct-st binary.
module.exports.expandOptions = expandOptions;
module.exports.startTunnel   = sauce.startTunnel;
<commit_msg>Fix my inversion of logic; and add some debugging statements<commit_after>/**
 * @license
 * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 */
var _       = require('lodash');
var request = require('request');

var browsers = require('./browsers');
var sauce    = require('./sauce');

/** WCT plugin that enables support for remote browsers via Sauce Labs. */
module.exports = function(wct, pluginOptions) {

  // The capabilities objects for browsers to run. We don't know the tunnel id
  // until `prepare`, so we've gotta hang onto them.
  var eachCapabilities = [];

  wct.hook('configure', function(done) {
    if (!pluginOptions.browsers || pluginOptions.browsers.length === 0) return done();

    expandOptions(pluginOptions);

    browsers.expand(pluginOptions, function(error, expanded) {
      if (error) return done(error);
      wct.emit('log:debug', 'Using sauce browsers:', expanded);
      // We are careful to append these to the configuration object, even though
      // we don't know the tunnel id yet. This allows WCT to give a useful error
      // if no browsers were configured.
      var activeBrowsers = wct.options.activeBrowsers;
      activeBrowsers.push.apply(activeBrowsers, expanded);
      // But we still need to inject the sauce tunnel ID once we know it.
      eachCapabilities = expanded;

      done();
    });
  });

  wct.hook('prepare', function(done) {
    // Don't bother spinning up the tunnel if we don't have any browsers talking
    // over it.
    if (eachCapabilities.length === 0) return done();

    // Is there already an active sauce tunnel?
    if (pluginOptions.tunnelId) {
      _injectTunnelId(eachCapabilities, pluginOptions.tunnelId);
      return done();
    }

    // Let anyone know, and give them a chance to modify the options prior to
    // booting up the Sauce Connect tunnel.
    wct.emitHook('prepare:sauce-tunnel', function(error) {
      if (error) return done(error);
      sauce.startTunnel(pluginOptions, wct, function(error, tunnelId) {
        if (error) return done(error);
        _injectTunnelId(eachCapabilities, tunnelId);
        done();
      });
    });
  });

  wct.on('browser-end', function(def, error, stats, sessionId) {
    if (eachCapabilities.length === 0 || !sessionId) return done();

    var payload = {
      passed: (stats.status === 'complete' && stats.failing === 0),
    };
    wct.emit('log:debug', 'Updating sauce job', sessionId, payload);

    // Send the pass/fail info to sauce-labs if we are testing remotely.
    var username  = wct.options.plugins.sauce.username;
    var accessKey = wct.options.plugins.sauce.accessKey;
    request.put({
      url:  'https://saucelabs.com/rest/v1/' + encodeURIComponent(username) + '/jobs/' + encodeURIComponent(sessionId),
      auth: {user: username, pass: accessKey},
      json: true,
      body: payload,
    });
  });

};

function expandOptions(options) {
  _.defaults(options, {
    username:  process.env.SAUCE_USERNAME,
    accessKey: process.env.SAUCE_ACCESS_KEY,
    tunnelId:  process.env.SAUCE_TUNNEL_ID,
  });
}

/**
 * @param {!Array<!Object>} eachCapabilities
 * @param {string} tunnelId
 */
function _injectTunnelId(eachCapabilities, tunnelId) {
  eachCapabilities.forEach(function(browser) {
    browser['tunnel-identifier'] = tunnelId;
  });
}

// Hacks for the wct-st binary.
module.exports.expandOptions = expandOptions;
module.exports.startTunnel   = sauce.startTunnel;
<|endoftext|>


<commit_before>var
	kind = require('enyo/kind');

var
	Divider = require('moonstone/Divider'),
	Button = require('moonstone/Button'),
	CheckboxItem = require('moonstone/CheckboxItem'),
	Dialog = require('moonstone/Dialog');

module.exports = kind({
	name: 'moons.sample.DialogSample',
	classes: 'moon enyo-unselectable enyo-fit',
	components: [
		{kind: Divider, content: 'Dialog'},
		{kind: Button, content: 'Open Dialog', ontap: 'showDialog'},
		{classes: 'moon-1v'},
		{kind: Divider, content: 'Options'},
		{kind: CheckboxItem, content: 'Tap outside to close (autoDismiss)', name: 'autoDismissToggle'},
		{kind: CheckboxItem, content: 'Modal', name: 'modalToggle'},
		{kind: CheckboxItem, content: 'Show Close Button', name: 'showCloseButtonToggle'},
		{kind: CheckboxItem, content: 'Animate', name: 'animateToggle'},
		{kind: CheckboxItem, content: 'Lock 5-way inside popup (spotlightModal)', name: 'spotlightModalToggle'},
		{kind: CheckboxItem, content: 'Close by back key (allowBackKey)', name: 'allowBackKeyToggle'},
		{
			name: 'dialog',
			kind: Dialog,
			title: 'You\'ve been watching TV for a very long time so let\'s do a quick check-in.',
			subTitle: 'This TV has been active for 10 hours.',
			message: 'Perhaps it is time to take a break and get some fresh air. There is a nice coffee shop around the corner',
			components: [
				{kind: Button, content: 'Go get a coffee', ontap: 'hideDialog'},
				{kind: Button, content: 'Keep watching TV', ontap: 'addMessage'}
			]
		}
	],
	bindings: [
		{from: '.$.dialog.allowBackKey', to: '.$.allowBackKeyToggle.checked', oneWay: false},
		{from: '.$.dialog.modal', to: '.$.modalToggle.checked', oneWay: false},
		{from: '.$.dialog.animate', to: '.$.animateToggle.checked', oneWay: false},
		{from: '.$.dialog.autoDismiss', to: '.$.autoDismissToggle.checked', oneWay: false},
		{from: '.$.dialog.spotlightModal', to: '.$.spotlightModalToggle.checked', oneWay: false},
		{from: '.$.dialog.showCloseButton', to: '.$.showCloseButtonToggle.checked', oneWay: false}
	],
	showDialog: function (sender) {
		this.$.dialog.show();
	},
	hideDialog: function (sender, ev) {
		this.$.dialog.hide();
	},
	addMessage: function () {
		this.$.dialog.setMessage(this.$.dialog.getMessage() + '
 No, seriously, you should probably take a break.');
	}
});<commit_msg>PLAT-6842: Added new features for example and testing purposes. Also updated binding style.<commit_after>var
	kind = require('enyo/kind');

var
	Divider = require('moonstone/Divider'),
	Button = require('moonstone/Button'),
	CheckboxItem = require('moonstone/CheckboxItem'),
	InputDecorator = require('moonstone/InputDecorator'),
	Input = require('moonstone/Input'),
	Dialog = require('moonstone/Dialog');

module.exports = kind({
	name: 'moons.sample.DialogSample',
	classes: 'moon enyo-unselectable enyo-fit',
	components: [
		{kind: Divider, content: 'Dialog'},
		{kind: Button, content: 'Open Dialog', ontap: 'showDialog'},
		{classes: 'moon-1v'},
		{kind: Divider, content: 'Options'},
		{kind: CheckboxItem, content: 'Tap outside to close (autoDismiss)', name: 'autoDismissToggle'},
		{kind: CheckboxItem, content: 'Modal', name: 'modalToggle'},
		{kind: CheckboxItem, content: 'Show Close Button', name: 'showCloseButtonToggle'},
		{kind: CheckboxItem, content: 'Animate', name: 'animateToggle'},
		{kind: CheckboxItem, content: 'Lock 5-way inside popup (spotlightModal)', name: 'spotlightModalToggle'},
		{kind: CheckboxItem, content: 'Close by back key (allowBackKey)', name: 'allowBackKeyToggle'},
		{kind: CheckboxItem, content: 'Use divider to separate title from body', name: 'useDivider'},
		{classes: 'moon-1v'},
		{kind: Divider, content: 'Set a custom title, or remove the titles'},
		{kind: InputDecorator, components: [
			{kind: Input, placeholder: 'Title', value: 'Dialog Title', name: 'inputTitle'}
		]},
		{kind: InputDecorator, components: [
			{kind: Input, placeholder: 'Sub-Title', value: 'A subtitle for dialog.', name: 'inputSubTitle'}
		]},
		{
			name: 'dialog',
			kind: Dialog,
			title: 'You\'ve been watching TV for a very long time so let\'s do a quick check-in.',
			subTitle: 'This TV has been active for 10 hours.',
			message: 'Perhaps it is time to take a break and get some fresh air. There is a nice coffee shop around the corner',
			// message: [
			// 	{kind: Button, content: 'Fancy button'}
			// ],
			components: [
				{kind: Button, content: 'Go get a coffee', ontap: 'hideDialog'},
				{kind: Button, content: 'Keep watching TV', ontap: 'addMessage'}
			]
		}
	],
	bindings: [
		{from: '$.dialog.autoDismiss', to: '$.autoDismissToggle.checked', oneWay: false},
		{from: '$.dialog.modal', to: '$.modalToggle.checked', oneWay: false},
		{from: '$.dialog.showCloseButton', to: '$.showCloseButtonToggle.checked', oneWay: false},
		{from: '$.dialog.animate', to: '$.animateToggle.checked', oneWay: false},
		{from: '$.dialog.spotlightModal', to: '$.spotlightModalToggle.checked', oneWay: false},
		{from: '$.dialog.allowBackKey', to: '$.allowBackKeyToggle.checked', oneWay: false},
		{from: '$.dialog.useDivider', to: '$.useDivider.checked', oneWay: false},
		{from: '$.dialog.title', to: '$.inputTitle.value', oneWay: false},
		{from: '$.dialog.subTitle', to: '$.inputSubTitle.value', oneWay: false}
	],
	showDialog: function (sender) {
		this.$.dialog.show();
	},
	hideDialog: function (sender, ev) {
		this.$.dialog.hide();
	},
	addMessage: function () {
		this.$.dialog.setMessage(this.$.dialog.getMessage() + '
 No, seriously, you should probably take a break.');
	}
});<|endoftext|>


<commit_before>define({

	define : {
		allow   : "*",
		require : [
			"morph",
			"transistor",
			"transit",
			"event_master"
		]
	},

	make : function ( define ) {

		var table_body, event_circle

		table_body = this.library.transistor.make(
			this.define_body( define )
		)

		event_circle = this.library.event_master.make({
			state  : this.define_state( define ),
			events : this.define_event({
				body : table_body,
				with : define
			})
		})
		event_circle.add_listener(
			this.define_listener({
				body         : table_body,
				class_name   : define.class_name,
				with         : define.with,
				event_circle : event_circle
			})
		)

		return this.define_interface({
			body         : table_body,
			event_master : event_circle
		})
	},

	define_interface : function ( define ) {
		return {
			body      : define.body.body,
			append    : define.body.append,
			set_value : function ( set ) {
				define.event_master.stage_event({
					called : "change table",
					as     : function ( state ) {
						return {
							state : {
								data : set.data
							},
							event : define.body.body
						}
					}
				})
			}
		}
	},

	define_state : function ( define ) {
		var data
		data = {}
		if ( define.with.data ) {
			data = define.with.data
			// data.
		}
		return {
			data                 : define.with.data || {},
			new_table_definition : {}
		}
	},

	define_event : function ( define ) {
		return [
			{
				called : "change table"
			},
			{
				called : "change view",
				that_happens : [
					{
						on : define.body.body,
						is : [ "click" ]
					}
				],
				only_if : function ( heard ) {
					return heard.event.target.hasAttribute("data-table-choose-view")
				}
			},
		]
	},

	define_listener : function ( define ) {

		var self = this
		return [
			{
				for       : "change view",
				that_does : function ( heard ) {

					var view_name
					view_name = heard.event.target.getAttribute("data-table-choose-view")

					return define.event_circle.stage_event({
						called : "change table",
						as     : function ( state ) {
							state.new_table_definition = heard.state.data.view[view_name]
							return {
								state : state,
								event : {
									target : define.body.body
								}
							}
						}
					})
				}
			},
			{
				for       : "change table",
				that_does : function ( heard ) {

					var table_body, table_content

					table_body    = heard.event.target
					table_content = self.library.transistor.make(
						self.define_row_and_column({
							class_name : define.class_name,
							with       : {
								data   : heard.state.new_table_definition,
								format : define.with.format
							}
						})
					)
					table_body.removeChild( table_body.firstChild )
					table_content.append( table_body )

					return heard
				}
			}
		]
	},

	define_body : function ( define ) {

		var self, content

		self    = this
		content = []
		console.log( define )
		if ( define.with.data ) {
			content = [
				this.define_row_and_column({
					class_name : define.class_name,
					with       : {
						data   : define.with.data.view.main,
						format : define.with.format
					}
				})
			]
		}

		return {
			"width" : ( define.with.format.field.width * define.with.data.view.main.column.length ) + "px",
			"class" : define.class_name.wrap,
			"child" : content
		}
	},

	define_row_and_column : function ( define ) {

		var self = this
		return {
			"class" : define.class_name.content,
			"child" : [
				this.define_column_name_row({
					class_name : define.class_name,
					with       : {
						column : define.with.data.column,
						format : define.with.format
					}
				}),
				this.define_row({
					class_name : define.class_name,
					with       : {
						row    : define.with.data.row,
						format : define.with.format
					}
				})
			]
		}
	},

	define_column_name_row : function ( define ) {
		var self = this
		return {
			"class" : define.class_name.head_wrap,
			"child" : this.library.morph.index_loop({
				subject : this.format_column_field_definition( define.with.column ),
				else_do : function ( loop ) {
					return loop.into.concat(
						self.define_column_name_field({
							class_name : define.class_name,
							with       : loop.indexed,
							format     : define.with.format
						})
					)
				}
			})
		}
	},

	define_column_name_field : function ( define ) {
		return {
			"class" : define.class_name.head_name,
			"width" : define.format.field.width + "px",
			"text"  : define.with.text
		}
	},

	format_column_field_definition : function ( definition ) {
		return this.library.morph.index_loop({
			subject : definition,
			else_do : function ( loop ) {

				var field_definition

				if ( loop.indexed.constructor === String ) {
					field_definition = {
						"text" : loop.indexed
					}
				}

				if ( loop.indexed.constructor === Object ) {
					field_definition = loop.indexed
				}

				return loop.into.concat( field_definition )
			}
		})
	},

	format_row_field_definition : function ( definition ) {
		return this.library.morph.object_loop({
			subject : definition,
			else_do : function ( loop ) {

				var field_definition

				if ( loop.value.constructor === String ) {
					field_definition = {
						"text" : loop.value
					}
				}

				if ( loop.value.constructor === Object ) {
					field_definition = loop.value
				}

				return {
					key   : loop.key,
					value : field_definition,
				}
			}
		})
	},

	define_row_field : function ( define ) {
		var definition

		definition = {
			"class" : define.class_name.row_name,
			"text"  : define.with.text,
			"width" : define.format.field.width +"px"
		}

		if ( define.with.view ) {
			definition["data-table-choose-view"] = define.with.view
		}

		return definition
	},

	define_row : function ( define ) {
		var self = this
		return {
			"class" : define.class_name.body_wrap,
			"child" : this.library.morph.index_loop({
				subject : this.library.morph.index_loop({
					subject : define.with.row,
					else_do : function ( format_loop ) {
						return format_loop.into.concat(
							self.format_row_field_definition( format_loop.indexed )
						)
					}
				}),
				else_do : function ( content_loop ) {

					return content_loop.into.concat({
						"class" : define.class_name.row_wrap,
						"child" : self.library.morph.object_loop({
							"subject" : content_loop.indexed,
							"into?"   : [],
							"else_do" : function ( loop ) {
								return {
									into : loop.into.concat(
										self.define_row_field({
											class_name : define.class_name,
											format     : define.with.format,
											with       : loop.value
										})
									)
								}
							}
						})
					})
				}
			})
		}
	},

	convert_string_to_option_name : function ( string ) {
		return string.toLowerCase().replace(/\s/g, "_")
	}
})<commit_msg>Table update<commit_after>define({

	define : {
		allow   : "*",
		require : [
			"morph",
			"transistor",
			"transit",
			"event_master"
		]
	},

	make : function ( define ) {

		var table_body, event_circle

		table_body = this.library.transistor.make(
			this.define_body( define )
		)

		event_circle = this.library.event_master.make({
			state  : this.define_state( define ),
			events : this.define_event({
				body : table_body,
				with : define
			})
		})
		event_circle.add_listener(
			this.define_listener({
				body         : table_body,
				class_name   : define.class_name,
				with         : define.with,
				event_circle : event_circle
			})
		)

		return this.define_interface({
			body         : table_body,
			event_master : event_circle
		})
	},

	define_interface : function ( define ) {
		return {
			body      : define.body.body,
			append    : define.body.append,
			set_value : function ( set ) {
				define.event_master.stage_event({
					called : "change table",
					as     : function ( state ) {
						return {
							state : {
								data : set.data
							},
							event : define.body.body
						}
					}
				})
			}
		}
	},

	define_state : function ( define ) {
		return {
			data                 : define.with.data || {},
			new_table_definition : {}
		}
	},

	define_event : function ( define ) {
		return [
			{
				called : "change table"
			},
			{
				called : "change view",
				that_happens : [
					{
						on : define.body.body,
						is : [ "click" ]
					}
				],
				only_if : function ( heard ) {
					return heard.event.target.hasAttribute("data-table-choose-view")
				}
			},
		]
	},

	define_listener : function ( define ) {

		var self = this
		return [
			{
				for       : "change view",
				that_does : function ( heard ) {

					var view_name
					view_name = heard.event.target.getAttribute("data-table-choose-view")

					return define.event_circle.stage_event({
						called : "change table",
						as     : function ( state ) {
							state.new_table_definition = heard.state.data.view[view_name]
							return {
								state : state,
								event : {
									target : define.body.body
								}
							}
						}
					})
				}
			},
			{
				for       : "change table",
				that_does : function ( heard ) {

					var table_body, table_content

					table_body    = heard.event.target
					table_content = self.library.transistor.make(
						self.define_row_and_column({
							class_name : define.class_name,
							with       : {
								data   : heard.state.new_table_definition,
								format : define.with.format
							}
						})
					)
					table_body.removeChild( table_body.children[1] )
					table_content.append( table_body )

					return heard
				}
			}
		]
	},

	define_body : function ( define ) {

		var self, content

		self    = this
		content = [
			this.define_control_body( define )
		]

		if ( define.with.data ) {
			content = content.concat([
				this.define_row_and_column({
					class_name : define.class_name,
					with       : {
						data   : define.with.data.view.main,
						format : define.with.format
					}
				})
			])
		}

		return {
			"width" : ( define.with.format.field.width * define.with.data.view.main.column.length ) + "px",
			"class" : define.class_name.wrap,
			"child" : content
		}
	},

	define_control_body : function ( define ) {
		return {
			"class" : "",
			"child" : [
				{
					"class" : "",
					"text"  : "Back",
					"mark_as" : "",
				},
				{
					"class" : "",
					"text"  : "Forward"
				},
				{
					"class" : "",
					"text"  : "Some text here"
				}
			]
		}
	},

	define_row_and_column : function ( define ) {

		var self = this
		return {
			"class" : define.class_name.content,
			"child" : [
				this.define_column_name_row({
					class_name : define.class_name,
					with       : {
						column : define.with.data.column,
						format : define.with.format
					}
				}),
				this.define_row({
					class_name : define.class_name,
					with       : {
						row    : define.with.data.row,
						format : define.with.format
					}
				})
			]
		}
	},

	define_column_name_row : function ( define ) {
		var self = this
		return {
			"class" : define.class_name.head_wrap,
			"child" : this.library.morph.index_loop({
				subject : this.format_column_field_definition( define.with.column ),
				else_do : function ( loop ) {
					return loop.into.concat(
						self.define_column_name_field({
							class_name : define.class_name,
							with       : loop.indexed,
							format     : define.with.format
						})
					)
				}
			})
		}
	},

	define_column_name_field : function ( define ) {
		return {
			"class" : define.class_name.head_name,
			"width" : define.format.field.width + "px",
			"text"  : define.with.text
		}
	},

	format_column_field_definition : function ( definition ) {
		return this.library.morph.index_loop({
			subject : definition,
			else_do : function ( loop ) {

				var field_definition

				if ( loop.indexed.constructor === String ) {
					field_definition = {
						"text" : loop.indexed
					}
				}

				if ( loop.indexed.constructor === Object ) {
					field_definition = loop.indexed
				}

				return loop.into.concat( field_definition )
			}
		})
	},

	format_row_field_definition : function ( definition ) {
		return this.library.morph.object_loop({
			subject : definition,
			else_do : function ( loop ) {

				var field_definition

				if ( loop.value.constructor === String ) {
					field_definition = {
						"text" : loop.value
					}
				}

				if ( loop.value.constructor === Object ) {
					field_definition = loop.value
				}

				return {
					key   : loop.key,
					value : field_definition,
				}
			}
		})
	},

	define_row_field : function ( define ) {
		var definition

		definition = {
			"class" : define.class_name.row_name,
			"text"  : define.with.text,
			"width" : define.format.field.width +"px"
		}

		if ( define.with.view ) {
			definition["data-table-choose-view"] = define.with.view
		}

		return definition
	},

	define_row : function ( define ) {
		var self = this
		return {
			"class" : define.class_name.body_wrap,
			"child" : this.library.morph.index_loop({
				subject : this.library.morph.index_loop({
					subject : define.with.row,
					else_do : function ( format_loop ) {
						return format_loop.into.concat(
							self.format_row_field_definition( format_loop.indexed )
						)
					}
				}),
				else_do : function ( content_loop ) {

					return content_loop.into.concat({
						"class" : define.class_name.row_wrap,
						"child" : self.library.morph.object_loop({
							"subject" : content_loop.indexed,
							"into?"   : [],
							"else_do" : function ( loop ) {
								return {
									into : loop.into.concat(
										self.define_row_field({
											class_name : define.class_name,
											format     : define.with.format,
											with       : loop.value
										})
									)
								}
							}
						})
					})
				}
			})
		}
	},

	convert_string_to_option_name : function ( string ) {
		return string.toLowerCase().replace(/\s/g, "_")
	}
})<|endoftext|>