<commit_before>var numPrompts = prompts.length;
var activePromptIndex = 3;
var storyIndex = 0;
var interval = 5000;

var particles = [];
var numParticles = 50;
var promptsArray = [];
var distance = 100;

var scrollCount = 0
var bReset = false;

var width;
var height;

var rectX, rectY, lenX, lenY;

// Socket.io server
// var socket = io.connect(socketServer)
var socket = io();

function refreshData () {
  socket.emit('refresh', {})
}

socket.on('refreshData', function (data) {
  console.log("refreshing data")
  app.stories = data
});

var Particle = {
  x: 0,
  y: 0,
  vx: 1,
  vy: 1,
  radius: 0.1,
  wander: 50,
  color: '#333',
  init: function(_x, _y) {
    this.x = _x;
    this.y = _y;
    this.theta = random( TWO_PI );
    this.alive = true;
  },
  update: function() {
    if (this.radius < 0.5) {
      this.radius += 0.01;
    }
    this.x += this.vx;
    this.y += this.vy;
    this.theta += random( -0.5, 0.5 ) * this.wander;
    this.vx += sin( this.theta ) * 0.1;
    this.vy += cos( this.theta ) * 0.1;
    if (this.x < 0 || this.x > width) {
      this.alive = false;
    }
    if (this.y < 0 || this.y > height) {
      this.alive = false;
    }
  },
  draw: function(ctx) {
    ctx.beginPath();
    ctx.arc( this.x, this.y, this.radius, 0, TWO_PI );
    ctx.fillStyle = this.color;
    ctx.fill();
  }
};

var Prompt = {
  x: 0,
  y: 0,
  newY: 0,
  text: '',
  color: 'rgba(155, 77, 202, 1)',
  alpha: 1,
  animating: true,
  init: function(_text, _x, _y) {
    this.text = _text;
    this.x = _x;
    this.y = _y;
    this.newY = _y;
  },
  setActive: function() {
    this.color = '#fff'
  },
  setInactive: function () {
    this.color = 'rgba(77, 77, 77, 0.7)'
  },
  update: function() {
    var dy = this.newY - this.y;
    this.y += dy * 0.10;
    // if (this.newY < this.y) {
    //   this.y -= 2
    // }
    // else if (this.newY > this.y) {
    //   this.y += 8
    // }
    if (abs(this.newY - this.y) < 1) {
      this.y = this.newY;
    }
    if (this.newY != this.y) {
      this.animating = true;
    } else {
      this.animating = false;
    }
  },
  draw: function(ctx) {
    var words = this.text.split(' ');
    var line = '';
    var maxWidth = 400;
    var lineHeight = 32;
    var x = this.x;
    var y = this.y;
    ctx.fillStyle = this.color,
    // ctx.fillStyle = 'rgba(77, 77, 77, 0.5)'
    ctx.globalAlpha = this.alpha;
    ctx.font = "28px Fedra Sans Pro";
    for(var n = 0; n < words.length; n++) {
      var testLine = line + words[n] + ' ';
      var metrics = ctx.measureText(testLine);
      var testWidth = metrics.width;
      if (testWidth > maxWidth && n > 0) {
        ctx.fillText(line, x, y);
        line = words[n] + ' ';
        y += lineHeight;
      }
      else {
        line = testLine;
      }
    }
    ctx.fillText(line, x, y);

    ctx.globalAlpha = 1;
  }
}

var app = new Vue({
  el: '#app',
  data: {
    currentIndex: 0,
    bShowStory: false,
    stories: stories,
    prompts: prompts,
    currentStories: [],
    story: ""
  },
  components: {
    'heading': {
      props: ['story'],
      template: "<transition name='slidefade'>

{{ story }}

</transition>"
    }
  },
  created: function() {
    console.log('vue ready')
    this.setupStories(activePromptIndex)
    this.updateStory(storyIndex)
    this.showStory()
  },
  methods: {
    setupStories: function (activePromptIndex) {
      this.currentStories = []
      var promptId = this.prompts[activePromptIndex]._id
      for (var i = 0; i < this.stories.length; i++) {
        if (this.stories[i].promptId == promptId) {
          this.currentStories.push(this.stories[i].text)
        }
      }
    },
    updateStory: function (storyIndex) {
      // TODO
      this.story = this.currentStories[storyIndex]
    },
    showStory: function() {
      this.bShowStory = true
    },
    hideStory: function() {
      this.bShowStory = false
    },
    toggleStory: function() {
      this.bShowStory = !(this.bShowStory)
    },
    clearStory: function() {
      this.story = ""
    }
  }
});

Sketch.create({
  container: document.getElementById( 'container' ),
  retina: 'auto',
  setup() {
    this.r = this.g = this.b = random(100, 200)
    this.startTime = this.millis;
    this.removed = false;
    app.updateStory(storyIndex);

    width = this.width;
    height = this.height;

    //Create a particle
    for (i = 0; i < numParticles; i++) {
      x = random ( this.width )
      y = random ( this.height )
      var particle = Object.create(Particle);
      particle.init(x, y)
      particles.push(particle)
    }

    //Create prompts
    var xPos = 50;
    var y = 0;
    var yStep = Math.floor(height/6)
    for (i = 0; i < prompts.length; i++) {
      x = xPos;
      var prompt = Object.create(Prompt)
      prompt.init(prompts[i].prompt, x, y)
      if (i === 3) {
        prompt.setActive()
        rectX = 0;
        rectY = y - 50;
        lenX = width*0.3;
        lenY = 120;
      }
      else {
        prompt.setInactive()
      }
      y += yStep;
      promptsArray.push(prompt)
    }

  },
  update() {
    var animInProgress = false;
    for (i = 0; i < promptsArray.length; i++) {
      if (promptsArray[i].animating) {
        animInProgress = true;
        break;
      }
    }

    if (!animInProgress && scrollCount == 0) {
      if (this.millis - this.startTime > 4000) {
        this.startTime = this.millis;
        app.toggleStory();
        if (app.bShowStory == false) {
          // Last prompt, reset
          if (activePromptIndex == numPrompts-1) {
            // TODO: reset
            bReset = true;
            activePromptIndex = 0;
            app.setupStories(activePromptIndex);
            scrollCount += 1;
          }
          else {
            storyIndex += 1;
            if (storyIndex >= app.currentStories.length) {
              storyIndex = 0;
              app.currentStories = [];
              var startIndex = activePromptIndex;
              while (app.currentStories.length == 0) {
                activePromptIndex += 1;
                var checkIndex = (activePromptIndex) % numPrompts;
                scrollCount += 1;
                app.setupStories(checkIndex);
                if (checkIndex == startIndex) {
                  scrollCount = 0;
                  activePromptIndex = startIndex;
                  bReset = true;
                  break;
                }
              }
            }
          }
          app.updateStory(storyIndex);
        }
      }
    }

    for (i = 0; i < particles.length; i++) {
      if (!particles[i].alive) {
        particles.splice(i, 1);
        this.removed = true;
      }
    }
    if (this.removed) {
      var numToAdd = numParticles - particles.length;
      for (i=0; i < numToAdd; i++) {
        x = random ( this.width )
        y = random ( this.height )
        var particle = Object.create(Particle)
        particle.init(x, y)
        particles.push(particle)
      }
      this.removed = false;
    }
    for (i = 0; i < particles.length; i++) {
      if (particles[i].alive) {
        particles[i].update();
      }
    }
    if (scrollCount > 0) {
      promptsArray.push(promptsArray.shift());
      promptsArray[promptsArray.length-1].y = promptsArray[promptsArray.length-1].newY = promptsArray[promptsArray.length-2].y + Math.floor(height/6);
      for (i = 0; i < promptsArray.length; i++) {
        promptsArray[i].newY -= Math.floor(height/6)
        if (i === 3) {
          promptsArray[i].setActive()
        }
        else {
          promptsArray[i].setInactive()
        }
      }
      scrollCount--;
    }

    if (bReset) {
      refreshData();
      bReset = false;
    }

    for (i = 0; i < promptsArray.length; i++) {
      promptsArray[i].update()
    }

  },
  mousemove() {
    this.r = 255 * (this.mouse.x / this.width)
    this.g = 255 * (this.mouse.y / this.height)
    this.b = 255 * abs(cos(PI * this.mouse.y / this.width))
  },
  draw() {
    this.fillStyle = '#fff'
    this.fillRect(0, 0, this.width, this.height)
    for (i = 0; i < particles.length; i++) {
      particles[i].draw(this)
    }
    this.drawActivePromptRect()
    for (i = 0; i < promptsArray.length; i++) {
      promptsArray[i].draw(this)
    }
    for (i = 0; i < particles.length; i++) {
      for (j = i+1 ; j < particles.length; j++) {
        var dist = this.distance(particles[i].x, particles[i].y, particles[j].x, particles[j].y);
        if (dist < distance) {
          this.beginPath();
          this.moveTo(particles[i].x, particles[i].y);
          this.lineTo(particles[j].x, particles[j].y);
          this.lineWidth = 0.2;
          this.strokeStyle = '#333';
          this.stroke();
        }
      }
    }
  },
  distance(x1, y1, x2, y2) {
    return sqrt( pow((x1-x2),2) + pow((y1-y2),2) );
  },
  drawActivePromptRect() {
    this.fillStyle = 'rgba(155, 77, 202, 0.9)'
    this.fillRect(rectX, rectY, lenX, lenY)
  },
});<commit_msg>use a left column<commit_after>var numPrompts = prompts.length;
var activePromptIndex = 3;
var storyIndex = 0;
var interval = 5000;

var particles = [];
var numParticles = 50;
var promptsArray = [];
var distance = 100;

var scrollCount = 0
var bReset = false;

var width;
var height;

var rectX, rectY, lenX, lenY;

// Socket.io server
// var socket = io.connect(socketServer)
var socket = io();

function refreshData () {
  socket.emit('refresh', {})
}

socket.on('refreshData', function (data) {
  console.log("refreshing data")
  app.stories = data
});

var Particle = {
  x: 0,
  y: 0,
  vx: 1,
  vy: 1,
  radius: 0.1,
  wander: 50,
  color: '#333',
  init: function(_x, _y) {
    this.x = _x;
    this.y = _y;
    this.theta = random( TWO_PI );
    this.alive = true;
  },
  update: function() {
    if (this.radius < 0.5) {
      this.radius += 0.01;
    }
    this.x += this.vx;
    this.y += this.vy;
    this.theta += random( -0.5, 0.5 ) * this.wander;
    this.vx += sin( this.theta ) * 0.1;
    this.vy += cos( this.theta ) * 0.1;
    if (this.x < 0 || this.x > width) {
      this.alive = false;
    }
    if (this.y < 0 || this.y > height) {
      this.alive = false;
    }
  },
  draw: function(ctx) {
    ctx.beginPath();
    ctx.arc( this.x, this.y, this.radius, 0, TWO_PI );
    ctx.fillStyle = this.color;
    ctx.fill();
  }
};

var Prompt = {
  x: 0,
  y: 0,
  newY: 0,
  text: '',
  color: 'rgba(155, 77, 202, 1)',
  alpha: 1,
  animating: true,
  init: function(_text, _x, _y) {
    this.text = _text;
    this.x = _x;
    this.y = _y;
    this.newY = _y;
  },
  setActive: function() {
    this.color = '#fff'
  },
  setInactive: function () {
    this.color = 'rgba(255, 255, 255, 0.7)'
  },
  update: function() {
    var dy = this.newY - this.y;
    this.y += dy * 0.10;
    if (abs(this.newY - this.y) < 1) {
      this.y = this.newY;
    }
    if (this.newY != this.y) {
      this.animating = true;
    } else {
      this.animating = false;
    }
  },
  draw: function(ctx) {
    var words = this.text.split(' ');
    var line = '';
    var maxWidth = 400;
    var lineHeight = 32;
    var x = this.x;
    var y = this.y;
    ctx.fillStyle = this.color,
    // ctx.fillStyle = 'rgba(77, 77, 77, 0.5)'
    ctx.globalAlpha = this.alpha;
    ctx.font = "28px Fedra Sans Pro";
    for(var n = 0; n < words.length; n++) {
      var testLine = line + words[n] + ' ';
      var metrics = ctx.measureText(testLine);
      var testWidth = metrics.width;
      if (testWidth > maxWidth && n > 0) {
        ctx.fillText(line, x, y);
        line = words[n] + ' ';
        y += lineHeight;
      }
      else {
        line = testLine;
      }
    }
    ctx.fillText(line, x, y);

    ctx.globalAlpha = 1;
  }
}

