<commit_before>import mobxStore from '../../mobxStore'
import { path as pathUtil } from '../../utils'
import api from '../../backendAPI'
import * as Modal from '../../components/Modal/actions'
import TabStore from 'components/Tab/store'
import FileState from 'commons/File/state'
import FileStore from 'commons/File/store'
import { notify } from '../../components/Notification/actions'
import i18n from 'utils/createI18n'
import icons from 'file-icons-js'
import { toJS, when } from 'mobx'

const nodeToNearestDirPath = (node) => {
  if (!node) node = { isDir: true, path: '/' } // fake a root node if !node
  if (node.isDir) {
    var path = node.path
  } else {
    var path = node.parent.path
  }
  if (path != '/') path += '/'
  return path
}

const nodeToParentDirPath = (node) => {
  const pathSplitted = node.path.split('/')
  if (pathSplitted.pop() == '') { pathSplitted.pop() }
  return `${pathSplitted.join('/')}/`
}

function createFolderAtPath (path) {
  return api.createFolder(path)
  .then((data) => {
    if (data.code < 0) {
      Modal.updateModal({ statusMessage: data.msg }).then(createFolderAtPath)
    } else {
      Modal.dismissModal()
    }
  })
  .then(() => path)
    // if error, try again.
  .catch(err =>
    Modal.updateModal({ statusMessage: err.msg }).then(createFolderAtPath)
  )
}

export function openFile (obj) {
  // 做一些encoding的调度
  if (FileState.initData.get('_init')) {
    when(() => !FileState.initData.get('_init'), () => {
      const { encoding } = FileState.initData.get(obj.path) || {}
      openFileWithEncoding({ ...obj, encoding })
      FileState.initData.set(obj.path, {})
    })
  } else {
    const { encoding } = FileState.initData.get(obj.path) || {}
    openFileWithEncoding({ ...obj, encoding })
    FileState.initData.set(obj.path, {})
  }
}

export function openFileWithEncoding ({ path, editor = {}, others = {}, allGroup = false, encoding }) {
  const { encoding: currentEncoding } = FileStore.get(path) || {}
  return api.readFile(path, encoding || currentEncoding)
    .then((data) => {
      FileStore.loadNodeData(data)
      return data
    })
    .then(() => {
      const activeTabGroup = TabStore.getState().activeTabGroup
      const existingTabs = TabStore.findTab(
        tab => tab.file && tab.file.path === path && (tab.tabGroup === activeTabGroup || allGroup)
      )
      if (existingTabs.length) {
        const existingTab = existingTabs[0]
        if (editor.gitBlame) {
          existingTab.editor.gitBlame = editor.gitBlame
        }
        existingTab.activate()
      } else {
        TabStore.createTab({
          icon: icons.getClassWithColor(path.split('/').pop()) || 'fa fa-file-text-o',
          editor: {
            ...editor,
            filePath: path,
          },
          ...others
        })
      }
    })
}

function createFileWithContent (content) {
  return function createFileAtPath (path) {
    if (content) {
      return api.createFile(path, content)
        .then((res) => {
          if (res.msg) {
            throw new Error(res.msg)
          } else {
            Modal.dismissModal()
          }
        })
        .then(() => api.writeFile(path, content))
        .then(() => {
          api.readFile(path).then((data) => {
            const { EditorTabState } = mobxStore
            const activeTab = EditorTabState.activeTab
            FileStore.loadNodeData(data)
            TabStore.updateTab({
              icon: (path && icons.getClassWithColor(path.split('/').pop())) || 'fa fa-file-text-o',
              id: activeTab.id,
              editor: { filePath: path },
            })
          })
        })
        .catch((err) => {
          Modal.updateModal({ statusMessage: err.message }).then(createFileAtPath)
        })
    }
    return api.createFile(path, content)
      .then((res) => {
        if (res.msg) {
          throw new Error(res.msg)
        } else {
          Modal.dismissModal()
        }
      })
      .then(() => {
        openFile({ path })
      })
      // if error, try again.
      .catch((err) => {
        Modal.updateModal({ statusMessage: err.message }).then(createFileAtPath)
      })
  }
}

const fileCommands = {
  'file:open_file': (c) => { // 在当前 tabgroup 中优先打开已有的 tab
    if (typeof c.data === 'string') {
      openFile({ path: c.data })
    } else {
      openFile(c.data)
    }
  },
  'file:open_exist_file': (c) => { // 在所有 tabgroup 中优先打开已有的 tab
    if (typeof c.data === 'string') {
      openFile({ path: c.data, allGroup: true })
    } else {
      openFile(c.data)
    }
  },
  'file:new_file': (c) => {
    const node = c.context
    const path = nodeToNearestDirPath(node)
    const defaultValue = pathUtil.join(path, 'untitled')

    const createFile = createFileWithContent(null)

    Modal.showModal('Prompt', {
      message: i18n`file.newFilePath`,
      defaultValue,
      selectionRange: [path.length, defaultValue.length]
    })
    .then(createFile)
  },
  'file:new_folder': (c) => {
    const node = c.context
    const path = nodeToNearestDirPath(node)
    const defaultValue = pathUtil.join(path, 'untitled')
    Modal.showModal('Prompt', {
      message: i18n`file.newFileFolderPath`,
      defaultValue,
      selectionRange: [path.length, defaultValue.length],
    }).then(createFolderAtPath)
  },
  'file:save': (c) => {
    const { EditorTabState } = mobxStore
    const activeTab = EditorTabState.activeTab
    const content = activeTab ? activeTab.editor.cm.getValue() : ''

    if (!activeTab.file) {
      const createFile = createFileWithContent(content)
      const defaultPath = activeTab._title ? `/${activeTab._title}` : '/untitled'
      Modal.showModal('Prompt', {
        message: i18n`file.newFilePath`,
        defaultValue: defaultPath,
        selectionRange: [1, defaultPath.length]
      })
        .then(createFile)
    } else {
      api.writeFile(activeTab.file.path, content)
        .then((res) => {
          FileStore.updateFile({
            path: activeTab.file.path,
            isSynced: true,
            lastModified: res.lastModified,
            // content,
          })
        })
    }
  },

  'file:rename': (c) => {
    const node = c.context
    const oldPath = node.path
    const parentPath = nodeToParentDirPath(node)
    const existingTabs = TabStore.findTab(
      tab => tab.file && tab.file.path.startsWith(oldPath)
    )

    const moveFile = (from, to, force) => {
      api.moveFile(from, to, force)
        .then(() => Modal.dismissModal())
        .catch(err =>
          Modal.updateModal({ statusMessage: err.msg }).then((_to, _force) =>
            moveFile(from, _to, _force)
          )
        ).then(() => {
          if (existingTabs.length) {
            existingTabs.forEach((tab) => {
              const newPath = tab.file.path.replace(from, to)
              api.readFile(newPath).then((data) => {
                FileStore.loadNodeData(data)
                TabStore.updateTab({ id: tab.id, editor: { filePath: newPath } })
              })
            })
          }
        })
    }

    Modal.showModal('Prompt', {
      message: i18n`file.newFileName`,
      defaultValue: oldPath,
      selectionRange: [parentPath.length, oldPath.length]
    }).then(newPath => moveFile(oldPath, newPath))
  },

  'file:delete': async (c) => {
    const confirmed = await Modal.showModal('Confirm', {
      header: i18n`file.deleteHeader`,
      message: i18n`file.deleteMessage${{ file: c.context.path }}`,
      okText: i18n`file.deleteButton`
    })

    if (confirmed) {
      api.deleteFile(c.context.path)
        .then(() => notify({ message: i18n`file.deleteNotifySuccess` }))
        .catch(err =>
          notify({ message: i18n`file.deleteNotifyFailed${err.msg}` })
        )
    }

    Modal.dismissModal()
  },

  'file:download': (c) => {
    api.downloadFile(c.context.path, c.context.isDir)
  },

  // 'file:unsaved_files_list':
}

export default fileCommands
<commit_msg>Fix file api for github version<commit_after>import mobxStore from '../../mobxStore'
import { path as pathUtil } from '../../utils'
import api from '../../backendAPI'
import * as Modal from '../../components/Modal/actions'
import TabStore from 'components/Tab/store'
import FileState from 'commons/File/state'
import FileStore from 'commons/File/store'
import { notify } from '../../components/Notification/actions'
import i18n from 'utils/createI18n'
import icons from 'file-icons-js'
import { toJS, when } from 'mobx'

const nodeToNearestDirPath = (node) => {
  if (!node) node = { isDir: true, path: '/' } // fake a root node if !node
  if (node.isDir) {
    var path = node.path
  } else {
    var path = node.parent.path
  }
  if (path != '/') path += '/'
  return path
}

const nodeToParentDirPath = (node) => {
  const pathSplitted = node.path.split('/')
  if (pathSplitted.pop() == '') { pathSplitted.pop() }
  return `${pathSplitted.join('/')}/`
}

function createFolderAtPath (path) {
  return api.createFolder(path)
  .then((data) => {
    if (data.code < 0) {
      Modal.updateModal({ statusMessage: data.msg }).then(createFolderAtPath)
    } else {
      Modal.dismissModal()
    }
  })
  .then(() => path)
    // if error, try again.
  .catch(err =>
    Modal.updateModal({ statusMessage: err.msg }).then(createFolderAtPath)
  )
}

export function openFile (obj) {
  // 做一些encoding的调度
  if (FileState.initData.get('_init')) {
    when(() => !FileState.initData.get('_init'), () => {
      const { encoding } = FileState.initData.get(obj.path) || {}
      openFileWithEncoding({ ...obj, encoding })
      FileState.initData.set(obj.path, {})
    })
  } else {
    const { encoding } = FileState.initData.get(obj.path) || {}
    openFileWithEncoding({ ...obj, encoding })
    FileState.initData.set(obj.path, {})
  }
}

