<commit_before>/* global FileReader, confirm, alert */
var yo = require('yo-yo')
var csjs = require('csjs-inject')
var Treeview = require('ethereum-remix').ui.TreeView

var EventManager = require('../lib/eventManager')

var css = csjs`
  .fileexplorer       {
    box-sizing        : border-box;
  }
  .folder,
  .file               {
    font-size         : 14px;
  }
  .hasFocus           {
    background-color  : #F4F6FF;
  }
  .rename             {
    background-color  : white;
  }
  .remove             {
    float             : right;
  }
  .activeMode         {
    margin-right      : 10px;
    padding-right     : 19px;
  }
  ul                  {
    padding           : 0;
  }
`
module.exports = fileExplorer

function fileExplorer (appAPI, files) {
  var fileEvents = files.event
  var treeView = new Treeview({
    extractData: function (value, tree, key) {
      var newValue = {}
      // var isReadOnly = false
      var isFile = false
      Object.keys(value).filter(function keep (x) {
        if (x === '/content') isFile = true
        // if (x === '/readOnly') isReadOnly = true
        if (x[0] !== '/') return true
      }).forEach(function (x) { newValue[x] = value[x] })
      return {
        path: (tree || {}).path ? tree.path + '/' + key : key,
        children: isFile ? undefined
        : value instanceof Array ? value.map((item, index) => ({
          key: index, value: item
        })) : value instanceof Object ? Object.keys(value).map(subkey => ({
          key: subkey, value: value[subkey]
        })) : undefined
      }
    },
    formatSelf: function (key, data) {
      return yo`${key}`
    }
  })

  var deleteButton = yo`

  `

  appAPI.event.register('currentFileChanged', (newFile) => {
    fileFocus(newFile)
  })
  fileEvents.register('fileRemoved', fileRemoved)
  fileEvents.register('fileRenamed', fileRenamed)
  fileEvents.register('fileAdded', fileAdded)

  var filepath = null
  var focusElement = null
  var textUnderEdit = null

  var element = treeView.render(files.listAsTree())
  element.className = css.fileexplorer

  var events = new EventManager()
  var api = {}
  api.addFile = function addFile (file) {
    var name = file.name
    if (!files.exists(name) || confirm('The file ' + name + ' already exists! Would you like to overwrite it?')) {
      var fileReader = new FileReader()
      fileReader.onload = function (event) {
        var success = files.set(name, event.target.result)
        if (!success) alert('Failed to create file ' + name)
        else events.trigger('focus', [name])
      }
      fileReader.readAsText(file)
    }
  }

  function focus (event) {
    event.cancelBubble = true
    var li = this
    if (focusElement === li) return
    if (focusElement) focusElement.classList.toggle(css.hasFocus)
    focusElement = li
    focusElement.classList.toggle(css.hasFocus)
    var label = getLabelFrom(li)
    var filepath = label.dataset.path
    var isFile = label.className.indexOf('file') === 0
    if (isFile) events.trigger('focus', [filepath])
  }

  function hover (event) {
    if (event.type === 'mouseout') {
      var exitedTo = event.toElement || event.relatedTarget
      if (this.contains(exitedTo)) return
      this.style.backgroundColor = ''
      this.style.paddingRight = '19px'
      return this.removeChild(deleteButton)
    }
    this.style.backgroundColor = '#F4F6FF'
    this.style.paddingRight = '0px'
    this.appendChild(deleteButton)
  }

  function getElement (path) {
    var label = element.querySelector(`label[data-path="${path}"]`)
    if (label) return getLiFrom(label)
  }

  function deletePath (event) {
    event.cancelBubble = true
    var span = this
    var li = span.parentElement.parentElement
    var label = getLabelFrom(li)
    var path = label.dataset.path
    var isFolder = !!~label.className.indexOf('folder')
    if (isFolder) path += '/'
    if (confirm(`Do you really want to delete "${path}" ?`)) {
      li.parentElement.removeChild(li)
      removeSubtree(files, path)
    }
  }

  function editModeOn (event) {
    var label = this
    var li = getLiFrom(label)
    var classes = li.className
    if (~classes.indexOf('hasFocus') && !label.getAttribute('contenteditable')) {
      textUnderEdit = label.innerText
      label.setAttribute('contenteditable', true)
      label.classList.add(css.rename)
      label.focus()
    }
  }

  function editModeOff (event) {
    var label = this
    if (event.type === 'blur' || event.which === 27 || event.which === 13) {
      var save = textUnderEdit !== label.innerText
      if (event.which === 13) event.preventDefault()
      if (save && event.which !== 13) save = confirm('Do you want to rename?')
      if (save) renameSubtree(label)
      else label.innerText = textUnderEdit
      label.removeAttribute('contenteditable')
      label.classList.remove(css.rename)
    }
  }

  function renameSubtree (label, dontcheck) {
    var oldPath = label.dataset.path
    var newPath = oldPath
    newPath = newPath.split('/')
    newPath[newPath.length - 1] = label.innerText
    newPath = newPath.join('/')
    if (!dontcheck) {
      var allPaths = Object.keys(files.list())
      for (var i = 0, len = allPaths.length, path, err; i < len; i++) {
        path = allPaths[i]
        if (files.isReadOnly(path)) {
          err = 'path contains readonly elements'
          break
        } else if (path.indexOf(newPath) === 0) {
          err = 'new path is conflicting with another existing path'
          break
        }
      }
    }
    if (err) {
      alert(`couldn't rename - ${err}`)
      label.innerText = textUnderEdit
    } else {
      textUnderEdit = label.innerText
      updateAllLabels([getElement(oldPath)], oldPath, newPath)
    }
  }

  function updateAllLabels (lis, oldPath, newPath) {
    lis.forEach(function (li) {
      var label = getLabelFrom(li)
      var path = label.dataset.path
      var newName = path.replace(oldPath, newPath)
      label.dataset.path = newName
      var isFile = label.className.indexOf('file') === 0
      if (isFile) files.rename(path, newName)
      var ul = li.lastChild
      if (ul.tagName === 'UL') {
        updateAllLabels([...ul.children], oldPath, newPath)
      }
    })
  }

  function fileFocus (path) {
    if (filepath === path) return
    filepath = path
    var el = getElement(filepath)
    expandPathTo(el)
    setTimeout(function focusNode () { el.click() }, 0)
  }

  function fileRemoved (filepath) {
    var li = getElement(filepath)
    if (li) li.parentElement.removeChild(li)
  }

  function fileRenamed (oldName, newName) {
    var li = getElement(oldName)
    if (li) {
      oldName = oldName.split('/')
      newName = newName.split('/')
      var index = oldName.reduce(function (idx, key, i) {
        return oldName[i] !== newName[i] ? i : idx
      }, undefined)
      var newKey = newName[index]
      var oldPath = oldName.slice(0, index + 1).join('/')
      li = getElement(oldPath)
      var label = getLabelFrom(li)
      label.innerText = newKey
      renameSubtree(label, true)
    }
  }

  function fileAdded (filepath) {
    var el = treeView.render(files.listAsTree())
    el.className = css.fileexplorer
    element.parentElement.replaceChild(el, element)
    element = el
  }

  element.events = events
  element.api = api
  return element
}
/******************************************************************************
  HELPER FUNCTIONS
******************************************************************************/
function adaptEnvironment (label, focus, hover) {
  var li = getLiFrom(label)
  li.style.position = 'relative'
  var span = li.firstChild
  // add focus
  li.addEventListener('click', focus)
  // add hover
  span.classList.add(css.activeMode)
  span.addEventListener('mouseover', hover)
  span.addEventListener('mouseout', hover)
}

function unadaptEnvironment (label, focus, hover) {
  var li = getLiFrom(label)
  var span = li.firstChild
  li.style.position = undefined
  // remove focus
  li.removeEventListener('click', focus)
  // remove hover
  span.classList.remove(css.activeMode)
  span.removeEventListener('mouseover', hover)
  span.removeEventListener('mouseout', hover)
}

function getLiFrom (label) {
  return label.parentElement.parentElement.parentElement
}

function getLabelFrom (li) {
  return li.children[0].children[1].children[0]
}