var app = new Vue({
  el: '#app',
  data: {
    currentIndex: 0,
    bShowStory: false,
    stories: stories,
    prompts: prompts,
    currentStories: [],
    story: ""
  },
  components: {
    'heading': {
      props: ['story'],
      template: "<transition name='slidefade'>

{{ story }}

</transition>"
    }
  },
  created: function() {
    console.log('vue ready')
    this.setupStories(activePromptIndex)
    this.updateStory(storyIndex)
    this.showStory()
  },
  methods: {
    setupStories: function (activePromptIndex) {
      this.currentStories = []
      var promptId = this.prompts[activePromptIndex]._id
      for (var i = 0; i < this.stories.length; i++) {
        if (this.stories[i].promptId == promptId) {
          this.currentStories.push(this.stories[i].text)
        }
      }
    },
    updateStory: function (storyIndex) {
      // TODO
      this.story = this.currentStories[storyIndex]
    },
    showStory: function() {
      this.bShowStory = true
    },
    hideStory: function() {
      this.bShowStory = false
    },
    toggleStory: function() {
      this.bShowStory = !(this.bShowStory)
    },
    clearStory: function() {
      this.story = ""
    }
  }
});

Sketch.create({
  container: document.getElementById( 'container' ),
  retina: 'auto',
  setup() {
    this.r = this.g = this.b = random(100, 200)
    this.startTime = this.millis;
    this.removed = false;
    app.updateStory(storyIndex);

    width = this.width;
    height = this.height;

    //Create a particle
    for (i = 0; i < numParticles; i++) {
      x = random ( this.width )
      y = random ( this.height )
      var particle = Object.create(Particle);
      particle.init(x, y)
      particles.push(particle)
    }

    //Create prompts
    var xPos = 50;
    var y = 0;
    var yStep = Math.floor(height/6)
    for (i = 0; i < prompts.length; i++) {
      x = xPos;
      var prompt = Object.create(Prompt)
      prompt.init(prompts[i].prompt, x, y)
      if (i === 3) {
        prompt.setActive()
        rectX = 0;
        rectY = y - 50;
        lenX = width*0.3;
        lenY = 120;
      }
      else {
        prompt.setInactive()
      }
      y += yStep;
      promptsArray.push(prompt)
    }

  },
  update() {
    var animInProgress = false;
    for (i = 0; i < promptsArray.length; i++) {
      if (promptsArray[i].animating) {
        animInProgress = true;
        break;
      }
    }

    if (!animInProgress && scrollCount == 0) {
      if (this.millis - this.startTime > 4000) {
        this.startTime = this.millis;
        app.toggleStory();
        if (app.bShowStory == false) {
          // Last prompt, reset
          if (activePromptIndex == numPrompts-1) {
            // TODO: reset
            bReset = true;
            activePromptIndex = 0;
            app.setupStories(activePromptIndex);
            scrollCount += 1;
          }
          else {
            storyIndex += 1;
            if (storyIndex >= app.currentStories.length) {
              storyIndex = 0;
              app.currentStories = [];
              var startIndex = activePromptIndex;
              while (app.currentStories.length == 0) {
                activePromptIndex += 1;
                var checkIndex = (activePromptIndex) % numPrompts;
                scrollCount += 1;
                app.setupStories(checkIndex);
                if (checkIndex == startIndex) {
                  scrollCount = 0;
                  activePromptIndex = startIndex;
                  bReset = true;
                  break;
                }
              }
            }
          }
          app.updateStory(storyIndex);
        }
      }
    }

    for (i = 0; i < particles.length; i++) {
      if (!particles[i].alive) {
        particles.splice(i, 1);
        this.removed = true;
      }
    }
    if (this.removed) {
      var numToAdd = numParticles - particles.length;
      for (i=0; i < numToAdd; i++) {
        x = random ( this.width )
        y = random ( this.height )
        var particle = Object.create(Particle)
        particle.init(x, y)
        particles.push(particle)
      }
      this.removed = false;
    }
    for (i = 0; i < particles.length; i++) {
      if (particles[i].alive) {
        particles[i].update();
      }
    }
    if (scrollCount > 0) {
      promptsArray.push(promptsArray.shift());
      promptsArray[promptsArray.length-1].y = promptsArray[promptsArray.length-1].newY = promptsArray[promptsArray.length-2].y + Math.floor(height/6);
      for (i = 0; i < promptsArray.length; i++) {
        promptsArray[i].newY -= Math.floor(height/6)
        if (i === 3) {
          promptsArray[i].setActive()
        }
        else {
          promptsArray[i].setInactive()
        }
      }
      scrollCount--;
    }

    if (bReset) {
      refreshData();
      bReset = false;
    }

    for (i = 0; i < promptsArray.length; i++) {
      promptsArray[i].update()
    }

  },
  mousemove() {
    this.r = 255 * (this.mouse.x / this.width)
    this.g = 255 * (this.mouse.y / this.height)
    this.b = 255 * abs(cos(PI * this.mouse.y / this.width))
  },
  draw() {
    this.fillStyle = '#fff'
    this.fillRect(0, 0, this.width, this.height)
    for (i = 0; i < particles.length; i++) {
      particles[i].draw(this)
    }

    // Draw a left column
    this.fillStyle = 'rgba(46, 45, 77, 0.95)'
    this.fillRect(0, 0, lenX, this.height)

    this.drawActivePromptRect()
    for (i = 0; i < promptsArray.length; i++) {
      promptsArray[i].draw(this)
    }
    for (i = 0; i < particles.length; i++) {
      for (j = i+1 ; j < particles.length; j++) {
        var dist = this.distance(particles[i].x, particles[i].y, particles[j].x, particles[j].y);
        if (dist < distance) {
          this.beginPath();
          this.moveTo(particles[i].x, particles[i].y);
          this.lineTo(particles[j].x, particles[j].y);
          this.lineWidth = 0.2;
          this.strokeStyle = '#333';
          this.stroke();
        }
      }
    }
  },
  distance(x1, y1, x2, y2) {
    return sqrt( pow((x1-x2),2) + pow((y1-y2),2) );
  },
  drawActivePromptRect() {
    this.fillStyle = 'rgba(155, 77, 202, 0.9)'
    this.fillRect(rectX, rectY, lenX, lenY)
  },
});<|endoftext|>


<commit_before>import DomMock from '../../helpers/dom-mock';
import jsdom from 'mocha-jsdom';
import expect from 'expect';
import React from 'react';
import TestUtils from 'react-addons-test-utils';
import ControlBtn from '../../../portal/src/components/List/ControlBtn';
import IconButton from '../../../portal/src/components/IconButton';

DomMock('');

describe('[Portal] Testing ControlBtn Component', () => {
    jsdom({ skipWindowCheck: true });

    const props = {
        selectedSurveys: '',
        editSubjectActions: () => {},
        surveysActions: () => {},
        previewActions: () => {}
    };

    it('survey list control button: count surveys number', () => {
        const content = TestUtils.renderIntoDocument(
            <ControlBtn {...props} />
        );
        const btn = TestUtils.scryRenderedComponentsWithType(content, IconButton);
        expect(btn.length).toEqual(1);
    });

    it('survey list control button: if one selectedSurveys, buttons will show', () => {
        props.selectedSurveys = '2222-3333-4444-0000';

        const content = TestUtils.renderIntoDocument(
            <ControlBtn {...props} />
        );
        const btn = TestUtils.scryRenderedComponentsWithType(content, IconButton);
        expect(btn.length).toEqual(4);
    });
});
<commit_msg>Add ControlBtn test case in admin mode<commit_after>import DomMock from '../../helpers/dom-mock';
import jsdom from 'mocha-jsdom';
import expect from 'expect';
import React from 'react';
import TestUtils from 'react-addons-test-utils';
import ControlBtn from '../../../portal/src/components/List/ControlBtn';
import IconButton from '../../../portal/src/components/IconButton';

DomMock('');

describe('[Portal] Testing ControlBtn Component', () => {
    jsdom({ skipWindowCheck: true });

    const props = {
        selectedSurveys: '',
        selectedUser: {},
        editSubjectActions: () => {},
        surveysActions: () => {},
        previewActions: () => {}
    };

    it('survey list control button: count surveys number', () => {
        const content = TestUtils.renderIntoDocument(
            <ControlBtn {...props} />
        );
        const btn = TestUtils.scryRenderedComponentsWithType(content, IconButton);
        expect(btn.length).toEqual(1);
    });

    it('survey list control button: if one selectedSurveys, buttons will show', () => {
        props.selectedSurveys = '2222-3333-4444-0000';

        const content = TestUtils.renderIntoDocument(
            <ControlBtn {...props} />
        );
        const btn = TestUtils.scryRenderedComponentsWithType(content, IconButton);
        expect(btn.length).toEqual(4);
    });

    it('survey list control button: no create btn in admin mode', () => {
        props.selectedSurveys = '';
        props.selectedUser = {
            accountid: 'facebook-xxxxx',
            role: 'Admin',
            username: 'Admin TM'
        };

        const content = TestUtils.renderIntoDocument(
            <ControlBtn {...props} />
        );
        const btn = TestUtils.scryRenderedComponentsWithType(content, IconButton);
        expect(btn.length).toEqual(0);
    });
});
<|endoftext|>


<commit_before>// @flow
import * as I from 'immutable'
import * as Kb from '../common-adapters/mobile.native'
import * as Styles from '../styles'
import * as RouteTreeGen from '../actions/route-tree-gen'
import CardStackTransitioner from 'react-navigation/src/views/CardStack/CardStackTransitioner'
import GlobalError from './global-errors/container'
import Offline from '../offline/container'
import React, {Component} from 'react'
import RpcStats from './rpc-stats'
import TabBar from './tab-bar/container'
import type {Props, OwnProps} from './nav.types'
import {NavigationActions, type NavigationAction} from 'react-navigation'
import {addSizeListener} from '../styles/status-bar'
import {chatTab, loginTab, peopleTab} from '../constants/tabs'
import {connect} from '../util/container'
import {isIOS, isIPhoneX} from '../constants/platform'
import {makeLeafTags} from '../route-tree'
import {tabBarHeight} from './tab-bar/index.native'
import {type RouteRenderStack, type RenderRouteResult} from '../route-tree/render-route'
import {GatewayDest} from 'react-gateway'

type CardStackShimProps = {
  mode: 'modal' | 'card',
  renderRoute: (route: RenderRouteResult, shouldRender: boolean) => any,
  onNavigateBack: () => any,
  stack: RouteRenderStack,
  hidden: boolean,
}

const nop = () => {}
const emptyObj = () => ({})

class CardStackShim extends Component<CardStackShimProps> {
  getScreenOptions = () => ({})
  getStateForAction = emptyObj
  getActionForPathAndParams = emptyObj
  getPathAndParamsForState = emptyObj
  getComponentForState = emptyObj

  getComponentForRouteName = () => this.RenderRouteShim

  RenderRouteShim = ({navigation}) => {
    const {route, shouldRender} = navigation.state.params
    return this.props.renderRoute(route, shouldRender)
  }

  _dispatchShim = (action: NavigationAction) => {
    if (action.type === NavigationActions.BACK) {
      this.props.onNavigateBack()
    }
  }