export function openFileWithEncoding ({ path, editor = {}, others = {}, allGroup = false, encoding }) {
  const { encoding: currentEncoding } = FileStore.get(path) || {}
  return api.readFile(path, encoding || currentEncoding)
    .then((data) => {
      FileStore.loadNodeData(data)
      return data
    })
    .then(() => {
      const activeTabGroup = TabStore.getState().activeTabGroup
      const existingTabs = TabStore.findTab(
        tab => tab.file && tab.file.path === path && (tab.tabGroup === activeTabGroup || allGroup)
      )
      if (existingTabs.length) {
        const existingTab = existingTabs[0]
        if (editor.gitBlame) {
          existingTab.editor.gitBlame = editor.gitBlame
        }
        existingTab.activate()
      } else {
        TabStore.createTab({
          icon: icons.getClassWithColor(path.split('/').pop()) || 'fa fa-file-text-o',
          editor: {
            ...editor,
            filePath: path,
          },
          ...others
        })
      }
    })
}

function createFileWithContent (content) {
  return function createFileAtPath (path) {
    if (content) {
      return api.createFile(path, content)
        .then((res) => {
          if (res.msg) {
            throw new Error(res.msg)
          } else {
            Modal.dismissModal()
          }
        })
        .then(() => api.writeFile(path, content))
        .then(() => {
          api.readFile(path).then((data) => {
            const { EditorTabState } = mobxStore
            const activeTab = EditorTabState.activeTab
            FileStore.loadNodeData(data)
            TabStore.updateTab({
              icon: (path && icons.getClassWithColor(path.split('/').pop())) || 'fa fa-file-text-o',
              id: activeTab.id,
              editor: { filePath: path },
            })
          })
        })
        .catch((res) => {
          Modal.updateModal({ statusMessage: res.response ? res.response.data.msg : res.message }).then(createFileAtPath)
        })
    }
    return api.createFile(path, content)
      .then((res) => {
        if (res.msg) {
          throw new Error(res.msg)
        } else {
          Modal.dismissModal()
        }
      })
      .then(() => {
        openFile({ path })
      })
      // if error, try again.
      .catch((res) => {
        Modal.updateModal({ statusMessage: res.response ? res.response.data.msg : res.message }).then(createFileAtPath)
      })
  }
}

const fileCommands = {
  'file:open_file': (c) => { // 在当前 tabgroup 中优先打开已有的 tab
    if (typeof c.data === 'string') {
      openFile({ path: c.data })
    } else {
      openFile(c.data)
    }
  },
  'file:open_exist_file': (c) => { // 在所有 tabgroup 中优先打开已有的 tab
    if (typeof c.data === 'string') {
      openFile({ path: c.data, allGroup: true })
    } else {
      openFile(c.data)
    }
  },
  'file:new_file': (c) => {
    const node = c.context
    const path = nodeToNearestDirPath(node)
    const defaultValue = pathUtil.join(path, 'untitled')

    const createFile = createFileWithContent(null)

    Modal.showModal('Prompt', {
      message: i18n`file.newFilePath`,
      defaultValue,
      selectionRange: [path.length, defaultValue.length]
    })
    .then(createFile)
  },
  'file:new_folder': (c) => {
    const node = c.context
    const path = nodeToNearestDirPath(node)
    const defaultValue = pathUtil.join(path, 'untitled')
    Modal.showModal('Prompt', {
      message: i18n`file.newFileFolderPath`,
      defaultValue,
      selectionRange: [path.length, defaultValue.length],
    }).then(createFolderAtPath)
  },
  'file:save': (c) => {
    const { EditorTabState } = mobxStore
    const activeTab = EditorTabState.activeTab
    const content = activeTab ? activeTab.editor.cm.getValue() : ''

    if (!activeTab.file) {
      const createFile = createFileWithContent(content)
      const defaultPath = activeTab._title ? `/${activeTab._title}` : '/untitled'
      Modal.showModal('Prompt', {
        message: i18n`file.newFilePath`,
        defaultValue: defaultPath,
        selectionRange: [1, defaultPath.length]
      })
        .then(createFile)
    } else {
      api.writeFile(activeTab.file.path, content)
        .then((res) => {
          FileStore.updateFile({
            path: activeTab.file.path,
            isSynced: true,
            lastModified: res.lastModified,
            // content,
          })
        })
    }
  },

  'file:rename': (c) => {
    const node = c.context
    const oldPath = node.path
    const parentPath = nodeToParentDirPath(node)
    const existingTabs = TabStore.findTab(
      tab => tab.file && tab.file.path.startsWith(oldPath)
    )

    const moveFile = (from, to, force) => {
      api.moveFile(from, to, force)
        .then(() => Modal.dismissModal())
        .catch(err =>
          Modal.updateModal({ statusMessage: err.msg }).then((_to, _force) =>
            moveFile(from, _to, _force)
          )
        ).then(() => {
          if (existingTabs.length) {
            existingTabs.forEach((tab) => {
              const newPath = tab.file.path.replace(from, to)
              api.readFile(newPath).then((data) => {
                FileStore.loadNodeData(data)
                TabStore.updateTab({ id: tab.id, editor: { filePath: newPath } })
              })
            })
          }
        })
    }

    Modal.showModal('Prompt', {
      message: i18n`file.newFileName`,
      defaultValue: oldPath,
      selectionRange: [parentPath.length, oldPath.length]
    }).then(newPath => moveFile(oldPath, newPath))
  },

  'file:delete': async (c) => {
    const confirmed = await Modal.showModal('Confirm', {
      header: i18n`file.deleteHeader`,
      message: i18n`file.deleteMessage${{ file: c.context.path }}`,
      okText: i18n`file.deleteButton`
    })

    if (confirmed) {
      api.deleteFile(c.context.path)
        .then(() => notify({ message: i18n`file.deleteNotifySuccess` }))
        .catch(err =>
          notify({ message: i18n`file.deleteNotifyFailed${err.msg}` })
        )
    }

    Modal.dismissModal()
  },

  'file:download': (c) => {
    api.downloadFile(c.context.path, c.context.isDir)
  },

  // 'file:unsaved_files_list':
}

export default fileCommands
<|endoftext|>


<commit_before>
// debugger

//Three.js rendering:
var camera, scene, renderer;
var effect, controls;
var element, container;
var cube, time, text, text_geo;

var particleSystem, particles, boxes,
particleSystemHeight = 500,
particleCount = 50;

var clock = new THREE.Clock();
var raycaster = new THREE.Raycaster();
var center = new THREE.Vector2(0,0);

var VR = false;

var full_button = document.getElementById('fullscreen');
full_button.addEventListener('click', fullscreen, false);

var vr_button = document.getElementById('vr-mode');
vr_button.addEventListener('click', toggleVR, false);

function toggleVR(){

  if(VR){

    VR = false;

    camera.position.set(0, 0, 0);

    controls = new THREE.OrbitControls(camera, element);
    controls.rotateUp(Math.PI / 4);
    controls.target.set(
      camera.position.x + 0.1,
      camera.position.y,
      camera.position.z
    );
    controls.noZoom = true;
    controls.noPan = true;
    controls.update();
    controls.autoFollowMouse(true);

  }else{

    VR = true;

    //if mobile device, user device orientation controls:
    if(window.DeviceOrientationEvent){

      camera.position.set(0, 0, 0);

      //console.log('orientation');
      controls = new THREE.DeviceOrientationControls(camera, true);
      controls.connect();
      controls.update();
    }
  }
}

//start three.js stuff
init();
animate();

function init() {

  //set up camera stuff:
  var errorCallback = function(e) {
    console.log('Reeeejected!', e);
  };

  navigator.getUserMedia  = navigator.getUserMedia ||
                          navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia ||
                          navigator.msGetUserMedia;

  function gotSources(sourceInfos) {

    console.log(sourceInfos);

    var sourceId;

    //the back facing camera on nexus 5 is the 4th source:
    if(sourceInfos[4]){

      sourceId = sourceInfos[4].id;
    }

    //set the constraints for this preference
    var constraints = {
      audio: false,
      video: {
        optional: [{sourceId: sourceId}]
      }
    }

    /*
    //video containers for left and right eye
    var video1 = document.querySelector('video.left');
    var video2 = document.querySelector('video.right');

    //set the video source for both eyes to the same video stream:
    if (navigator.getUserMedia) {
      navigator.getUserMedia(constraints, function(stream) {
        video1.src = window.URL.createObjectURL(stream);
        video2.src = window.URL.createObjectURL(stream);

        //annyang.start();

      }, errorCallback);
    }
    */
  }

  if (typeof MediaStreamTrack === 'undefined'){
    alert('This browser does not support MediaStreamTrack.');
  } else {
    MediaStreamTrack.getSources(gotSources);
  }

  // make the three.js background transparent:
  renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
  renderer.setClearColor( 0x000000, 0 );

  // create the three container:
  element = renderer.domElement;
  container = document.getElementById('threejs');
  container.appendChild(element);

  //stereo render effect:
  effect = new THREE.StereoEffect(renderer);
  scene = new THREE.Scene();
  scene.fog = new THREE.FogExp2( 0x000000, 0.0025 );

  //set up the camera:
  camera = new THREE.PerspectiveCamera(90, 1, 0.001, 700);
  camera.position.set(0, 0, 0);
  scene.add(camera);

  controls = new THREE.OrbitControls(camera, element);
  controls.rotateUp(Math.PI / 4);
  controls.target.set(
    camera.position.x + 0.1,
    camera.position.y,
    camera.position.z
  );
  controls.noZoom = true;
  controls.noPan = true;

  controls.autoFollowMouse(true);

  //add light to the scene (this is red light)
  var light = new THREE.HemisphereLight(0xffff00, 0x000000, 1);
  scene.add(light);

  particles = [];
  boxes = [];

  for(var i = 0; i < words.length; i++){

    var word = words[i];

    var group = new THREE.Object3D();//create an empty container

    var text_geo = new THREE.TextGeometry(word.word, {size: 20, height: 1, font: 'gentilis'});
    var text = new THREE.Mesh( text_geo, new THREE.MeshLambertMaterial({color: 0x00ff00}) );

    var box = new THREE.BoundingBoxHelper( text, 0x00ff00 );
    box.visible = false;
    box.word = word;
    box.update();

    group.add( text );
    group.add( box );

    group.box = box;
    group.text = text;

    group.position.x = Math.random() * 500 - 250;
    group.position.y = Math.random() * 500 - 250;
    group.position.z = Math.random() * 500 - 250;

    particles[i] = group;
    boxes[i] = box;

    word.particle = particles[i];

    scene.add( group );

  }

}