function removeSubtree (files, path) {
  var parts = path.split('/')
  var isFile = parts[parts.length - 1].length
  var removePaths = isFile ? [path] : Object.keys(files.list()).filter(keep)
  function keep (p) { return ~p.indexOf(path) }
  removePaths.forEach(function (path) {
    [...window.files.querySelectorAll('.file .name')].forEach(function (span) {
      if (span.innerText === path) {
        var li = span.parentElement
        li.parentElement.removeChild(li) // delete tab
      }
    })
    files.remove(path)
  })
}

function expandPathTo (li) {
  while ((li = li.parentElement.parentElement) && li.tagName === 'LI') {
    var caret = li.firstChild.firstChild
    if (caret.classList.contains('fa-caret-right')) caret.click() // expand
  }
}
<commit_msg>div instead of span<commit_after>/* global FileReader, confirm, alert */
var yo = require('yo-yo')
var csjs = require('csjs-inject')
var Treeview = require('ethereum-remix').ui.TreeView

var EventManager = require('../lib/eventManager')

var css = csjs`
  .fileexplorer       {
    box-sizing        : border-box;
  }
  .folder,
  .file               {
    font-size         : 14px;
  }
  .hasFocus           {
    background-color  : #F4F6FF;
  }
  .rename             {
    background-color  : white;
  }
  .remove             {
    float             : right;
  }
  .activeMode         {
    margin-right      : 10px;
    padding-right     : 19px;
  }
  ul                  {
    padding           : 0;
  }
`
module.exports = fileExplorer

function fileExplorer (appAPI, files) {
  var fileEvents = files.event
  var treeView = new Treeview({
    extractData: function (value, tree, key) {
      var newValue = {}
      // var isReadOnly = false
      var isFile = false
      Object.keys(value).filter(function keep (x) {
        if (x === '/content') isFile = true
        // if (x === '/readOnly') isReadOnly = true
        if (x[0] !== '/') return true
      }).forEach(function (x) { newValue[x] = value[x] })
      return {
        path: (tree || {}).path ? tree.path + '/' + key : key,
        children: isFile ? undefined
        : value instanceof Array ? value.map((item, index) => ({
          key: index, value: item
        })) : value instanceof Object ? Object.keys(value).map(subkey => ({
          key: subkey, value: value[subkey]
        })) : undefined
      }
    },
    formatSelf: function (key, data) {
      return yo`${key}`
    }
  })

  var deleteButton = yo`

  `

  appAPI.event.register('currentFileChanged', (newFile) => {
    fileFocus(newFile)
  })
  fileEvents.register('fileRemoved', fileRemoved)
  fileEvents.register('fileRenamed', fileRenamed)
  fileEvents.register('fileAdded', fileAdded)

  var filepath = null
  var focusElement = null
  var textUnderEdit = null

  var element = treeView.render(files.listAsTree())
  element.className = css.fileexplorer

  var events = new EventManager()
  var api = {}
  api.addFile = function addFile (file) {
    var name = file.name
    if (!files.exists(name) || confirm('The file ' + name + ' already exists! Would you like to overwrite it?')) {
      var fileReader = new FileReader()
      fileReader.onload = function (event) {
        var success = files.set(name, event.target.result)
        if (!success) alert('Failed to create file ' + name)
        else events.trigger('focus', [name])
      }
      fileReader.readAsText(file)
    }
  }

  function focus (event) {
    event.cancelBubble = true
    var li = this
    if (focusElement === li) return
    if (focusElement) focusElement.classList.toggle(css.hasFocus)
    focusElement = li
    focusElement.classList.toggle(css.hasFocus)
    var label = getLabelFrom(li)
    var filepath = label.dataset.path
    var isFile = label.className.indexOf('file') === 0
    if (isFile) events.trigger('focus', [filepath])
  }

  function hover (event) {
    if (event.type === 'mouseout') {
      var exitedTo = event.toElement || event.relatedTarget
      if (this.contains(exitedTo)) return
      this.style.backgroundColor = ''
      this.style.paddingRight = '19px'
      return this.removeChild(deleteButton)
    }
    this.style.backgroundColor = '#F4F6FF'
    this.style.paddingRight = '0px'
    this.appendChild(deleteButton)
  }

  function getElement (path) {
    var label = element.querySelector(`label[data-path="${path}"]`)
    if (label) return getLiFrom(label)
  }

  function deletePath (event) {
    event.cancelBubble = true
    var span = this
    var li = span.parentElement.parentElement
    var label = getLabelFrom(li)
    var path = label.dataset.path
    var isFolder = !!~label.className.indexOf('folder')
    if (isFolder) path += '/'
    if (confirm(`Do you really want to delete "${path}" ?`)) {
      li.parentElement.removeChild(li)
      removeSubtree(files, path)
    }
  }

  function editModeOn (event) {
    var label = this
    var li = getLiFrom(label)
    var classes = li.className
    if (~classes.indexOf('hasFocus') && !label.getAttribute('contenteditable')) {
      textUnderEdit = label.innerText
      label.setAttribute('contenteditable', true)
      label.classList.add(css.rename)
      label.focus()
    }
  }

  function editModeOff (event) {
    var label = this
    if (event.type === 'blur' || event.which === 27 || event.which === 13) {
      var save = textUnderEdit !== label.innerText
      if (event.which === 13) event.preventDefault()
      if (save && event.which !== 13) save = confirm('Do you want to rename?')
      if (save) renameSubtree(label)
      else label.innerText = textUnderEdit
      label.removeAttribute('contenteditable')
      label.classList.remove(css.rename)
    }
  }

  function renameSubtree (label, dontcheck) {
    var oldPath = label.dataset.path
    var newPath = oldPath
    newPath = newPath.split('/')
    newPath[newPath.length - 1] = label.innerText
    newPath = newPath.join('/')
    if (!dontcheck) {
      var allPaths = Object.keys(files.list())
      for (var i = 0, len = allPaths.length, path, err; i < len; i++) {
        path = allPaths[i]
        if (files.isReadOnly(path)) {
          err = 'path contains readonly elements'
          break
        } else if (path.indexOf(newPath) === 0) {
          err = 'new path is conflicting with another existing path'
          break
        }
      }
    }
    if (err) {
      alert(`couldn't rename - ${err}`)
      label.innerText = textUnderEdit
    } else {
      textUnderEdit = label.innerText
      updateAllLabels([getElement(oldPath)], oldPath, newPath)
    }
  }

  function updateAllLabels (lis, oldPath, newPath) {
    lis.forEach(function (li) {
      var label = getLabelFrom(li)
      var path = label.dataset.path
      var newName = path.replace(oldPath, newPath)
      label.dataset.path = newName
      var isFile = label.className.indexOf('file') === 0
      if (isFile) files.rename(path, newName)
      var ul = li.lastChild
      if (ul.tagName === 'UL') {
        updateAllLabels([...ul.children], oldPath, newPath)
      }
    })
  }

  function fileFocus (path) {
    if (filepath === path) return
    filepath = path
    var el = getElement(filepath)
    expandPathTo(el)
    setTimeout(function focusNode () { el.click() }, 0)
  }

  function fileRemoved (filepath) {
    var li = getElement(filepath)
    if (li) li.parentElement.removeChild(li)
  }

  function fileRenamed (oldName, newName) {
    var li = getElement(oldName)
    if (li) {
      oldName = oldName.split('/')
      newName = newName.split('/')
      var index = oldName.reduce(function (idx, key, i) {
        return oldName[i] !== newName[i] ? i : idx
      }, undefined)
      var newKey = newName[index]
      var oldPath = oldName.slice(0, index + 1).join('/')
      li = getElement(oldPath)
      var label = getLabelFrom(li)
      label.innerText = newKey
      renameSubtree(label, true)
    }
  }

  function fileAdded (filepath) {
    var el = treeView.render(files.listAsTree())
    el.className = css.fileexplorer
    element.parentElement.replaceChild(el, element)
    element = el
  }

  element.events = events
  element.api = api
  return element
}
/******************************************************************************
  HELPER FUNCTIONS
******************************************************************************/
function adaptEnvironment (label, focus, hover) {
  var li = getLiFrom(label)
  li.style.position = 'relative'
  var span = li.firstChild
  // add focus
  li.addEventListener('click', focus)
  // add hover
  span.classList.add(css.activeMode)
  span.addEventListener('mouseover', hover)
  span.addEventListener('mouseout', hover)
}