  shouldComponentUpdate(nextProps: CardStackShimProps) {
    return (
      this.props.mode !== nextProps.mode ||
      this.props.renderRoute !== nextProps.renderRoute ||
      this.props.onNavigateBack !== nextProps.onNavigateBack ||
      !I.is(this.props.stack, nextProps.stack)
    )
  }

  _transitionConfig = () => ({
    containerStyle: {
      backgroundColor: Styles.globalColors.fastBlank,
    },
  })

  render() {
    const stack = this.props.stack

    const navigation = {
      dispatch: this._dispatchShim,
      goBack: nop,
      navigate: nop,
      setParams: nop,
      state: {
        index: stack.size - 1,
        routes: stack
          .map((route, index) => {
            const routeName = route.path.join('/')
            // The bottom/back item of the stack is our top (active) screen
            const shouldRender =
              !this.props.hidden && (index === stack.size - 1 || (isIOS && index === stack.size - 2))
            return {key: routeName, params: {route, shouldRender}, routeName}
          })
          .toArray(),
      },
    }

    return (
      <CardStackTransitioner
        navigation={navigation}
        router={this}
        headerMode="none"
        mode={this.props.mode}
        style={this.props.hidden ? styles.hiddenTransitioner : undefined}
        cardStyle={styles.card}
        transitionConfig={this._transitionConfig}
      />
    )
  }
}

const barStyle = showStatusBarDarkContent => {
  // android always uses light-content
  if (!isIOS) {
    return 'light-content'
  }
  // allow an override when underStatusBar is true, but
  // the content being displayed has a light background
  if (showStatusBarDarkContent) {
    return 'dark-content'
  }
  // default to showing dark-content (dark text/icons) when
  // on iOS
  return 'dark-content'
}

function renderStackRoute(route, shouldRender) {
  const {showStatusBarDarkContent, hideStatusBar, root, underNotch} = route.tags || {}
  // We always wrap with a safe top area unless
  // 1. Root view
  // 2. They want to go under the notch
  // 3. Android and they hide the status bar
  const makeSafeAreaOnTop = !root && !underNotch && !(Styles.isAndroid && hideStatusBar)

  return (
    <Kb.NativeView style={styles.routeOuter}>
      {!isIPhoneX && (
        <Kb.NativeStatusBar
          hidden={hideStatusBar}
          translucent={true}
          backgroundColor="rgba(0, 26, 51, 0.25)"
          barStyle={barStyle(showStatusBarDarkContent)}
        />
      )}
      {makeSafeAreaOnTop && <Kb.SafeAreaViewTop />}
      <Kb.BoxGrow>{route.component({shouldRender})}</Kb.BoxGrow>
    </Kb.NativeView>
  )
}

class MainNavStack extends Component<any, {verticalOffset: number}> {
  _listener = null
  _mounted = false
  state = {
    verticalOffset: 0,
  }

  componentDidMount() {
    this._mounted = true
    this._listener = addSizeListener(this.statusBarListener)
  }

  componentWillUnmount() {
    this._mounted = false
    // turns out remove() doesn't guarantee that the callback doesn't happen. This comes from native
    // so there's a race, so we need _mounted to really protect ourself. i could 100% repro statusBarListener being called AFTEr remove() is called :(
    this._listener && this._listener.remove()
  }

  statusBarListener = (frameData: any) => {
    if (frameData.height === 0 && isIPhoneX) {
      // this is a rotation event
      return
    }

    // the iPhone X has default status bar height of 45px
    // and it doesn't increase in height like earlier devices.
    // (so this should always be 0 on an iPhone X, but this should still
    // be correct if it expands)
    if (this._mounted) {
      this.setState({verticalOffset: frameData.height - (isIPhoneX ? 45 : 20)})
    }
  }

  render() {
    const props = this.props

    const stacks = (
      <CardStackShim
        key={props.routeSelected}
        hidden={false}
        mode="card"
        stack={props.routeStack}
        renderRoute={renderStackRoute}
        onNavigateBack={props.navigateUp}
      />
    )

    // if the route is under the status bar keep this at 0 always
    const keyboardVerticalOffset = this.state.verticalOffset

    const content = (
      <Kb.NativeView style={styles.content}>
        {stacks}
        {![chatTab, peopleTab].includes(props.routeSelected) ? <Offline key="offline" /> : null}
        <GlobalError key="globalError" />
        {!props.hideNav && (
          <Kb.NativeSafeAreaView style={props.keyboardShowing ? styles.noTabSafeArea : styles.tabSafeArea}>
            <AnimatedTabBar show={!props.keyboardShowing}>
              <TabBar routeSelected={props.routeSelected} routePath={props.routePath} />
            </AnimatedTabBar>
          </Kb.NativeSafeAreaView>
        )}
      </Kb.NativeView>
    )
    return (
      <Kb.NativeView style={styles.container}>
        <Kb.NativeKeyboardAvoidingView
          style={styles.keyboard}
          behavior={isIOS ? 'padding' : undefined}
          /** TODO get rid of this once a better fix exists
           * keyboardVerticalOffset is to work around a bug in KeyboardAvoidingView
           * when the in-call status bar is active. See https://github.com/facebook/react-native/issues/17862
           * We need to account for the extra offset made by the larger in call status bar (on pre-iPhone X devices).
           */
          keyboardVerticalOffset={keyboardVerticalOffset}
        >
          {content}
          <GatewayDest
            name="keyboard-avoiding-root"
            component={ViewForGatewayDest}
            pointerEvents="box-none"
            style={styles.gatewayDest}
          />
        </Kb.NativeKeyboardAvoidingView>
      </Kb.NativeView>
    )
  }
}
const ViewForGatewayDest = <T>(props: T) => <Kb.NativeView {...props} />

type AnimatedTabBarProps = {
  show: boolean,
  children: any,
}

class AnimatedTabBar extends Component<AnimatedTabBarProps, {offset: any}> {
  state: {offset: any}

  constructor(props: AnimatedTabBarProps) {
    super(props)

    this.state = {
      offset: new Kb.NativeAnimated.Value(props.show ? tabBarHeight : 0),
    }
  }

  componentDidUpdate(prevProps: AnimatedTabBarProps) {
    if (!isIOS) return null
    if (this.props.show !== prevProps.show) {
      Kb.NativeAnimated.timing(this.state.offset, {
        duration: 200,
        toValue: this.props.show ? tabBarHeight : 0,
      }).start()
    }
  }

  render() {
    if (isIOS) {
      return (
        <Kb.NativeAnimated.View
          style={Styles.collapseStyles([{maxHeight: this.state.offset}, styles.tabBar])}
        >
          {this.props.children}
        </Kb.NativeAnimated.View>
      )
    } else {
      return (
        <Kb.NativeView
          style={Styles.collapseStyles([
            this.props.show ? styles.tabBarHeightBar : styles.tabBarHeightZero,
            styles.tabBar,
          ])}
        >
          {this.props.children}
        </Kb.NativeView>
      )
    }
  }
}

class Nav extends Component<Props, {keyboardShowing: boolean}> {
  state = {
    keyboardShowing: false,
  }

  _keyboardShowListener = null
  _keyboardHideListener = null

  componentDidMount() {
    this._keyboardShowListener = Kb.NativeKeyboard.addListener(
      isIOS ? 'keyboardWillShow' : 'keyboardDidShow',
      () => this.setState({keyboardShowing: true})
    )
    this._keyboardHideListener = Kb.NativeKeyboard.addListener(
      isIOS ? 'keyboardWillHide' : 'keyboardDidHide',
      () => this.setState({keyboardShowing: false})
    )
  }

  componentWillUnmount() {
    this._keyboardShowListener && this._keyboardShowListener.remove()
    this._keyboardHideListener && this._keyboardHideListener.remove()

    this._keyboardShowListener = null
    this._keyboardHideListener = null
  }

  componentDidUpdate(prevProps: Props) {
    const nextRS = this.props.routeStack
    const nextLastPath = nextRS ? nextRS.last() : null
    const nextPath = nextLastPath ? nextLastPath.path : I.List()
    const RS = prevProps.routeStack
    const curLastPath = RS ? RS.last() : null
    const curPath = curLastPath ? curLastPath.path : I.List()
    const curTags = curLastPath ? curLastPath.tags : {}
    if (!nextPath.equals(curPath) && (!curTags || !curTags.keepKeyboardOnLeave)) {
      Kb.NativeKeyboard.dismiss()
    }
  }

  render() {
    const baseScreens = this.props.routeStack.filter(r => !r.tags || !r.tags.layerOnTop)
    if (!baseScreens.size) {
      throw new Error('no route component to render without layerOnTop tag')
    }

    const fullscreenPred = r => r.tags && r.tags.fullscreen
    const mainScreens = baseScreens.takeUntil(fullscreenPred)
    const fullScreens: any = baseScreens.skipUntil(fullscreenPred).unshift({
      component: () => (
        <MainNavStack
          {...this.props}
          hideNav={this.props.hideNav}
          keyboardShowing={this.state.keyboardShowing}
          routeStack={mainScreens}
        />
      ),
      path: ['main'],
      tags: makeLeafTags({root: true}), // special case to avoid padding else we'll double pad
    })

    const shim = (
      <CardStackShim
        stack={fullScreens}
        renderRoute={renderStackRoute}
        onNavigateBack={this.props.navigateUp}
        mode="modal"
        hidden={false}
      />
    )
    const layerScreens = this.props.routeStack.filter(r => r.tags && r.tags.layerOnTop)
    const layers = layerScreens.map((r, idx) =>
      r.tags.hideStatusBar ? (
        <React.Fragment key={String(idx)}>
          <Kb.NativeStatusBar hidden={!isIPhoneX} translucent={true} />
          {!r.tags.underNotch && <Kb.SafeAreaViewTop />}
          {r.leafComponent({shouldRender: true})}
        </React.Fragment>
      ) : (
        r.leafComponent({shouldRender: true})
      )
    )

    return (
      <>
        {shim}
        {layers}
        <RpcStats />
      </>
    )
  }
}

const mapStateToProps = (state, ownProps: OwnProps) => ({
  _me: state.config.username,
  hideNav: ownProps.routeSelected === loginTab,
})

const mapDispatchToProps = dispatch => ({
  navigateUp: () => dispatch(RouteTreeGen.createNavigateUp()),
})

const mergeProps = (stateProps, dispatchProps, ownProps) => ({
  // MUST spread ownProps as navigateUp overrides the passed in props!!
  ...ownProps,
  hideNav: stateProps.hideNav,
  navigateUp: dispatchProps.navigateUp,
})

const styles = Styles.styleSheetCreate({
  card: {backgroundColor: Styles.globalColors.fastBlank},
  container: {flexGrow: 1, position: 'relative'},
  content: {...Styles.globalStyles.flexGrow},
  gatewayDest: {height: '100%', position: 'absolute', top: 0, width: '100%'},
  hiddenTransitioner: {
    height: '100%',
    left: -9999,
    position: 'absolute',
    width: '100%',
  },
  keyboard: {
    ...Styles.globalStyles.fillAbsolute,
    backgroundColor: Styles.globalColors.fastBlank,
  },
  noTabSafeArea: {backgroundColor: Styles.globalColors.white, flexGrow: 0},
  routeOuter: {height: '100%', position: 'relative'},
  tabBar: {overflow: 'hidden'},
  tabBarHeightBar: {height: tabBarHeight},
  tabBarHeightZero: {height: 0},
  tabSafeArea: {backgroundColor: Styles.globalColors.darkBlue2, flexGrow: 0},
})