function resize() {
  var width = container.offsetWidth;
  var height = container.offsetHeight;

  camera.aspect = width / height;
  //camera.position.set(0, 0, 0);

  camera.updateProjectionMatrix();

  renderer.setSize(width, height);
  effect.setSize(width, height);
}

function update(dt) {

  resize();

  camera.updateProjectionMatrix();

  controls.update(dt);
}

function render(dt) {

  time = clock.getElapsedTime();

  //cube.rotation.x += 0.02;
  //cube.rotation.y += 0.02;
  //cube.rotation.z += 0.02;
  //cube.position.x  = 100 + 20 * Math.sin(time * 3);

  // simple billboard method
  //text.quaternion.copy( camera.quaternion );

  for(var i = 0; i < words.length; i++){

    particles[i].quaternion.copy( camera.quaternion );

    particles[i].position.x -= 0.02;
    particles[i].position.y -= 0.02;
    particles[i].position.z -= 0.02;

    if(particles[i].explode > 0){

      particles[i].explode--;

      particles[i].box.object.material.wireframe = true;

      particles[i].object.scale.set(12,6,1);

      particles[i].object.opacity -= 0.1;

    }else if(particles[i].box.intersected && particles[i].box.intersected > 0){

      particles[i].box.intersected--;

    }else{

      particles[i].box.intersected = false;

      particles[i].box.object.material.color.set( 0x00ff00 );
    }

  }

  // update the picking ray with the camera and mouse position
  raycaster.setFromCamera( center, camera );

  // calculate objects intersecting the picking ray
  var intersects = raycaster.intersectObjects( boxes );

  for ( var i = 0; i < intersects.length; i++ ) {

    // console.log('intersects', intersects);

    intersects[ i ].object.object.material.color.set( 0xff0000 );

    intersects[ i ].object.intersected = 300;
  }

  if(VR){

    effect.render(scene, camera);

  }else{

    renderer.render(scene, camera);
  }

}

function animate(t) {
  requestAnimationFrame(animate);

  var dt = clock.getDelta();

  update(dt);
  render(dt);
}

function fullscreen() {
  if (document.body.requestFullscreen) {
    document.body.requestFullscreen();
  } else if (document.body.msRequestFullscreen) {
    document.body.msRequestFullscreen();
  } else if (document.body.mozRequestFullScreen) {
    document.body.mozRequestFullScreen();
  } else if (document.body.webkitRequestFullscreen) {
    document.body.webkitRequestFullscreen();
  }
}

<commit_msg>funny fail<commit_after>
// debugger

//Three.js rendering:
var camera, scene, renderer;
var effect, controls;
var element, container;
var cube, time, text, text_geo;

var particleSystem, particles, boxes,
particleSystemHeight = 500,
particleCount = 50;

var clock = new THREE.Clock();
var raycaster = new THREE.Raycaster();
var center = new THREE.Vector2(0,0);

var VR = false;

var full_button = document.getElementById('fullscreen');
full_button.addEventListener('click', fullscreen, false);

var vr_button = document.getElementById('vr-mode');
vr_button.addEventListener('click', toggleVR, false);

function toggleVR(){

  if(VR){

    VR = false;

    camera.position.set(0, 0, 0);

    controls = new THREE.OrbitControls(camera, element);
    controls.rotateUp(Math.PI / 4);
    controls.target.set(
      camera.position.x + 0.1,
      camera.position.y,
      camera.position.z
    );
    controls.noZoom = true;
    controls.noPan = true;
    controls.update();
    controls.autoFollowMouse(true);

  }else{

    VR = true;

    //if mobile device, user device orientation controls:
    if(window.DeviceOrientationEvent){

      camera.position.set(0, 0, 0);

      //console.log('orientation');
      controls = new THREE.DeviceOrientationControls(camera, true);
      controls.connect();
      controls.update();
    }
  }
}

//start three.js stuff
init();
animate();

function init() {

  //set up camera stuff:
  var errorCallback = function(e) {
    console.log('Reeeejected!', e);
  };

  navigator.getUserMedia  = navigator.getUserMedia ||
                          navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia ||
                          navigator.msGetUserMedia;

  function gotSources(sourceInfos) {

    console.log(sourceInfos);

    var sourceId;

    //the back facing camera on nexus 5 is the 4th source:
    if(sourceInfos[4]){

      sourceId = sourceInfos[4].id;
    }

    //set the constraints for this preference
    var constraints = {
      audio: false,
      video: {
        optional: [{sourceId: sourceId}]
      }
    }

    /*
    //video containers for left and right eye
    var video1 = document.querySelector('video.left');
    var video2 = document.querySelector('video.right');

    //set the video source for both eyes to the same video stream:
    if (navigator.getUserMedia) {
      navigator.getUserMedia(constraints, function(stream) {
        video1.src = window.URL.createObjectURL(stream);
        video2.src = window.URL.createObjectURL(stream);

        //annyang.start();

      }, errorCallback);
    }
    */
  }

  if (typeof MediaStreamTrack === 'undefined'){
    alert('This browser does not support MediaStreamTrack.');
  } else {
    MediaStreamTrack.getSources(gotSources);
  }

  // make the three.js background transparent:
  renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
  renderer.setClearColor( 0x000000, 0 );

  // create the three container:
  element = renderer.domElement;
  container = document.getElementById('threejs');
  container.appendChild(element);

  //stereo render effect:
  effect = new THREE.StereoEffect(renderer);
  scene = new THREE.Scene();
  scene.fog = new THREE.FogExp2( 0x000000, 0.0025 );

  //set up the camera:
  camera = new THREE.PerspectiveCamera(90, 1, 0.001, 700);
  camera.position.set(0, 0, 0);
  scene.add(camera);

  controls = new THREE.OrbitControls(camera, element);
  controls.rotateUp(Math.PI / 4);
  controls.target.set(
    camera.position.x + 0.1,
    camera.position.y,
    camera.position.z
  );
  controls.noZoom = true;
  controls.noPan = true;

  controls.autoFollowMouse(true);

  //add light to the scene (this is red light)
  var light = new THREE.HemisphereLight(0xffff00, 0x000000, 1);
  scene.add(light);

  particles = [];
  boxes = [];

  for(var i = 0; i < words.length; i++){

    var word = words[i];

    var group = new THREE.Object3D();//create an empty container

    var text_geo = new THREE.TextGeometry(word.word, {size: 20, height: 1, font: 'gentilis'});
    var text = new THREE.Mesh( text_geo, new THREE.MeshLambertMaterial({color: 0x00ff00}) );

    var box = new THREE.BoundingBoxHelper( text, 0x00ff00 );
    box.visible = false;
    box.word = word;
    box.update();

    group.add( text );
    group.add( box );

    group.box = box;
    group.text = text;

    group.position.x = Math.random() * 500 - 250;
    group.position.y = Math.random() * 500 - 250;
    group.position.z = Math.random() * 500 - 250;

    particles[i] = group;
    boxes[i] = box;

    word.particle = particles[i];

    scene.add( group );

  }

}

function resize() {
  var width = container.offsetWidth;
  var height = container.offsetHeight;

  camera.aspect = width / height;
  //camera.position.set(0, 0, 0);

  camera.updateProjectionMatrix();

  renderer.setSize(width, height);
  effect.setSize(width, height);
}

function update(dt) {

  resize();

  camera.updateProjectionMatrix();

  controls.update(dt);
}

function render(dt) {

  time = clock.getElapsedTime();

  //cube.rotation.x += 0.02;
  //cube.rotation.y += 0.02;
  //cube.rotation.z += 0.02;
  //cube.position.x  = 100 + 20 * Math.sin(time * 3);

  // simple billboard method
  //text.quaternion.copy( camera.quaternion );

  for(var i = 0; i < words.length; i++){

    particles[i].quaternion.copy( camera.quaternion );

    particles[i].position.x -= 0.02;
    particles[i].position.y -= 0.02;
    particles[i].position.z -= 0.02;

    if(particles[i].box.explode > 0){

      particles[i].box.explode--;

      particles[i].box.object.material.wireframe = true;

      particles[i].scale.set( particles[i].scale.x * 1.02,particles[i].scale.y * 1.02, particles[i].scale.z * 1.02);

      particles[i].text.material.opacity -= 0.1;

    }else if(particles[i].box.intersected && particles[i].box.intersected > 0){

      particles[i].box.intersected--;

    }else{

      particles[i].box.intersected = false;

      particles[i].box.object.material.color.set( 0x00ff00 );
    }

  }

  // update the picking ray with the camera and mouse position
  raycaster.setFromCamera( center, camera );

  // calculate objects intersecting the picking ray
  var intersects = raycaster.intersectObjects( boxes );

  for ( var i = 0; i < intersects.length; i++ ) {

    // console.log('intersects', intersects);

    intersects[ i ].object.object.material.color.set( 0xff0000 );

    intersects[ i ].object.intersected = 300;

    intersects[ i ].object.explode = 300;
  }

  if(VR){

    effect.render(scene, camera);

  }else{

    renderer.render(scene, camera);
  }

}

function animate(t) {
  requestAnimationFrame(animate);

  var dt = clock.getDelta();

  update(dt);
  render(dt);
}

function fullscreen() {
  if (document.body.requestFullscreen) {
    document.body.requestFullscreen();
  } else if (document.body.msRequestFullscreen) {
    document.body.msRequestFullscreen();
  } else if (document.body.mozRequestFullScreen) {
    document.body.mozRequestFullScreen();
  } else if (document.body.webkitRequestFullscreen) {
    document.body.webkitRequestFullscreen();
  }
}

<|endoftext|>


<commit_before>// main.js
//