function unadaptEnvironment (label, focus, hover) {
  var li = getLiFrom(label)
  var span = li.firstChild
  li.style.position = undefined
  // remove focus
  li.removeEventListener('click', focus)
  // remove hover
  span.classList.remove(css.activeMode)
  span.removeEventListener('mouseover', hover)
  span.removeEventListener('mouseout', hover)
}

function getLiFrom (label) {
  return label.parentElement.parentElement.parentElement
}

function getLabelFrom (li) {
  return li.children[0].children[1].children[0]
}

function removeSubtree (files, path) {
  var parts = path.split('/')
  var isFile = parts[parts.length - 1].length
  var removePaths = isFile ? [path] : Object.keys(files.list()).filter(keep)
  function keep (p) { return ~p.indexOf(path) }
  removePaths.forEach(function (path) {
    [...window.files.querySelectorAll('.file .name')].forEach(function (span) {
      if (span.innerText === path) {
        var li = span.parentElement
        li.parentElement.removeChild(li) // delete tab
      }
    })
    files.remove(path)
  })
}

function expandPathTo (li) {
  while ((li = li.parentElement.parentElement) && li.tagName === 'LI') {
    var caret = li.firstChild.firstChild
    if (caret.classList.contains('fa-caret-right')) caret.click() // expand
  }
}
<|endoftext|>


<commit_before>// configuration

var USE_SWFOBJECT = true, //!!window.swfobject; // ... to embed youtube flash player
	PLAY_TIMEOUT = 10000;

window.$ = window.$ || function(){return window.$};
$.html = $.html || function(){return $};
$.remove = $.remove || function(){return $};

// utility functions

if (undefined == window.console)
	window.console = {log:function(){}};

loader = new (function Loader() {
	var FINAL_STATES = {"loaded": true, "complete": true, 4: true},
		head = document.getElementsByTagName("head")[0],
		pending = {};
	return {
		loadJSON: function(src, cb){
			if (pending[src]) return;
			pending[src] = true;
			// cross-domain ajax call
			var xdr = new XMLHttpRequest();
			xdr.onload = function() {
				cb(JSON.parse(xdr.responseText));
				delete pending[src];
			}
			xdr.open("GET", src, true);
			xdr.send();
		},
		includeJS: function(src, cb){
			if (pending[src]) return;
			pending[src] = true;
			var inc = document.createElement("script");
			inc.onload = inc.onreadystatechange = function() {
				if (pending[src] && (!inc.readyState || FINAL_STATES[inc.readyState])) {
					cb && cb();
					delete pending[src];
				}
			};
			inc.src = src;
			head.appendChild(inc);
		}
	};
});

// EventEmitter

function EventEmitter() {
	this._eventListeners = {};
}

EventEmitter.prototype.on = function(eventName, handler){
	this._eventListeners[eventName] = (this._eventListeners[eventName] || []).concat(handler);
}

EventEmitter.prototype.emit = function(eventName){
	var i, args = Array.prototype.slice.call(arguments, 1), // remove eventName from arguments, and make it an array
		listeners = this._eventListeners[eventName];
	for (i in listeners)
		listeners[i].apply(null, args);
}

/**
 * Inherit the prototype methods from one constructor into another. (from Node.js)
 *
 * The Function.prototype.inherits from lang.js rewritten as a standalone
 * function (not on Function.prototype). NOTE: If this file is to be loaded
 * during bootstrapping this function needs to be rewritten using some native
 * functions as prototype setup using normal JavaScript does not work as
 * expected during bootstrapping (see mirror.js in r114903).
 *
 * @param {function} ctor Constructor function which needs to inherit the
 *     prototype.
 * @param {function} superCtor Constructor function to inherit prototype from.
 */
function inherits(ctor, superCtor) {
  ctor.super_ = superCtor;
  ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
};

/**
 * Plays a sequence of streamed audio/video tracks by embedding the corresponding players
 *
 * Events:
 * - "onError", {code,source}
 * - "onReady"
 * - "onPlay"
 * - "onPause"
 * - "onEnd"
 * - "onTrackInfo", track{}
 * - "onTrackChange", track{}
 * - "loadMore"
 */

function Playem(playemPrefs) {

	function Playem(playemPrefs) {

		EventEmitter.call(this);

		playemPrefs = playemPrefs || {};
		playemPrefs.loop = playemPrefs.hasOwnProperty("loop") ? playemPrefs.loop : true;

		var players = [], // instanciated Player classes, added by client
			i,
			exportedMethods,
			currentTrack = null,
			trackList = [],
			whenReady = null,
			playersToLoad = 0,
			progress = null,
			that = this,
			playTimeout = null,
			volume = 1;

		this.setPref = function(key, val){
			playemPrefs[key] = val;
		}

		function doWhenReady(player, fct) {
			var interval = null;
			function poll(){
				if (player.isReady && interval) {
					clearInterval(interval);
					fct();
				}
				else
					console.warn("PLAYEM waiting for", player.label, "...");
			}
			if (player.isReady)
				setTimeout(fct);
			else
				interval = setInterval(poll, 1000);
		}

		function addTrack(metadata, url) {
			var track = {
				index: trackList.length,
				metadata: metadata || {}
			};
			if (url)
				track.url = url;
			trackList.push(track);
			return track;
		}

		function addTrackById(id, player, metadata) {
			if (id) {
				var track = addTrack(metadata);
				track.trackId = id;
				track.player = player;
				track.playerName = player.label.replace(/ /g, "_");
				return track;
				//console.log("added:", player.label, "track", id, track/*, metadata*/);
			}
			else
				throw new Error("no id provided");
		}

		function setVolume(vol) {
			volume = vol;
			callPlayerFct("setVolume", vol);
		}

		function stopTrack() {
			if (currentTrack) {
				callPlayerFct("stop");
				if (progress)
					clearInterval(progress);
			}
		}

		function playTrack(track) {
			//console.log("playTrack", track);
			stopTrack();
			currentTrack = track;
			delete currentTrack.trackPosition; // = null;
			delete currentTrack.trackDuration; // = null;
			that.emit("onTrackChange", track);
			if (!track.player)
				return that.emit("onError", {code:"unrecognized_track", source:"Playem", track:track});
			doWhenReady(track.player, function() {
				//console.log("playTrack #" + track.index + " (" + track.playerName+ ")", track);
				callPlayerFct("play", track.trackId);
				setVolume(volume);
				if (currentTrack.index == trackList.length-1)
					that.emit("loadMore");
				// if the track does not start playing within 7 seconds, skip to next track
				setPlayTimeout(function() {
					console.warn("PLAYEM TIMEOUT"); // => skipping to next song
					that.emit("onError", {code:"timeout", source:"Playem"});
					//exportedMethods.next();
				});
			});
		}

		function setPlayTimeout(handler) {
			if (playTimeout)
				clearTimeout(playTimeout);
			playTimeout = !handler ? null : setTimeout(handler, PLAY_TIMEOUT);
		}

		function callPlayerFct(fctName, param){
			try {
				return currentTrack.player[fctName](param);
			}
			catch(e) {
				console.warn("Player call error", fctName, e, e.stack);
			}
		}

		// functions that are called by players => to propagate to client
		function createEventHandlers (playemFunctions) {
			var eventHandlers = {
				onApiReady: function(player){
					//console.log(player.label + " api ready");
					if (whenReady && player == whenReady.player)
						whenReady.fct();
					if (0 == --playersToLoad)
						that.emit("onReady");
				},
				onEmbedReady: function(player) {
					//console.log("embed ready");
					setVolume(volume);
				},
				onBuffering: function(player) {
					setTimeout(function() {
						setPlayTimeout();
						that.emit("onBuffering");
					});
				},
				onPlaying: function(player) {
					//console.log(player.label + ".onPlaying");
					//setPlayTimeout(); // removed because soundcloud sends a "onPlaying" event, even for not authorized tracks
					setVolume(volume);
					setTimeout(function() {
						that.emit("onPlay");
					}, 1);
					if (player.trackInfo && player.trackInfo.duration)
						eventHandlers.onTrackInfo({
							position: player.trackInfo.position || 0,
							duration: player.trackInfo.duration
						});

					if (progress)
						clearInterval(progress);

					if (player.getTrackPosition) {
						//var that = eventHandlers; //this;
						progress = setInterval(function(){
							player.getTrackPosition(function(trackPos) {
								eventHandlers.onTrackInfo({
									position: trackPos,
									duration: player.trackInfo.duration || currentTrack.trackDuration
								});
							});
						}, 1000);
					}
				},
				onTrackInfo: function(trackInfo) {
					//console.log("ontrackinfo", trackInfo, currentTrack);
					if (currentTrack && trackInfo) {
						if (trackInfo.duration) {
							currentTrack.trackDuration = trackInfo.duration;
							setPlayTimeout();
						}
						if (trackInfo.position)
							currentTrack.trackPosition = trackInfo.position;
					}
					that.emit("onTrackInfo", currentTrack);
				},
				onPaused: function(player) {
					//console.log(player.label + ".onPaused");
					setPlayTimeout();
					if (progress)
						clearInterval(progress);
					progress = null;
					//if (!avoidPauseEventPropagation)
					//	that.emit("onPause");
					//avoidPauseEventPropagation = false;
				},
				onEnded: function(player) {
					//console.log(player.label + ".onEnded");
					stopTrack();
					that.emit("onEnd");
					playemFunctions.next();
				},
				onError: function(player, error) {
					console.error(player.label + " error:", ((error || {}).exception || error || {}).stack || error);
					setPlayTimeout();
					that.emit("onError", error);
				}
			};
			// handlers will only be triggered is their associated player is currently active
			["onEmbedReady", "onBuffering", "onPlaying", "onPaused", "onEnded", "onError"].map(function (evt){
				var fct = eventHandlers[evt];
				eventHandlers[evt] = function(player, x){
					if (player == currentTrack.player)
						return fct(player, x);
					else if (evt != "onEmbedReady")
						console.warn("ignore event:", evt, "from", player, "instead of:", currentTrack.player);
				};
			});
			return eventHandlers;
		}

		// exported methods, mostly wrappers to Players' methods
		exportedMethods = {
			addPlayer: function (playerClass, vars) {
				playersToLoad++;
				players.push(new playerClass(createEventHandlers(this), vars));
			},
			getQueue: function() {
				return trackList;
			},
			clearQueue: function() {
				trackList = [];
			},
			addTrackByUrl: function(url, metadata) {
				var p, player, eid;
				for (p=0; p<players.length; ++p) {
					player = players[p];
					//console.log("test ", player.label, eid);
					eid = player.getEid(url);
					if (eid)
						return addTrackById(eid, player, metadata);
				}
				return addTrack(metadata, url);
			},
			play: function(i) {
				playTrack(i != undefined ? trackList[i] : currentTrack || trackList[0]);
			},
			pause: function() {
				callPlayerFct("pause");
				that.emit("onPause");
			},
			stop: stopTrack,
			resume: function() {
				callPlayerFct("resume");
			},
			next: function() {
				if (playemPrefs.loop || currentTrack.index + 1 < trackList.length)
					playTrack(trackList[(currentTrack.index + 1) % trackList.length]);
			},
			prev: function() {
				playTrack(trackList[(trackList.length + currentTrack.index - 1) % trackList.length]);
			},
			seekTo: function(pos) {
				if ((currentTrack || {}).trackDuration)
					callPlayerFct("setTrackPosition", pos * currentTrack.trackDuration);
			},
			setVolume: setVolume
		};
		//return exportedMethods;
		for (i in exportedMethods)
			this[i] = exportedMethods[i];
	}

	inherits(Playem, EventEmitter);

	return new Playem();
};