export default connect<OwnProps, _, _, _, _>(
  mapStateToProps,
  mapDispatchToProps,
  mergeProps
)(Nav)
<commit_msg>show black bar above fullscreen routes (#15561)<commit_after>// @flow
import * as I from 'immutable'
import * as Kb from '../common-adapters/mobile.native'
import * as Styles from '../styles'
import * as RouteTreeGen from '../actions/route-tree-gen'
import CardStackTransitioner from 'react-navigation/src/views/CardStack/CardStackTransitioner'
import GlobalError from './global-errors/container'
import Offline from '../offline/container'
import React, {Component} from 'react'
import RpcStats from './rpc-stats'
import TabBar from './tab-bar/container'
import type {Props, OwnProps} from './nav.types'
import {NavigationActions, type NavigationAction} from 'react-navigation'
import {addSizeListener} from '../styles/status-bar'
import {chatTab, loginTab, peopleTab} from '../constants/tabs'
import {connect} from '../util/container'
import {isIOS, isIPhoneX} from '../constants/platform'
import {makeLeafTags} from '../route-tree'
import {tabBarHeight} from './tab-bar/index.native'
import {type RouteRenderStack, type RenderRouteResult} from '../route-tree/render-route'
import {GatewayDest} from 'react-gateway'

type CardStackShimProps = {
  mode: 'modal' | 'card',
  renderRoute: (route: RenderRouteResult, shouldRender: boolean) => any,
  onNavigateBack: () => any,
  stack: RouteRenderStack,
  hidden: boolean,
}

const nop = () => {}
const emptyObj = () => ({})

class CardStackShim extends Component<CardStackShimProps> {
  getScreenOptions = () => ({})
  getStateForAction = emptyObj
  getActionForPathAndParams = emptyObj
  getPathAndParamsForState = emptyObj
  getComponentForState = emptyObj

  getComponentForRouteName = () => this.RenderRouteShim

  RenderRouteShim = ({navigation}) => {
    const {route, shouldRender} = navigation.state.params
    return this.props.renderRoute(route, shouldRender)
  }

  _dispatchShim = (action: NavigationAction) => {
    if (action.type === NavigationActions.BACK) {
      this.props.onNavigateBack()
    }
  }

  shouldComponentUpdate(nextProps: CardStackShimProps) {
    return (
      this.props.mode !== nextProps.mode ||
      this.props.renderRoute !== nextProps.renderRoute ||
      this.props.onNavigateBack !== nextProps.onNavigateBack ||
      !I.is(this.props.stack, nextProps.stack)
    )
  }

  _transitionConfig = () => ({
    containerStyle: {
      backgroundColor: Styles.globalColors.fastBlank,
    },
  })

  render() {
    const stack = this.props.stack

    const navigation = {
      dispatch: this._dispatchShim,
      goBack: nop,
      navigate: nop,
      setParams: nop,
      state: {
        index: stack.size - 1,
        routes: stack
          .map((route, index) => {
            const routeName = route.path.join('/')
            // The bottom/back item of the stack is our top (active) screen
            const shouldRender =
              !this.props.hidden && (index === stack.size - 1 || (isIOS && index === stack.size - 2))
            return {key: routeName, params: {route, shouldRender}, routeName}
          })
          .toArray(),
      },
    }

    return (
      <CardStackTransitioner
        navigation={navigation}
        router={this}
        headerMode="none"
        mode={this.props.mode}
        style={this.props.hidden ? styles.hiddenTransitioner : undefined}
        cardStyle={styles.card}
        transitionConfig={this._transitionConfig}
      />
    )
  }
}

const barStyle = showStatusBarDarkContent => {
  // android always uses light-content
  if (!isIOS) {
    return 'light-content'
  }
  // allow an override when underStatusBar is true, but
  // the content being displayed has a light background
  if (showStatusBarDarkContent) {
    return 'dark-content'
  }
  // default to showing dark-content (dark text/icons) when
  // on iOS
  return 'dark-content'
}

function renderStackRoute(route, shouldRender) {
  const {showStatusBarDarkContent, hideStatusBar, root, underNotch} = route.tags || {}
  // We always wrap with a safe top area unless
  // 1. Root view
  // 2. They want to go under the notch
  // 3. Android and they hide the status bar
  const makeSafeAreaOnTop = !root && !underNotch && !(Styles.isAndroid && hideStatusBar)

  return (
    <Kb.NativeView style={styles.routeOuter}>
      {!isIPhoneX && (
        <Kb.NativeStatusBar
          hidden={hideStatusBar}
          translucent={true}
          backgroundColor="rgba(0, 26, 51, 0.25)"
          barStyle={barStyle(showStatusBarDarkContent)}
        />
      )}
      {makeSafeAreaOnTop && <Kb.SafeAreaViewTop />}
      <Kb.BoxGrow>{route.component({shouldRender})}</Kb.BoxGrow>
    </Kb.NativeView>
  )
}

class MainNavStack extends Component<any, {verticalOffset: number}> {
  _listener = null
  _mounted = false
  state = {
    verticalOffset: 0,
  }

  componentDidMount() {
    this._mounted = true
    this._listener = addSizeListener(this.statusBarListener)
  }

  componentWillUnmount() {
    this._mounted = false
    // turns out remove() doesn't guarantee that the callback doesn't happen. This comes from native
    // so there's a race, so we need _mounted to really protect ourself. i could 100% repro statusBarListener being called AFTEr remove() is called :(
    this._listener && this._listener.remove()
  }

  statusBarListener = (frameData: any) => {
    if (frameData.height === 0 && isIPhoneX) {
      // this is a rotation event
      return
    }

    // the iPhone X has default status bar height of 45px
    // and it doesn't increase in height like earlier devices.
    // (so this should always be 0 on an iPhone X, but this should still
    // be correct if it expands)
    if (this._mounted) {
      this.setState({verticalOffset: frameData.height - (isIPhoneX ? 45 : 20)})
    }
  }

  render() {
    const props = this.props

    const stacks = (
      <CardStackShim
        key={props.routeSelected}
        hidden={false}
        mode="card"
        stack={props.routeStack}
        renderRoute={renderStackRoute}
        onNavigateBack={props.navigateUp}
      />
    )

    // if the route is under the status bar keep this at 0 always
    const keyboardVerticalOffset = this.state.verticalOffset

    const content = (
      <Kb.NativeView style={styles.content}>
        {stacks}
        {![chatTab, peopleTab].includes(props.routeSelected) ? <Offline key="offline" /> : null}
        {!props.hideNav && (
          <Kb.NativeSafeAreaView style={props.keyboardShowing ? styles.noTabSafeArea : styles.tabSafeArea}>
            <AnimatedTabBar show={!props.keyboardShowing}>
              <TabBar routeSelected={props.routeSelected} routePath={props.routePath} />
            </AnimatedTabBar>
          </Kb.NativeSafeAreaView>
        )}
      </Kb.NativeView>
    )
    return (
      <Kb.NativeView style={styles.container}>
        <Kb.NativeKeyboardAvoidingView
          style={styles.keyboard}
          behavior={isIOS ? 'padding' : undefined}
          /** TODO get rid of this once a better fix exists
           * keyboardVerticalOffset is to work around a bug in KeyboardAvoidingView
           * when the in-call status bar is active. See https://github.com/facebook/react-native/issues/17862
           * We need to account for the extra offset made by the larger in call status bar (on pre-iPhone X devices).
           */
          keyboardVerticalOffset={keyboardVerticalOffset}
        >
          {content}
          <GatewayDest
            name="keyboard-avoiding-root"
            component={ViewForGatewayDest}
            pointerEvents="box-none"
            style={styles.gatewayDest}
          />
        </Kb.NativeKeyboardAvoidingView>
      </Kb.NativeView>
    )
  }
}
const ViewForGatewayDest = <T>(props: T) => <Kb.NativeView {...props} />

type AnimatedTabBarProps = {
  show: boolean,
  children: any,
}

class AnimatedTabBar extends Component<AnimatedTabBarProps, {offset: any}> {
  state: {offset: any}

  constructor(props: AnimatedTabBarProps) {
    super(props)

    this.state = {
      offset: new Kb.NativeAnimated.Value(props.show ? tabBarHeight : 0),
    }
  }

  componentDidUpdate(prevProps: AnimatedTabBarProps) {
    if (!isIOS) return null
    if (this.props.show !== prevProps.show) {
      Kb.NativeAnimated.timing(this.state.offset, {
        duration: 200,
        toValue: this.props.show ? tabBarHeight : 0,
      }).start()
    }
  }

  render() {
    if (isIOS) {
      return (
        <Kb.NativeAnimated.View
          style={Styles.collapseStyles([{maxHeight: this.state.offset}, styles.tabBar])}
        >
          {this.props.children}
        </Kb.NativeAnimated.View>
      )
    } else {
      return (
        <Kb.NativeView
          style={Styles.collapseStyles([
            this.props.show ? styles.tabBarHeightBar : styles.tabBarHeightZero,
            styles.tabBar,
          ])}
        >
          {this.props.children}
        </Kb.NativeView>
      )
    }
  }
}

class Nav extends Component<Props, {keyboardShowing: boolean}> {
  state = {
    keyboardShowing: false,
  }

  _keyboardShowListener = null
  _keyboardHideListener = null

  componentDidMount() {
    this._keyboardShowListener = Kb.NativeKeyboard.addListener(
      isIOS ? 'keyboardWillShow' : 'keyboardDidShow',
      () => this.setState({keyboardShowing: true})
    )
    this._keyboardHideListener = Kb.NativeKeyboard.addListener(
      isIOS ? 'keyboardWillHide' : 'keyboardDidHide',
      () => this.setState({keyboardShowing: false})
    )
  }

  componentWillUnmount() {
    this._keyboardShowListener && this._keyboardShowListener.remove()
    this._keyboardHideListener && this._keyboardHideListener.remove()

    this._keyboardShowListener = null
    this._keyboardHideListener = null
  }

  componentDidUpdate(prevProps: Props) {
    const nextRS = this.props.routeStack
    const nextLastPath = nextRS ? nextRS.last() : null
    const nextPath = nextLastPath ? nextLastPath.path : I.List()
    const RS = prevProps.routeStack
    const curLastPath = RS ? RS.last() : null
    const curPath = curLastPath ? curLastPath.path : I.List()
    const curTags = curLastPath ? curLastPath.tags : {}
    if (!nextPath.equals(curPath) && (!curTags || !curTags.keepKeyboardOnLeave)) {
      Kb.NativeKeyboard.dismiss()
    }
  }

  render() {
    const baseScreens = this.props.routeStack.filter(r => !r.tags || !r.tags.layerOnTop)
    if (!baseScreens.size) {
      throw new Error('no route component to render without layerOnTop tag')
    }

    const fullscreenPred = r => r.tags && r.tags.fullscreen
    const mainScreens = baseScreens.takeUntil(fullscreenPred)
    const fullScreens: any = baseScreens.skipUntil(fullscreenPred).unshift({
      component: () => (
        <MainNavStack
          {...this.props}
          hideNav={this.props.hideNav}
          keyboardShowing={this.state.keyboardShowing}
          routeStack={mainScreens}
        />
      ),
      path: ['main'],
      tags: makeLeafTags({root: true}), // special case to avoid padding else we'll double pad
    })

    const shim = (
      <CardStackShim
        stack={fullScreens}
        renderRoute={renderStackRoute}
        onNavigateBack={this.props.navigateUp}
        mode="modal"
        hidden={false}
      />
    )
    const layerScreens = this.props.routeStack.filter(r => r.tags && r.tags.layerOnTop)
    const layers = layerScreens.map((r, idx) =>
      r.tags.hideStatusBar ? (
        <React.Fragment key={String(idx)}>
          <Kb.NativeStatusBar hidden={!isIPhoneX} translucent={true} />
          {!r.tags.underNotch && <Kb.SafeAreaViewTop />}
          {r.leafComponent({shouldRender: true})}
        </React.Fragment>
      ) : (
        r.leafComponent({shouldRender: true})
      )
    )

    return (
      <>
        {shim}
        {layers}
        <GlobalError key="globalError" />
        <RpcStats />
      </>
    )
  }
}

const mapStateToProps = (state, ownProps: OwnProps) => ({
  _me: state.config.username,
  hideNav: ownProps.routeSelected === loginTab,
})

const mapDispatchToProps = dispatch => ({
  navigateUp: () => dispatch(RouteTreeGen.createNavigateUp()),
})

const mergeProps = (stateProps, dispatchProps, ownProps) => ({
  // MUST spread ownProps as navigateUp overrides the passed in props!!
  ...ownProps,
  hideNav: stateProps.hideNav,
  navigateUp: dispatchProps.navigateUp,
})

const styles = Styles.styleSheetCreate({
  card: {backgroundColor: Styles.globalColors.fastBlank},
  container: {flexGrow: 1, position: 'relative'},
  content: {...Styles.globalStyles.flexGrow},
  gatewayDest: {height: '100%', position: 'absolute', top: 0, width: '100%'},
  hiddenTransitioner: {
    height: '100%',
    left: -9999,
    position: 'absolute',
    width: '100%',
  },
  keyboard: {
    ...Styles.globalStyles.fillAbsolute,
    backgroundColor: Styles.globalColors.fastBlank,
  },
  noTabSafeArea: {backgroundColor: Styles.globalColors.white, flexGrow: 0},
  routeOuter: {height: '100%', position: 'relative'},
  tabBar: {overflow: 'hidden'},
  tabBarHeightBar: {height: tabBarHeight},
  tabBarHeightZero: {height: 0},
  tabSafeArea: {backgroundColor: Styles.globalColors.darkBlue2, flexGrow: 0},
})

export default connect<OwnProps, _, _, _, _>(
  mapStateToProps,
  mapDispatchToProps,
  mergeProps
)(Nav)
<|endoftext|>


<commit_before>/*
 * Ext JS Library 2.0.2
 * Copyright(c) 2006-2008, Ext JS, LLC.
 * licensing@extjs.com
 *
 * http://extjs.com/license
 */

/**
  * Ext.ux.fbk.sonet.MeteoTrentino Extension Class
  *
  * @author  Marco Frassoni, Maurizio Napolitano & Davide Setti
  * @version 1.0
  * @class Ext.ux.fbk.sonet.MeteoTrentino
  *
MeteoTrentino weather forecast

  *

    This is a example of the json

*/

MeteoTrentino = function(conf, panel_conf){
    Ext.apply(this, panel_conf);

    var l = conf.selected;

    if(!(l in conf.lang))
        l = conf.defaultValue;

    var url = conf.lang[l].url;
    var xslt = conf.lang[l].xslt_file;

    this.html = '';

    this.loadForecast = function(){

        var p = this;

        Ext.Ajax.request({
            url : 'xslt-applier.php',
            params: {'url': url, 'xslt': xslt},
            method: 'POST',
            success: function(result, request){
                p.html = result.responseText;
                p.renderForecast();
            },
            failure: function(result, request){
                $('#'+p.getId()+'-forecast-overview').html('
').class('error-msg').text('Uh oh! Something apparently went wrong, please apoligize us and send us a feedback!');
            }
        });
    };

    this.renderForecast = function(){

        var ov = $('#' +this.getId()+'-forecast-overview');
        var dv = $('#' +this.getId()+'-forecast-detailedview');

        if(this.html === null || this.html === '')
            ov.html('
Uh oh! Something apparently went wrong, please apoligize us and send us a feedback!
');

        var doc = $("
").html(this.html);

        ov.html(doc.find('#meteo_sintesi'));

        var f = doc.find('.meteo_forecast');

        f.not('#today').hide();

        dv.html(f);

        this.visualize();
    }

    this.visualize = function(day){

        var ov = $('#' +this.getId()+'-forecast-overview');
        var dv = $('#' +this.getId()+'-forecast-detailedview');
        var lk = $('#' +this.getId()+'-forecast-links');

        var w_id = this.getId();

        var link = 'Ext.getCmp(\''+w_id+'\').visualize(\'{0}\')';

        if(this.html === null || this.html === '')
            ov.html('<div').class('error-msg').text('Uh oh! Something apparently went wrong, please apoligize us and send us a feedback!');

        lk.html('');

        if (day == null || day == '')
            day = 'today';

        dv.children().each(function(){
            var id = $(this).attr('id');
            var label = $(this).attr('label');
            if(id == day){
                lk.append($('').text(label));
                $(this).show();
            } else {
                lk.append($('').addClass('a').attr('onclick', String.format(link,id)).text(label));
                $(this).hide();
            }
        });

        lk.children().css({'padding' : '10px', 'font-size' : '13px'});
    }

    MeteoTrentino.superclass.constructor.call(this, {
        autoHeight: true
        ,autoWidth: true
        ,defaults: {
            autoScroll: true
        }
        ,items: [{
            html:
                '
'
                    +'

'
                    +'

'
                    +'

'
                    +'
ReloadChange language
'
                +'
'
            ,border: false
            ,autoHeight: true
        }]
        ,listeners: {
            render: function(){
                this.doLayout(); // TO DO: do this only if it is collapsed
                this.loadForecast()
            }
        }
    });
};
Ext.extend(MeteoTrentino, Ext.Panel);
<commit_msg>Errata<commit_after>/*
 * Ext JS Library 2.0.2
 * Copyright(c) 2006-2008, Ext JS, LLC.
 * licensing@extjs.com
 *
 * http://extjs.com/license
 */

/**
  * Ext.ux.fbk.sonet.MeteoTrentino Extension Class
  *
  * @author  Marco Frassoni, Maurizio Napolitano & Davide Setti
  * @version 1.0
  * @class Ext.ux.fbk.sonet.MeteoTrentino
  *
MeteoTrentino weather forecast

  *

    This is a example of the json

*/

MeteoTrentino = function(conf, panel_conf){
    Ext.apply(this, panel_conf);

    var l = conf.selected;

    if(!(l in conf.lang))
        l = conf.defaultValue;

    var url = conf.lang[l].url;
    var xslt = conf.lang[l].xslt_file;

    this.html = '';

    this.loadForecast = function(){

        var p = this;

        Ext.Ajax.request({
            url : 'xslt-applier.php',
            params: {'url': url, 'xslt': xslt},
            method: 'POST',
            success: function(result, request){
                p.html = result.responseText;
                p.renderForecast();
            },
            failure: function(result, request){
                $('#'+p.getId()+'-forecast-overview').html('
').addClass('error-msg').text('Uh oh! Something apparently went wrong, please apoligize us and send us a feedback!');
            }
        });
    };

    this.renderForecast = function(){

        var ov = $('#' +this.getId()+'-forecast-overview');
        var dv = $('#' +this.getId()+'-forecast-detailedview');

        if(this.html === null || this.html === '')
            ov.html('
Uh oh! Something apparently went wrong, please apoligize us and send us a feedback!
');

        var doc = $("
").html(this.html);

        ov.html(doc.find('#meteo_sintesi'));

        var f = doc.find('.meteo_forecast');

        f.not('#today').hide();

        dv.html(f);

        this.visualize();
    }

    this.visualize = function(day){

        var ov = $('#' +this.getId()+'-forecast-overview');
        var dv = $('#' +this.getId()+'-forecast-detailedview');
        var lk = $('#' +this.getId()+'-forecast-links');

        var w_id = this.getId();

        var link = 'Ext.getCmp(\''+w_id+'\').visualize(\'{0}\')';

        if(this.html === null || this.html === '')
            ov.html('
').addClass('error-msg').text('Uh oh! Something apparently went wrong, please apoligize us and send us a feedback!');

        lk.html('');

        if (day == null || day == '')
            day = 'today';

        dv.children().each(function(){
            var id = $(this).attr('id');
            var label = $(this).attr('label');
            if(id == day){
                lk.append($('').text(label));
                $(this).show();
            } else {
                lk.append($('').addClass('a').attr('onclick', String.format(link,id)).text(label));
                $(this).hide();
            }
        });

        lk.children().css({'padding' : '10px', 'font-size' : '13px'});
    }

    MeteoTrentino.superclass.constructor.call(this, {
        autoHeight: true
        ,autoWidth: true
        ,defaults: {
            autoScroll: true
        }
        ,items: [{
            html:
                '
'
                    +'

'
                    +'

'
                    +'

'
                    +'
ReloadChange language
'
                +'
'
            ,border: false
            ,autoHeight: true
        }]
        ,listeners: {
            render: function(){
                this.doLayout(); // TO DO: do this only if it is collapsed
                this.loadForecast()
            }
        }
    });
};
Ext.extend(MeteoTrentino, Ext.Panel);
<|endoftext|>


<commit_before>var numPrompts = prompts.length;
var activePromptIndex = 3;
var storyIndex = 0;
var interval = 5000;

var particles = [];
var numParticles = 50;
var promptsArray = [];
var distance = 100;

var scrollCount = 0
var bReset = false;

var width;
var height;

var rectX, rectY, lenX, lenY;

// Socket.io server
// var socket = io.connect(socketServer)
var socket = io();

function refreshData () {
  socket.emit('refresh', {})
}

socket.on('refreshData', function (data) {
  console.log("refreshing data")
  app.stories = data
});

var Particle = {
  x: 0,
  y: 0,
  vx: 1,
  vy: 1,
  radius: 0.1,
  wander: 50,
  color: '#333',
  init: function(_x, _y) {
    this.x = _x;
    this.y = _y;
    this.theta = random( TWO_PI );
    this.alive = true;
  },
  update: function() {
    if (this.radius < 0.5) {
      this.radius += 0.01;
    }
    this.x += this.vx;
    this.y += this.vy;
    this.theta += random( -0.5, 0.5 ) * this.wander;
    this.vx += sin( this.theta ) * 0.1;
    this.vy += cos( this.theta ) * 0.1;
    if (this.x < 0 || this.x > width) {
      this.alive = false;
    }
    if (this.y < 0 || this.y > height) {
      this.alive = false;
    }
  },
  draw: function(ctx) {
    ctx.beginPath();
    ctx.arc( this.x, this.y, this.radius, 0, TWO_PI );
    ctx.fillStyle = this.color;
    ctx.fill();
  }
};

var Prompt = {
  x: 0,
  y: 0,
  newY: 0,
  text: '',
  color: 'rgba(155, 77, 202, 1)',
  alpha: 1,
  animating: true,
  init: function(_text, _x, _y) {
    this.text = _text;
    this.x = _x;
    this.y = _y;
    this.newY = _y;
  },
  setActive: function() {
    this.color = '#fff'
  },
  setInactive: function () {
    this.color = 'rgba(255, 255, 255, 0.7)'
  },
  update: function() {
    var dy = this.newY - this.y;
    this.y += dy * 0.10;
    if (abs(this.newY - this.y) < 1) {
      this.y = this.newY;
    }
    if (this.newY != this.y) {
      this.animating = true;
    } else {
      this.animating = false;
    }
  },
  draw: function(ctx) {
    var words = this.text.split(' ');
    var line = '';
    var maxWidth = 400;
    var lineHeight = 32;
    var x = this.x;
    var y = this.y;
    ctx.fillStyle = this.color,
    // ctx.fillStyle = 'rgba(77, 77, 77, 0.5)'
    ctx.globalAlpha = this.alpha;
    ctx.font = "28px Fedra Sans Pro";
    for(var n = 0; n < words.length; n++) {
      var testLine = line + words[n] + ' ';
      var metrics = ctx.measureText(testLine);
      var testWidth = metrics.width;
      if (testWidth > maxWidth && n > 0) {
        ctx.fillText(line, x, y);
        line = words[n] + ' ';
        y += lineHeight;
      }
      else {
        line = testLine;
      }
    }
    ctx.fillText(line, x, y);

    ctx.globalAlpha = 1;
  }
}

var app = new Vue({
  el: '#app',
  data: {
    currentIndex: 0,
    bShowStory: false,
    stories: stories,
    prompts: prompts,
    currentStories: [],
    story: ""
  },
  components: {
    'heading': {
      props: ['story'],
      template: "<transition name='slidefade'>

{{ story }}

</transition>"
    }
  },
  created: function() {
    console.log('vue ready')
    this.setupStories(activePromptIndex)
    this.updateStory(storyIndex)
    this.showStory()
  },
  methods: {
    setupStories: function (activePromptIndex) {
      this.currentStories = []
      var promptId = this.prompts[activePromptIndex]._id
      for (var i = 0; i < this.stories.length; i++) {
        if (this.stories[i].promptId == promptId) {
          this.currentStories.push(this.stories[i].text)
        }
      }
    },
    updateStory: function (storyIndex) {
      // TODO
      this.story = this.currentStories[storyIndex]
    },
    showStory: function() {
      this.bShowStory = true
    },
    hideStory: function() {
      this.bShowStory = false
    },
    toggleStory: function() {
      this.bShowStory = !(this.bShowStory)
    },
    clearStory: function() {
      this.story = ""
    }
  }
});

Sketch.create({
  container: document.getElementById( 'container' ),
  retina: 'auto',
  setup() {
    this.r = this.g = this.b = random(100, 200)
    this.startTime = this.millis;
    this.removed = false;
    app.updateStory(storyIndex);

    width = this.width;
    height = this.height;

    //Create a particle
    for (i = 0; i < numParticles; i++) {
      x = random ( this.width )
      y = random ( this.height )
      var particle = Object.create(Particle);
      particle.init(x, y)
      particles.push(particle)
    }

    //Create prompts
    var xPos = 50;
    var y = 0;
    var yStep = Math.floor(height/6)
    for (i = 0; i < prompts.length; i++) {
      x = xPos;
      var prompt = Object.create(Prompt)
      prompt.init(prompts[i].prompt, x, y)
      if (i === 3) {
        prompt.setActive()
        rectX = 0;
        rectY = y - 50;
        lenX = width*0.3;
        lenY = 120;
      }
      else {
        prompt.setInactive()
      }
      y += yStep;
      promptsArray.push(prompt)
    }

  },
  update() {
    var animInProgress = false;
    for (i = 0; i < promptsArray.length; i++) {
      if (promptsArray[i].animating) {
        animInProgress = true;
        break;
      }
    }

    if (!animInProgress && scrollCount == 0) {
      if (this.millis - this.startTime > 4000) {
        this.startTime = this.millis;
        app.toggleStory();
        if (app.bShowStory == false) {
          // Last prompt, reset
          if (activePromptIndex == numPrompts-1) {
            // TODO: reset
            bReset = true;
            activePromptIndex = 0;
            app.setupStories(activePromptIndex);
            scrollCount += 1;
          }
          else {
            storyIndex += 1;
            if (storyIndex >= app.currentStories.length) {
              storyIndex = 0;
              app.currentStories = [];
              var startIndex = activePromptIndex;
              while (app.currentStories.length == 0) {
                activePromptIndex += 1;
                var checkIndex = (activePromptIndex) % numPrompts;
                scrollCount += 1;
                app.setupStories(checkIndex);
                if (checkIndex == startIndex) {
                  scrollCount = 0;
                  activePromptIndex = startIndex;
                  bReset = true;
                  break;
                }
              }
            }
          }
          app.updateStory(storyIndex);
        }
      }
    }

    for (i = 0; i < particles.length; i++) {
      if (!particles[i].alive) {
        particles.splice(i, 1);
        this.removed = true;
      }
    }
    if (this.removed) {
      var numToAdd = numParticles - particles.length;
      for (i=0; i < numToAdd; i++) {
        x = random ( this.width )
        y = random ( this.height )
        var particle = Object.create(Particle)
        particle.init(x, y)
        particles.push(particle)
      }
      this.removed = false;
    }
    for (i = 0; i < particles.length; i++) {
      if (particles[i].alive) {
        particles[i].update();
      }
    }
    if (scrollCount > 0) {
      promptsArray.push(promptsArray.shift());
      promptsArray[promptsArray.length-1].y = promptsArray[promptsArray.length-1].newY = promptsArray[promptsArray.length-2].y + Math.floor(height/6);
      for (i = 0; i < promptsArray.length; i++) {
        promptsArray[i].newY -= Math.floor(height/6)
        if (i === 3) {
          promptsArray[i].setActive()
        }
        else {
          promptsArray[i].setInactive()
        }
      }
      scrollCount--;
    }

    if (bReset) {
      refreshData();
      bReset = false;
    }

    for (i = 0; i < promptsArray.length; i++) {
      promptsArray[i].update()
    }

  },
  mousemove() {
    this.r = 255 * (this.mouse.x / this.width)
    this.g = 255 * (this.mouse.y / this.height)
    this.b = 255 * abs(cos(PI * this.mouse.y / this.width))
  },
  draw() {
    this.fillStyle = '#fff'
    this.fillRect(0, 0, this.width, this.height)
    for (i = 0; i < particles.length; i++) {
      particles[i].draw(this)
    }

    // Draw a left column
    this.fillStyle = 'rgba(46, 45, 77, 0.95)'
    this.fillRect(0, 0, lenX, this.height)

    this.drawActivePromptRect()
    for (i = 0; i < promptsArray.length; i++) {
      promptsArray[i].draw(this)
    }
    for (i = 0; i < particles.length; i++) {
      for (j = i+1 ; j < particles.length; j++) {
        var dist = this.distance(particles[i].x, particles[i].y, particles[j].x, particles[j].y);
        if (dist < distance) {
          this.beginPath();
          this.moveTo(particles[i].x, particles[i].y);
          this.lineTo(particles[j].x, particles[j].y);
          this.lineWidth = 0.2;
          this.strokeStyle = '#333';
          this.stroke();
        }
      }
    }
  },
  distance(x1, y1, x2, y2) {
    return sqrt( pow((x1-x2),2) + pow((y1-y2),2) );
  },
  drawActivePromptRect() {
    this.fillStyle = 'rgba(155, 77, 202, 0.9)'
    this.fillRect(rectX, rectY, lenX, lenY)
  },
});<commit_msg>change duration to 5 seconds<commit_after>var numPrompts = prompts.length;
var activePromptIndex = 3;
var storyIndex = 0;
var interval = 5000;

var particles = [];
var numParticles = 50;
var promptsArray = [];
var distance = 100;

var scrollCount = 0
var bReset = false;

var width;
var height;

var rectX, rectY, lenX, lenY;

// Socket.io server
// var socket = io.connect(socketServer)
var socket = io();

function refreshData () {
  socket.emit('refresh', {})
}

socket.on('refreshData', function (data) {
  console.log("refreshing data")
  app.stories = data
});

var Particle = {
  x: 0,
  y: 0,
  vx: 1,
  vy: 1,
  radius: 0.1,
  wander: 50,
  color: '#333',
  init: function(_x, _y) {
    this.x = _x;
    this.y = _y;
    this.theta = random( TWO_PI );
    this.alive = true;
  },
  update: function() {
    if (this.radius < 0.5) {
      this.radius += 0.01;
    }
    this.x += this.vx;
    this.y += this.vy;
    this.theta += random( -0.5, 0.5 ) * this.wander;
    this.vx += sin( this.theta ) * 0.1;
    this.vy += cos( this.theta ) * 0.1;
    if (this.x < 0 || this.x > width) {
      this.alive = false;
    }
    if (this.y < 0 || this.y > height) {
      this.alive = false;
    }
  },
  draw: function(ctx) {
    ctx.beginPath();
    ctx.arc( this.x, this.y, this.radius, 0, TWO_PI );
    ctx.fillStyle = this.color;
    ctx.fill();
  }
};

var Prompt = {
  x: 0,
  y: 0,
  newY: 0,
  text: '',
  color: 'rgba(155, 77, 202, 1)',
  alpha: 1,
  animating: true,
  init: function(_text, _x, _y) {
    this.text = _text;
    this.x = _x;
    this.y = _y;
    this.newY = _y;
  },
  setActive: function() {
    this.color = '#fff'
  },
  setInactive: function () {
    this.color = 'rgba(255, 255, 255, 0.7)'
  },
  update: function() {
    var dy = this.newY - this.y;
    this.y += dy * 0.10;
    if (abs(this.newY - this.y) < 1) {
      this.y = this.newY;
    }
    if (this.newY != this.y) {
      this.animating = true;
    } else {
      this.animating = false;
    }
  },
  draw: function(ctx) {
    var words = this.text.split(' ');
    var line = '';
    var maxWidth = 400;
    var lineHeight = 32;
    var x = this.x;
    var y = this.y;
    ctx.fillStyle = this.color,
    // ctx.fillStyle = 'rgba(77, 77, 77, 0.5)'
    ctx.globalAlpha = this.alpha;
    ctx.font = "28px Fedra Sans Pro";
    for(var n = 0; n < words.length; n++) {
      var testLine = line + words[n] + ' ';
      var metrics = ctx.measureText(testLine);
      var testWidth = metrics.width;
      if (testWidth > maxWidth && n > 0) {
        ctx.fillText(line, x, y);
        line = words[n] + ' ';
        y += lineHeight;
      }
      else {
        line = testLine;
      }
    }
    ctx.fillText(line, x, y);

    ctx.globalAlpha = 1;
  }
}

var app = new Vue({
  el: '#app',
  data: {
    currentIndex: 0,
    bShowStory: false,
    stories: stories,
    prompts: prompts,
    currentStories: [],
    story: ""
  },
  components: {
    'heading': {
      props: ['story'],
      template: "<transition name='slidefade'>

{{ story }}

</transition>"
    }
  },
  created: function() {
    console.log('vue ready')
    this.setupStories(activePromptIndex)
    this.updateStory(storyIndex)
    this.showStory()
  },
  methods: {
    setupStories: function (activePromptIndex) {
      this.currentStories = []
      var promptId = this.prompts[activePromptIndex]._id
      for (var i = 0; i < this.stories.length; i++) {
        if (this.stories[i].promptId == promptId) {
          this.currentStories.push(this.stories[i].text)
        }
      }
    },
    updateStory: function (storyIndex) {
      // TODO
      this.story = this.currentStories[storyIndex]
    },
    showStory: function() {
      this.bShowStory = true
    },
    hideStory: function() {
      this.bShowStory = false
    },
    toggleStory: function() {
      this.bShowStory = !(this.bShowStory)
    },
    clearStory: function() {
      this.story = ""
    }
  }
});

Sketch.create({
  container: document.getElementById( 'container' ),
  retina: 'auto',
  setup() {
    this.r = this.g = this.b = random(100, 200)
    this.startTime = this.millis;
    this.removed = false;
    app.updateStory(storyIndex);

    width = this.width;
    height = this.height;

    //Create a particle
    for (i = 0; i < numParticles; i++) {
      x = random ( this.width )
      y = random ( this.height )
      var particle = Object.create(Particle);
      particle.init(x, y)
      particles.push(particle)
    }

    //Create prompts
    var xPos = 50;
    var y = 0;
    var yStep = Math.floor(height/6)
    for (i = 0; i < prompts.length; i++) {
      x = xPos;
      var prompt = Object.create(Prompt)
      prompt.init(prompts[i].prompt, x, y)
      if (i === 3) {
        prompt.setActive()
        rectX = 0;
        rectY = y - 50;
        lenX = width*0.3;
        lenY = 120;
      }
      else {
        prompt.setInactive()
      }
      y += yStep;
      promptsArray.push(prompt)
    }

  },
  update() {
    var animInProgress = false;
    for (i = 0; i < promptsArray.length; i++) {
      if (promptsArray[i].animating) {
        animInProgress = true;
        break;
      }
    }

    if (!animInProgress && scrollCount == 0) {
      if (this.millis - this.startTime > 5000) {
        this.startTime = this.millis;
        app.toggleStory();
        if (app.bShowStory == false) {
          // Last prompt, reset
          if (activePromptIndex == numPrompts-1) {
            // TODO: reset
            bReset = true;
            activePromptIndex = 0;
            app.setupStories(activePromptIndex);
            scrollCount += 1;
          }
          else {
            storyIndex += 1;
            if (storyIndex >= app.currentStories.length) {
              storyIndex = 0;
              app.currentStories = [];
              var startIndex = activePromptIndex;
              while (app.currentStories.length == 0) {
                activePromptIndex += 1;
                var checkIndex = (activePromptIndex) % numPrompts;
                scrollCount += 1;
                app.setupStories(checkIndex);
                if (checkIndex == startIndex) {
                  scrollCount = 0;
                  activePromptIndex = startIndex;
                  bReset = true;
                  break;
                }
              }
            }
          }
          app.updateStory(storyIndex);
        }
      }
    }

    for (i = 0; i < particles.length; i++) {
      if (!particles[i].alive) {
        particles.splice(i, 1);
        this.removed = true;
      }
    }
    if (this.removed) {
      var numToAdd = numParticles - particles.length;
      for (i=0; i < numToAdd; i++) {
        x = random ( this.width )
        y = random ( this.height )
        var particle = Object.create(Particle)
        particle.init(x, y)
        particles.push(particle)
      }
      this.removed = false;
    }
    for (i = 0; i < particles.length; i++) {
      if (particles[i].alive) {
        particles[i].update();
      }
    }
    if (scrollCount > 0) {
      promptsArray.push(promptsArray.shift());
      promptsArray[promptsArray.length-1].y = promptsArray[promptsArray.length-1].newY = promptsArray[promptsArray.length-2].y + Math.floor(height/6);
      for (i = 0; i < promptsArray.length; i++) {
        promptsArray[i].newY -= Math.floor(height/6)
        if (i === 3) {
          promptsArray[i].setActive()
        }
        else {
          promptsArray[i].setInactive()
        }
      }
      scrollCount--;
    }

    if (bReset) {
      refreshData();
      bReset = false;
    }

    for (i = 0; i < promptsArray.length; i++) {
      promptsArray[i].update()
    }

  },
  mousemove() {
    this.r = 255 * (this.mouse.x / this.width)
    this.g = 255 * (this.mouse.y / this.height)
    this.b = 255 * abs(cos(PI * this.mouse.y / this.width))
  },
  draw() {
    this.fillStyle = '#fff'
    this.fillRect(0, 0, this.width, this.height)
    for (i = 0; i < particles.length; i++) {
      particles[i].draw(this)
    }

    // Draw a left column
    this.fillStyle = 'rgba(46, 45, 77, 0.95)'
    this.fillRect(0, 0, lenX, this.height)

    this.drawActivePromptRect()
    for (i = 0; i < promptsArray.length; i++) {
      promptsArray[i].draw(this)
    }
    for (i = 0; i < particles.length; i++) {
      for (j = i+1 ; j < particles.length; j++) {
        var dist = this.distance(particles[i].x, particles[i].y, particles[j].x, particles[j].y);
        if (dist < distance) {
          this.beginPath();
          this.moveTo(particles[i].x, particles[i].y);
          this.lineTo(particles[j].x, particles[j].y);
          this.lineWidth = 0.2;
          this.strokeStyle = '#333';
          this.stroke();
        }
      }
    }
  },
  distance(x1, y1, x2, y2) {
    return sqrt( pow((x1-x2),2) + pow((y1-y2),2) );
  },
  drawActivePromptRect() {
    this.fillStyle = 'rgba(155, 77, 202, 0.9)'
    this.fillRect(rectX, rectY, lenX, lenY)
  },
});<|endoftext|>


<commit_before>import { restRequest } from 'girder/rest';
import ItemCollection from 'girder/collections/ItemCollection';
import View from 'girder/views/View';
import 'girder/utilities/jquery/girderModal';

import events from '../events';
import router from '../router';

import template from '../templates/dialogs/openAnnotatedImage.pug';
import '../stylesheets/dialogs/openAnnotatedImage.styl';

let dialog;

const OpenAnnotatedImage = View.extend({
    events: {
        'click .h-annotated-image': '_submit'
    },

    initialize() {
        this.collection = new ItemCollection();
        this.listenTo(this.collection, 'reset', this.render);
    },

    render() {
        this.$el.html(template({
            items: this.collection.toJSON()
        })).girderModal(this);
        return this;
    },

    fetch() {
        return restRequest({
            path: 'annotation/images'
        }).done((items) => {
            this.collection.reset(items);
        });
    },

    _submit(evt) {
        const id = this.$(evt.currentTarget).data('id');
        router.setQuery('bounds', null, {trigger: false});
        router.setQuery('image', id, {trigger: true});
        this.$el.modal('hide');
    }
});

function createDialog() {
    return new OpenAnnotatedImage({
        parentView: null
    });
}

events.on('h:openAnnotatedImageUi', function () {
    if (!dialog) {
        dialog = createDialog();
    }
    dialog.setElement($('#g-dialog-container')).fetch();
});

export default createDialog;
<commit_msg>Limit the number of results to 10<commit_after>import { restRequest } from 'girder/rest';
import ItemCollection from 'girder/collections/ItemCollection';
import View from 'girder/views/View';
import 'girder/utilities/jquery/girderModal';

import events from '../events';
import router from '../router';

import template from '../templates/dialogs/openAnnotatedImage.pug';
import '../stylesheets/dialogs/openAnnotatedImage.styl';

let dialog;

const OpenAnnotatedImage = View.extend({
    events: {
        'click .h-annotated-image': '_submit'
    },

    initialize() {
        this.collection = new ItemCollection();
        this.listenTo(this.collection, 'reset', this.render);
    },

    render() {
        this.$el.html(template({
            items: this.collection.toJSON()
        })).girderModal(this);
        return this;
    },

    fetch() {
        return restRequest({
            path: 'annotation/images',
            data: {
                limit: 10
            }
        }).done((items) => {
            this.collection.reset(items);
        });
    },

    _submit(evt) {
        const id = this.$(evt.currentTarget).data('id');
        router.setQuery('bounds', null, {trigger: false});
        router.setQuery('image', id, {trigger: true});
        this.$el.modal('hide');
    }
});

function createDialog() {
    return new OpenAnnotatedImage({
        parentView: null
    });
}

events.on('h:openAnnotatedImageUi', function () {
    if (!dialog) {
        dialog = createDialog();
    }
    dialog.setElement($('#g-dialog-container')).fetch();
});

export default createDialog;
<|endoftext|>


<commit_before>/**
* This file is part of taolin project (http://taolin.fbk.eu)
* Copyright (C) 2008, 2009 FBK Foundation, (http://www.fbk.eu)
* Authors: SoNet Group (see AUTHORS.txt)
*
* Taolin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* Taolin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Taolin. If not, see <http://www.gnu.org/licenses/>.
*
*/

CommentWindow = function(c_model, foreign_id) {

    this.model = c_model;

    this.store = new Ext.data.JsonStore({
        url: model + '/getcomments'
        ,root: 'comments'
        ,method: 'POST'
        ,fields: ['id','user_id','text', {name: 'created', type: 'date', dateFormat: 'Y-m-d H:i:s'}, 'name', 'surname']
        ,baseParams: {
            foreign_id: foreign_id
        }
        ,autoLoad: true
    });

    this.view = new Ext.DataView({
        store: this.store
        ,tpl: new Ext.XTemplate(
            '<tpl for=".">',
                '
',
                    '
',
                        '
',
                            '',
                                '
',
                                    '',
                                '
',
                            '	',
                            '',
                                '{name} {surname} {text} ',
                                '
October, 21 2009
',
                            '	',
                        '
',
                    '
',
                    //'<tpl if="!this.isLastComment(xindex)">',
                        '
',
                    //'</tpl>',
                '
',
            '</tpl>'
        ,{
            parent: this
            ,isLastComment: function(index){
                return  index >= this.parent.store.totalLength;
            }
        })
        ,emptyText: '

No comments!

'
	    ,itemSelector: 'div.comment'
        ,autoHeight: true
        ,style: 'padding-top: 10px'
    });

    this.form = new Ext.form.FormPanel({
        autoWidth: true
        ,autoHeight: true
        ,buttonAlign: 'center'
        ,style: 'padding: 10px 20px'
        ,labelAlign: 'top'
        ,border: false
        ,items: [
        {
            xtype: 'textarea'
            ,fieldLabel: 'Add your comment'
            ,grow: true
            ,growMin: 20
            ,name: 'comment'
            ,anchor: '100%'
        }],
        buttons: [{
            text: 'Submit'
            ,handler: function(){

                var store = this.view.store;
                var model = this.model;

                this.form.getForm().submit(
                    {
                        url: model + '/addcomment',
                        waitMsg:'Saving Data...',
                        success: function(form,action){

                            var jsondata = Ext.util.JSON.decode(action.response.responseText);
                            var commentRecord = Ext.data.Record.create(['id','user_id','text', {name: 'created', type: 'date', dateFormat: 'Y-m-d H:i:s'}, 'name', 'surname']);

                            form.reset(); // Cleaning form
                            store.add(new commentRecord(jsondata.comment)); // Adding the new record to the store
                        }
                    }
                );

            }
            ,scope: this
            ,formBind: true
        },{
            text: 'Close'
            ,handler: function(){
                this.close();
            }
            ,scope: this
        }]
    });

    CommentWindow.superclass.constructor.call(this, {
        title: 'Comments'
        ,id: 'comments_window'
        ,width:500
        ,minwidth:300
        ,resizable: true
        ,iconCls:'chatwindowicon'
        ,items: [{
            items: this.view
            ,border: false
        },{
            items: this.form
            ,border: false
        }]
    });

    this.show();
}

Ext.extend(CommentWindow, Ext.Window);
<commit_msg>fixing a bug<commit_after>/**
* This file is part of taolin project (http://taolin.fbk.eu)
* Copyright (C) 2008, 2009 FBK Foundation, (http://www.fbk.eu)
* Authors: SoNet Group (see AUTHORS.txt)
*
* Taolin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* Taolin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Taolin. If not, see <http://www.gnu.org/licenses/>.
*
*/

CommentWindow = function(c_model, foreign_id) {

    this.model = c_model;

    this.store = new Ext.data.JsonStore({
        url: this.model + '/getcomments'
        ,root: 'comments'
        ,method: 'POST'
        ,fields: ['id','user_id','text', {name: 'created', type: 'date', dateFormat: 'Y-m-d H:i:s'}, 'name', 'surname']
        ,baseParams: {
            foreign_id: foreign_id
        }
        ,autoLoad: true
    });

    this.view = new Ext.DataView({
        store: this.store
        ,tpl: new Ext.XTemplate(
            '<tpl for=".">',
                '
',
                    '
',
                        '
',
                            '',
                                '
',
                                    '',
                                '
',
                            '	',
                            '',
                                '{name} {surname} {text} ',
                                '
October, 21 2009
',
                            '	',
                        '
',
                    '
',
                    //'<tpl if="!this.isLastComment(xindex)">',
                        '
',
                    //'</tpl>',
                '
',
            '</tpl>'
        ,{
            parent: this
            ,isLastComment: function(index){
                return  index >= this.parent.store.totalLength;
            }
        })
        ,emptyText: '

No comments!

'
	    ,itemSelector: 'div.comment'
        ,autoHeight: true
        ,style: 'padding-top: 10px'
    });

    this.form = new Ext.form.FormPanel({
        autoWidth: true
        ,autoHeight: true
        ,buttonAlign: 'center'
        ,style: 'padding: 10px 20px'
        ,labelAlign: 'top'
        ,border: false
        ,items: [
        {
            xtype: 'textarea'
            ,fieldLabel: 'Add your comment'
            ,grow: true
            ,growMin: 20
            ,name: 'comment'
            ,anchor: '100%'
        }],
        buttons: [{
            text: 'Submit'
            ,handler: function(){

                var store = this.view.store;
                var model = this.model;

                this.form.getForm().submit(
                    {
                        url: model + '/addcomment',
                        waitMsg:'Saving Data...',
                        success: function(form,action){

                            var jsondata = Ext.util.JSON.decode(action.response.responseText);
                            var commentRecord = Ext.data.Record.create(['id','user_id','text', {name: 'created', type: 'date', dateFormat: 'Y-m-d H:i:s'}, 'name', 'surname']);

                            form.reset(); // Cleaning form
                            store.add(new commentRecord(jsondata.comment)); // Adding the new record to the store
                        }
                    }
                );

            }
            ,scope: this
            ,formBind: true
        },{
            text: 'Close'
            ,handler: function(){
                this.close();
            }
            ,scope: this
        }]
    });

    CommentWindow.superclass.constructor.call(this, {
        title: 'Comments'
        ,id: 'comments_window'
        ,width:500
        ,minwidth:300
        ,resizable: true
        ,iconCls:'chatwindowicon'
        ,items: [{
            items: this.view
            ,border: false
        },{
            items: this.form
            ,border: false
        }]
    });

    this.show();
}

Ext.extend(CommentWindow, Ext.Window);
<|endoftext|>


<commit_before>/**
 * index.js - Main library for index page/view.
 * Authors: Ian McGaunn; Dave Zimmelman
 * Modified: 09 Mar 15
 */
(function (window, $) {
    'use strict';

    window.onpopstate = function (event) {
        if (document.location.pathname === '/') window.load_splash_view();
        else {
            var re = /^\/podcast\/(\d+)\//;
            var r = re.exec(document.location.pathname);
            window.load_podcast_view(r[1]);
        }
    };

    window.load_splash_view = function (first) {
        $.get('/api/view/splash', function (data) {

            if (!first) window.history.pushState({}, document.title, '/');

            $('#left-col').html(data);

            $.get('/api/castcat/0', function (data) {
                insertPodcasts(data.podcasts, '#pc-0 > .panel-body', false, false);
            });

            $('#left-col .genre-panel').each(function () {
                var i, el = $(this).find('.panel-body'), gid = $(this).data('genreid');
                $.get('/api/castcat/' + gid, function (data) {
                    el.html('');
                    if (data.favorites) {
                        insertPodcasts(data.favorites, el, false, true);
                    }
                    insertPodcasts(data.podcasts, el, false, false);
                });
            });

            $('#podcast-search-input').on('change keyup paste', function (e) {
                if (e.type == "keyup" && e.which == 13) {
                    // Enter key pressed
                    submitSearch();
                }
                else if ($(this).val().trim() !== "" &&
                         $(this).val().trim() !== window.lastTickSearch &&
                         window.searchBoxTH === null) {
                    window.quicksearch();
                    window.searchBoxTH = setInterval(window.quicksearch, 250);
                }
                else if ($(this).val().trim() === "") {
                    clearInterval(window.searchBoxTH);
                    window.searchBoxTH = null;
                    searchResults({});
                }
            });
            // Search button press
            $('#podcast-search-button').click(function () {
                submitSearch();
            });
        });
    };

    window.load_podcast_view = function (id) {
        $.get('/api/view/podcast/'+ id, function (data) {
            $('#left-col').html(data);

            // Reformat URL to reflect appropriate title.
            if (window['preload_cast']) {
                window.history.replaceState({}, document.title, '/podcast/' + window.safetitle);
                window['preload_cast'] = false;
            } else {
                window.history.pushState({}, document.title, '/podcast/' + window.safetitle);
            }
        });
    };

    function insertPodcasts(pcasts, selector, append, fav) {
        var i;
        if (!append) $(selector).html('');
        for (i in pcasts) {
            var classes = (fav) ? "castnail favorite" : "castnail";
            $(selector).append('

');
        }
    }

    /**
     * Populate results table with search data.
     * @param {Object} data - The JSON object returned from iTunes query.
     */
    function searchResults(results) {
        var podcast, row, count;
        // Update table title with result count.
        if (results.length > 0) {
            $('#result-counter').html(results.length + " Results");
            $('#search-results').css('height', '120px');
            $('#search-results').css('padding', '10px');
        } else {
            $('#result-counter').html("No Results");
            $('#search-results').css('height', '0px');
            $('#search-results').css('padding', '0px');
        }
        insertPodcasts(results, '#search-results');
    }

    /* When document is finished loading, execute following code: */
    $().ready(function () {

        window.state = 0; // Overlay window tracking

        $('#btn-sin').click(function () {
            if (window.state != 1) {
                $('#register').css("display", "none");
                $('#dimmer').css("display", "block");
                $('#login').css("display", "block");
                $('#btn-sin').html('X');
                window.state = 1;
            } else {
                $('#dimmer').css("display", "none");
                $('#login').css("display", "none");
                $('#btn-sin').html('Sign In');
                window.state = 0;
            }
        });

        $('#btn-sup').click(function () {
            if (window.state != 2) {
                $('#login').css("display", "none");
                $('#dimmer').css("display", "block");
                $('#register').css("display", "block");
                $('#btn-sup').html('X');
                window.state = 2;
            } else {
                $('#dimmer').css("display", "none");
                $('#register').css("display", "none");
                $('#btn-sup').html('Register');
                window.state = 0;
            }
        });

        window.searchBoxTH = null;
        window.lastTickSearch = "";
        // Submit search query
        var submitSearch = function () {
            clearInterval(window.searchBoxTH);
            window.searchBoxTH = null;
            var searchTerm = $('#podcast-search-input').val();
            // Get search data from API.
            $.get('/api/search/?term=' + searchTerm, function (data) {
                // Parse results and add to table.
                searchResults(data);
                // Push new URL state.
                //window.history.pushState({}, document.title, '/search/' + searchTerm);
            });
        };
        // Search box change
        var quicksearch = function () {
            var s = $('#podcast-search-input').val().trim();
            if (s == window.lastTickSearch) {
                clearInterval(window.searchBoxTH);
                window.searchBoxTH = null;
                return;
            }
            if (s != "") {
                window.lastTickSearch = s;
                $.get('/api/quicksearch/?term=' + s, function (data) {
                    searchResults(data);
                });
            }
        };
        if (window['preload_cast']) {
            window.load_podcast_view(window.preload_cast);
        }
        else {
            window.load_splash_view(true);
        }

    });
}(window, jQuery));
<commit_msg>[Fix] typo<commit_after>/**
 * index.js - Main library for index page/view.
 * Authors: Ian McGaunn; Dave Zimmelman
 * Modified: 09 Mar 15
 */
(function (window, $) {
    'use strict';

    window.onpopstate = function (event) {
        if (document.location.pathname === '/') window.load_splash_view();
        else {
            var re = /^\/podcast\/(\d+)\//;
            var r = re.exec(document.location.pathname);
            window.load_podcast_view(r[1]);
        }
    };

    window.load_splash_view = function (first) {
        $.get('/api/view/splash', function (data) {

            if (!first) window.history.pushState({}, document.title, '/');

            $('#left-col').html(data);

            $.get('/api/castcat/0', function (data) {
                insertPodcasts(data.podcasts, '#pc-0 > .panel-body', false, false);
            });

            $('#left-col .genre-panel').each(function () {
                var i, el = $(this).find('.panel-body'), gid = $(this).data('genreid');
                $.get('/api/castcat/' + gid, function (data) {
                    el.html('');
                    if (data.favorites) {
                        insertPodcasts(data.favorites, el, false, true);
                    }
                    insertPodcasts(data.podcasts, el, false, false);
                });
            });

            $('#podcast-search-input').on('change keyup paste', function (e) {
                if (e.type == "keyup" && e.which == 13) {
                    // Enter key pressed
                    submitSearch();
                }
                else if ($(this).val().trim() !== "" &&
                         $(this).val().trim() !== window.lastTickSearch &&
                         window.searchBoxTH === null) {
                    window.quicksearch();
                    window.searchBoxTH = setInterval(window.quicksearch, 250);
                }
                else if ($(this).val().trim() === "") {
                    clearInterval(window.searchBoxTH);
                    window.searchBoxTH = null;
                    searchResults({});
                }
            });
            // Search button press
            $('#podcast-search-button').click(function () {
                submitSearch();
            });
        });
    };

    window.load_podcast_view = function (id) {
        $.get('/api/view/podcast/'+ id, function (data) {
            $('#left-col').html(data);

            // Reformat URL to reflect appropriate title.
            if (window['preload_cast']) {
                window.history.replaceState({}, document.title, '/podcast/' + window.safetitle);
                window['preload_cast'] = false;
            } else {
                window.history.pushState({}, document.title, '/podcast/' + window.safetitle);
            }
        });
    };

    function insertPodcasts(pcasts, selector, append, fav) {
        var i;
        if (!append) $(selector).html('');
        for (i in pcasts) {
            var classes = (fav) ? "castnail favorite" : "castnail";
            $(selector).append('

');
        }
    }

    /**
     * Populate results table with search data.
     * @param {Object} data - The JSON object returned from iTunes query.
     */
    function searchResults(results) {
        var podcast, row, count;
        // Update table title with result count.
        if (results.length > 0) {
            $('#result-counter').html(results.length + " Results");
            $('#search-results').css('height', '120px');
            $('#search-results').css('padding', '10px');
        } else {
            $('#result-counter').html("No Results");
            $('#search-results').css('height', '0px');
            $('#search-results').css('padding', '0px');
        }
        insertPodcasts(results, '#search-results');
    }

    /* When document is finished loading, execute following code: */
    $().ready(function () {

        window.state = 0; // Overlay window tracking

        $('#btn-sin').click(function () {
            if (window.state != 1) {
                $('#register').css("display", "none");
                $('#dimmer').css("display", "block");
                $('#login').css("display", "block");
                $('#btn-sin').html('X');
                $('#btn-sup').html('Register');
                $('#btn-sin input[type=text]').focus();
                window.state = 1;
            } else {
                $('#dimmer').css("display", "none");
                $('#login').css("display", "none");
                $('#btn-sin').html('Sign In');
                window.state = 0;
            }
        });

        $('#btn-sup').click(function () {
            if (window.state != 2) {
                $('#login').css("display", "none");
                $('#dimmer').css("display", "block");
                $('#register').css("display", "block");
                $('#btn-sin').html('Sign In');
                $('#btn-sup').html('X');
                window.state = 2;
            } else {
                $('#dimmer').css("display", "none");
                $('#register').css("display", "none");
                $('#btn-sup').html('Register');
                window.state = 0;
            }
        });

        window.searchBoxTH = null;
        window.lastTickSearch = "";
        // Submit search query
        var submitSearch = function () {
            clearInterval(window.searchBoxTH);
            window.searchBoxTH = null;
            var searchTerm = $('#podcast-search-input').val();
            // Get search data from API.
            $.get('/api/search/?term=' + searchTerm, function (data) {
                // Parse results and add to table.
                searchResults(data);
                // Push new URL state.
                //window.history.pushState({}, document.title, '/search/' + searchTerm);
            });
        };
        // Search box change
        var quicksearch = function () {
            var s = $('#podcast-search-input').val().trim();
            if (s == window.lastTickSearch) {
                clearInterval(window.searchBoxTH);
                window.searchBoxTH = null;
                return;
            }
            if (s != "") {
                window.lastTickSearch = s;
                $.get('/api/quicksearch/?term=' + s, function (data) {
                    searchResults(data);
                });
            }
        };
        if (window['preload_cast']) {
            window.load_podcast_view(window.preload_cast);
        }
        else {
            window.load_splash_view(true);
        }

    });
}(window, jQuery));
<|endoftext|>