(function(window, $, undefined) {
  "use strict";

  $.fn.isOnScreen = function(){

    var viewport    = {};
    viewport.top    = $(window).scrollTop();
    viewport.bottom = viewport.top + $(window).height();

    var bounds    = {};
    bounds.top    = this.offset().top;
    bounds.bottom = bounds.top + this.outerHeight();

    return ((bounds.top <= viewport.bottom) && (bounds.bottom >= viewport.top));
  };

  // LOCAL STREAM
  // Prototype functionality

	var Local = {

    config: {
      newArticlesInMs: 7000,
      popInHangTimeMs: 5000
    },

    init: function() {
      Local.$page = $('#js-page');

      // Partials
      Local.partials = {
        masthead: '#js-masthead',
        footer: '#js-footer'
      };
      Local.numPartials           = Object.keys(Local.partials).length - 1;
      Local.numIncludedPartials   = 0;
      Local.awaitingNotification  = false;
      Local.updatesInserted       = false;
      Local.streamHeaderOffsetTop = 0;

      // Start
      Local.bindEvts();
      Local.includePartials();
    },

    bindEvts: function() {
      $.subscribe('partials.included', function() {
        $.unsubscribe('partials.included');
        Local.$page.addClass('page--rendered');
      });

      // Tappy.js
      $('a', Local.$page).each(function() {
        var href = $(this).attr('href');

        // Bind 'tap' event to anchors which go somewhere,
        // and preventDefault on all '#'-only anchors.
        if(href.indexOf('#') !== 0) {
          $(this).on('tap', function() {
            window.location.href = this.href;
          });
        } else {
          $(this).on('tap', function(e) {
            e.preventDefault();
          });
        }
      });

      // Show More button
      $('#js-smu', Local.$page).on('tap', function(e) {
        e.preventDefault();
        $('#js-sm-wrap', Local.$page).addClass('sm-wrap--show-all');
      });

      // Load New updates
      $('#js-stream-snu,#js-pop-in', Local.$page).on('tap', Local.loadNewUpdates);

      // Scroll Position
      // - London page
      if(Local.$page.data('page') === 'london') {

        Local.streamHeaderOffsetTop = $('#js-stream-header', Local.$page).offset().top;

        $(window).on('scroll', function() {

          // if( ( $(window).scrollTop() + $(window).height() ) >= Local.streamHeaderOffsetTop ) {
          if( $(window).scrollTop() >= Local.streamHeaderOffsetTop ) {
            setTimeout(Local.fireNewUpdatesNotification, Local.config.newArticlesInMs);
            $(window).off('scroll');
          }

        });

      }

    },

    includePartials: function() {
      $.each(Local.partials, function(partName) {
        var partPath = 'partials/' + partName + '.html';

        $.get( partPath )
          .done(function( data ) {
            $(Local.partials[ partName ], Local.$page).html( data );

            // If this is our last partial, emit an event
            if(Local.numIncludedPartials === Local.numPartials) {
              $.publish('partials.included');
            }
            Local.numIncludedPartials++;
          });
      });
    },

    fireNewUpdatesNotification: function() {
      $('#js-stream-snu', Local.$page).addClass('stream__snu--visible');
      Local.awaitingNotification = true;

      if( ! $('#js-stream-snu', Local.$page).isOnScreen() ) {

        // Make pop-in visible for Local.config.popInHangTimeMs
        $('#js-pop-in').addClass('pop-in--visible');
        setTimeout(function() {
          $('#js-pop-in').removeClass('pop-in--visible');
        }, Local.config.popInHangTimeMs);
      }
    },

    loadNewUpdates: function(e) {
      e.preventDefault();

      // Disable clicking DOM elements when a notification isn't waiting
      if( ! Local.awaitingNotification ) {
        return;
      }

      $('#js-stream-snu', Local.$page).removeClass('stream__snu--visible');
      $('#js-pop-in', Local.$page).removeClass('pop-in--visible');

      // Scroll before inserting if inserting from pop-in CTA,
      // otherwise straight call insertNewUpdates().
      if(e.target.id === 'js-pop-in') {

        $('html,body').animate({

          scrollTop: Local.streamHeaderOffsetTop

        }, 250, 'swing', function() {

          Local.insertNewUpdates();
          Local.updatesInserted = true;

        });

      } else {
        Local.insertNewUpdates();
      }
    },

    insertNewUpdates: function() {
      if(Local.updatesInserted) {
        return;
      }

      $('#js-new-updates', Local.$page).addClass('new-updates--visible');
      $('#js-sm-wrap', Local.$page).addClass('sm-wrap--after-snu');

      Local.awaitingNotification = false;

      Local.coolHotUpdates();
    },

    coolHotUpdates: function() {
      var $freshUnits = $('#js-new-updates .stream__unit--fresh', Local.$page);

      $freshUnits.each(function(i, elm) {

          var timeout = ( $freshUnits.length - i ) * 1500;

          setTimeout(function() {
            $(elm).removeClass('stream__unit--fresh');
          }, timeout);

        });
    }

  };

	$(Local.init);
})(window, jQuery);
<commit_msg>Update<commit_after>// main.js
//

(function(window, $, undefined) {
  "use strict";

  $.fn.isOnScreen = function(){

    var viewport    = {};
    viewport.top    = $(window).scrollTop();
    viewport.bottom = viewport.top + $(window).height();

    var bounds    = {};
    bounds.top    = this.offset().top;
    bounds.bottom = bounds.top + this.outerHeight();

    return ((bounds.top <= viewport.bottom) && (bounds.bottom >= viewport.top));
  };

  // LOCAL STREAM
  // Prototype functionality

	var Local = {

    config: {
      newArticlesInMs: 7000,
      popInHangTimeMs: 5000
    },

    init: function() {
      Local.$page = $('#js-page');

      // Partials
      Local.partials = {
        masthead: '#js-masthead',
        footer: '#js-footer'
      };
      Local.numPartials           = Object.keys(Local.partials).length - 1;
      Local.numIncludedPartials   = 0;
      Local.awaitingNotification  = false;
      Local.updatesInserted       = false;
      Local.streamHeaderOffsetTop = 0;

      // Start
      Local.bindEvts();
      Local.includePartials();
    },

    bindEvts: function() {
      $.subscribe('partials.included', function() {
        $.unsubscribe('partials.included');
        Local.$page.addClass('page--rendered');
      });

      // Tappy.js
      $('a', Local.$page).each(function() {
        var href = $(this).attr('href');

        // Bind 'tap' event to anchors which go somewhere,
        // and preventDefault on all '#'-only anchors.
        if(href.indexOf('#') !== 0) {
          $(this).on('tap', function() {
            window.location.href = this.href;
          });
        } else {
          $(this).on('tap', function(e) {
            e.preventDefault();
          });
        }
      });

      // Show More button
      $('#js-smu', Local.$page).on('tap', function(e) {
        e.preventDefault();
        $('#js-sm-wrap', Local.$page).addClass('sm-wrap--show-all');
      });

      // Load New updates
      $('#js-stream-snu,#js-pop-in', Local.$page).on('tap', Local.loadNewUpdates);

      // Scroll Position
      // - London page
      if(Local.$page.data('page') === 'london') {

        Local.streamHeaderOffsetTop = $('#js-stream-header', Local.$page).offset().top;

        $(window).on('scroll', function() {

          if( $(window).scrollTop() >= Local.streamHeaderOffsetTop ) {
            setTimeout(Local.fireNewUpdatesNotification, Local.config.newArticlesInMs);
            $(window).off('scroll');
          }

        });

      }

    },

    includePartials: function() {
      $.each(Local.partials, function(partName) {
        var partPath = 'partials/' + partName + '.html';

        $.get( partPath )
          .done(function( data ) {
            $(Local.partials[ partName ], Local.$page).html( data );

            // If this is our last partial, emit an event
            if(Local.numIncludedPartials === Local.numPartials) {
              $.publish('partials.included');
            }
            Local.numIncludedPartials++;
          });
      });
    },

    fireNewUpdatesNotification: function() {
      $('#js-stream-snu', Local.$page).addClass('stream__snu--visible');
      Local.awaitingNotification = true;

      if( ! $('#js-stream-snu', Local.$page).isOnScreen() ) {

        // Make pop-in visible for Local.config.popInHangTimeMs
        $('#js-pop-in').addClass('pop-in--visible');
        setTimeout(function() {
          $('#js-pop-in').removeClass('pop-in--visible');
        }, Local.config.popInHangTimeMs);
      }
    },

    loadNewUpdates: function(e) {
      e.preventDefault();

      // Disable clicking DOM elements when a notification isn't waiting
      if( ! Local.awaitingNotification ) {
        return;
      }

      $('#js-stream-snu', Local.$page).removeClass('stream__snu--visible');
      $('#js-pop-in', Local.$page).removeClass('pop-in--visible');

      // Scroll before inserting if inserting from pop-in CTA,
      // otherwise straight call insertNewUpdates().
      if(e.target.id === 'js-pop-in') {

        $('html,body').animate({

          scrollTop: Local.streamHeaderOffsetTop

        }, 250, 'swing', function() {

          Local.insertNewUpdates();
          Local.updatesInserted = true;

        });

      } else {
        Local.insertNewUpdates();
      }
    },

    insertNewUpdates: function() {
      if(Local.updatesInserted) {
        return;
      }

      $('#js-new-updates', Local.$page).addClass('new-updates--visible');
      $('#js-sm-wrap', Local.$page).addClass('sm-wrap--after-snu');

      Local.awaitingNotification = false;

      Local.coolHotUpdates();
    },

    coolHotUpdates: function() {
      var $freshUnits = $('#js-new-updates .stream__unit--fresh', Local.$page);

      $freshUnits.each(function(i, elm) {

          var timeout = ( $freshUnits.length - i ) * 1500;

          setTimeout(function() {
            $(elm).removeClass('stream__unit--fresh');
          }, timeout);

        });
    }

  };

	$(Local.init);
})(window, jQuery);
<|endoftext|>