<commit_msg>prevent loader.loadJSON() from crashing when returned data is not JSON<commit_after>// configuration

var USE_SWFOBJECT = true, //!!window.swfobject; // ... to embed youtube flash player
	PLAY_TIMEOUT = 10000;

window.$ = window.$ || function(){return window.$};
$.html = $.html || function(){return $};
$.remove = $.remove || function(){return $};

// utility functions

if (undefined == window.console)
	window.console = {log:function(){}};

loader = new (function Loader() {
	var FINAL_STATES = {"loaded": true, "complete": true, 4: true},
		head = document.getElementsByTagName("head")[0],
		pending = {};
	return {
		loadJSON: function(src, cb){
			if (pending[src]) return;
			pending[src] = true;
			// cross-domain ajax call
			var xdr = new XMLHttpRequest();
			xdr.onload = function() {
				var data = xdr.responseText;
				try{
					data = JSON.parse(data);
				} catch(e){};
				cb(data);
				delete pending[src];
			}
			xdr.open("GET", src, true);
			xdr.send();
		},
		includeJS: function(src, cb){
			if (pending[src]) return;
			pending[src] = true;
			var inc = document.createElement("script");
			inc.onload = inc.onreadystatechange = function() {
				if (pending[src] && (!inc.readyState || FINAL_STATES[inc.readyState])) {
					cb && cb();
					delete pending[src];
				}
			};
			inc.src = src;
			head.appendChild(inc);
		}
	};
});

// EventEmitter

function EventEmitter() {
	this._eventListeners = {};
}

EventEmitter.prototype.on = function(eventName, handler){
	this._eventListeners[eventName] = (this._eventListeners[eventName] || []).concat(handler);
}

EventEmitter.prototype.emit = function(eventName){
	var i, args = Array.prototype.slice.call(arguments, 1), // remove eventName from arguments, and make it an array
		listeners = this._eventListeners[eventName];
	for (i in listeners)
		listeners[i].apply(null, args);
}

/**
 * Inherit the prototype methods from one constructor into another. (from Node.js)
 *
 * The Function.prototype.inherits from lang.js rewritten as a standalone
 * function (not on Function.prototype). NOTE: If this file is to be loaded
 * during bootstrapping this function needs to be rewritten using some native
 * functions as prototype setup using normal JavaScript does not work as
 * expected during bootstrapping (see mirror.js in r114903).
 *
 * @param {function} ctor Constructor function which needs to inherit the
 *     prototype.
 * @param {function} superCtor Constructor function to inherit prototype from.
 */
function inherits(ctor, superCtor) {
  ctor.super_ = superCtor;
  ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
};

/**
 * Plays a sequence of streamed audio/video tracks by embedding the corresponding players
 *
 * Events:
 * - "onError", {code,source}
 * - "onReady"
 * - "onPlay"
 * - "onPause"
 * - "onEnd"
 * - "onTrackInfo", track{}
 * - "onTrackChange", track{}
 * - "loadMore"
 */