<commit_before>$(function(){

	// main navigation
	$("#sections").tabs({
		"show":300,
		"activate":function(event, ui){
			$.Storage.saveItem('navtab', ui.newPanel.attr('id'));
			}
		});
	$('ul#nav')
		.css('width', $.Storage.loadItem('navsize'))
		.resizable({
			"minWidth":150,
			"maxWidth":700,
			"handles":"e",
			"stop":function(){
				$.Storage.saveItem('navsize', $(this).width());
				}
			});
	var lastTab = $.Storage.loadItem('navtab');
	if(lastTab)
		$('a[href="#'+lastTab+'"]').trigger('click');

	// sortables
    $("ul.section").sortable({
    	"revert":true,
    	"items":"li:not(.empty)"
    	});

    // droppables
	// $("ul.sections_nav li.droppable a").droppable({
	// 	"tolerance":"pointer",
	// 	"accept":"ul.sortable li",
	// 	"drop":function(event, ui){
	// 		$(this).effect('highlight');//.trigger('click');
	// 		//var listaDestino = destinationTab.find();

	// 		}
	// 	});

	// handle uploads
	$('#arriving').hide();
	$(document).filedrop({
		"url":"/library",
		"paramname":"musica",
		"maxfilesize":20,
		"allowedfiletypes":['audio/webm','audio/ogg','audio/mpeg','audio/mp3'],
	    "uploadFinished":function(i,file,response){
			//$('#inbox').removeClass('ocupado');
			update();
			},
		"drop":function(){
			//$('#inbox').addClass('ocupado');
			},
		"rename":function(nome){
			return escape(nome);
			},
		"docOver":function(){
			$('#arriving').fadeIn();
			},
		"docLeave":function(){
			$('#arriving').fadeOut();
			},
		"error":function(err, file){}
		});

	// loads library
	var updating;
	var library = [];
	var lastLibEtag = '';
	function update(){
		clearInterval(updating);
		loadsLibrary();
		updating = setInterval(loadsLibrary, 3000);
		}
	function loadsLibrary(){
		var jqXHR = $.getJSON('/library/library.json', function(data){
			var libEtag = jqXHR.getResponseHeader('Etag');
			if(libEtag != lastLibEtag)
				{
				library = data;
				updateList('library', library);
				}
	        lastLibEtag = libEtag;
			});
		}
	function updateList(listAlias, listSongs){
		var list = $('ul#'+listAlias);
		if(listSongs.length)
			list.html(listSongs.map(function(song){
				var picture = song.picture.length
					? ''
					: '';
				var artist = typeof song.artist != 'undefined' && song.artist.length
					? song.artist.join(', ')
					: '';
				var genre = typeof song.genre != 'undefined' && song.genre.length
					? song.genre.join(', ')
					: '';
				return '
'
						+''+picture+''
						+'▸'
						+''+song.title+''
						+''+artist+''
						+''+genre+''
						+''+song.album+''
						+''+song.year+''
					+'
';
				}).join(''));
		else
			{
			list.html('
add songs here
');
			size();
			}
		}
	$('ul.section').each(function(){
		updateList(this.id, []);
		});
	update();
	function getSong(time){
		for(var i=0,l=library.length;i<l;i++)
			if(library[i].timeAdded == time)
				return library[i];
		}

	// lists events
	$('ul.section li, ul.section span.play').live('mouseenter', function(){
		$(this).addClass('over');
		});
	$('ul.section li, ul.section span.play').live('mouseleave', function(){
		$(this).removeClass('over');
		});
	$('ul.section span.play').live('click', function(){
		play($(this).closest('li').attr('id').replace('song_',''));
		});

	// view switches
	var vbts = $('ul.views button');
	var allViewClasses = [];
	vbts.each(function(){
		allViewClasses.push(this.className);
		});
	allViewClasses = allViewClasses.join(' ');
	vbts.click(function(){
		var sectionId = $('ul.section:visible').removeClass(allViewClasses).addClass(this.className).attr('id');
		$.Storage.saveItem(sectionId+'_view', this.className);
		});
	$('ul.section').each(function(){
		var view = $.Storage.loadItem(this.id+'_view');
		if(view)
			$(this).addClass(view);
		else
			vbts.filter(':first').trigger('click');
		});

	// setup the player
	var audio = false;
	function play(id){
		$('#player').animate({"height":playerHeight}, function(){size();});
		$('li.current').removeClass('current');
		$('#song_'+id).addClass('current');
		var song = getSong(id);
		$('title').text('▸'+song.title);
		if(audio === false)
			audio = a[0];
		audio.load('/library/'+song.fileName);
		audio.play();
		}
	function playNext(){
		var current = $('li.current');
		var next = current.next();
		if(!next.length)
			next = current.siblings('li').first();
		play(next.get(0).id.replace('song_', ''));
		}
	function playPrevious(){
		var current = $('li.current');
		var prev = current.prev();
		if(!prev.length)
			prev = current.siblings('li').last();
		play(prev.get(0).id.replace('song_', ''));
		}
    var a = audiojs.createAll({
		"trackEnded":playNext
		});

    // key bindings
	$(document).keydown(function(e){
		if(audio === false)
			return;

		var unicode = e.charCode
			? e.charCode
			: e.keyCode;

		// right arrow
		if(unicode == 39)
			playNext();

		// left arrow
		else if(unicode == 37)
			playPrevious();

		// spacebar
		else if(unicode == 32)
			audio.playPause();
		});

	// handle resize
	function size(){
		var total = $("html").height();
		var header = $("#header").height();
		var player = $("#player").height();
		var avaliable = total - header - player;
	    $("#sections").height(avaliable);
	    $("#arriving").css('line-height', total+'px');
	    $("li.empty").css('line-height', avaliable+'px');
	    $("#player .scrubber").width($("html").width() - 200);
		}
	$(window).resize(size);
	var playerHeight = $('#player').height();
	$('#player').height(0);
	size();
	});<commit_msg>Text formatting<commit_after>$(function(){

	// main navigation
	$("#sections").tabs({
		"show":300,
		"activate":function(event, ui){
			$.Storage.saveItem('navtab', ui.newPanel.attr('id'));
			}
		});
	$('ul#nav')
		.css('width', $.Storage.loadItem('navsize'))
		.resizable({
			"minWidth":150,
			"maxWidth":700,
			"handles":"e",
			"stop":function(){
				$.Storage.saveItem('navsize', $(this).width());
				}
			});
	var lastTab = $.Storage.loadItem('navtab');
	if(lastTab)
		$('a[href="#'+lastTab+'"]').trigger('click');

	// sortables
    $("ul.section").sortable({
    	"revert":true,
    	"items":"li:not(.empty)"
    	});

    // droppables
	// $("ul.sections_nav li.droppable a").droppable({
	// 	"tolerance":"pointer",
	// 	"accept":"ul.sortable li",
	// 	"drop":function(event, ui){
	// 		$(this).effect('highlight');//.trigger('click');
	// 		//var listaDestino = destinationTab.find();

	// 		}
	// 	});

	// handle uploads
	$('#arriving').hide();
	$(document).filedrop({
		"url":"/library",
		"paramname":"musica",
		"maxfilesize":20,
		"allowedfiletypes":['audio/webm','audio/ogg','audio/mpeg','audio/mp3'],
	    "uploadFinished":function(i,file,response){
			//$('#inbox').removeClass('ocupado');
			update();
			},
		"drop":function(){
			//$('#inbox').addClass('ocupado');
			},
		"rename":function(nome){
			return escape(nome);
			},
		"docOver":function(){
			$('#arriving').fadeIn();
			},
		"docLeave":function(){
			$('#arriving').fadeOut();
			},
		"error":function(err, file){}
		});

	// loads library
	var updating;
	var library = [];
	var lastLibEtag = '';
	function update(){
		clearInterval(updating);
		loadsLibrary();
		updating = setInterval(loadsLibrary, 3000);
		}
	function loadsLibrary(){
		var jqXHR = $.getJSON('/library/library.json', function(data){
			var libEtag = jqXHR.getResponseHeader('Etag');
			if(libEtag != lastLibEtag)
				{
				library = data;
				updateList('library', library);
				}
	        lastLibEtag = libEtag;
			});
		}
	function updateList(listAlias, listSongs){
		var list = $('ul#'+listAlias);
		if(listSongs.length)
			list.html(listSongs.map(function(song){
				var picture = song.picture.length
					? ''
					: '';
				var artist = typeof song.artist != 'undefined' && song.artist.length
					? song.artist.join(', ')
					: '';
				var genre = typeof song.genre != 'undefined' && song.genre.length
					? song.genre.join(', ')
					: '';
				return '
'
						+''+picture+''
						+'▸'
						+''+song.title+''
						+''+artist+''
						+''+genre+''
						+''+song.album+''
						+''+song.year+''
					+'
';
				}).join(''));
		else
			{
			list.html('
add songs here
');
			size();
			}
		}
	$('ul.section').each(function(){
		updateList(this.id, []);
		});
	update();
	function getSong(time){
		for(var i=0,l=library.length;i<l;i++)
			if(library[i].timeAdded == time)
				return library[i];
		}

	// lists events
	$('ul.section li, ul.section span.play').live('mouseenter', function(){
		$(this).addClass('over');
		});
	$('ul.section li, ul.section span.play').live('mouseleave', function(){
		$(this).removeClass('over');
		});
	$('ul.section span.play').live('click', function(){
		play($(this).closest('li').attr('id').replace('song_',''));
		});

	// view switches
	var vbts = $('ul.views button');
	var allViewClasses = [];
	vbts.each(function(){
		allViewClasses.push(this.className);
		});
	allViewClasses = allViewClasses.join(' ');
	vbts.click(function(){
		var sectionId = $('ul.section:visible').removeClass(allViewClasses).addClass(this.className).attr('id');
		$.Storage.saveItem(sectionId+'_view', this.className);
		});
	$('ul.section').each(function(){
		var view = $.Storage.loadItem(this.id+'_view');
		if(view)
			$(this).addClass(view);
		else
			vbts.filter(':first').trigger('click');
		});

	// setup the player
	var audio = false;
	function play(id){
		$('#player').animate({"height":playerHeight}, function(){size();});
		$('li.current').removeClass('current');
		$('#song_'+id).addClass('current');
		var song = getSong(id);
		$('title').text('▸ '+song.title);
		if(audio === false)
			audio = a[0];
		audio.load('/library/'+song.fileName);
		audio.play();
		}
	function playNext(){
		var current = $('li.current');
		var next = current.next();
		if(!next.length)
			next = current.siblings('li').first();
		play(next.get(0).id.replace('song_', ''));
		}
	function playPrevious(){
		var current = $('li.current');
		var prev = current.prev();
		if(!prev.length)
			prev = current.siblings('li').last();
		play(prev.get(0).id.replace('song_', ''));
		}
    var a = audiojs.createAll({
		"trackEnded":playNext
		});

    // key bindings
	$(document).keydown(function(e){
		if(audio === false)
			return;

		var unicode = e.charCode
			? e.charCode
			: e.keyCode;

		// right arrow
		if(unicode == 39)
			playNext();

		// left arrow
		else if(unicode == 37)
			playPrevious();

		// spacebar
		else if(unicode == 32)
			audio.playPause();
		});

	// handle resize
	function size(){
		var total = $("html").height();
		var header = $("#header").height();
		var player = $("#player").height();
		var avaliable = total - header - player;
	    $("#sections").height(avaliable);
	    $("#arriving").css('line-height', total+'px');
	    $("li.empty").css('line-height', avaliable+'px');
	    $("#player .scrubber").width($("html").width() - 200);
		}
	$(window).resize(size);
	var playerHeight = $('#player').height();
	$('#player').height(0);
	size();
	});<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import Relay from 'react-relay/classic';

import Button from '../../shared/Button';

import FlashesStore from '../../../stores/FlashesStore';

import OrganizationMemberDeleteMutation from '../../../mutations/OrganizationMemberDelete';

class Remove extends React.PureComponent {
  static displayName = "Member.Edit.Remove";

  static propTypes = {
    viewer: PropTypes.shape({
      user: PropTypes.shape({
        id: PropTypes.string.isRequired
      }).isRequired
    }).isRequired,
    organizationMember: PropTypes.shape({
      uuid: PropTypes.string.isRequired,
      permissions: PropTypes.object.isRequired,
      user: PropTypes.shape({
        id: PropTypes.string.isRequired
      }).isRequired
    }),
    isSelf: PropTypes.bool.isRequired
  };

  static contextTypes = {
    router: PropTypes.object.isRequired
  };

  state = {
    removing: false
  };

  render() {
    // Don't show the remove panel if you can't actually remove them
    if (!this.props.organizationMember.permissions.organizationMemberDelete.allowed) {
      return null;
    }

    const loading = this.state.removing && (
      this.props.isSelf
        ? 'Leaving Organization…'
        : 'Removing from Organization…'
    );

    return (
      <Button
        theme="error"
        loading={loading}
        onClick={this.handleRemoveClick}
      >
        {
          this.props.isSelf
            ? 'Leave Organization'
            : 'Remove from Organization'
        }
      </Button>
    );
  }

  handleRemoveClick = () => {
    const message = this.props.isSelf
      ? 'Removing yourself will immediately revoke your access to this organization.'
      : 'Removing this user will immediately revoke their access to this organization.';

    if (confirm(message)) {
      this.performRemove();
    }
  };

  performRemove = () => {
    // Show the removing indicator
    this.setState({ removing: true });

    const mutation = new OrganizationMemberDeleteMutation({
      organizationMember: this.props.organizationMember
    });

    // Run the mutation
    Relay.Store.commitUpdate(mutation, {
      onSuccess: this.handleMutationSuccess,
      onFailure: this.handleMutationFailure
    });
  };

  handleMutationSuccess = (response) => {
    this.setState({ removing: false });

    if (response.organizationMemberDelete.user.id === this.props.viewer.user.id) {
      // if we remove ourself, kickflip outta there
      // because we won't have access anymore!
      window.location = '/';
    } else {
      this.context.router.push(`/organizations/${response.organizationMemberDelete.organization.slug}/users`);
    }
  };

  handleMutationFailure = (transaction) => {
    this.setState({ removing: false });

    FlashesStore.flash(FlashesStore.ERROR, transaction.getError());
  };
}

export default Relay.createContainer(Remove, {
  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        user {
          id
        }
      }
    `,
    organizationMember: () => Relay.QL`
      fragment on OrganizationMember {
        uuid
        user {
          id
        }
        permissions {
          organizationMemberDelete {
            allowed
            message
          }
        }
        ${OrganizationMemberDeleteMutation.getFragment('organizationMember')}
      }
    `
  }
});
<commit_msg>De-emphasise "leave organization" button<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import Relay from 'react-relay/classic';

import Button from '../../shared/Button';

import FlashesStore from '../../../stores/FlashesStore';

import OrganizationMemberDeleteMutation from '../../../mutations/OrganizationMemberDelete';

class Remove extends React.PureComponent {
  static displayName = "Member.Edit.Remove";

  static propTypes = {
    viewer: PropTypes.shape({
      user: PropTypes.shape({
        id: PropTypes.string.isRequired
      }).isRequired
    }).isRequired,
    organizationMember: PropTypes.shape({
      uuid: PropTypes.string.isRequired,
      permissions: PropTypes.object.isRequired,
      user: PropTypes.shape({
        id: PropTypes.string.isRequired
      }).isRequired
    }),
    isSelf: PropTypes.bool.isRequired
  };

  static contextTypes = {
    router: PropTypes.object.isRequired
  };

  state = {
    removing: false
  };

  render() {
    // Don't show the remove panel if you can't actually remove them
    if (!this.props.organizationMember.permissions.organizationMemberDelete.allowed) {
      return null;
    }

    const loading = this.state.removing && (
      this.props.isSelf
        ? 'Leaving Organization…'
        : 'Removing from Organization…'
    );

    return (
      <Button
        theme="default"
        outline={true}
        loading={loading}
        onClick={this.handleRemoveClick}
      >
        {
          this.props.isSelf
            ? 'Leave Organization'
            : 'Remove from Organization'
        }
      </Button>
    );
  }

  handleRemoveClick = () => {
    const message = this.props.isSelf
      ? 'Removing yourself will immediately revoke your access to this organization.'
      : 'Removing this user will immediately revoke their access to this organization.';

    if (confirm(message)) {
      this.performRemove();
    }
  };

  performRemove = () => {
    // Show the removing indicator
    this.setState({ removing: true });

    const mutation = new OrganizationMemberDeleteMutation({
      organizationMember: this.props.organizationMember
    });

    // Run the mutation
    Relay.Store.commitUpdate(mutation, {
      onSuccess: this.handleMutationSuccess,
      onFailure: this.handleMutationFailure
    });
  };

  handleMutationSuccess = (response) => {
    this.setState({ removing: false });

    if (response.organizationMemberDelete.user.id === this.props.viewer.user.id) {
      // if we remove ourself, kickflip outta there
      // because we won't have access anymore!
      window.location = '/';
    } else {
      this.context.router.push(`/organizations/${response.organizationMemberDelete.organization.slug}/users`);
    }
  };

  handleMutationFailure = (transaction) => {
    this.setState({ removing: false });

    FlashesStore.flash(FlashesStore.ERROR, transaction.getError());
  };
}

export default Relay.createContainer(Remove, {
  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        user {
          id
        }
      }
    `,
    organizationMember: () => Relay.QL`
      fragment on OrganizationMember {
        uuid
        user {
          id
        }
        permissions {
          organizationMemberDelete {
            allowed
            message
          }
        }
        ${OrganizationMemberDeleteMutation.getFragment('organizationMember')}
      }
    `
  }
});
<|endoftext|>