function Playem(playemPrefs) {

	function Playem(playemPrefs) {

		EventEmitter.call(this);

		playemPrefs = playemPrefs || {};
		playemPrefs.loop = playemPrefs.hasOwnProperty("loop") ? playemPrefs.loop : true;

		var players = [], // instanciated Player classes, added by client
			i,
			exportedMethods,
			currentTrack = null,
			trackList = [],
			whenReady = null,
			playersToLoad = 0,
			progress = null,
			that = this,
			playTimeout = null,
			volume = 1;

		this.setPref = function(key, val){
			playemPrefs[key] = val;
		}

		function doWhenReady(player, fct) {
			var interval = null;
			function poll(){
				if (player.isReady && interval) {
					clearInterval(interval);
					fct();
				}
				else
					console.warn("PLAYEM waiting for", player.label, "...");
			}
			if (player.isReady)
				setTimeout(fct);
			else
				interval = setInterval(poll, 1000);
		}

		function addTrack(metadata, url) {
			var track = {
				index: trackList.length,
				metadata: metadata || {}
			};
			if (url)
				track.url = url;
			trackList.push(track);
			return track;
		}

		function addTrackById(id, player, metadata) {
			if (id) {
				var track = addTrack(metadata);
				track.trackId = id;
				track.player = player;
				track.playerName = player.label.replace(/ /g, "_");
				return track;
				//console.log("added:", player.label, "track", id, track/*, metadata*/);
			}
			else
				throw new Error("no id provided");
		}

		function setVolume(vol) {
			volume = vol;
			callPlayerFct("setVolume", vol);
		}

		function stopTrack() {
			if (currentTrack) {
				callPlayerFct("stop");
				if (progress)
					clearInterval(progress);
			}
		}

		function playTrack(track) {
			//console.log("playTrack", track);
			stopTrack();
			currentTrack = track;
			delete currentTrack.trackPosition; // = null;
			delete currentTrack.trackDuration; // = null;
			that.emit("onTrackChange", track);
			if (!track.player)
				return that.emit("onError", {code:"unrecognized_track", source:"Playem", track:track});
			doWhenReady(track.player, function() {
				//console.log("playTrack #" + track.index + " (" + track.playerName+ ")", track);
				callPlayerFct("play", track.trackId);
				setVolume(volume);
				if (currentTrack.index == trackList.length-1)
					that.emit("loadMore");
				// if the track does not start playing within 7 seconds, skip to next track
				setPlayTimeout(function() {
					console.warn("PLAYEM TIMEOUT"); // => skipping to next song
					that.emit("onError", {code:"timeout", source:"Playem"});
					//exportedMethods.next();
				});
			});
		}

		function setPlayTimeout(handler) {
			if (playTimeout)
				clearTimeout(playTimeout);
			playTimeout = !handler ? null : setTimeout(handler, PLAY_TIMEOUT);
		}

		function callPlayerFct(fctName, param){
			try {
				return currentTrack.player[fctName](param);
			}
			catch(e) {
				console.warn("Player call error", fctName, e, e.stack);
			}
		}

		// functions that are called by players => to propagate to client
		function createEventHandlers (playemFunctions) {
			var eventHandlers = {
				onApiReady: function(player){
					//console.log(player.label + " api ready");
					if (whenReady && player == whenReady.player)
						whenReady.fct();
					if (0 == --playersToLoad)
						that.emit("onReady");
				},
				onEmbedReady: function(player) {
					//console.log("embed ready");
					setVolume(volume);
				},
				onBuffering: function(player) {
					setTimeout(function() {
						setPlayTimeout();
						that.emit("onBuffering");
					});
				},
				onPlaying: function(player) {
					//console.log(player.label + ".onPlaying");
					//setPlayTimeout(); // removed because soundcloud sends a "onPlaying" event, even for not authorized tracks
					setVolume(volume);
					setTimeout(function() {
						that.emit("onPlay");
					}, 1);
					if (player.trackInfo && player.trackInfo.duration)
						eventHandlers.onTrackInfo({
							position: player.trackInfo.position || 0,
							duration: player.trackInfo.duration
						});

					if (progress)
						clearInterval(progress);

					if (player.getTrackPosition) {
						//var that = eventHandlers; //this;
						progress = setInterval(function(){
							player.getTrackPosition(function(trackPos) {
								eventHandlers.onTrackInfo({
									position: trackPos,
									duration: player.trackInfo.duration || currentTrack.trackDuration
								});
							});
						}, 1000);
					}
				},
				onTrackInfo: function(trackInfo) {
					//console.log("ontrackinfo", trackInfo, currentTrack);
					if (currentTrack && trackInfo) {
						if (trackInfo.duration) {
							currentTrack.trackDuration = trackInfo.duration;
							setPlayTimeout();
						}
						if (trackInfo.position)
							currentTrack.trackPosition = trackInfo.position;
					}
					that.emit("onTrackInfo", currentTrack);
				},
				onPaused: function(player) {
					//console.log(player.label + ".onPaused");
					setPlayTimeout();
					if (progress)
						clearInterval(progress);
					progress = null;
					//if (!avoidPauseEventPropagation)
					//	that.emit("onPause");
					//avoidPauseEventPropagation = false;
				},
				onEnded: function(player) {
					//console.log(player.label + ".onEnded");
					stopTrack();
					that.emit("onEnd");
					playemFunctions.next();
				},
				onError: function(player, error) {
					console.error(player.label + " error:", ((error || {}).exception || error || {}).stack || error);
					setPlayTimeout();
					that.emit("onError", error);
				}
			};
			// handlers will only be triggered is their associated player is currently active
			["onEmbedReady", "onBuffering", "onPlaying", "onPaused", "onEnded", "onError"].map(function (evt){
				var fct = eventHandlers[evt];
				eventHandlers[evt] = function(player, x){
					if (player == currentTrack.player)
						return fct(player, x);
					else if (evt != "onEmbedReady")
						console.warn("ignore event:", evt, "from", player, "instead of:", currentTrack.player);
				};
			});
			return eventHandlers;
		}

		// exported methods, mostly wrappers to Players' methods
		exportedMethods = {
			addPlayer: function (playerClass, vars) {
				playersToLoad++;
				players.push(new playerClass(createEventHandlers(this), vars));
			},
			getQueue: function() {
				return trackList;
			},
			clearQueue: function() {
				trackList = [];
			},
			addTrackByUrl: function(url, metadata) {
				var p, player, eid;
				for (p=0; p<players.length; ++p) {
					player = players[p];
					//console.log("test ", player.label, eid);
					eid = player.getEid(url);
					if (eid)
						return addTrackById(eid, player, metadata);
				}
				return addTrack(metadata, url);
			},
			play: function(i) {
				playTrack(i != undefined ? trackList[i] : currentTrack || trackList[0]);
			},
			pause: function() {
				callPlayerFct("pause");
				that.emit("onPause");
			},
			stop: stopTrack,
			resume: function() {
				callPlayerFct("resume");
			},
			next: function() {
				if (playemPrefs.loop || currentTrack.index + 1 < trackList.length)
					playTrack(trackList[(currentTrack.index + 1) % trackList.length]);
			},
			prev: function() {
				playTrack(trackList[(trackList.length + currentTrack.index - 1) % trackList.length]);
			},
			seekTo: function(pos) {
				if ((currentTrack || {}).trackDuration)
					callPlayerFct("setTrackPosition", pos * currentTrack.trackDuration);
			},
			setVolume: setVolume
		};
		//return exportedMethods;
		for (i in exportedMethods)
			this[i] = exportedMethods[i];
	}

	inherits(Playem, EventEmitter);

	return new Playem();
};

<|endoftext|>


<commit_before>if (enyo && enyo.version) {
	enyo.version.spotlight = "2.3.0-pre.10-dev";
}
<commit_msg>Update version string to 2.3.0-pre.10<commit_after>if (enyo && enyo.version) {
	enyo.version.spotlight = "2.3.0-pre.10";
}
<|endoftext|>


<commit_before>const windshaft = require('windshaft');
const MapConfig = windshaft.model.MapConfig;
const Datasource = windshaft.model.Datasource;
const cleanUpQueryParams = require('../middlewares/clean-up-query-params');
const credentials = require('../middlewares/credentials');
const dbConnSetup = require('../middlewares/db-conn-setup');
const authorize = require('../middlewares/authorize');
const initProfiler = require('../middlewares/init-profiler');
const checkJsonContentType = require('../middlewares/check-json-content-type');
const incrementMapViewCount = require('../middlewares/increment-map-view-count');
const augmentLayergroupData = require('../middlewares/augment-layergroup-data');
const cacheControlHeader = require('../middlewares/cache-control-header');
const cacheChannelHeader = require('../middlewares/cache-channel-header');
const surrogateKeyHeader = require('../middlewares/surrogate-key-header');
const lastModifiedHeader = require('../middlewares/last-modified-header');
const lastUpdatedTimeLayergroup = require('../middlewares/last-updated-time-layergroup');
const layerStats = require('../middlewares/layer-stats');
const layergroupIdHeader = require('../middlewares/layergroup-id-header');
const layergroupMetadata = require('../middlewares/layergroup-metadata');
const mapError = require('../middlewares/map-error');
const CreateLayergroupMapConfigProvider = require('../../models/mapconfig/provider/create-layergroup-provider');
const rateLimit = require('../middlewares/rate-limit');
const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit;