<commit_before>$.extend(true, window, {
  aposPages: {
    groups: {},
    // Return a page type object if one was configured for the given type name.
    // JavaScript doesn't iterate over object properties in a defined order,
    // so we maintain the list of types as a flat array. This convenience method
    // prevents this from being inconvenient and allows us to choose to do more
    // optimization later.

    getType: function(name) {
      return _.find(apos.data.aposPages.types, function(item) {
        return item.name === name;
      });
    },

    addType: function(type) {
      apos.data.aposPages.types.push(type);
    },

    // Replace a type with a new type object. Typically this is done to replace
    // a type object we got from the server (with just a name and a label) with a
    // type object that includes a settings property with functions for a page
    // settings dialog and so on.
    //
    // We replace rather than extending so that closures with references
    // to "self" still do the right thing.

    replaceType: function(name, object) {
      var newTypes = [];
      for (var i in apos.data.aposPages.types) {
        var type = apos.data.aposPages.types[i];
        if (type.name === name) {
          object.name = type.name;
          object.label = type.label;
          newTypes.push(object);
        } else {
          newTypes.push(type);
        }
      }
      apos.data.aposPages.types = newTypes;
    },

    // Right now this is called even for noneditors, but we don't put the
    // menu dropdown markup in the admin bar for them. TODO: we need to better
    // separate globally useful stuff like apos.data.aposPages.types from
    // clearly editor-specific stuff like editing page settings
    enableUI: function(options) {

      if (!options) {
        options = {};
      }
      if (!options.root) {
        options.root = apos.data.aposPages.root;
      }

      // Allow / or /pages/ to be specified, just quietly fix it
      options.root = options.root.replace(/\/$/, '');

      // Available in other scopes
      aposPages.options = options;

      // Shared state closure for the page settings dialogs (new and edit)
      (function() {
        var oldTypeName;
        var typeData = {};
        // Active dialog
        var $el;

        $('body').on('click', '.apos-new-page', function() {
          var parent = $(this).data('slug');
          $el = apos.modalFromTemplate('.apos-new-page-settings', {
            init: function(callback) {
              populateType();
              refreshType();
              return callback(null);
            },
            save: save
          });
          function save(callback) {
            return addOrEdit('new', { parent: parent }, callback);
          }
          return false;
        });

        $('body').on('click', '.apos-edit-page', function() {
          var slug = $(this).data('slug');
          $el = apos.modalFromTemplate('.apos-edit-page-settings', {
            save: save,
            init: function(callback) {
              populateType();
              $el.find('[name=type]').val(apos.data.aposPages.page.type);
              $el.find('[name=title]').val(apos.data.aposPages.page.title);
              $el.find('[name=slug]').val(slug);
              refreshType();

              // Watch the title for changes, update the slug - but only if
              // the slug was in sync with the title to start with

              var $slug = $el.find('[name=slug]');
              var $title = $el.find('[name=title]');

              apos.suggestSlugOnTitleEdits($slug, $title);

              return callback(null);
            }
          });
          function save(callback) {
            return addOrEdit('edit', { slug: slug }, callback);
          }
          return false;
        });

        function populateType() {
          var $type = $el.find('[name=type]');
          $type.html('');
          _.each(apos.data.aposPages.menu || apos.data.aposPages.types, function(type) {
            var $option = $('<option></option>');
            $option.text(type.label);
            $option.attr('value', type.name);
            $type.append($option);
          });
          // Some types have custom settings of their own. When appropriate
          // instantiate the additional template and make it part of the form.
          // If the type has a selector for a settings template (settings.sel)
          // then it must also have an unserialize function to populate that
          // template's form fields from an object and a serialize function
          // to return an object based on the form fields. You can set up
          // client side javascript to assist with the use of the fields in
          // your unserialize function.

          $el.on('change', '[name=type]', function() {
            refreshType();
          });
        }

        function refreshType() {
          var typeName = $el.find('[name=type]').val();
          if (oldTypeName) {
            var oldType = aposPages.getType(oldTypeName);
            if (oldType.settings) {
              typeData[oldTypeName] = oldType.settings.serialize($el, $el.find('[data-type-details]'));
            }
            $el.find('[data-type-details]').html('');
          }
          oldTypeName = typeName;
          var type = aposPages.getType(typeName);

          if (type.settings) {
            var $typeEl = apos.fromTemplate('.apos-page-settings-' + type._css);
            $el.find('[data-type-details]').html($typeEl);
            var typeDefaults = typeData[typeName];
            if (!typeDefaults) {
              if (apos.data.aposPages.page.type === type.name) {
                typeDefaults = apos.data.aposPages.page.typeSettings;
              }
            }
            if (!typeDefaults) {
              typeDefaults = {};
            }
            type.settings.unserialize(typeDefaults, $el, $el.find('[data-type-details]'));
          }
        }

        function addOrEdit(action, options, callback) {
          var typeName = $el.find('[name=type]').val();
          var type = aposPages.getType(typeName);
          var data = {
            title: $el.find('[name=title]').val(),
            slug: $el.find('[name=slug]').val(),
            type: $el.find('[name=type]').val()
          };
          _.extend(data, { parent: options.parent, originalSlug: options.slug });
          if (type.settings && type.settings.serialize) {
            data.typeSettings = type.settings.serialize($el, $el.find('[data-type-details]'));
          }
          $.ajax(
            {
              url: '/apos-pages/' + action,
              data: data,
              type: 'POST',
              dataType: 'json',
              success: function(data) {
                window.location.href = aposPages.options.root + data.slug;
              },
              error: function() {
                alert('Server error');
                callback('Server error');
              }
            }
          );
          return false;
        }
      })();

      $('body').on('click', '[data-reorganize-page]', function() {
        var $tree;
        var $el = apos.modalFromTemplate('.apos-reorganize-page', {
          init: function(callback) {
            $tree = $el.find('[data-tree]');
            $tree.tree({
              data: [],
              autoOpen: 3,
              dragAndDrop: true,
              onCanMoveTo: function(moved_node, target_node, position) {
                // Cannot create peers of root
                if ((target_node.slug === '/') && (position !== 'inside')) {
                  return false;
                }
                return true;
              }
            });
            $tree.on('tree.move', function(e) {
              e.preventDefault();
              var data = {
                  moved: e.move_info.moved_node.slug,
                  target: e.move_info.target_node.slug,
                  position: e.move_info.position
              };
              apos.log('ajax call beginning');
              $.ajax({
                url: '/apos-pages/move-jqtree',
                data: data,
                type: 'POST',
                dataType: 'json',
                success: function() {
                  apos.log('success called');
                  e.move_info.do_move();
                },
                error: function() {
                  apos.log('error called');
                  // This didn't work, probably because something
                  // else has changed in the page tree. Refreshing
                  // is an appropriate response
                  apos.afterYield(function() { reload(null); });
                }
              });
            });
            reload(callback);
          },
          // After a reorg the page URL may have changed, be prepared to
          // navigate there or to the home page or just refresh to reflect
          // possible new tabs
          afterHide: function(callback) {
            var page = apos.data.aposPages.page;
            var _id = page._id;
            $.get('/apos-pages/info', { _id: _id }, function(data) {
              var newPathname = (apos.data.aposPages.root + data.slug).replace(/^\/\//, '/');
              if (window.location.pathname === newPathname) {
                apos.change('tree');
                return callback();
              } else {
                // Navigates away, so don't call the callback
                window.location.pathname = newPathname;
              }
            }).error(function() {
              // If the page no longer exists, navigate away to home page
              window.location.pathname = apos.data.aposPages.root;
            });
          }
        });
        function reload(callback) {
          $.getJSON('/apos-pages/get-jqtree', function(data) {
            $tree.tree('loadData', data);
            if (callback) {
              return callback();
            }
          }).error(function() {
            alert('The server did not respond or you do not have the appropriate privileges.');
            $el.trigger('aposModalHide');
          });
        }
      });

      $('body').on('click', '.apos-delete-page', function() {
        var slug = $(this).data('slug');
        if (confirm('Move this page to the trash?')) {
          $.ajax(
            {
              url: '/apos-pages/delete',
              data: {
                slug: slug
              },
              type: 'POST',
              dataType: 'json',
              success: function(data) {
                if(data.status === 'ok') {
                  alert('Moved to the trash. Select "Reorganize" from the "Page" menu to drag it back out.');
                  window.location.href = aposPages.options.root + data.parent;
                } else {
                  alert(data.status);
                }
              },
              error: function() {
                alert('Server error');
              }
            }
          );
          return false;
        }
      });
    }
  }
});

<commit_msg>No confirmation to move to trash, since you can always move back<commit_after>$.extend(true, window, {
  aposPages: {
    groups: {},
    // Return a page type object if one was configured for the given type name.
    // JavaScript doesn't iterate over object properties in a defined order,
    // so we maintain the list of types as a flat array. This convenience method
    // prevents this from being inconvenient and allows us to choose to do more
    // optimization later.

    getType: function(name) {
      return _.find(apos.data.aposPages.types, function(item) {
        return item.name === name;
      });
    },

    addType: function(type) {
      apos.data.aposPages.types.push(type);
    },

    // Replace a type with a new type object. Typically this is done to replace
    // a type object we got from the server (with just a name and a label) with a
    // type object that includes a settings property with functions for a page
    // settings dialog and so on.
    //
    // We replace rather than extending so that closures with references
    // to "self" still do the right thing.

    replaceType: function(name, object) {
      var newTypes = [];
      for (var i in apos.data.aposPages.types) {
        var type = apos.data.aposPages.types[i];
        if (type.name === name) {
          object.name = type.name;
          object.label = type.label;
          newTypes.push(object);
        } else {
          newTypes.push(type);
        }
      }
      apos.data.aposPages.types = newTypes;
    },

    // Right now this is called even for noneditors, but we don't put the
    // menu dropdown markup in the admin bar for them. TODO: we need to better
    // separate globally useful stuff like apos.data.aposPages.types from
    // clearly editor-specific stuff like editing page settings
    enableUI: function(options) {

      if (!options) {
        options = {};
      }
      if (!options.root) {
        options.root = apos.data.aposPages.root;
      }

      // Allow / or /pages/ to be specified, just quietly fix it
      options.root = options.root.replace(/\/$/, '');

      // Available in other scopes
      aposPages.options = options;

      // Shared state closure for the page settings dialogs (new and edit)
      (function() {
        var oldTypeName;
        var typeData = {};
        // Active dialog
        var $el;

        $('body').on('click', '.apos-new-page', function() {
          var parent = $(this).data('slug');
          $el = apos.modalFromTemplate('.apos-new-page-settings', {
            init: function(callback) {
              populateType();
              refreshType();
              return callback(null);
            },
            save: save
          });
          function save(callback) {
            return addOrEdit('new', { parent: parent }, callback);
          }
          return false;
        });

        $('body').on('click', '.apos-edit-page', function() {
          var slug = $(this).data('slug');
          $el = apos.modalFromTemplate('.apos-edit-page-settings', {
            save: save,
            init: function(callback) {
              populateType();
              $el.find('[name=type]').val(apos.data.aposPages.page.type);
              $el.find('[name=title]').val(apos.data.aposPages.page.title);
              $el.find('[name=slug]').val(slug);
              refreshType();

              // Watch the title for changes, update the slug - but only if
              // the slug was in sync with the title to start with

              var $slug = $el.find('[name=slug]');
              var $title = $el.find('[name=title]');

              apos.suggestSlugOnTitleEdits($slug, $title);

              return callback(null);
            }
          });
          function save(callback) {
            return addOrEdit('edit', { slug: slug }, callback);
          }
          return false;
        });

        function populateType() {
          var $type = $el.find('[name=type]');
          $type.html('');
          _.each(apos.data.aposPages.menu || apos.data.aposPages.types, function(type) {
            var $option = $('<option></option>');
            $option.text(type.label);
            $option.attr('value', type.name);
            $type.append($option);
          });
          // Some types have custom settings of their own. When appropriate
          // instantiate the additional template and make it part of the form.
          // If the type has a selector for a settings template (settings.sel)
          // then it must also have an unserialize function to populate that
          // template's form fields from an object and a serialize function
          // to return an object based on the form fields. You can set up
          // client side javascript to assist with the use of the fields in
          // your unserialize function.

          $el.on('change', '[name=type]', function() {
            refreshType();
          });
        }

        function refreshType() {
          var typeName = $el.find('[name=type]').val();
          if (oldTypeName) {
            var oldType = aposPages.getType(oldTypeName);
            if (oldType.settings) {
              typeData[oldTypeName] = oldType.settings.serialize($el, $el.find('[data-type-details]'));
            }
            $el.find('[data-type-details]').html('');
          }
          oldTypeName = typeName;
          var type = aposPages.getType(typeName);

          if (type.settings) {
            var $typeEl = apos.fromTemplate('.apos-page-settings-' + type._css);
            $el.find('[data-type-details]').html($typeEl);
            var typeDefaults = typeData[typeName];
            if (!typeDefaults) {
              if (apos.data.aposPages.page.type === type.name) {
                typeDefaults = apos.data.aposPages.page.typeSettings;
              }
            }
            if (!typeDefaults) {
              typeDefaults = {};
            }
            type.settings.unserialize(typeDefaults, $el, $el.find('[data-type-details]'));
          }
        }

        function addOrEdit(action, options, callback) {
          var typeName = $el.find('[name=type]').val();
          var type = aposPages.getType(typeName);
          var data = {
            title: $el.find('[name=title]').val(),
            slug: $el.find('[name=slug]').val(),
            type: $el.find('[name=type]').val()
          };
          _.extend(data, { parent: options.parent, originalSlug: options.slug });
          if (type.settings && type.settings.serialize) {
            data.typeSettings = type.settings.serialize($el, $el.find('[data-type-details]'));
          }
          $.ajax(
            {
              url: '/apos-pages/' + action,
              data: data,
              type: 'POST',
              dataType: 'json',
              success: function(data) {
                window.location.href = aposPages.options.root + data.slug;
              },
              error: function() {
                alert('Server error');
                callback('Server error');
              }
            }
          );
          return false;
        }
      })();

      $('body').on('click', '[data-reorganize-page]', function() {
        var $tree;
        var $el = apos.modalFromTemplate('.apos-reorganize-page', {
          init: function(callback) {
            $tree = $el.find('[data-tree]');
            $tree.tree({
              data: [],
              autoOpen: 3,
              dragAndDrop: true,
              onCanMoveTo: function(moved_node, target_node, position) {
                // Cannot create peers of root
                if ((target_node.slug === '/') && (position !== 'inside')) {
                  return false;
                }
                return true;
              }
            });
            $tree.on('tree.move', function(e) {
              e.preventDefault();
              var data = {
                  moved: e.move_info.moved_node.slug,
                  target: e.move_info.target_node.slug,
                  position: e.move_info.position
              };
              apos.log('ajax call beginning');
              $.ajax({
                url: '/apos-pages/move-jqtree',
                data: data,
                type: 'POST',
                dataType: 'json',
                success: function() {
                  apos.log('success called');
                  e.move_info.do_move();
                },
                error: function() {
                  apos.log('error called');
                  // This didn't work, probably because something
                  // else has changed in the page tree. Refreshing
                  // is an appropriate response
                  apos.afterYield(function() { reload(null); });
                }
              });
            });
            reload(callback);
          },
          // After a reorg the page URL may have changed, be prepared to
          // navigate there or to the home page or just refresh to reflect
          // possible new tabs
          afterHide: function(callback) {
            var page = apos.data.aposPages.page;
            var _id = page._id;
            $.get('/apos-pages/info', { _id: _id }, function(data) {
              var newPathname = (apos.data.aposPages.root + data.slug).replace(/^\/\//, '/');
              if (window.location.pathname === newPathname) {
                apos.change('tree');
                return callback();
              } else {
                // Navigates away, so don't call the callback
                window.location.pathname = newPathname;
              }
            }).error(function() {
              // If the page no longer exists, navigate away to home page
              window.location.pathname = apos.data.aposPages.root;
            });
          }
        });
        function reload(callback) {
          $.getJSON('/apos-pages/get-jqtree', function(data) {
            $tree.tree('loadData', data);
            if (callback) {
              return callback();
            }
          }).error(function() {
            alert('The server did not respond or you do not have the appropriate privileges.');
            $el.trigger('aposModalHide');
          });
        }
      });

      $('body').on('click', '.apos-delete-page', function() {
        var slug = $(this).data('slug');
        $.ajax(
          {
            url: '/apos-pages/delete',
            data: {
              slug: slug
            },
            type: 'POST',
            dataType: 'json',
            success: function(data) {
              if(data.status === 'ok') {
                alert('Moved to the trash. Select "Reorganize" from the "Page" menu to drag it back out.');
                window.location.href = aposPages.options.root + data.parent;
              } else {
                alert(data.status);
              }
            },
            error: function() {
              alert('Server error');
            }
          }
        );
        return false;
      });
    }
  }
});

<|endoftext|>


<commit_before>var mediaList = new Media.Collection();
var mediaDB   = new Media.List({collection: mediaList,
                                fixed: true,
                                name: 'Media Database'});
var Universe  = new Media.Universe();
var Schedule  = new Media.Schedule();

var DEBUG = false;
if (DEBUG) {
    var i = 0;
    cols = [mediaList, Universe, Schedule];
    setInterval (function () {
        for (col in cols) {
            c = cols[col];
            c.create({name: i++, file: 'file' + i, duration: 293829829});
            console.log ('hello, ' + col + ' : ', c.models.length,
                         _.zip(c.pluck('file'), c.pluck('name'), c.pluck('_id')));
        }
    }, 5000);
}

Universe.bind ('all', function (arg) {
    console.log ('UNIVERSE:' , arg);
});

Universe.bind ('add', function (arg) {
    console.log('something happened in the universe',Universe, 'ADD', arg);
    console.trace ();
});

Universe.bind ('create', function (arg) {
    console.log('something happened in the universe',Universe, 'CREATE', arg);
    console.trace ();
});

var appCollection = new App.Collection();

window.appCollection = appCollection;
window.appstatus = new App.Status();
window.framestatus = new App.ProgressStatus();

var AppRouter = Backbone.Router.extend({

    routes: {
        "media"	: "list",
        "universe"          : "universe",
        "media/add"         : "upload",
        "media/edit"        : "editMedia",
        "media/:id"         : "mediaDetails",
        "program/:id"       : "listProgram",

        "schedule"          : "schedule",
        "admin"             : "conf",
        "about"             : "about",
    },

    initialize: function () {
        window.socket = io.connect('http://' + window.location.hostname);
        window.socket.on('medias:moved', function (move) {
            console.log ('got medias:moved from server', move);
        });

        _([appCollection, mediaList, Universe, Schedule]).each( function (col) {
            console.log ('fetching', col);
            col.fetch();
        });

        this.headerView = new HeaderView({appstatus: window.appstatus, framestatus: window.framestatus});
    },

    schedule: function() {
        new ScheduleView({collection: Schedule});
        this.headerView.selectMenuItem('schedule-menu');
    },

    list: function() {
        new MediaListView({model: mediaDB});
        this.headerView.selectMenuItem('list-menu');
    },

    universe: function () {
        new UniverseListView({collection: Universe});
    },

    mediaDetails: function (id) {
        new MediaView({model: mediaList.get(id)});
        this.headerView.selectMenuItem('list-menu');
    },

    upload: function () {
        new UploadView ({collection: appCollection});
        this.headerView.selectMenuItem('add-menu');
    },

    addMedia: function() {
        var media = new Media.Model();
        new MediaView({model: media});
        this.headerView.selectMenuItem('add-menu');
    },

    editMedia: function() {
        new EditView ({el: $("#content"), collection: Universe});
        this.headerView.selectMenuItem('edit-menu');
    },

    about: function () {
        if (!this.aboutView) {
            this.aboutView = new AboutView();
        }
        $('#content').html(this.aboutView.el);
        this.headerView.selectMenuItem('about-menu');
    },
    conf: function () {
        new ConfView({collection: appCollection});
        this.headerView.selectMenuItem('conf-menu');
    },
});

var lang = $('html')[0].lang;
var i18n;
$.ajax({
    type: 'GET',
    url: '/po/' + lang,
    dataType: 'json',
    success: function(data) {
        i18n = new Jed ({
            locale_data : data,
            'domain' : 'messages'
        });
    },
    data: {},
    async: false
});

    app = new AppRouter();
    Backbone.history.start();
<commit_msg>Fetching models before render views<commit_after>var mediaList = new Media.Collection();
var mediaDB   = new Media.List({collection: mediaList,
                                fixed: true,
                                name: 'Media Database'});
var Universe  = new Media.Universe();
var Schedule  = new Media.Schedule();

var DEBUG = false;
if (DEBUG) {
    var i = 0;
    cols = [mediaList, Universe, Schedule];
    setInterval (function () {
        for (col in cols) {
            c = cols[col];
            c.create({name: i++, file: 'file' + i, duration: 293829829});
            console.log ('hello, ' + col + ' : ', c.models.length,
                         _.zip(c.pluck('file'), c.pluck('name'), c.pluck('_id')));
        }
    }, 5000);
}

Universe.bind ('all', function (arg) {
    console.log ('UNIVERSE:' , arg);
});

Universe.bind ('add', function (arg) {
    console.log('something happened in the universe',Universe, 'ADD', arg);
    console.trace ();
});

Universe.bind ('create', function (arg) {
    console.log('something happened in the universe',Universe, 'CREATE', arg);
    console.trace ();
});

var appCollection = new App.Collection();

window.appCollection = appCollection;
window.appstatus = new App.Status();
window.framestatus = new App.ProgressStatus();

var AppRouter = Backbone.Router.extend({

    routes: {
        "media"	: "list",
        "universe"          : "universe",
        "media/add"         : "upload",
        "media/edit"        : "editMedia",
        "media/:id"         : "mediaDetails",
        "program/:id"       : "listProgram",

        "schedule"          : "schedule",
        "admin"             : "conf",
        "about"             : "about",
    },

    initialize: function () {
        window.socket = io.connect('http://' + window.location.hostname);
        window.socket.on('medias:moved', function (move) {
            console.log ('got medias:moved from server', move);
        });

        this.headerView = new HeaderView({appstatus: window.appstatus, framestatus: window.framestatus});
    },

    schedule: function() {
        new ScheduleView({collection: Schedule});
        this.headerView.selectMenuItem('schedule-menu');
    },

    list: function() {
        new MediaListView({model: mediaDB});
        this.headerView.selectMenuItem('list-menu');
    },

    universe: function () {
        new UniverseListView({collection: Universe});
    },

    mediaDetails: function (id) {
        new MediaView({model: mediaList.get(id)});
        this.headerView.selectMenuItem('list-menu');
    },

    upload: function () {
        new UploadView ({collection: appCollection});
        this.headerView.selectMenuItem('add-menu');
    },

    addMedia: function() {
        var media = new Media.Model();
        new MediaView({model: media});
        this.headerView.selectMenuItem('add-menu');
    },

    editMedia: function() {
        new EditView ({el: $("#content"), collection: Universe});
        this.headerView.selectMenuItem('edit-menu');
    },

    about: function () {
        if (!this.aboutView) {
            this.aboutView = new AboutView();
        }
        $('#content').html(this.aboutView.el);
        this.headerView.selectMenuItem('about-menu');
    },
    conf: function () {
        new ConfView({collection: appCollection});
        this.headerView.selectMenuItem('conf-menu');
    },
});

var lang = $('html')[0].lang;
var i18n;
$.ajax({
    type: 'GET',
    url: '/po/' + lang,
    dataType: 'json',
    success: function(data) {
        i18n = new Jed ({
            locale_data : data,
            'domain' : 'messages'
        });
    },
    data: {},
    async: false
});

appCollection.fetch({success: function() {
    mediaList.fetch({success: function() {
        Universe.fetch({success: function() {
            Schedule.fetch({success: function() {
                app = new AppRouter();
                Backbone.history.start();
            }});
        }});
    }});
}});

<|endoftext|>