module.exports = class AnonymousMapController {
    /**
     * @param {AuthBackend} authBackend
     * @param {PgConnection} pgConnection
     * @param {TemplateMaps} templateMaps
     * @param {MapBackend} mapBackend
     * @param metadataBackend
     * @param {SurrogateKeysCache} surrogateKeysCache
     * @param {UserLimitsBackend} userLimitsBackend
     * @param {LayergroupAffectedTables} layergroupAffectedTables
     * @param {MapConfigAdapter} mapConfigAdapter
     * @param {StatsBackend} statsBackend
     * @constructor
     */
    constructor (
        pgConnection,
        templateMaps,
        mapBackend,
        metadataBackend,
        surrogateKeysCache,
        userLimitsBackend,
        layergroupAffectedTables,
        mapConfigAdapter,
        statsBackend,
        authBackend,
        layergroupMetadata
    ) {
        this.pgConnection = pgConnection;
        this.templateMaps = templateMaps;
        this.mapBackend = mapBackend;
        this.metadataBackend = metadataBackend;
        this.surrogateKeysCache = surrogateKeysCache;
        this.userLimitsBackend = userLimitsBackend;
        this.layergroupAffectedTables = layergroupAffectedTables;
        this.mapConfigAdapter = mapConfigAdapter;
        this.statsBackend = statsBackend;
        this.authBackend = authBackend;
        this.layergroupMetadata = layergroupMetadata;
    }

    register (mapRouter) {
        mapRouter.options('/');
        mapRouter.get('/', this.composeCreateMapMiddleware());
        mapRouter.post('/', this.composeCreateMapMiddleware());
    }

    composeCreateMapMiddleware () {
        const isTemplateInstantiation = false;
        const useTemplateHash = false;
        const includeQuery = true;
        const label = 'ANONYMOUS LAYERGROUP';
        const addContext = true;

        return [
            credentials(),
            authorize(this.authBackend),
            dbConnSetup(this.pgConnection),
            rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ANONYMOUS),
            cleanUpQueryParams(['aggregation']),
            initProfiler(isTemplateInstantiation),
            checkJsonContentType(),
            checkCreateLayergroup(),
            prepareAdapterMapConfig(this.mapConfigAdapter),
            createLayergroup (
                this.mapBackend,
                this.userLimitsBackend,
                this.pgConnection,
                this.layergroupAffectedTables
            ),
            incrementMapViewCount(this.metadataBackend),
            augmentLayergroupData(),
            cacheControlHeader({ ttl: global.environment.varnish.layergroupTtl || 86400, revalidate: true }),
            cacheChannelHeader(),
            surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }),
            lastModifiedHeader({ now: true }),
            lastUpdatedTimeLayergroup(),
            layerStats(this.pgConnection, this.statsBackend),
            layergroupIdHeader(this.templateMaps, useTemplateHash),
            layergroupMetadata(this.layergroupMetadata, includeQuery),
            mapError({ label, addContext })
        ];
    }
};

function checkCreateLayergroup () {
    return function checkCreateLayergroupMiddleware (req, res, next) {
        if (req.method === 'GET') {
            const { config } = req.query;

            if (!config) {
                return next(new Error('layergroup GET needs a "config" parameter'));
            }

            try {
                req.body = JSON.parse(config);
            } catch (err) {
                return next(err);
            }
        }

        req.profiler.done('checkCreateLayergroup');
        return next();
    };
}

function prepareAdapterMapConfig (mapConfigAdapter) {
    return function prepareAdapterMapConfigMiddleware(req, res, next) {
        const requestMapConfig = req.body;

        const { user, api_key } = res.locals;
        const { dbuser, dbname, dbpassword, dbhost, dbport } = res.locals;
        const params = Object.assign({ dbuser, dbname, dbpassword, dbhost, dbport }, req.query);

        const context = {
            analysisConfiguration: {
                user,
                db: {
                    host: dbhost,
                    port: dbport,
                    dbname: dbname,
                    user: dbuser,
                    pass: dbpassword
                },
                batch: {
                    username: user,
                    apiKey: api_key
                }
            }
        };

        mapConfigAdapter.getMapConfig(user, requestMapConfig, params, context, (err, requestMapConfig) => {
            req.profiler.done('anonymous.getMapConfig');
            if (err) {
                return next(err);
            }

            req.body = requestMapConfig;
            res.locals.context = context;

            next();
        });
    };
}

function createLayergroup (mapBackend, userLimitsBackend, pgConnection, affectedTablesCache) {
    return function createLayergroupMiddleware (req, res, next) {
        const requestMapConfig = req.body;

        const { context } = res.locals;
        const { user, cache_buster, api_key } = res.locals;
        const { dbuser, dbname, dbpassword, dbhost, dbport } = res.locals;

        const params = {
            cache_buster, api_key,
            dbuser, dbname, dbpassword, dbhost, dbport
        };

        const datasource = context.datasource || Datasource.EmptyDatasource();
        const mapConfig = new MapConfig(requestMapConfig, datasource);

        const mapConfigProvider = new CreateLayergroupMapConfigProvider(
            mapConfig,
            user,
            userLimitsBackend,
            pgConnection,
            affectedTablesCache,
            params
        );

        res.locals.mapConfig = mapConfig;
        res.locals.analysesResults = context.analysesResults;

        const mapParams = { dbuser, dbname, dbpassword, dbhost, dbport };

        mapBackend.createLayergroup(mapConfig, mapParams, mapConfigProvider, (err, layergroup) => {
            req.profiler.done('createLayergroup');
            if (err) {
                return next(err);
            }

            res.statusCode = 200;
            res.body = layergroup;
            res.locals.mapConfigProvider = mapConfigProvider;

            next();
        });
    };
}
<commit_msg>Rename function<commit_after>const windshaft = require('windshaft');
const MapConfig = windshaft.model.MapConfig;
const Datasource = windshaft.model.Datasource;
const cleanUpQueryParams = require('../middlewares/clean-up-query-params');
const credentials = require('../middlewares/credentials');
const dbConnSetup = require('../middlewares/db-conn-setup');
const authorize = require('../middlewares/authorize');
const initProfiler = require('../middlewares/init-profiler');
const checkJsonContentType = require('../middlewares/check-json-content-type');
const incrementMapViewCount = require('../middlewares/increment-map-view-count');
const augmentLayergroupData = require('../middlewares/augment-layergroup-data');
const cacheControlHeader = require('../middlewares/cache-control-header');
const cacheChannelHeader = require('../middlewares/cache-channel-header');
const surrogateKeyHeader = require('../middlewares/surrogate-key-header');
const lastModifiedHeader = require('../middlewares/last-modified-header');
const lastUpdatedTimeLayergroup = require('../middlewares/last-updated-time-layergroup');
const layerStats = require('../middlewares/layer-stats');
const layergroupIdHeader = require('../middlewares/layergroup-id-header');
const layergroupMetadata = require('../middlewares/layergroup-metadata');
const mapError = require('../middlewares/map-error');
const CreateLayergroupMapConfigProvider = require('../../models/mapconfig/provider/create-layergroup-provider');
const rateLimit = require('../middlewares/rate-limit');
const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit;

module.exports = class AnonymousMapController {
    /**
     * @param {AuthBackend} authBackend
     * @param {PgConnection} pgConnection
     * @param {TemplateMaps} templateMaps
     * @param {MapBackend} mapBackend
     * @param metadataBackend
     * @param {SurrogateKeysCache} surrogateKeysCache
     * @param {UserLimitsBackend} userLimitsBackend
     * @param {LayergroupAffectedTables} layergroupAffectedTables
     * @param {MapConfigAdapter} mapConfigAdapter
     * @param {StatsBackend} statsBackend
     * @constructor
     */
    constructor (
        pgConnection,
        templateMaps,
        mapBackend,
        metadataBackend,
        surrogateKeysCache,
        userLimitsBackend,
        layergroupAffectedTables,
        mapConfigAdapter,
        statsBackend,
        authBackend,
        layergroupMetadata
    ) {
        this.pgConnection = pgConnection;
        this.templateMaps = templateMaps;
        this.mapBackend = mapBackend;
        this.metadataBackend = metadataBackend;
        this.surrogateKeysCache = surrogateKeysCache;
        this.userLimitsBackend = userLimitsBackend;
        this.layergroupAffectedTables = layergroupAffectedTables;
        this.mapConfigAdapter = mapConfigAdapter;
        this.statsBackend = statsBackend;
        this.authBackend = authBackend;
        this.layergroupMetadata = layergroupMetadata;
    }

    register (mapRouter) {
        mapRouter.options('/');
        mapRouter.get('/', this.middlewares());
        mapRouter.post('/', this.middlewares());
    }

    middlewares () {
        const isTemplateInstantiation = false;
        const useTemplateHash = false;
        const includeQuery = true;
        const label = 'ANONYMOUS LAYERGROUP';
        const addContext = true;

        return [
            credentials(),
            authorize(this.authBackend),
            dbConnSetup(this.pgConnection),
            rateLimit(this.userLimitsBackend, RATE_LIMIT_ENDPOINTS_GROUPS.ANONYMOUS),
            cleanUpQueryParams(['aggregation']),
            initProfiler(isTemplateInstantiation),
            checkJsonContentType(),
            checkCreateLayergroup(),
            prepareAdapterMapConfig(this.mapConfigAdapter),
            createLayergroup (
                this.mapBackend,
                this.userLimitsBackend,
                this.pgConnection,
                this.layergroupAffectedTables
            ),
            incrementMapViewCount(this.metadataBackend),
            augmentLayergroupData(),
            cacheControlHeader({ ttl: global.environment.varnish.layergroupTtl || 86400, revalidate: true }),
            cacheChannelHeader(),
            surrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }),
            lastModifiedHeader({ now: true }),
            lastUpdatedTimeLayergroup(),
            layerStats(this.pgConnection, this.statsBackend),
            layergroupIdHeader(this.templateMaps, useTemplateHash),
            layergroupMetadata(this.layergroupMetadata, includeQuery),
            mapError({ label, addContext })
        ];
    }
};

function checkCreateLayergroup () {
    return function checkCreateLayergroupMiddleware (req, res, next) {
        if (req.method === 'GET') {
            const { config } = req.query;

            if (!config) {
                return next(new Error('layergroup GET needs a "config" parameter'));
            }

            try {
                req.body = JSON.parse(config);
            } catch (err) {
                return next(err);
            }
        }

        req.profiler.done('checkCreateLayergroup');
        return next();
    };
}

function prepareAdapterMapConfig (mapConfigAdapter) {
    return function prepareAdapterMapConfigMiddleware(req, res, next) {
        const requestMapConfig = req.body;

        const { user, api_key } = res.locals;
        const { dbuser, dbname, dbpassword, dbhost, dbport } = res.locals;
        const params = Object.assign({ dbuser, dbname, dbpassword, dbhost, dbport }, req.query);

        const context = {
            analysisConfiguration: {
                user,
                db: {
                    host: dbhost,
                    port: dbport,
                    dbname: dbname,
                    user: dbuser,
                    pass: dbpassword
                },
                batch: {
                    username: user,
                    apiKey: api_key
                }
            }
        };

        mapConfigAdapter.getMapConfig(user, requestMapConfig, params, context, (err, requestMapConfig) => {
            req.profiler.done('anonymous.getMapConfig');
            if (err) {
                return next(err);
            }

            req.body = requestMapConfig;
            res.locals.context = context;

            next();
        });
    };
}

function createLayergroup (mapBackend, userLimitsBackend, pgConnection, affectedTablesCache) {
    return function createLayergroupMiddleware (req, res, next) {
        const requestMapConfig = req.body;

        const { context } = res.locals;
        const { user, cache_buster, api_key } = res.locals;
        const { dbuser, dbname, dbpassword, dbhost, dbport } = res.locals;

        const params = {
            cache_buster, api_key,
            dbuser, dbname, dbpassword, dbhost, dbport
        };

        const datasource = context.datasource || Datasource.EmptyDatasource();
        const mapConfig = new MapConfig(requestMapConfig, datasource);

        const mapConfigProvider = new CreateLayergroupMapConfigProvider(
            mapConfig,
            user,
            userLimitsBackend,
            pgConnection,
            affectedTablesCache,
            params
        );

        res.locals.mapConfig = mapConfig;
        res.locals.analysesResults = context.analysesResults;

        const mapParams = { dbuser, dbname, dbpassword, dbhost, dbport };

        mapBackend.createLayergroup(mapConfig, mapParams, mapConfigProvider, (err, layergroup) => {
            req.profiler.done('createLayergroup');
            if (err) {
                return next(err);
            }

            res.statusCode = 200;
            res.body = layergroup;
            res.locals.mapConfigProvider = mapConfigProvider;

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


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

    var REG_CHECK_EMPTY_STRING = /^(\u200B|\ufeff)*$/;
    var REG_REPLACE_EMPTY_CHAR = /\u200B|\ufeff/g;
    var REG_CHECK_LINK = /(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|mailto:)/i;
    var REG_CHECK_LINK_START = /^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|mailto:)/i;
    var REG_PROTO_HTTP = /^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|mailto:)/i;
    var REG_MAILTO = /^mailto:([^\?]+)/i;
    var REG_EMAIL = /^[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9!#$%&'*+\/=?.^_`{|}~-]+?@(?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9](?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9-_]*?[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9])?\.)+?(?:xn--[-a-z0-9]+|[a-zа-яё]{2,}|\d{1,3})$/i;
    var REG_CHECK_EMAIL = /(?:^|\s+)[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9!#$%&'*+\/=?.^_`{|}~-]+?@(?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9](?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9-_]*?[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9])?\.)+?(?:xn--[-a-z0-9]+|[a-zа-яё]{2,}|\d{1,3})(?:$|\s+)/i;
    var REG_CHECK_EMAIL_START = /^[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9!#$%&'*+\/=?.^_`{|}~-]+?@(?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9](?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9-_]*?[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9])?\.)+?(?:xn--[-a-z0-9]+|[a-zа-яё]{2,}|\d{1,3})/i;
    var REG_BREAK_STRING = /(?:^|\s)\S+$/;

    CKEDITOR.plugins.add('autolink2', {
        'modes': { 'wysiwyg': 1 },

        'init': function(editor) {
            editor.addCommand('autolink2', {
                'modes': { 'wysiwyg': 1 },
                'editorFocus': false,
                'exec': function(editor) {
                    autolink(editor);
                }
            } );

            editor.on('key', function(event) {
                if (this.mode !== 'wysiwyg') {
                    return;
                }

                if (event.data.keyCode === 32 || event.data.keyCode === 13) {
                    this.execCommand('autolink2');
                }
            });
        }
    });

    function autolink(editor) {
        var context = editor.editable().$;
        var selection = editor.getSelection();
        var rangeNative = selection.getNative().getRangeAt(0).cloneRange();
        var offset;
        var charCode;
        var start = rangeNative.startContainer;
        var execReg;
        var diff;

        while (start.nodeType === Node.ELEMENT_NODE && rangeNative.startOffset > 0) {
            start = rangeNative.startContainer.childNodes[ rangeNative.startOffset - 1 ];
            if (!start) {
                break;
            }

            rangeNative.setStart(start, getOffsetNode(start));
            rangeNative.collapse(true);
            start = rangeNative.startContainer;
        }

        do {
            diff = -1;

            if (rangeNative.startOffset === 0) {
                start = rangeNative.startContainer.previousSibling;

                while (start && start.nodeType === Node.ELEMENT_NODE) {
                    if (isEmptyNode(start)) {
                        break;
                    }

                    if (!(CKEDITOR.env.gecko && (start = start.firstChild))) {
                        start = start.lastChild;
                    }
                }

                if (!start) {
                    break;
                }

                offset = getOffsetNode(start) || 1;

                if (start.nodeType === Node.TEXT_NODE) {
                    if (!REG_CHECK_EMPTY_STRING.test(start.nodeValue)) {
                        if ((execReg = REG_BREAK_STRING.exec(start.nodeValue))) {
                            offset = execReg.index;
                            diff = 0;

                        } else {
                            break;
                        }
                    }
                }

            } else {
                start = rangeNative.startContainer;
                offset = rangeNative.startOffset;
            }

            offset = offset + diff;

            if (offset < 0) {
                break;
            }

            rangeNative.setStart(start, offset);
            charCode = rangeNative.toString().charCodeAt(0);

        } while (charCode !== 160 && charCode !== 32);

        var rangeString = rangeNative.toString().replace(REG_REPLACE_EMPTY_CHAR, '');
        var isLink = REG_CHECK_LINK.test(rangeString);
        var isEmail = REG_CHECK_EMAIL.test(rangeString);

        if (!isLink && !isEmail) {
            return;
        }

        var next;
        while ((rangeString = rangeNative.toString())) {
            if (isLink && REG_CHECK_LINK_START.test(rangeString)) {
                break;
            }

            if (isEmail && REG_CHECK_EMAIL_START.test(rangeString)) {
                break;
            }

            try {
                rangeNative.setStart(rangeNative.startContainer, rangeNative.startOffset + 1);

            } catch (error) {
                start = rangeNative.startContainer;

                while (!(next = start.nextSibling)) {
                    if (!context.contains(start)) {
                        return;
                    }

                    start = start.parentNode;
                }

                rangeNative.setStart(next, 0);
            }
        }

        var mailto = rangeNative.toString().match(REG_MAILTO);
        if (mailto) {
            if (!REG_EMAIL.test(mailto[ 1 ])) {
                return;
            }
        }

        var parent = rangeNative.startContainer;
        do {
            if (!context.contains(parent)) {
                break;
            }

            if (parent.tagName === 'A') {
                return;
            }

        } while ((parent = parent.parentNode));

        applyLink(rangeNative, editor);
    }

    function applyLink(rangeNative, editor) {
        editor.fire('saveSnapshot');

        var range = editor.createRange();
        range.setStart(new CKEDITOR.dom.node(rangeNative.startContainer), rangeNative.startOffset);
        range.setEnd(new CKEDITOR.dom.node(rangeNative.endContainer), rangeNative.endOffset);

        var href = rangeNative.toString().replace(REG_REPLACE_EMPTY_CHAR, '');
        href = CKEDITOR.tools.htmlDecodeAttr(href);

        if (!REG_PROTO_HTTP.test(href)) {
            if (REG_EMAIL.test(href)) {
                href = 'mailto:' + href;

            } else {
                href = 'http://' + href;
            }
        }

        var style = new CKEDITOR.style({
			'element': 'a',
			'attributes': { 'href': href }
		});

        style.type = CKEDITOR.STYLE_INLINE;
        style.applyToRange(range, editor);

        editor.fire('saveSnapshot');
    }

    function isEmptyNode(node) {
        if (CKEDITOR.dtd.$inline[ node.tagName.toLowerCase() ] &&
            !node.textContent.replace(REG_REPLACE_EMPTY_CHAR, '').length) {

            return true;
        }

        return false;
    }

    function getOffsetNode(node) {
        return node.nodeType === Node.ELEMENT_NODE ?
            node.childNodes.length :
            node.nodeValue.length;
    }

}());
<commit_msg>замена табов<commit_after>(function() {
    'use strict';

    var REG_CHECK_EMPTY_STRING = /^(\u200B|\ufeff)*$/;
    var REG_REPLACE_EMPTY_CHAR = /\u200B|\ufeff/g;
    var REG_CHECK_LINK = /(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|mailto:)/i;
    var REG_CHECK_LINK_START = /^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|mailto:)/i;
    var REG_PROTO_HTTP = /^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|mailto:)/i;
    var REG_MAILTO = /^mailto:([^\?]+)/i;
    var REG_EMAIL = /^[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9!#$%&'*+\/=?.^_`{|}~-]+?@(?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9](?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9-_]*?[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9])?\.)+?(?:xn--[-a-z0-9]+|[a-zа-яё]{2,}|\d{1,3})$/i;
    var REG_CHECK_EMAIL = /(?:^|\s+)[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9!#$%&'*+\/=?.^_`{|}~-]+?@(?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9](?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9-_]*?[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9])?\.)+?(?:xn--[-a-z0-9]+|[a-zа-яё]{2,}|\d{1,3})(?:$|\s+)/i;
    var REG_CHECK_EMAIL_START = /^[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9!#$%&'*+\/=?.^_`{|}~-]+?@(?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9](?:[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9-_]*?[a-zа-яёÇçĞğIıİiÖöŞşÜüẞß0-9])?\.)+?(?:xn--[-a-z0-9]+|[a-zа-яё]{2,}|\d{1,3})/i;
    var REG_BREAK_STRING = /(?:^|\s)\S+$/;

    CKEDITOR.plugins.add('autolink2', {
        'modes': { 'wysiwyg': 1 },

        'init': function(editor) {
            editor.addCommand('autolink2', {
                'modes': { 'wysiwyg': 1 },
                'editorFocus': false,
                'exec': function(editor) {
                    autolink(editor);
                }
            } );

            editor.on('key', function(event) {
                if (this.mode !== 'wysiwyg') {
                    return;
                }

                if (event.data.keyCode === 32 || event.data.keyCode === 13) {
                    this.execCommand('autolink2');
                }
            });
        }
    });

    function autolink(editor) {
        var context = editor.editable().$;
        var selection = editor.getSelection();
        var rangeNative = selection.getNative().getRangeAt(0).cloneRange();
        var offset;
        var charCode;
        var start = rangeNative.startContainer;
        var execReg;
        var diff;

        while (start.nodeType === Node.ELEMENT_NODE && rangeNative.startOffset > 0) {
            start = rangeNative.startContainer.childNodes[ rangeNative.startOffset - 1 ];
            if (!start) {
                break;
            }

            rangeNative.setStart(start, getOffsetNode(start));
            rangeNative.collapse(true);
            start = rangeNative.startContainer;
        }

        do {
            diff = -1;

            if (rangeNative.startOffset === 0) {
                start = rangeNative.startContainer.previousSibling;

                while (start && start.nodeType === Node.ELEMENT_NODE) {
                    if (isEmptyNode(start)) {
                        break;
                    }

                    if (!(CKEDITOR.env.gecko && (start = start.firstChild))) {
                        start = start.lastChild;
                    }
                }

                if (!start) {
                    break;
                }

                offset = getOffsetNode(start) || 1;

                if (start.nodeType === Node.TEXT_NODE) {
                    if (!REG_CHECK_EMPTY_STRING.test(start.nodeValue)) {
                        if ((execReg = REG_BREAK_STRING.exec(start.nodeValue))) {
                            offset = execReg.index;
                            diff = 0;

                        } else {
                            break;
                        }
                    }
                }

            } else {
                start = rangeNative.startContainer;
                offset = rangeNative.startOffset;
            }

            offset = offset + diff;

            if (offset < 0) {
                break;
            }

            rangeNative.setStart(start, offset);
            charCode = rangeNative.toString().charCodeAt(0);

        } while (charCode !== 160 && charCode !== 32);

        var rangeString = rangeNative.toString().replace(REG_REPLACE_EMPTY_CHAR, '');
        var isLink = REG_CHECK_LINK.test(rangeString);
        var isEmail = REG_CHECK_EMAIL.test(rangeString);

        if (!isLink && !isEmail) {
            return;
        }

        var next;
        while ((rangeString = rangeNative.toString())) {
            if (isLink && REG_CHECK_LINK_START.test(rangeString)) {
                break;
            }

            if (isEmail && REG_CHECK_EMAIL_START.test(rangeString)) {
                break;
            }

            try {
                rangeNative.setStart(rangeNative.startContainer, rangeNative.startOffset + 1);

            } catch (error) {
                start = rangeNative.startContainer;

                while (!(next = start.nextSibling)) {
                    if (!context.contains(start)) {
                        return;
                    }

                    start = start.parentNode;
                }

                rangeNative.setStart(next, 0);
            }
        }

        var mailto = rangeNative.toString().match(REG_MAILTO);
        if (mailto) {
            if (!REG_EMAIL.test(mailto[ 1 ])) {
                return;
            }
        }

        var parent = rangeNative.startContainer;
        do {
            if (!context.contains(parent)) {
                break;
            }

            if (parent.tagName === 'A') {
                return;
            }

        } while ((parent = parent.parentNode));

        applyLink(rangeNative, editor);
    }

    function applyLink(rangeNative, editor) {
        editor.fire('saveSnapshot');

        var range = editor.createRange();
        range.setStart(new CKEDITOR.dom.node(rangeNative.startContainer), rangeNative.startOffset);
        range.setEnd(new CKEDITOR.dom.node(rangeNative.endContainer), rangeNative.endOffset);

        var href = rangeNative.toString().replace(REG_REPLACE_EMPTY_CHAR, '');
        href = CKEDITOR.tools.htmlDecodeAttr(href);

        if (!REG_PROTO_HTTP.test(href)) {
            if (REG_EMAIL.test(href)) {
                href = 'mailto:' + href;

            } else {
                href = 'http://' + href;
            }
        }

        var style = new CKEDITOR.style({
            'element': 'a',
            'attributes': { 'href': href }
        });

        style.type = CKEDITOR.STYLE_INLINE;
        style.applyToRange(range, editor);

        editor.fire('saveSnapshot');
    }

    function isEmptyNode(node) {
        if (CKEDITOR.dtd.$inline[ node.tagName.toLowerCase() ] &&
            !node.textContent.replace(REG_REPLACE_EMPTY_CHAR, '').length) {

            return true;
        }

        return false;
    }

    function getOffsetNode(node) {
        return node.nodeType === Node.ELEMENT_NODE ?
            node.childNodes.length :
            node.nodeValue.length;
    }

}());
<|endoftext|>