<commit_before>import React, { Component } from 'react';
import {
  AppRegistry,
  AsyncStorage,
  ListView,
  Navigator,
  Image,
  StyleSheet,
  Text,
  TextInput,
  TouchableHighlight,
  View,
} from 'react-native';

import PlayDates from './PlayDates';
import MainScene from './MainScene';
import UserDogs from './UserDogs';

class PlayDateCreate extends Component {
  constructor(props) {
    super(props);
    this.state={
      userID: false
    };
  }

  createGroupPressed() {
    console.log('createGroupPressed');
    // AsyncStorage.getItem("userID")
    //             .then((value) => { this.setState( {"userID": value} ); })
    //             .done();
    console.log('this.state: ' + this.state);
    let data = {
      method: 'POST',
      body: JSON.stringify({
        name: this.state.name, time_day: this.state.time_day, location: this.state.location, description: this.state.description, user_id: "21"
      }),
      headers: {
        'Accept':       'application/json',
        'Content-Type': 'application/json'
      }
    }
    fetch('http://localhost:3000/playdates', data)
        .then((response) => response.json())  // promise
        .then((responseData) => console.log(responseData))
        .catch((error) => console.log("boo"));
    this.props.navigator.pop();
  }

  componentDidMount() {
    console.log("PlayDateCreate: componentDidMount: " + this.props);
  }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.pageTitle}>
          Create your new PlayDate
        </Text>

        <Text style={styles.label}>Group Name:</Text>
        <TextInput
          style={styles.inputText}
          value={this.state.name}
          onChangeText={(text) => this.setState({name: text})}
        />

        <Text style={styles.label}>Location:</Text>
        <TextInput
          style={styles.inputText}
          value={this.state.location}
          onChangeText={(text) => this.setState({location: text})}
        />

        <Text style={styles.label}>Time & Day of Week:</Text>
        <TextInput
          style={styles.inputText}
          value={this.state.time_day}
          onChangeText={(text) => this.setState({time_day: text})}
        />

        <Text style={styles.label}>Description:</Text>
        <TextInput
          style={styles.inputText}
          value={this.state.description}
          onChangeText={(text) => this.setState({description: text})}
        />

        <TouchableHighlight
          style={styles.button}
          onPress={() => this.createGroupPressed()}>
          <Text>Create PlayDate</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    fontSize: 14,
  },
  button: {
    borderWidth: 2,
    borderRadius: 12,
    padding: 10,
    backgroundColor: 'antiquewhite'
  },
  inputText: {
    height: 30,
    borderColor: 'gray',
    borderWidth: 1,
    borderRadius: 16,
    padding: 10,
    backgroundColor: '#EBFAFF',
    marginBottom: 10,
  },
  textArea: {
    height: 100,
  },
  label: {
    fontSize: 14,
  }
});

module.exports = PlayDateCreate;
<commit_msg>Add post request to create new playdate<commit_after>import React, { Component } from 'react';
import {
  AppRegistry,
  AsyncStorage,
  ListView,
  Navigator,
  Image,
  StyleSheet,
  Text,
  TextInput,
  TouchableHighlight,
  View,
} from 'react-native';

import PlayDates from './PlayDates';
import MainScene from './MainScene';
import UserDogs from './UserDogs';

class PlayDateCreate extends Component {
  constructor(props) {
    super(props);
    this.state={
      name: '',
      address: '',
      time_day: '',
      description: '',
      userID: false,
    };
  }

  componentDidMount() {
    AsyncStorage.getItem("userID").then((value) => {
      console.log('current.val '+ value);
        this.setState({userID: value});
    }).done();
  }

  createGroupPressed() {
    console.log('createGroupPressed');
    console.log('this.state: ' + this.state);
    let data = {
      method: 'POST',
      body: JSON.stringify({
        name: this.state.name,
        time_day: this.state.time_day,
        address: this.state.address,
        description: this.state.description,
        user_id: this.state.userID
      }),
      headers: {
        'Accept':       'application/json',
        'Content-Type': 'application/json'
      }
    }
    fetch('http://localhost:3000/playdates', data)
      .then((response) => response.json())  // promise
      .then((responseData) => {
        console.log(responseData)
        this.props.navigator.pop();
      })
      .catch((error) => console.log("boo"))
      .done();
  }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.pageTitle}>
          Create your new PlayDate
        </Text>

        <Text style={styles.label}>Group Name:</Text>
        <TextInput
          style={styles.inputText}
          value={this.state.name}
          onChangeText={(text) => this.setState({name: text})}
        />

        <Text style={styles.label}>Address:</Text>
        <TextInput
          style={styles.inputText}
          value={this.state.address}
          onChangeText={(text) => this.setState({address: text})}
        />

        <Text style={styles.label}>Time & Day of Week:</Text>
        <TextInput
          style={styles.inputText}
          value={this.state.time_day}
          onChangeText={(text) => this.setState({time_day: text})}
        />

        <Text style={styles.label}>Description:</Text>
        <TextInput
          style={styles.inputText}
          value={this.state.description}
          onChangeText={(text) => this.setState({description: text})}
        />

        <TouchableHighlight
          style={styles.button}
          onPress={() => this.createGroupPressed()}>
          <Text>Create PlayDate</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    fontSize: 14,
  },
  button: {
    borderWidth: 2,
    borderRadius: 12,
    padding: 10,
    backgroundColor: 'antiquewhite'
  },
  inputText: {
    height: 30,
    borderColor: 'gray',
    borderWidth: 1,
    borderRadius: 16,
    padding: 10,
    backgroundColor: '#EBFAFF',
    marginBottom: 10,
  },
  textArea: {
    height: 100,
  },
  label: {
    fontSize: 14,
  }
});

module.exports = PlayDateCreate;
<|endoftext|>


<commit_before>import React from 'react';
import createClass from 'create-react-class';
import Formsy from 'formsy-react';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import Paper from 'material-ui/Paper';
import RaisedButton from 'material-ui/RaisedButton';
import MenuItem from 'material-ui/MenuItem';
import { FormsyCheckbox, FormsyDate, FormsyRadio, FormsyRadioGroup,
    FormsySelect, FormsyText, FormsyTime, FormsyToggle, FormsyAutoComplete } from 'formsy-material-ui/lib';

const Main = createClass({

  /**
   * As an alternative to `MuiThemeProvider` you can add a theme directly into context.
   * See the [Material-UI themes](http://www.material-ui.com/#/customization/themes) docs for details.
   *
   * childContextTypes: {
   *   muiTheme: PropTypes.object,
   * },
   * getChildContext(){
   *   return {
   *     muiTheme: getMuiTheme(),
   *   }
   * },
   */

  getInitialState() {
    return {
      canSubmit: false,
    };
  },

  errorMessages: {
    wordsError: "Please only use letters",
    numericError: "Please provide a number",
    urlError: "Please provide a valid URL",
  },

  styles: {
    paperStyle: {
      width: 300,
      margin: 'auto',
      padding: 20,
    },
    switchStyle: {
      marginBottom: 16,
    },
    submitStyle: {
      marginTop: 32,
    },
  },

  enableButton() {
    this.setState({
      canSubmit: true,
    });
  },

  disableButton() {
    this.setState({
      canSubmit: false,
    });
  },

  submitForm(data) {
    alert(JSON.stringify(data, null, 4));
  },

  notifyFormError(data) {
    console.error('Form error:', data);
  },

  render() {
    let {paperStyle, switchStyle, submitStyle } = this.styles;
    let { wordsError, numericError, urlError } = this.errorMessages;

    return (
      <MuiThemeProvider muiTheme={getMuiTheme()}>
        <Paper style={paperStyle}>
          <Formsy.Form
            onValid={this.enableButton}
            onInvalid={this.disableButton}
            onValidSubmit={this.submitForm}
            onInvalidSubmit={this.notifyFormError}
          >
            <FormsyDate
              name="date"
              required
              floatingLabelText="Date"
            />
            <FormsyTime
              name="time"
              required
              floatingLabelText="Time"
            />
            <FormsySelect
              name="frequency"
              required
              floatingLabelText="How often do you?"
            >
              <MenuItem value={'never'} primaryText="Never" />
              <MenuItem value={'nightly'} primaryText="Every Night" />
              <MenuItem value={'weeknights'} primaryText="Weeknights" />
            </FormsySelect>
            <FormsyAutoComplete
              name="frequency-auto-complete"
              required
              floatingLabelText="How often do you?"
              dataSource={[
                'Never',
                'Every Night',
                'Weeknights'
              ]}
            />
            <FormsyCheckbox
              name="agree"
              label="Do you agree to disagree?"
              style={switchStyle}
            />
            <FormsyToggle
              name="toggle"
              label="Toggle"
              style={switchStyle}
            />
            <FormsyRadioGroup name="shipSpeed" defaultSelected="not_light">
              <FormsyRadio
                value="light"
                label="prepare for light speed"
                style={switchStyle}
              />
              <FormsyRadio
                value="not_light"
                label="light speed too slow"
                style={switchStyle}
              />
              <FormsyRadio
                value="ludicrous"
                label="go to ludicrous speed"
                style={switchStyle}
                disabled={true}
              />
            </FormsyRadioGroup>
            <FormsyText
              name="name"
              validations="isWords"
              validationError={wordsError}
              required
              hintText="What is your name?"
              floatingLabelText="Name"
            />
            <FormsyText
              name="age"
              validations="isNumeric"
              validationError={numericError}
              hintText="Are you a wrinkly?"
              floatingLabelText="Age (optional)"
            />
            <FormsyText
              name="url"
              validations="isUrl"
              validationError={urlError}
              required
              hintText="http://www.example.com"
              floatingLabelText="URL"
              updateImmediately
            />
            <RaisedButton
              style={submitStyle}
              type="submit"
              label="Submit"
              disabled={!this.state.canSubmit}
            />
          </Formsy.Form>
        </Paper>
      </MuiThemeProvider>
    );
  },
});

export default Main;
<commit_msg>Fix lint issue<commit_after>import React from 'react';
import createClass from 'create-react-class';
import Formsy from 'formsy-react';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import Paper from 'material-ui/Paper';
import RaisedButton from 'material-ui/RaisedButton';
import MenuItem from 'material-ui/MenuItem';
import { FormsyCheckbox, FormsyDate, FormsyRadio, FormsyRadioGroup,
    FormsySelect, FormsyText, FormsyTime, FormsyToggle, FormsyAutoComplete } from 'formsy-material-ui/lib';

const Main = createClass({

  /**
   * As an alternative to `MuiThemeProvider` you can add a theme directly into context.
   * See the [Material-UI themes](http://www.material-ui.com/#/customization/themes) docs for details.
   *
   * childContextTypes: {
   *   muiTheme: PropTypes.object,
   * },
   * getChildContext(){
   *   return {
   *     muiTheme: getMuiTheme(),
   *   }
   * },
   */

  getInitialState() {
    return {
      canSubmit: false,
    };
  },

  errorMessages: {
    wordsError: "Please only use letters",
    numericError: "Please provide a number",
    urlError: "Please provide a valid URL",
  },

  styles: {
    paperStyle: {
      width: 300,
      margin: 'auto',
      padding: 20,
    },
    switchStyle: {
      marginBottom: 16,
    },
    submitStyle: {
      marginTop: 32,
    },
  },

  enableButton() {
    this.setState({
      canSubmit: true,
    });
  },

  disableButton() {
    this.setState({
      canSubmit: false,
    });
  },

  submitForm(data) {
    alert(JSON.stringify(data, null, 4));
  },

  notifyFormError(data) {
    console.error('Form error:', data);
  },

  render() {
    let {paperStyle, switchStyle, submitStyle } = this.styles;
    let { wordsError, numericError, urlError } = this.errorMessages;

    return (
      <MuiThemeProvider muiTheme={getMuiTheme()}>
        <Paper style={paperStyle}>
          <Formsy.Form
            onValid={this.enableButton}
            onInvalid={this.disableButton}
            onValidSubmit={this.submitForm}
            onInvalidSubmit={this.notifyFormError}
          >
            <FormsyDate
              name="date"
              required
              floatingLabelText="Date"
            />
            <FormsyTime
              name="time"
              required
              floatingLabelText="Time"
            />
            <FormsySelect
              name="frequency"
              required
              floatingLabelText="How often do you?"
            >
              <MenuItem value={'never'} primaryText="Never" />
              <MenuItem value={'nightly'} primaryText="Every Night" />
              <MenuItem value={'weeknights'} primaryText="Weeknights" />
            </FormsySelect>
            <FormsyAutoComplete
              name="frequency-auto-complete"
              required
              floatingLabelText="How often do you?"
              dataSource={[
                'Never',
                'Every Night',
                'Weeknights',
              ]}
            />
            <FormsyCheckbox
              name="agree"
              label="Do you agree to disagree?"
              style={switchStyle}
            />
            <FormsyToggle
              name="toggle"
              label="Toggle"
              style={switchStyle}
            />
            <FormsyRadioGroup name="shipSpeed" defaultSelected="not_light">
              <FormsyRadio
                value="light"
                label="prepare for light speed"
                style={switchStyle}
              />
              <FormsyRadio
                value="not_light"
                label="light speed too slow"
                style={switchStyle}
              />
              <FormsyRadio
                value="ludicrous"
                label="go to ludicrous speed"
                style={switchStyle}
                disabled={true}
              />
            </FormsyRadioGroup>
            <FormsyText
              name="name"
              validations="isWords"
              validationError={wordsError}
              required
              hintText="What is your name?"
              floatingLabelText="Name"
            />
            <FormsyText
              name="age"
              validations="isNumeric"
              validationError={numericError}
              hintText="Are you a wrinkly?"
              floatingLabelText="Age (optional)"
            />
            <FormsyText
              name="url"
              validations="isUrl"
              validationError={urlError}
              required
              hintText="http://www.example.com"
              floatingLabelText="URL"
              updateImmediately
            />
            <RaisedButton
              style={submitStyle}
              type="submit"
              label="Submit"
              disabled={!this.state.canSubmit}
            />
          </Formsy.Form>
        </Paper>
      </MuiThemeProvider>
    );
  },
});

export default Main;
<|endoftext|>


<commit_before>/*
  SlideShow

  TODO
   * Get filesuffix better
   * Open asset from url!

*/

engine.ImportExtension("qt.core");
engine.ImportExtension("qt.gui");

// connect to Drag events
ui.GraphicsView().DragEnterEvent.connect(handleEnter);
ui.GraphicsView().DragMoveEvent.connect(handleMove);
ui.GraphicsView().DropEvent.connect(handleDrop);
print ('foo')

var entity;
var canvassource;
var slides;
var slide_index = 0;

function checkSuffix(url) {
    // FIXME
    if (("" + url).split('.txt').length == 2) {
	print("I accept!");

	return true;
    }
    print("No sir, I don't like it");
    return false;
}

function accept(event) {

    var mimedata = event.mimeData();

    if (mimedata.hasUrls()) {
	var urls = mimedata.urls();
	for (u = 0; u < urls.length; u++ ) {
	    if (checkSuffix(urls[u])) {
		event.acceptProposedAction();
	    }
	}
    }
}

function handleEnter(event) {
    print("Enter the event!");
    accept(event);
}

function handleMove(event) {
    print("I like to move it move it!");
    accept(event);
}

function handleDrop(event) {
    print ("DROP!");
    accept(event);

    var mimedata = event.mimeData();
    var urls = mimedata.urls();
    for (u = 0; u < urls.length; u++ ) {
	if (checkSuffix(urls[u])) {
	    //FIXME!!!!!!1!
	    print(urls[u]+"");
	    var filename = ("" + urls[u]).split('//')[1];
	    print(filename)
	    var file = new QFile(filename);
	    file.open(QIODevice.ReadOnly);
	    var streamer = new QTextStream(file);
	    slides = [];
	    while (true) {
		var line = streamer.readLine();
		print(line)
		if (!line) {
		    break;
		}
		slides.push(line)
	    }
    	    print(slides);
	    createCanvas(filename, slides, event);
	}
    }
}

function vprint(v) {
    print(v.x + ", " + v.y + ", " + v.z);
}

function crossp(v1, v2) {
    var result = new Vector3df();

    result.x = v1.y * v2.z - v1.z * v2.y;
    result.y = v1.z * v2.x - v1.x * v2.z;
    result.z = v1.x * v2.y - v1.y * v2.x;

    return result;
}

function vadd(v1, v2) {
    var result = new Vector3df();

    result.x = v1.x + v2.x;
    result.y = v1.y + v2.y;
    result.z = v1.z + v2.z;

    return result;
}

function smul(v1, s) {
    var result = new Vector3df();

    result.x = v1.x * s;
    result.y = v1.y * s;
    result.z = v1.z * s;

    return result;
}

function conjg(quat, v) {
    var qvec = new Vector3df();
    qvec.x = quat.x;
    qvec.y = quat.y;
    qvec.z = quat.z;

    var uv = crossp(qvec, v);
    var uuv = crossp(qvec, uv);
    uv = smul(uv, 2.0 * quat.w);
    uuv = smul(uuv, 2.0);

    return vadd(vadd(v, uv), uuv);
}

function createCanvas(filename, slides, event) {
    entity = scene.CreateEntityRaw(scene.NextFreeId(), ['EC_Placeable', 'EC_Mesh', 'EC_3DCanvasSource', 'EC_Name', 'EC_DynamicComponent', 'EC_Script']);

    // set name
    entity.name.name = "Slideshow: " + filename;
    entity.name.description = "Simple slideshow app from " + filename;

    // set mesh
    var mesh_ref = entity.mesh.meshRef;
    mesh_ref.ref = 'local://screen.mesh';
    entity.mesh.meshRef = mesh_ref;

    // set source to first slide
    canvassource = entity.GetComponentRaw('EC_3DCanvasSource')
    canvassource.show2d = false;
    canvassource.source = slides[0];
    canvassource.submesh = 1;

    // Make dynamic component of the slide stuff

    var dyn = entity.dynamiccomponent;

    dyn.Name = "Slidelist";

    for (s = 0; s < slides.length; s++) {
	var slidename = s;
	var attr = dyn.CreateAttribute("string", slidename);
	dyn.SetAttribute(slidename, slides[s] + "");
    }

    dyn.CreateAttribute("int", "Current");
    dyn.SetAttribute("Current", 0);

    var worldpos;

    var res = renderer.Raycast(event.pos().x(), event.pos().y());

    // Calculationg the correct position for dropped slideshow
    if (!res.entity) {
    	// no hit
    	var ids = scene.GetEntityIdsWithComponent('EC_OgreCamera');
    	for (i = 0; i < ids.length; i++) {
	    var camentity = scene.GetEntityRaw(ids[i]);
    	    var placeable = camentity.GetComponentRaw('EC_Placeable');
    	    if (placeable) {
    		var q = placeable.Orientation;

		// create unitvector for negative Z-axis
		var unz = new Vector3df();
		unz.z = -1;

		// calculate conjugate
		var v = conjg(q, unz);
		worldpos = vadd(placeable.Position, smul(v, 20));
    		break;
    	    }
    	}
    } else {
    	worldpos = res.pos();
    }

    // set postition and rotation
    var transform = entity.placeable.transform;

    transform.pos.x = worldpos.x;
    transform.pos.y = worldpos.y;
    transform.pos.z = worldpos.z;
    transform.rot.x = placeable.transform.rot.x - 90;
    transform.rot.y = placeable.transform.rot.y;
    transform.rot.z = placeable.transform.rot.z - 180;

    entity.placeable.transform = transform;

    // ec_script
    var script = entity.script;
    script.type = "js";
    script.runOnLoad = true;
    var r = script.scriptRef;
    r.ref = "local://slideshow.js";
    script.scriptRef = r;

    //FIXME move this and makeslide widget to slideshow.js when
    // appropriate
    // Create UI
    //makeSlideWidget(slides);

    // add buttons

    tempvec = new Vector3df();
    rotvec = new Vector3df();

    tempvec.x = -6;

    rotvec.x = 180;
    rotvec.y = 0

    makeButton('prev', vadd(entity.placeable.Position, tempvec), rotvec);

    tempvec.x = 6;

    rotvec.x = 187;
    rotvec.y = 180

    makeButton('next', vadd(entity.placeable.Position, tempvec), rotvec);

    // Now we are done
    scene.EmitEntityCreatedRaw(entity);

}

function makeButton(name, position, rotation) {
    var button = scene.CreateEntityRaw(scene.NextFreeId(), ['EC_Mesh', 'EC_Placeable', 'EC_Name']);
    button.name.name = 'Button ' + name +' (' + entity.name.name + ')';

    var button_mesh_ref = button.mesh.meshRef;
    button_mesh_ref.ref = 'local://kolmionappi.mesh';
    button.mesh.meshRef = button_mesh_ref;

    var transform = button.placeable.transform;
    transform.pos = position;

    transform.rot = rotation;

    button.placeable.transform = transform;

    scene.EmitEntityCreatedRaw(button);

}

function makeSlideWidget(slides) {
    var gfxscene = new QGraphicsScene();
    var view = new QGraphicsView(gfxscene);

    view.resize(110, 400);

    for (s = 0; s < slides.length; s++) {
	var label = new MyLabel(gfxscene, s);
	var pic = new QPixmap("C:\\Users\\playsign\\sand_d.jpg");
	label.setPixmap(pic.scaledToWidth(100));
	label.move(0, 110 * s);
	gfxscene.addWidget(label)

    }
    uiservice.AddWidgetToScene(view);
    view.show();

}

function MyLabel(parent, slide) {
    this.slide = slide;
    QLabel.call(this, "", parent, 0);
}

MyLabel.prototype = new QLabel();

MyLabel.prototype.mousePressEvent = function (event) {
    event.accept();
    print('AAAAARGH! ' + this.slide);
    var dyn = entity.dynamiccomponent;
    dyn.SetAttribute("Current", this.slide + "");
}
<commit_msg>Got the buttons to right places for sceen in slideshow<commit_after>/*
  SlideShow

  TODO
   * Get filesuffix better
   * Open asset from url!

*/

engine.ImportExtension("qt.core");
engine.ImportExtension("qt.gui");

// connect to Drag events
ui.GraphicsView().DragEnterEvent.connect(handleEnter);
ui.GraphicsView().DragMoveEvent.connect(handleMove);
ui.GraphicsView().DropEvent.connect(handleDrop);
print ('foo')

var entity;
var canvassource;
var slides;
var slide_index = 0;

function checkSuffix(url) {
    // FIXME
    if (("" + url).split('.txt').length == 2) {
	print("I accept!");

	return true;
    }
    print("No sir, I don't like it");
    return false;
}

function accept(event) {

    var mimedata = event.mimeData();

    if (mimedata.hasUrls()) {
	var urls = mimedata.urls();
	for (u = 0; u < urls.length; u++ ) {
	    if (checkSuffix(urls[u])) {
		event.acceptProposedAction();
	    }
	}
    }
}

function handleEnter(event) {
    print("Enter the event!");
    accept(event);
}

function handleMove(event) {
    print("I like to move it move it!");
    accept(event);
}

function handleDrop(event) {
    print ("DROP!");
    accept(event);

    var mimedata = event.mimeData();
    var urls = mimedata.urls();
    for (u = 0; u < urls.length; u++ ) {
	if (checkSuffix(urls[u])) {
	    //FIXME!!!!!!1!
	    print(urls[u]+"");
	    var filename = ("" + urls[u]).split('//')[1];
	    print(filename)
	    var file = new QFile(filename);
	    file.open(QIODevice.ReadOnly);
	    var streamer = new QTextStream(file);
	    slides = [];
	    while (true) {
		var line = streamer.readLine();
		print(line)
		if (!line) {
		    break;
		}
		slides.push(line)
	    }
    	    print(slides);
	    createCanvas(filename, slides, event);
	}
    }
}

function vprint(v) {
    print(v.x + ", " + v.y + ", " + v.z);
}

function crossp(v1, v2) {
    var result = new Vector3df();

    result.x = v1.y * v2.z - v1.z * v2.y;
    result.y = v1.z * v2.x - v1.x * v2.z;
    result.z = v1.x * v2.y - v1.y * v2.x;

    return result;
}

function vadd(v1, v2) {
    var result = new Vector3df();

    result.x = v1.x + v2.x;
    result.y = v1.y + v2.y;
    result.z = v1.z + v2.z;

    return result;
}

function smul(v1, s) {
    var result = new Vector3df();

    result.x = v1.x * s;
    result.y = v1.y * s;
    result.z = v1.z * s;

    return result;
}

function conjg(quat, v) {
    var qvec = new Vector3df();
    qvec.x = quat.x;
    qvec.y = quat.y;
    qvec.z = quat.z;

    var uv = crossp(qvec, v);
    var uuv = crossp(qvec, uv);
    uv = smul(uv, 2.0 * quat.w);
    uuv = smul(uuv, 2.0);

    return vadd(vadd(v, uv), uuv);
}

function createCanvas(filename, slides, event) {
    entity = scene.CreateEntityRaw(scene.NextFreeId(), ['EC_Placeable', 'EC_Mesh', 'EC_3DCanvasSource', 'EC_Name', 'EC_DynamicComponent', 'EC_Script']);

    // set name
    entity.name.name = "Slideshow: " + filename;
    entity.name.description = "Simple slideshow app from " + filename;

    // set mesh
    var mesh_ref = entity.mesh.meshRef;
    mesh_ref.ref = 'local://screen.mesh';
    entity.mesh.meshRef = mesh_ref;

    // set source to first slide
    canvassource = entity.GetComponentRaw('EC_3DCanvasSource')
    canvassource.show2d = false;
    canvassource.source = slides[0];
    canvassource.submesh = 1;

    // Make dynamic component of the slide stuff

    var dyn = entity.dynamiccomponent;

    dyn.Name = "Slidelist";

    for (s = 0; s < slides.length; s++) {
	var slidename = s;
	var attr = dyn.CreateAttribute("string", slidename);
	dyn.SetAttribute(slidename, slides[s] + "");
    }

    dyn.CreateAttribute("int", "Current");
    dyn.SetAttribute("Current", 0);

    var worldpos;

    var res = renderer.Raycast(event.pos().x(), event.pos().y());

    // Calculationg the correct position for dropped slideshow
    if (!res.entity) {
    	// no hit
    	var ids = scene.GetEntityIdsWithComponent('EC_OgreCamera');
    	for (i = 0; i < ids.length; i++) {
	    var camentity = scene.GetEntityRaw(ids[i]);
    	    var placeable = camentity.GetComponentRaw('EC_Placeable');
    	    if (placeable) {
    		var q = placeable.Orientation;

		// create unitvector for negative Z-axis
		var unz = new Vector3df();
		unz.z = -1;

		// calculate conjugate
		var v = conjg(q, unz);
		worldpos = vadd(placeable.Position, smul(v, 20));
    		break;
    	    }
    	}
    } else {
    	worldpos = res.pos();
    }

    // set postition and rotation
    var transform = entity.placeable.transform;

    transform.pos.x = worldpos.x;
    transform.pos.y = worldpos.y;
    transform.pos.z = worldpos.z;
    transform.rot.x = placeable.transform.rot.x - 90;
    transform.rot.y = placeable.transform.rot.y;
    transform.rot.z = placeable.transform.rot.z - 180;

    entity.placeable.transform = transform;

    // ec_script
    var script = entity.script;
    script.type = "js";
    script.runOnLoad = true;
    var r = script.scriptRef;
    r.ref = "local://slideshow.js";
    script.scriptRef = r;

    //FIXME move this and makeslide widget to slideshow.js when
    // appropriate
    // Create UI
    //makeSlideWidget(slides);

    // add buttons

    rotvec = new Vector3df();

    rotvec.x = 180;
    rotvec.y = 0;

    makeButton('prev', entity.placeable, -1, rotvec);

    rotvec.x = 187;
    rotvec.y = 180;

    makeButton('next', entity.placeable, 1, rotvec);

    // Now we are done
    scene.EmitEntityCreatedRaw(entity);

}

function makeButton(name, placeable, dir, rotation) {

    var button = scene.CreateEntityRaw(scene.NextFreeId(), ['EC_Mesh', 'EC_Placeable', 'EC_Name']);
    button.name.name = 'Button ' + name +' (' + entity.name.name + ')';

    var button_mesh_ref = button.mesh.meshRef;
    button_mesh_ref.ref = 'local://kolmionappi.mesh';
    button.mesh.meshRef = button_mesh_ref;

    // create unit vector for X-axis (negative or positive)
    var unx = new Vector3df();
    unx.x = dir;

    // calculate conjugate
    var v = conjg(placeable.Orientation, unx);
    worldpos = vadd(placeable.Position, smul(v, 6));

    var transform = button.placeable.transform;
    transform.pos = worldpos;

    transform.rot = vadd(placeable.transform.rot, rotation);

    button.placeable.transform = transform;

    scene.EmitEntityCreatedRaw(button);

}

function makeSlideWidget(slides) {
    var gfxscene = new QGraphicsScene();
    var view = new QGraphicsView(gfxscene);

    view.resize(110, 400);

    for (s = 0; s < slides.length; s++) {
	var label = new MyLabel(gfxscene, s);
	var pic = new QPixmap("C:\\Users\\playsign\\sand_d.jpg");
	label.setPixmap(pic.scaledToWidth(100));
	label.move(0, 110 * s);
	gfxscene.addWidget(label)

    }
    uiservice.AddWidgetToScene(view);
    view.show();

}

function MyLabel(parent, slide) {
    this.slide = slide;
    QLabel.call(this, "", parent, 0);
}

MyLabel.prototype = new QLabel();

MyLabel.prototype.mousePressEvent = function (event) {
    event.accept();
    print('AAAAARGH! ' + this.slide);
    var dyn = entity.dynamiccomponent;
    dyn.SetAttribute("Current", this.slide + "");
}
<|endoftext|>


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

window.onload = function() {
  // This is half-precise, but false positives will be very rare, so it's ok.
  if (document.title === 'Console') {
    // TODO(ussuri): This won't be needed once owned URLs are registered with the
    // extension in CWS.
    var isInstalledMarker = document.createElement('div');
    isInstalledMarker.id = 'chrome-agent-is-installed';
    document.body.appendChild(isInstalledMarker);
  }
};
<commit_msg>Content script injection is precise now: no need to verify page<commit_after>// Copyright (c) 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

window.onload = function() {
  // TODO(ussuri): This won't be needed once owned URLs are registered with the
  // extension in CWS.
  var isInstalledMarker = document.createElement('div');
  isInstalledMarker.id = 'chrome-agent-is-installed';
  document.body.appendChild(isInstalledMarker);
};
<|endoftext|>


<commit_before>/*

 Created by LingaRaja.

 Has the events and helpers related to home page.

 */

 Meteor.subscribe('featuredimage');

Template.header.events({
    'click #pageName': function() {
        Session.set('selectedPostId',"");
        Session.set("pageId",this._id);
    }
});

Template.header.helpers({
    'pagesList' : function() {
        return Pages.find();
    },
});

Template.home.events({
    'click #postTitle': function() {
        Session.set('selectedPageId',Session.get("pageId"));
        Session.set("pageId","");
        Session.set('selectedPostId',this._id);
        $('#postDetail').fadeIn(10000);
        Router.go("/post/"+this._id);
    },
    'click #backToPage' : function()  {
        console.log('pageId...'+Session.get("pageId"));
        console.log('postid....'+Session.get('selectedPostId'));
        Session.set('selectedPostId',"");
        Session.set("pageId",Session.get("selectedPageId"));
        history.back();
    }
});
Template.home.helpers({
    'postsList' : function() {
        return Posts.find({pageId:Session.get("pageId")});
    },
	'mediaList' : function() {
    	return Media.find();
    },

    'showSelectedPost' : function() {
        if(Session.get('selectedPostId')){
            // var temp = Session.get('selectedPostId');
            // Session.set('selectedPostId',"");
            // console.log('temp.........'+temp);
            return Posts.findOne({_id: Session.get('selectedPostId')});
        }
    },
    'imageList' : function() {
        return featuredimage.find();
    }
});

// Template.home.rendered = function(){
//     console.log('rendered');
//       $('.animate').fadeIn(3000);
// };

// Tracker.afterFlush(function(){
//   $('.animate').delay(1000).fadeOut('slow');
// });
Template.home.animations({
  ".item": {
    container: ".container", // container of the ".item" elements
    in: "animated fast fadeInLeft", // class applied to inserted elements
    out: "animated fast fadeOutRight", // class applied to removed elements
    inCallback: function(element) {}, // callback after an element gets inserted
    outCallback: function(element) {}, // callback after an element gets removed
    delayIn: 500, // Delay before inserted items animate
    delayOut: 500, // Delay before removed items animate
    animateInitial: true, // animate the elements already rendered
    animateInitialStep: 200, // Step between animations for each initial item
    animateInitialDelay: 500 // Delay before the initial items animate
  }
});<commit_msg>Added animation in home page<commit_after>/*

 Created by LingaRaja.

 Has the events and helpers related to home page.

 */

 Meteor.subscribe('featuredimage');

Template.header.events({
    'click #pageName': function() {
        Session.set('selectedPostId',"");
        Session.set("pageId",this._id);
    }
});

Template.header.helpers({
    'pagesList' : function() {
        return Pages.find();
    },
});

Template.home.events({
    'click #postTitle': function() {
        Session.set('selectedPageId',Session.get("pageId"));
        Session.set("pageId","");
        Session.set('selectedPostId',this._id);
        $('#postDetail').fadeIn(10000);
        Router.go("/post/"+this._id);
    },
    'click #backToPage' : function()  {
        console.log('pageId...'+Session.get("pageId"));
        console.log('postid....'+Session.get('selectedPostId'));
        Session.set('selectedPostId',"");
        Session.set("pageId",Session.get("selectedPageId"));
        history.back();
    }
});
Template.home.helpers({
    'postsList' : function() {
        return Posts.find({pageId:Session.get("pageId")});
    },
	'mediaList' : function() {
    	return Media.find();
    },

    'showSelectedPost' : function() {
        if(Session.get('selectedPostId')){
            // var temp = Session.get('selectedPostId');
            // Session.set('selectedPostId',"");
            // console.log('temp.........'+temp);
            return Posts.findOne({_id: Session.get('selectedPostId')});
        }
    },
    'imageList' : function() {
        return featuredimage.find();
    }
});

// Template.home.rendered = function(){
//     console.log('rendered');
//       $('.animate').fadeIn(3000);
// };

// Tracker.afterFlush(function(){
//   $('.animate').delay(1000).fadeOut('slow');
// });
Template.home.animations({
  ".item": {
    container: ".container", // container of the ".item" elements
    in: "animated fast fadeInLeft", // class applied to inserted elements
    out: "animated fast fadeOutRight", // class applied to removed elements
    inCallback: function(element) {}, // callback after an element gets inserted
    outCallback: function(element) {}, // callback after an element gets removed
    delayIn: 500, // Delay before inserted items animate
    delayOut: 500, // Delay before removed items animate
    animateInitial: true, // animate the elements already rendered
    animateInitialStep: 200, // Step between animations for each initial item
    animateInitialDelay: 500 // Delay before the initial items animate
  }
});<|endoftext|>


<commit_before>/*globals qq, XMLHttpRequest*/
/**
 * Sends a POST request to the server to notify it of a successful upload to S3.  The server is expected to indicate success
 * or failure via the response status.  Specific information about the failure can be passed from the server via an `error`
 * property (by default) in an "application/json" response.
 *
 * @param o Options associated with all requests.
 * @returns {{sendSuccessRequest: Function}} API method used to initiate the request.
 * @constructor
 */
qq.s3.UploadSuccessAjaxRequester = function(o) {
    "use strict";

    var requester,
        pendingRequests = [],
        options = {
            method: "POST",
            endpoint: null,
            maxConnections: 3,
            customHeaders: {},
            paramsStore: {},
            cors: {
                expected: false,
                sendCredentials: false
            },
            log: function(str, level) {}
        };

    qq.extend(options, o);

    function handleSuccessResponse(id, xhrOrXdr, isError) {
        var promise = pendingRequests[id],
            responseJson = xhrOrXdr.responseText,
            successIndicator = {success: true},
            failureIndicator = {success: false},
            parsedResponse;

        delete pendingRequests[id];

        options.log(qq.format("Received the following response body to an AWS upload success request for id {}: {}", id, responseJson));

        try {
            parsedResponse = qq.parseJson(responseJson);

            // If this is a cross-origin request, the server may return a 200 response w/ error or success properties
            // in order to ensure any specific error message is picked up by Fine Uploader for all browsers,
            // since XDomainRequest (used in IE9 and IE8) doesn't give you access to the
            // response body for an "error" response.
            if (isError || (parsedResponse && (parsedResponse.error || parsedResponse.success === false))) {
                options.log('Upload success request was rejected by the server.', 'error');
                promise.failure(qq.extend(parsedResponse, failureIndicator));
            }
            else {
                options.log('Upload success was acknowledged by the server.');
                promise.success(qq.extend(parsedResponse, successIndicator));
            }
        }
        catch (error) {
            // This will be executed if a JSON response is not present.  This is not mandatory, so account for this properly.
            if (isError) {
                options.log(qq.format('Your server indicated failure in its AWS upload success request response for id {}!', id), 'error');
                promise.failure(failureIndicator);
            }
            else {
                options.log('Upload success was acknowledged by the server.');
                promise.success(successIndicator);
            }
        }
    }

    requester = new qq.AjaxRequester({
        method: options.method,
        endpointStore: {
            getEndpoint: function() {
                return options.endpoint;
            }
        },
        paramsStore: options.paramsStore,
        maxConnections: options.maxConnections,
        customHeaders: options.customHeaders,
        log: options.log,
        onComplete: handleSuccessResponse,
        cors: options.cors,
        successfulResponseCodes: {
            POST: [200]
        }
    });

    return {
        /**
         * Sends a request to the server, notifying it that a recently submitted file was successfully sent to S3.
         *
         * @param id ID of the associated file
         * @param spec `Object` with the properties that correspond to important values that we want to
         * send to the server with this request.
         * @returns {qq.Promise} A promise to be fulfilled when the response has been received and parsed.  The parsed
         * payload of the response will be passed into the `failure` or `success` promise method.
         */
        sendSuccessRequest: function(id, spec) {
            var promise = new qq.Promise();

            options.log("Submitting upload success request/notification for " + id);

            requester.initTransport(id)
                .withParams(spec)
                .send();

            pendingRequests[id] = promise;

            return promise;
        }
    };
};
<commit_msg>s3/uploadsuccess.ajax.requester.js<commit_after>/*globals qq, XMLHttpRequest*/
/**
 * Sends a POST request to the server to notify it of a successful upload to S3.  The server is expected to indicate success
 * or failure via the response status.  Specific information about the failure can be passed from the server via an `error`
 * property (by default) in an "application/json" response.
 *
 * @param o Options associated with all requests.
 * @returns {{sendSuccessRequest: Function}} API method used to initiate the request.
 * @constructor
 */
qq.s3.UploadSuccessAjaxRequester = function(o) {
    "use strict";

    var requester,
        pendingRequests = [],
        options = {
            method: "POST",
            endpoint: null,
            maxConnections: 3,
            customHeaders: {},
            paramsStore: {},
            cors: {
                expected: false,
                sendCredentials: false
            },
            log: function(str, level) {}
        };

    qq.extend(options, o);

    function handleSuccessResponse(id, xhrOrXdr, isError) {
        var promise = pendingRequests[id],
            responseJson = xhrOrXdr.responseText,
            successIndicator = {success: true},
            failureIndicator = {success: false},
            parsedResponse;

        delete pendingRequests[id];

        options.log(qq.format("Received the following response body to an AWS upload success request for id {}: {}", id, responseJson));

        try {
            parsedResponse = qq.parseJson(responseJson);

            // If this is a cross-origin request, the server may return a 200 response w/ error or success properties
            // in order to ensure any specific error message is picked up by Fine Uploader for all browsers,
            // since XDomainRequest (used in IE9 and IE8) doesn't give you access to the
            // response body for an "error" response.
            if (isError || (parsedResponse && (parsedResponse.error || parsedResponse.success === false))) {
                options.log("Upload success request was rejected by the server.", "error");
                promise.failure(qq.extend(parsedResponse, failureIndicator));
            }
            else {
                options.log("Upload success was acknowledged by the server.");
                promise.success(qq.extend(parsedResponse, successIndicator));
            }
        }
        catch (error) {
            // This will be executed if a JSON response is not present.  This is not mandatory, so account for this properly.
            if (isError) {
                options.log(qq.format("Your server indicated failure in its AWS upload success request response for id {}!", id), "error");
                promise.failure(failureIndicator);
            }
            else {
                options.log("Upload success was acknowledged by the server.");
                promise.success(successIndicator);
            }
        }
    }

    requester = new qq.AjaxRequester({
        method: options.method,
        endpointStore: {
            getEndpoint: function() {
                return options.endpoint;
            }
        },
        paramsStore: options.paramsStore,
        maxConnections: options.maxConnections,
        customHeaders: options.customHeaders,
        log: options.log,
        onComplete: handleSuccessResponse,
        cors: options.cors,
        successfulResponseCodes: {
            POST: [200]
        }
    });

    return {
        /**
         * Sends a request to the server, notifying it that a recently submitted file was successfully sent to S3.
         *
         * @param id ID of the associated file
         * @param spec `Object` with the properties that correspond to important values that we want to
         * send to the server with this request.
         * @returns {qq.Promise} A promise to be fulfilled when the response has been received and parsed.  The parsed
         * payload of the response will be passed into the `failure` or `success` promise method.
         */
        sendSuccessRequest: function(id, spec) {
            var promise = new qq.Promise();

            options.log("Submitting upload success request/notification for " + id);

            requester.initTransport(id)
                .withParams(spec)
                .send();

            pendingRequests[id] = promise;

            return promise;
        }
    };
};
<|endoftext|>


<commit_before>'use strict';
require('./<%= name %>');

//require angular mock for testing
require('angular-mocks');

describe('filter 100000', function() {
    var <%= name %>Filter;
    beforeEach(angular.mock.module('<%= name %>Module'));
    beforeEach(angular.mock.inject(function(_$injector_) {
        <%= name %>Filter = _$injector_.get('<%= name %>Filter');
    }));

    it('should be equal 100,000', function() {
        expect(<%=name %>Filter(100000)).toEqual('100,000');
    });
});
<commit_msg>update template for filter testing<commit_after>'use strict';
require('./<%= name %>');

//require angular mock for testing
require('angular-mocks');

describe('filter 100000', function() {
    var <%= name %>Filter;
    beforeEach(angular.mock.module('<%= name %>Module'));
    beforeEach(angular.mock.inject(function(_$filter_) {
        <%= name %>Filter = _$filter_('<%= name %>Filter');
    }));

    it('should be equal 100,000', function() {
        expect(<%=name %>Filter(100000)).toEqual('100,000');
    });
});
<|endoftext|>


<commit_before>(function($) {

	/**
	 * @class Base edit form, provides ajaxified saving
	 * and reloading itself through the ajax return values.
	 * Takes care of resizing tabsets within the layout container.
	 * @name ss.Form_EditForm
	 */
	$('#Form_EditForm').concrete('ss',function($){
		return/** @lends ss.Form_EditForm */{

			/**
			 * @type String HTML text to show when the form has been deleted.
			 * @todo i18n
			 */
			RemoveHtml: 'Removed',

			onmatch: function() {
				// Don't bind any events here, as we dont replace the
				// full <form> tag by any ajax updates they won't automatically reapply

				_super();
			},

			/**
			 * Suppress submission unless it is handled through ajaxSubmit()
			 */
			onsubmit: function(e) {
				return false;
			},

			/**
			 * @param {DOMElement} button The pressed button (optional)
			 */
			ajaxSubmit: function(button) {
				// default to first button if none given - simulates browser behaviour
				if(!button) button = this.find(':submit:first');

				var self = this;

				this.trigger('ajaxsubmit', {button: button});

				// set button to "submitting" state
				$(button).addClass('loading');

				// @todo TinyMCE coupling
				if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();

				// validate if required
				if(!this.validate()) {
					// TODO Automatically switch to the tab/position of the first error
					statusMessage("Validation failed.", "bad");

					$(button).removeClass('loading');

					return false;
				}

				// get all data from the form
				var data = this.serializeArray();
				// add button action
				data.push({name: $(button).attr('name'), value:'1'});
				$.post(
					this.attr('action'),
					data,
					function(response) {
						$(button).removeClass('loading');

						self._loadResponse(response);
					},
					// @todo Currently all responses are assumed to be evaluated
					'script'
				);

				return false;
			},

			/**
			 * Hook in (optional) validation routines.
			 * Currently clientside validation is not supported out of the box in the CMS.
			 *
			 * @todo Placeholder implementation
			 *
			 * @return {boolean}
			 */
			validate: function() {
				var isValid = true;
				this.trigger('validate', {isValid: isValid});

				return isValid;
			},

			/**
			 * @param String url
			 * @param Function callback (Optional)
			 */
			load: function(url, callback) {
				var self = this;
				$.get(
					url,
					function(response) {
						self._loadResponse(response);
						if(callback) callback.apply(self, [response]);
					},
					// @todo Currently all responses are assumed to be evaluated
					'script'
				);
			},

			/**
			 * Remove everying inside the <form> tag
			 * with a custom HTML fragment. Useful e.g. for deleting a page in the CMS.
			 *
			 * @param {String} removeText Short note why the form has been removed, displayed in
 tags.
			 *  Falls back to the default RemoveText() option (Optional)
			 */
			remove: function(removeText) {
				this.html('
' + removeText + '
');
			},

			/**
			 * Remove all the currently active TinyMCE editors.
			 * Note: Everything that calls this externally has an inappropriate coupling to TinyMCE.
			 */
			cleanup: function() {
				if((typeof tinymce != 'undefined') && tinymce.EditorManager) {
					var id;
					for(id in tinymce.EditorManager.editors) {
						tinymce.EditorManager.editors[id].remove();
					}
					tinymce.EditorManager.editors = {};
				}
			},

			/**
			 * @param {String} result Either HTML for straight insertion, or eval'ed JavaScript.
			 *  If passed as HTML, it is assumed that everying inside the <form> tag is replaced,
			 *  but the old <form> tag itself stays intact.
			 */
			_loadResponse: function(response) {
				this.cleanup();

				var html = response;

				// Rewrite # links
				html = html.replace(/(]+href *= *")#/g, '$1' + window.location.href.replace(/#.*$/,'') + '#');

				// Rewrite iframe links (for IE)
				html = html.replace(/(]*src=")([^"]+)("[^>]*>)/g, '$1' + $('base').attr('href') + '$2$3');

				// Prepare iframes for removal, otherwise we get loading bugs
				this.find('iframe').each(function() {
					this.contentWindow.location.href = 'about:blank';
					this.remove();
				});

				this.html(html);

				if(this.hasClass('validationerror')) {
					statusMessage(ss.i18n._t('ModelAdmin.VALIDATIONERROR', 'Validation Error'), 'bad');
				} else {
					statusMessage(ss.i18n._t('ModelAdmin.SAVED', 'Saved'), 'good');
				}

				Behaviour.apply(); // refreshes ComplexTableField

				// focus input on first form element
				this.find(':input:visible:first').focus();

				this.trigger('loadnewpage', {response: response});
			}
		};
	});

	/**
	 * @class All buttons in the right CMS form go through here by default.
	 * We need this onclick overloading because we can't get to the
	 * clicked button from a form.onsubmit event.
	 * @name ss.Form_EditForm.Actions.submit
	 */
	$('#Form_EditForm .Actions :submit').concrete('ss', function($){
		return/** @lends ss.Form_EditForm.Actions.submit */{
			onmatch: function() {
				var self = this;
				// TODO Fix once concrete library is updated
				this.bind('click', function(e) {self.clickFake(e);});
			},
			clickFake: function(e) {
				$(this[0].form).concrete('ss').ajaxSubmit(this);
				return false;
			}
		};
	});
}(jQuery));<commit_msg>MINOR Supporting override attributes in hidden form fields in LeftAndMain.EditForm.js<commit_after>(function($) {

	/**
	 * @class Base edit form, provides ajaxified saving
	 * and reloading itself through the ajax return values.
	 * Takes care of resizing tabsets within the layout container.
	 * @name ss.Form_EditForm
	 */
	$('#Form_EditForm').concrete('ss',function($){
		return/** @lends ss.Form_EditForm */{

			/**
			 * @type String HTML text to show when the form has been deleted.
			 * @todo i18n
			 */
			RemoveHtml: 'Removed',

			onmatch: function() {
				// Don't bind any events here, as we dont replace the
				// full <form> tag by any ajax updates they won't automatically reapply

				_super();
			},

			/**
			 * Suppress submission unless it is handled through ajaxSubmit()
			 */
			onsubmit: function(e) {
				return false;
			},

			/**
			 * @param {DOMElement} button The pressed button (optional)
			 */
			ajaxSubmit: function(button) {
				// default to first button if none given - simulates browser behaviour
				if(!button) button = this.find(':submit:first');

				var self = this;

				this.trigger('ajaxsubmit', {button: button});

				// set button to "submitting" state
				$(button).addClass('loading');

				// @todo TinyMCE coupling
				if(typeof tinyMCE != 'undefined') tinyMCE.triggerSave();

				// validate if required
				if(!this.validate()) {
					// TODO Automatically switch to the tab/position of the first error
					statusMessage("Validation failed.", "bad");

					$(button).removeClass('loading');

					return false;
				}

				// get all data from the form
				var data = this.serializeArray();
				// add button action
				data.push({name: $(button).attr('name'), value:'1'});
				$.post(
					this.attr('action'),
					data,
					function(response) {
						$(button).removeClass('loading');

						self._loadResponse(response);
					},
					// @todo Currently all responses are assumed to be evaluated
					'script'
				);

				return false;
			},

			/**
			 * Hook in (optional) validation routines.
			 * Currently clientside validation is not supported out of the box in the CMS.
			 *
			 * @todo Placeholder implementation
			 *
			 * @return {boolean}
			 */
			validate: function() {
				var isValid = true;
				this.trigger('validate', {isValid: isValid});

				return isValid;
			},

			/**
			 * @param String url
			 * @param Function callback (Optional)
			 */
			load: function(url, callback) {
				var self = this;
				$.get(
					url,
					function(response) {
						self._loadResponse(response);
						if(callback) callback.apply(self, [response]);
					},
					// @todo Currently all responses are assumed to be evaluated
					'script'
				);
			},

			/**
			 * Remove everying inside the <form> tag
			 * with a custom HTML fragment. Useful e.g. for deleting a page in the CMS.
			 *
			 * @param {String} removeText Short note why the form has been removed, displayed in
 tags.
			 *  Falls back to the default RemoveText() option (Optional)
			 */
			remove: function(removeText) {
				this.html('
' + removeText + '
');
			},

			/**
			 * Remove all the currently active TinyMCE editors.
			 * Note: Everything that calls this externally has an inappropriate coupling to TinyMCE.
			 */
			cleanup: function() {
				if((typeof tinymce != 'undefined') && tinymce.EditorManager) {
					var id;
					for(id in tinymce.EditorManager.editors) {
						tinymce.EditorManager.editors[id].remove();
					}
					tinymce.EditorManager.editors = {};
				}
			},

			/**
			 * @param {String} result Either HTML for straight insertion, or eval'ed JavaScript.
			 *  If passed as HTML, it is assumed that everying inside the <form> tag is replaced,
			 *  but the old <form> tag itself stays intact.
			 */
			_loadResponse: function(response) {
				this.cleanup();

				var html = response;

				// Rewrite # links
				html = html.replace(/(]+href *= *")#/g, '$1' + window.location.href.replace(/#.*$/,'') + '#');

				// Rewrite iframe links (for IE)
				html = html.replace(/(]*src=")([^"]+)("[^>]*>)/g, '$1' + $('base').attr('href') + '$2$3');

				// Prepare iframes for removal, otherwise we get loading bugs
				this.find('iframe').each(function() {
					this.contentWindow.location.href = 'about:blank';
					this.remove();
				});

				this.html(html);
				// Optionally get the form attributes from embedded fields, see Form->formHtmlContent()
				for(var overrideAttr in {'action':true,'method':true,'enctype':true,'name':true}) {
					var el = this.find(':input[name='+ '_form_' + overrideAttr + ']');
					if(el) {
						this.attr(overrideAttr, el.val());
						el.remove();
					}
				}

				if(this.hasClass('validationerror')) {
					statusMessage(ss.i18n._t('ModelAdmin.VALIDATIONERROR', 'Validation Error'), 'bad');
				} else {
					statusMessage(ss.i18n._t('ModelAdmin.SAVED', 'Saved'), 'good');
				}

				Behaviour.apply(); // refreshes ComplexTableField

				// focus input on first form element
				this.find(':input:visible:first').focus();

				this.trigger('loadnewpage', {response: response});
			}
		};
	});

	/**
	 * @class All buttons in the right CMS form go through here by default.
	 * We need this onclick overloading because we can't get to the
	 * clicked button from a form.onsubmit event.
	 * @name ss.Form_EditForm.Actions.submit
	 */
	$('#Form_EditForm .Actions :submit').concrete('ss', function($){
		return/** @lends ss.Form_EditForm.Actions.submit */{
			onmatch: function() {
				var self = this;
				// TODO Fix once concrete library is updated
				this.bind('click', function(e) {self.clickFake(e);});
			},
			clickFake: function(e) {
				$(this[0].form).concrete('ss').ajaxSubmit(this);
				return false;
			}
		};
	});
}(jQuery));<|endoftext|>


<commit_before>const SubleaseObject = {
  additional_fees: '',
  address: '',
  appalcart: '0',
  bathroom_no: '1',
  bedroom_no: '1',
  campus_distance: '0',
  contact_info: '0',
  description: '',
  dishwasher: '0',
  furnished: '0',
  internet_type: '1',
  landlord_perm: '0',
  laundry_type: '0',
  lease_type: '0',
  monthly_rent: '0',
  move_in_date: 0,
  move_out_date: 0,
  name: '',
  parking_per_unit: '1',
  pets_allowed: '0',
  proptype: '0',
  smoking_allowed: '0',
  trash_type: '0',
  tv_type: '0',
  utilities_inc: '0',
}

export default SubleaseObject
<commit_msg>air conditioning added<commit_after>const SubleaseObject = {
  additional_fees: '',
  address: '',
  airconditioning: '0',
  appalcart: '0',
  bathroom_no: '1',
  bedroom_no: '1',
  campus_distance: '0',
  contact_info: '0',
  description: '',
  dishwasher: '0',
  furnished: '0',
  internet_type: '1',
  landlord_perm: '0',
  laundry_type: '0',
  lease_type: '0',
  monthly_rent: '0',
  move_in_date: 0,
  move_out_date: 0,
  name: '',
  parking_per_unit: '1',
  pets_allowed: '0',
  proptype: '0',
  smoking_allowed: '0',
  trash_type: '0',
  tv_type: '0',
  utilities_inc: '0',
}

export default SubleaseObject
<|endoftext|>


<commit_before>var startDate;
exports.config = {
  seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
  // seleniumAddress: 'selenium-hub:4444',

  framework: 'custom',
  params: {
    testDomainURL: ''
  },
  // path relative to the current config file
  frameworkPath: require.resolve('protractor-cucumber-framework'),

  //  capabilities: {
  //     'browserName': 'firefox'/*,
  //     'chromeOptions': {
  //       'args': ['--headless', '--disable-gpu'],
  //       'mobileEmulation' : {
  //         'deviceName': 'Apple iPhone 6 Plus'
  //       }
  //     }*/
  //   },
  multiCapabilities: [{
    'browserName': 'chrome'
  }],

  // restartBrowserBetweenTests: true,

  // Spec patterns are relative to this directory.
  specs: [
    'features/sample_application/hashing.feature'
  ],

  resultJsonOutputFile: 'reports/cucumber_reports/report.json',

  cucumberOpts: {
    require: ['features/step_definitions/servoy_step_definitions.js',
      'env.js'/*,
              'features/step_definitions/hooks.js'*/],
    tags: false,
    // format: ['json:reports/cucumber_reports/report.json', 'pretty'],
    format: 'pretty',
    profile: false,
    keepAlive: false,
    'no-source': true
  },

  beforeLaunch: () => {
    console.log('beforeLaunch');
    startDate = new Date();
    var path = require('path');
    var proc = require('process');
    var fs = require('fs');
    var pathToCreate = proc.cwd() + '/reports/cucumber_reports';
    pathToCreate.split(path.sep).reduce(function(currentPath, folder){
      currentPath += folder + path.sep;
      if(!fs.existsSync(currentPath)) {
        fs.mkdirSync(currentPath);
      }
      return currentPath;
    },'');
  },

  onPrepare: () => {
    console.log('onPrepare');
    // browser.driver.manage().window().maximize();
    browser.driver.executeScript(function () {
      return {
        width: window.screen.availWidth,
        height: window.screen.availHeight
      };
    }).then(function (result) {
      browser.driver.manage().window().setSize(result.width, result.height);
    });
  },

  onComplete: () => {
    console.log('onComplete');
  },

  onCleanUp: () => {
    console.log('onCleanUp');
  },

  afterLaunch: () => {
    console.log('afterLaunch');
    var proc = require('process');
    var fs = require('fs');
    var json = fs.readFileSync(proc.cwd() + '/reports/cucumber_reports/report.json');
    var a = JSON.parse(json);
    var scenarioSucceeded = a.length;
    for (var x in a) {
      var duration = 0;
      var failed = 0;
      var succeeded = 0;
      var skipped = 0;
      var scenarioFailed = 0;

      console.log("Scenario: " + a[x].description);
      for (var y in a[x].events) {
        console.log("\tCucumber step: \t\t\t\t" + a[x].events[y].name);
        //bug in protractor, if it's skipped, the step still counts as passed
        if (a[x].events[y].durationMillis > 0) {//no check means an NaN error
          // console.log("\tCucumber step: \t\t\t\t" + a[x].events[y].name);
          console.log("\tSuccess/fail: \t\t\t\t" + a[x].events[y].emitterEvent);
          console.log("\tDuration cucumber step: \t\t" + a[x].events[y].durationMillis + " miliseconds");
        } else {
          console.log("\tCucumber step: \t\t\t\ttestSkipped");
          console.log("\tDuration cucumber step: \t\tN/A");
          skipped++;
        }

        console.log();
        if (a[x].events[y].durationMillis > 0) {
          duration += a[x].events[y].durationMillis;
        }
        if (a[x].events[y].emitterEvent == "testPass" && a[x].events[y].durationMillis > 0) { //a skipped test still counts as passed in protractors JSON results file
          succeeded++;
        } else if (a[x].events[y].emitterEvent == "testFail") {
          failed++;
          scenarioSucceeded--;
        }
      }
      console.log('\tCucumber steps passed:\t' + succeeded);
      console.log('\tCucumber steps failed:\t' + failed);
      console.log('\tCucumber steps skipped:\t' + skipped);
      console.log("\tScenario ended after: " + duration + " miliseconds");
      console.log();
    }
    console.log('Scenarios passed:\t' + scenarioSucceeded);
    console.log('Scenarios failed:\t' + (a.length - scenarioSucceeded));
    console.log('Test(s) ended after: ' + ((new Date() - startDate) / 1000) + ' seconds.');
    // console.log(JSON.stringify(a, null, "    "));
    browser.restart();
  }
};<commit_msg>Added browser to report<commit_after>var startDate;
var browserName;
exports.config = {
  seleniumAddress: 'http://127.0.0.1:4444/wd/hub',
  // seleniumAddress: 'selenium-hub:4444',

  framework: 'custom',
  params: {
    testDomainURL: ''
  },
  // path relative to the current config file
  frameworkPath: require.resolve('protractor-cucumber-framework'),

  //  capabilities: {
  //     'browserName': 'firefox'/*,
  //     'chromeOptions': {
  //       'args': ['--headless', '--disable-gpu'],
  //       'mobileEmulation' : {
  //         'deviceName': 'Apple iPhone 6 Plus'
  //       }
  //     }*/
  //   },
  multiCapabilities: [{
    'browserName': 'chrome'
  }],

  // restartBrowserBetweenTests: true,

  // Spec patterns are relative to this directory.
  specs: [
    'features/sample_application/hashing.feature'
  ],

  resultJsonOutputFile: 'reports/cucumber_reports/report.json',

  cucumberOpts: {
    require: ['features/step_definitions/servoy_step_definitions.js',
      'env.js'/*,
              'features/step_definitions/hooks.js'*/],
    tags: false,
    // format: ['json:reports/cucumber_reports/report.json', 'pretty'],
    format: 'pretty',
    profile: false,
    keepAlive: false,
    'no-source': true
  },

  beforeLaunch: () => {
    console.log('beforeLaunch');
    startDate = new Date();
    var path = require('path');
    var proc = require('process');
    var fs = require('fs');
    var pathToCreate = proc.cwd() + '/reports/cucumber_reports';
    pathToCreate.split(path.sep).reduce(function(currentPath, folder){
      currentPath += folder + path.sep;
      if(!fs.existsSync(currentPath)) {
        fs.mkdirSync(currentPath);
      }
      return currentPath;
    },'');
  },

  onPrepare: () => {
    console.log('onPrepare');
    // browser.driver.manage().window().maximize();
    browser.driver.executeScript(function () {
      return {
        width: window.screen.availWidth,
        height: window.screen.availHeight
      };
    }).then(function (result) {
      browser.driver.manage().window().setSize(result.width, result.height);
    });
  },

  onComplete: () => {
    console.log('onComplete');
    browser.getCapabilities().then((c) => {
      browserName = c.get('browserName');
    });
  },

  onCleanUp: () => {
    console.log('onCleanUp');
  },

  afterLaunch: () => {
    console.log('afterLaunch');
    var proc = require('process');
    var fs = require('fs');
    var json = fs.readFileSync(proc.cwd() + '/reports/cucumber_reports/report.json');
    var a = JSON.parse(json);
    var scenarioSucceeded = a.length;
    console.log('Browser: ' + browserName)
    for (var x in a) {
      var duration = 0;
      var failed = 0;
      var succeeded = 0;
      var skipped = 0;
      var scenarioFailed = 0;

      console.log("Scenario: " + a[x].description);
      for (var y in a[x].events) {
        console.log("\tCucumber step: \t\t\t\t" + a[x].events[y].name);
        //bug in protractor, if it's skipped, the step still counts as passed
        if (a[x].events[y].durationMillis > 0) {//no check means an NaN error
          // console.log("\tCucumber step: \t\t\t\t" + a[x].events[y].name);
          console.log("\tSuccess/fail: \t\t\t\t" + a[x].events[y].emitterEvent);
          console.log("\tDuration cucumber step: \t\t" + a[x].events[y].durationMillis + " miliseconds");
        } else {
          console.log("\tCucumber step: \t\t\t\ttestSkipped");
          console.log("\tDuration cucumber step: \t\tN/A");
          skipped++;
        }

        console.log();
        if (a[x].events[y].durationMillis > 0) {
          duration += a[x].events[y].durationMillis;
        }
        if (a[x].events[y].emitterEvent == "testPass" && a[x].events[y].durationMillis > 0) { //a skipped test still counts as passed in protractors JSON results file
          succeeded++;
        } else if (a[x].events[y].emitterEvent == "testFail") {
          failed++;
          scenarioSucceeded--;
        }
      }
      console.log('\tCucumber steps passed:\t' + succeeded);
      console.log('\tCucumber steps failed:\t' + failed);
      console.log('\tCucumber steps skipped:\t' + skipped);
      console.log("\tScenario ended after: " + duration + " miliseconds");
      console.log();
    }
    console.log('Scenarios passed:\t' + scenarioSucceeded);
    console.log('Scenarios failed:\t' + (a.length - scenarioSucceeded));
    console.log('Test(s) ended after: ' + ((new Date() - startDate) / 1000) + ' seconds.');
    // console.log(JSON.stringify(a, null, "    "));
    browser.restart();
  }
};<|endoftext|>


<commit_before>// ==========================================================================
// Project:   SproutCore - JavaScript Application Framework
// Copyright: ©2006-2009 Sprout Systems, Inc. and contributors.
//            Portions ©2008-2009 Apple Inc. All rights reserved.
// License:   Licened under MIT license (see license.js)
// ==========================================================================

sc_require('mixins/border');

/** @class

  Implements a complete scroll view.  This class uses a manual implementation
  of scrollers in order to properly support clipping frames.

  Important Events:

  - contentView frame size changes (to autoshow/hide scrollbar - adjust scrollbar size)
  - horizontalScrollOffset change
  - verticalScrollOffsetChanges
  - scroll wheel events

  @extends SC.View
  @since SproutCore 1.0
*/
SC.TouchScrollView = SC.View.extend(SC.Border, {
  classNames: ['sc-touch-scroll-view'],

  // ..........................................................
  // PROPERTIES
  //

  isScrollable: YES,

  /**
    The content view you want the scroll view to manage. This will be assigned to the contentView of the clipView also.
  */
  contentView: null,

  /**
    The current horizontal scroll offset. Changing this value will update both the contentView and the horizontal scroller, if there is one.
  */
  horizontalScrollOffset: function(key, value) {
    if (value !== undefined) {
      this._scroll_horizontalScrollOffset = Math.max(0,Math.min(this.get('maximumHorizontalScrollOffset'), value)) ;
    }

    return this._scroll_horizontalScrollOffset||0;
  }.property().cacheable(),

  /**
    The current vertical scroll offset.  Changing this value will update both the contentView and the vertical scroller, if there is one.
  */
  verticalScrollOffset: 0,
  // verticalScrollOffset: function(key, value) {
  //   if (value !== undefined) {
  //     this._scroll_verticalScrollOffset = Math.max(0,Math.min(this.get('maximumVerticalScrollOffset'), value)) ;
  //   }
  //
  //   return this._scroll_verticalScrollOffset||0;
  // }.property().cacheable(),

  /**
    The maximum horizontal scroll offset allowed given the current contentView
    size and the size of the scroll view.  If horizontal scrolling is
    disabled, this will always return 0.

    @property {Number}
  */
  maximumHorizontalScrollOffset: function() {
    if (!this.get('canScrollHorizontal')) return 0 ;
    var view = this.get('contentView') ;
    var contentWidth = view ? view.get('frame').width : 0 ;

    // The following code checks if there is a calculatedWidth (collections)
    // to avoid looking at the incorrect value calculated by frame.
    if(view.calculatedWidth && view.calculatedWidth!==0){
      contentWidth = view.calculatedWidth;
    }
    var containerWidth = this.get('containerView').get('frame').width ;
    return Math.max(0, contentWidth-containerWidth) ;
  }.property(),

  /**
    The maximum vertical scroll offset allowed given the current contentView
    size and the size of the scroll view.  If vertical scrolling is disabled,
    this will always return 0.

    @property {Number}
  */
  maximumVerticalScrollOffset: function() {
    if (!this.get('canScrollVertical')) return 0 ;
    var view = this.get('contentView') ;
    var contentHeight = (view && view.get('frame')) ? view.get('frame').height : 0 ;

    // The following code checks if there is a calculatedWidth (collections)
    // to avoid looking at the incorrect value calculated by frame.
    if(view.calculatedHeight && view.calculatedHeight!==0){
      contentHeight = view.calculatedHeight;
    }
    var containerHeight = this.get('containerView').get('frame').height ;
    return Math.max(0, contentHeight-containerHeight) ;
  }.property(),

  /**
    Amount to scroll one vertical line.

    Used by the default implementation of scrollDownLine() and scrollUpLine().
    Defaults to 20px.
  */
  verticalLineScroll: 20,

  /**
    Amount to scroll one horizontal line.

    Used by the default implementation of scrollLeftLine() and
    scrollRightLine(). Defaults to 20px.
  */
  horizontalLineScroll: 20,

  /**
    Amount to scroll one vertical page.

    Used by the default implementation of scrollUpPage() and scrollDownPage().
    Defaults to current frame height.
  */
  verticalPageScroll: function() {
    return this.get('frame').height ;
  }.property('frame'),

  /**
    Amount to scroll one horizontal page.

    Used by the default implementation of scrollLeftPage() and
    scrollRightPage().  Defaults to current innerFrame width.
  */
  horizontalPageScroll: function() {
    return this.get('frame').width ;
  }.property('frame'),

  // ..........................................................
  // SCROLLERS
  //

  /**
    YES if the view should maintain a horizontal scroller.   This property
    must be set when the view is created.

    @property {Boolean}
  */
  hasHorizontalScroller: YES,

  /**
    The horizontal scroller view class. This will be replaced with a view
    instance when the ScrollView is created unless hasHorizontalScroller is
    NO.

    @property {SC.View}
  */
  horizontalScrollerView: SC.ScrollerView,

  /**
    YES if the horizontal scroller should be visible.  You can change this
    property value anytime to show or hide the horizontal scroller.  If you
    do not want to use a horizontal scroller at all, you should instead set
    hasHorizontalScroller to NO to avoid creating a scroller view in the
    first place.

    @property {Boolean}
  */
  isHorizontalScrollerVisible: YES,

  /**
    Returns YES if the view both has a horizontal scroller, the scroller is
    visible.

    @property {Boolean}
  */
  canScrollHorizontal: function() {
    return !!(this.get('hasHorizontalScroller') &&
      this.get('horizontalScrollerView') &&
      this.get('isHorizontalScrollerVisible')) ;
  }.property('isHorizontalScrollerVisible').cacheable(),

  /**
    If YES, the horizontal scroller will autohide if the contentView is
    smaller than the visible area.  You must set hasHorizontalScroller to YES
    for this property to have any effect.
  */
  autohidesHorizontalScroller: YES,

  /**
    YES if the view shuld maintain a vertical scroller.   This property must
    be set when the view is created.

    @property {Boolean}
  */
  hasVerticalScroller: YES,

  /**
    The vertical scroller view class. This will be replaced with a view
    instance when the ScrollView is created unless hasVerticalScroller is NO.

    @property {SC.View}
  */
  verticalScrollerView: SC.ScrollerView,

  /**
    YES if the vertical scroller should be visible.  You can change this
    property value anytime to show or hide the vertical scroller.  If you do
    not want to use a vertical scroller at all, you should instead set
    hasVerticalScroller to NO to avoid creating a scroller view in the first
    place.

    @property {Boolean}
  */
  isVerticalScrollerVisible: YES,

  /**
    Returns YES if the view both has a horizontal scroller, the scroller is
    visible.

    @property {Boolean}
  */
  canScrollVertical: function() {
    return !!(this.get('hasVerticalScroller') &&
      this.get('verticalScrollerView') &&
      this.get('isVerticalScrollerVisible')) ;
  }.property('isVerticalScrollerVisible').cacheable(),

  /**
    If YES, the vertical scroller will autohide if the contentView is
    smaller than the visible area.  You must set hasVerticalScroller to YES
    for this property to have any effect.
  */
  autohidesVerticalScroller: YES,

  /**
    Use this property to set the 'bottom' offset of your vertical scroller,
    to make room for a thumb view or other accessory view. Default is 0.

    @property {Number}
  */
  verticalScrollerBottom: 0,

  // ..........................................................
  // CUSTOM VIEWS
  //

  /**
    The container view that will contain your main content view.  You can
    replace this property with your own custom subclass if you prefer.

    @type {SC.ContainerView}
  */
  containerView: SC.ContainerView,

  // ..........................................................
  // METHODS
  //

  /**
    Scrolls the receiver to the specified x,y coordinate.  This should be the
    offset into the contentView you want to appear at the top-left corner of
    the scroll view.

    This method will contrain the actual scroll based on whether the view
    can scroll in the named direction and the maximum distance it can
    scroll.

    If you only want to scroll in one direction, pass null for the other
    direction.  You can also optionally pass a Hash for the first parameter
    with x and y coordinates.

    @param x {Number} the x scroll location
    @param y {Number} the y scroll location
    @returns {SC.ScrollView} receiver
  */
  scrollTo: function(x,y) {
    // normalize params
    if (y===undefined && SC.typeOf(x) === SC.T_HASH) {
      y = x.y; x = x.x;
    }

    if (!SC.none(x)) {
      x = Math.max(0,Math.min(this.get('maximumHorizontalScrollOffset'), x)) ;
      this.set('horizontalScrollOffset', x) ;
    }

    if (!SC.none(y)) {
      y = Math.max(0,Math.min(this.get('maximumVerticalScrollOffset'), y)) ;
      this.set('verticalScrollOffset', y) ;
    }

    return this ;
  },

  /**
    Scrolls the receiver in the horizontal and vertical directions by the
    amount specified, if allowed.  The actual scroll amount will be
    constrained by the current scroll view settings.

    If you only want to scroll in one direction, pass null or 0 for the other
    direction.  You can also optionally pass a Hash for the first parameter
    with x and y coordinates.

    @param x {Number} change in the x direction (or hash)
    @param y {Number} change in the y direction
    @returns {SC.ScrollView} receiver
  */
  scrollBy: function(x , y) {
    // normalize params
    if (y===undefined && SC.typeOf(x) === SC.T_HASH) {
      y = x.y; x = x.x;
    }

    // if null, undefined, or 0, pass null; otherwise just add current offset
    x = (x) ? this.get('horizontalScrollOffset')+x : null ;
    y = (y) ? this.get('verticalScrollOffset')+y : null ;
    return this.scrollTo(x,y) ;
  },

  /**
    Scroll the view to make the view's frame visible.  For this to make sense,
    the view should be a subview of the contentView.  Otherwise the results
    will be undefined.

    @param {SC.View} view view to scroll or null to scroll receiver visible
    @returns {Boolean} YES if scroll position was changed
  */
  scrollToVisible: function(view) {

    // if no view is passed, do default
    if (arguments.length === 0) return sc_super();

    var contentView = this.get('contentView') ;
    if (!contentView) return NO; // nothing to do if no contentView.

    // get the frame for the view - should work even for views with static
    // layout, assuming it has been added to the screen.
    var vf = view.get('frame');
    if (!vf) return NO; // nothing to do

    // convert view's frame to an offset from the contentView origin.  This
    // will become the new scroll offset after some adjustment.
    vf = contentView.convertFrameFromView(vf, view.get('parentView')) ;

    // find current visible frame.
    var vo = SC.cloneRect(this.get('containerView').get('frame')) ;

    vo.x = this.get('horizontalScrollOffset') ;
    vo.y = this.get('verticalScrollOffset') ;

    var origX = vo.x, origY = vo.y;

    // if top edge is not visible, shift origin
    vo.y -= Math.max(0, SC.minY(vo) - SC.minY(vf)) ;
    vo.x -= Math.max(0, SC.minX(vo) - SC.minX(vf)) ;

    // if bottom edge is not visible, shift origin
    vo.y += Math.max(0, SC.maxY(vf) - SC.maxY(vo)) ;
    vo.x += Math.max(0, SC.maxX(vf) - SC.maxX(vo)) ;

    // scroll to that origin.
    if ((origX !== vo.x) || (origY !== vo.y)) {
      this.scrollTo(vo.x, vo.y);
      return YES ;
    } else return NO;
  },

  /**
    Scrolls the receiver down one or more lines if allowed.  If number of
    lines is not specified, scrolls one line.

    @param lines {Number} options number of lines
    @returns {SC.ScrollView} receiver
  */
  scrollDownLine: function(lines) {
    if (lines === undefined) lines = 1 ;
    return this.scrollBy(null, this.get('verticalLineScroll')*lines) ;
  },

  /**
    Scrolls the receiver up one or more lines if allowed.  If number of
    lines is not specified, scrolls one line.

    @param lines {Number} options number of lines
    @returns {SC.ScrollView} receiver
  */
  scrollUpLine: function(lines) {
    if (lines === undefined) lines = 1 ;
    return this.scrollBy(null, 0-this.get('verticalLineScroll')*lines) ;
  },

  /**
    Scrolls the receiver right one or more lines if allowed.  If number of
    lines is not specified, scrolls one line.

    @param lines {Number} options number of lines
    @returns {SC.ScrollView} receiver
  */
  scrollRightLine: function(lines) {
    if (lines === undefined) lines = 1 ;
    return this.scrollTo(this.get('horizontalLineScroll')*lines, null) ;
  },

  /**
    Scrolls the receiver left one or more lines if allowed.  If number of
    lines is not specified, scrolls one line.

    @param lines {Number} options number of lines
    @returns {SC.ScrollView} receiver
  */
  scrollLeftLine: function(lines) {
    if (lines === undefined) lines = 1 ;
    return this.scrollTo(0-this.get('horizontalLineScroll')*lines, null) ;
  },

  /**
    Scrolls the receiver down one or more page if allowed.  If number of
    pages is not specified, scrolls one page.  The page size is determined by
    the verticalPageScroll value.  By default this is the size of the current
    scrollable area.

    @param pages {Number} options number of pages
    @returns {SC.ScrollView} receiver
  */
  scrollDownPage: function(pages) {
    if (pages === undefined) pages = 1 ;
    return this.scrollBy(null, this.get('verticalPageScroll')*pages) ;
  },

  /**
    Scrolls the receiver up one or more page if allowed.  If number of
    pages is not specified, scrolls one page.  The page size is determined by
    the verticalPageScroll value.  By default this is the size of the current
    scrollable area.

    @param pages {Number} options number of pages
    @returns {SC.ScrollView} receiver
  */
  scrollUpPage: function(pages) {
    if (pages === undefined) pages = 1 ;
    return this.scrollBy(null, 0-(this.get('verticalPageScroll')*pages)) ;
  },

  /**
    Scrolls the receiver right one or more page if allowed.  If number of
    pages is not specified, scrolls one page.  The page size is determined by
    the verticalPageScroll value.  By default this is the size of the current
    scrollable area.

    @param pages {Number} options number of pages
    @returns {SC.ScrollView} receiver
  */
  scrollRightPage: function(pages) {
    if (pages === undefined) pages = 1 ;
    return this.scrollBy(this.get('horizontalPageScroll')*pages, null) ;
  },

  /**
    Scrolls the receiver left one or more page if allowed.  If number of
    pages is not specified, scrolls one page.  The page size is determined by
    the verticalPageScroll value.  By default this is the size of the current
    scrollable area.

    @param pages {Number} options number of pages
    @returns {SC.ScrollView} receiver
  */
  scrollLeftPage: function(pages) {
    if (pages === undefined) pages = 1 ;
    return this.scrollBy(0-(this.get('horizontalPageScroll')*pages), null) ;
  },

  /**
    Adjusts the layout for the various internal views.  This method is called
    once when the scroll view is first configured and then anytime a scroller
    is shown or hidden.  You can call this method yourself as well to retile.

    You may also want to override this method to handle layout for any
    additional controls you have added to the view.
  */
  tile: function() {
    // get horizontal scroller/determine if we should have a scroller
    var hscroll = this.get('hasHorizontalScroller') ? this.get('horizontalScrollerView') : null ;
    var hasHorizontal = hscroll && this.get('isHorizontalScrollerVisible');

    // get vertical scroller/determine if we should have a scroller
    var vscroll = this.get('hasVerticalScroller') ? this.get('verticalScrollerView') : null ;
    var hasVertical = vscroll && this.get('isVerticalScrollerVisible') ;

    // get the containerView
    var clip = this.get('containerView') ;
    var clipLayout = { left: 0, top: 0 } ;
    var t ;

    var ht = ((hasHorizontal) ? hscroll.get('scrollbarThickness') : 0) ;
    var vt = (hasVertical) ?   vscroll.get('scrollbarThickness') : 0 ;

    if (hasHorizontal) {
      hscroll.set('layout', { left: 0, bottom: 0, right: vt-1, height: ht }) ;
      clipLayout.bottom = ht-1 ;
    } else {
      clipLayout.bottom = 0 ;
    }
    if (hscroll) hscroll.set('isVisible', hasHorizontal) ;

    if (hasVertical) {
      ht = ht + this.get('verticalScrollerBottom') ;
      vscroll.set('layout', { top: 0, bottom: ht, right: 0, width: vt }) ;
      clipLayout.right = vt-1 ;
    } else {
      clipLayout.right = 0 ;
    }
    if (vscroll) vscroll.set('isVisible', hasVertical) ;

    clip.set('layout', clipLayout) ;
  },

  /** @private
    Called whenever a scroller visibility changes.  Calls the tile() method.
  */
  scrollerVisibilityDidChange: function() {
    this.tile();
  }.observes('isVerticalScrollerVisible', 'isHorizontalScrollerVisible'),

  // ..........................................................
  // SCROLL WHEEL SUPPORT
  //

  /** @private */ _scroll_wheelDeltaX: 0,
  /** @private */ _scroll_wheelDeltaY: 0,

  // save adjustment and then invoke the actual scroll code later.  This will
  // keep the view feeling smooth.
  mouseWheel: function(evt) {
    this._scroll_wheelDeltaX += evt.wheelDeltaX;
    this._scroll_wheelDeltaY += evt.wheelDeltaY;
    this.invokeLater(this._scroll_mouseWheel, 10) ;
    return this.get('canScrollHorizontal') || this.get('canScrollVertical') ;
  },

  /** @private */
  _scroll_mouseWheel: function() {
    this.scrollBy(this._scroll_wheelDeltaX, this._scroll_wheelDeltaY);
    if (SC.WHEEL_MOMENTUM && this._scroll_wheelDeltaY > 0) {
      this._scroll_wheelDeltaY = Math.floor(this._scroll_wheelDeltaY*0.950);
      this._scroll_wheelDeltaY = Math.max(this._scroll_wheelDeltaY, 0);
      this.invokeLater(this._scroll_mouseWheel, 10) ;
    } else if (SC.WHEEL_MOMENTUM && this._scroll_wheelDeltaY < 0){
      this._scroll_wheelDeltaY = Math.ceil(this._scroll_wheelDeltaY*0.950);
      this._scroll_wheelDeltaY = Math.min(this._scroll_wheelDeltaY, 0);
      this.invokeLater(this._scroll_mouseWheel, 10) ;
    } else {
      this._scroll_wheelDeltaY = 0;
    }
  },

  // HACK! REMOVE THIS!
  // Proxy mouse events to touch events for desktop testing
  mouseDown: function(evt) {
    evt.touches = [{pageY: evt.pageY}];
    return this.touchStart(evt);
  },

  mouseDragged: function(evt) {
    evt.touches = [{pageY: evt.pageY}];
    return this.touchDragged(evt);
  },

  mouseUp: function(evt) {
    evt.touches = [{pageY: evt.pageY}];
    return this.touchEnd(evt);
  },

  touchStart: function(evt) {
    this.beginTouchTracking(evt);
    this.invokeLater(this.beginTouchesInContent, 150);

    return YES;
  },

  beginTouchesInContent: function() {
    var touch = this.touch, itemView;
    if (touch.tracking && !touch.dragging) {
      var ev = touch.originalEvent;
      console.log('beginTouches');
      ev.manufactured = YES;
      this.contentView.mouseDown(ev);
      // itemView = this.contentView.itemViewForEvent(ev);
      // itemView.$().addClass('sel');
      // this.contentView.select(itemView.contentIndex);
    }
  },

  beginTouchTracking: function(evt) {
    // initialize start state
    this.touch = {
      startScrollOffset: { x: this.horizontalScrollOffset, y: this.verticalScrollOffset },
      startTime: evt.timeStamp,
      startTimePosition: this.verticalScrollOffset,
      startTouchOffset: { x: evt.touches[0].pageX, y: evt.touches[0].pageY },
      decelerationVelocity: { y: 0 },
      originalTarget: SC.RootResponder.responder.targetViewForEvent(evt),
      originalPane: this.get('pane'),
      originalEvent: SC.copy(evt),

      tracking: YES,
      dragging: NO,
      decelerating: NO
    };

    this.tracking = YES;
    this.dragging = NO;
  },

  touchDragged: function(evt) {
    console.log('dragged');
    var touch = this.touch,
        touchY = evt.touches[0].pageY,
        offsetY = touch.startScrollOffset.y,
        maxOffset = this.get('maximumVerticalScrollOffset');

    var deltaY = touchY - touch.startTouchOffset.y;

    if (!touch.dragging) {
      // give the user 5 pixels of wiggle room before we begin a drag
      if (Math.abs(deltaY) > 5) {
        touch.dragging = YES;
        touch.firstDrag = YES;
        this.contentView.select(SC.IndexSet.create());
      }
    }

    if (touch.dragging) {
      offsetY = offsetY - deltaY;

      if (touch.firstDrag) {
        touch.firstDrag = NO;
        // this._scroll_startTouchOffset.y = offsetY;
        return;
      }
    }

    this.verticalScrollOffset = Math.max(0,Math.min(offsetY, maxOffset));
    this.get('containerView').$()[0].scrollTop = this.verticalScrollOffset;

    if (evt.timeStamp - touch.lastEventTime > 50) {
      touch.startTime = evt.timeStamp;
      touch.startTimePosition = this.verticalScrollOffset;
    }
    touch.lastEventTime = evt.timeStamp;
  },

  touchEnd: function(evt) {
    var touch = this.touch;

    this.tracking = NO;
    touch.tracking = NO;
    this.dragging = NO;
    if (touch.dragging) {
      touch.dragging = NO;

      if (evt.timeStamp - touch.lastEventTime <= 100) {
        touch.offsetBeforeDeceleration = { y: this.verticalScrollOffset };
        this.startDecelerationAnimation(evt);
      }
    }
  },

  startDecelerationAnimation: function(evt) {
    var touch = this.touch;

    var scrollDistance = this.verticalScrollOffset - touch.startTimePosition;
    var scrollDuration = (evt.timeStamp - touch.startTime)/15;
    touch.decelerationVelocity = { y: scrollDistance / scrollDuration };
    this.decelerateAnimation();
  },

  decelerateAnimation: function() {
    var touch = this.touch,
        maxOffset = this.get('maximumVerticalScrollOffset'),
        newY = this.verticalScrollOffset + touch.decelerationVelocity.y;

    this.verticalScrollOffset = Math.max(0,Math.min(Math.round(newY), maxOffset));
    this.get('containerView').$()[0].scrollTop = this.verticalScrollOffset;

    touch.decelerationVelocity.y *= 0.950;

    var absYVelocity = Math.abs(touch.decelerationVelocity.y);
    // console.log(absYVelocity);
    if (absYVelocity < 0.01) {
      touch.decelerationVelocity.y = 0;
      touch.decelerating = NO;
      return;
    }

    this.invokeLater(this.decelerateAnimation, 16);
  },

  // ..........................................................
  // INTERNAL SUPPORT
  //

  /** @private
    Instantiate scrollers & container views as needed.  Replace their classes
    in the regular properties.
  */
  createChildViews: function() {
    var childViews = [] , view;

    // create the containerView.  We must always have a container view.
    // also, setup the contentView as the child of the containerView...
    if (SC.none(view = this.containerView)) view = SC.ContainerView;

    childViews.push(this.containerView = this.createChildView(view, {
      contentView: this.contentView
    }));

    // and replace our own contentView...
    this.contentView = this.containerView.get('contentView');

    // create a horizontal scroller view if needed...
    if (view=this.horizontalScrollerView) {
      if (this.get('hasHorizontalScroller')) {
        view = this.horizontalScrollerView = this.createChildView(view, {
          layoutDirection: SC.LAYOUT_HORIZONTAL,
          valueBinding: '*owner.horizontalScrollOffset'
        }) ;
        childViews.push(view);
      } else this.horizontalScrollerView = null ;
    }

    // create a vertical scroller view if needed...
    if (view=this.verticalScrollerView) {
      if (this.get('hasVerticalScroller')) {
        view = this.verticalScrollerView = this.createChildView(view, {
          layoutDirection: SC.LAYOUT_VERTICAL,
          valueBinding: '*owner.verticalScrollOffset'
        }) ;
        childViews.push(view);
      } else this.verticalScrollerView = null ;
    }

    // set childViews array.
    this.childViews = childViews ;

    this.contentViewDidChange() ; // setup initial display...
    this.tile() ; // set up initial tiling
  },

  init: function() {
    sc_super();

    // start observing initial content view.  The content view's frame has
    // already been setup in prepareDisplay so we don't need to call
    // viewFrameDidChange...
    this._scroll_contentView = this.get('contentView') ;
    var contentView = this._scroll_contentView ;

    if (contentView) {
      contentView.addObserver('frame', this, this.contentViewFrameDidChange) ;
    }

    if (this.get('isVisibleInWindow')) this._scsv_registerAutoscroll() ;
  },

  /** @private Registers/deregisters view with SC.Drag for autoscrolling */
  _scsv_registerAutoscroll: function() {
    if (this.get('isVisibleInWindow')) SC.Drag.addScrollableView(this);
    else SC.Drag.removeScrollableView(this);
  }.observes('isVisibleInWindow'),

  /** @private
    Whenever the contentView is changed, we need to observe the content view's
    frame to be notified whenever it's size changes.
  */
  contentViewDidChange: function() {
    var newView = this.get('contentView'), oldView = this._scroll_contentView;
    var f = this.contentViewFrameDidChange ;
    if (newView !== oldView) {

      // stop observing old content view
      if (oldView) oldView.removeObserver('frame', this, f);

      // update cache
      this._scroll_contentView = newView;
      if (newView) newView.addObserver('frame', this, f);

      newView.adjust('top', 50);
      this.verticalScrollOffset = 50;
      // replace container
      this.containerView.set('contentView', newView);

      this.contentViewFrameDidChange();
    }
  }.observes('contentView'),

  didCreateLayer: function() {
    this.invokeLast(function() {
      this.containerView.$()[0].scrollTop = 50;
    });
  },

  /** @private
    Invoked whenever the contentView's frame changes.  This will update the
    scroller maxmimum and optionally update the scroller visibility if the
    size of the contentView changes.  We don't care about the origin since
    that is tracked separately from the offset values.
  */

  oldMaxHOffset: 0,
  oldMaxVOffset: 0,

  contentViewFrameDidChange: function() {

    var view   = this.get('contentView'),
        f      = (view) ? view.get('frame') : null,
        width  = (f) ? f.width : 0,
        height = (f) ? f.height : 0,
        dim    = this.get('frame') ;

    // cache out scroll settings...
    //if ((width === this._scroll_contentWidth) && (height === this._scroll_contentHeight)) return ;
    this._scroll_contentWidth = width;
    this._scroll_contentHeight = height ;

    if (this.get('hasHorizontalScroller') && (view = this.get('horizontalScrollerView'))) {
      width -= 1 ; // accurately account for our layout
      // decide if it should be visible or not
      if (this.get('autohidesHorizontalScroller')) {
        this.set('isHorizontalScrollerVisible', width > dim.width);
      }
      view.setIfChanged('maximum', width) ;
    }

    if (this.get('hasVerticalScroller') && (view = this.get('verticalScrollerView'))) {
      height -= 1 ; // accurately account for our layout
      // decide if it should be visible or not
      if (this.get('autohidesVerticalScroller')) {
        this.set('isVerticalScrollerVisible', height > dim.height);
      }
      height -= this.get('verticalScrollerBottom') ;
      view.setIfChanged('maximum', height) ;
    }

    // If there is no vertical scroller and auto hiding is on, make
    // sure we are at the top if not already there
    if (!this.get('isVerticalScrollerVisible') && (this.get('verticalScrollOffset') !== 0) &&
       this.get('autohidesVerticalScroller')) {
      this.set('verticalScrollOffset', 0);
    }

    // Same thing for horizontal scrolling.
    if (!this.get('isHorizontalScrollerVisible') && (this.get('horizontalScrollOffset') !== 0) &&
       this.get('autohidesHorizontalScroller')) {
      this.set('horizontalScrollOffset', 0);
    }

    // This forces to recalculate the height of the frame when is at the bottom
    // of the scroll and the content dimension are smaller that the previous one

    var mxVOffSet = this.get('maximumVerticalScrollOffset'),
        vOffSet = this.get('verticalScrollOffset'),
        mxHOffSet = this.get('maximumHorizontalScrollOffset'),
        hOffSet = this.get('horizontalScrollOffset');
    var forceHeight = mxVOffSet<vOffSet;
    var forceWidth = mxHOffSet<hOffSet;
    if(forceHeight || forceWidth){
      this.forceDimensionsRecalculation(forceWidth, forceHeight, vOffSet, hOffSet);
    }
  },

  /** @private
    Whenever the horizontal scroll offset changes, update the scrollers and
    edit the location of the contentView.
  */
  _scroll_horizontalScrollOffsetDidChange: function() {
    this.invokeLast(this.adjustElementScroll);
  }.observes('horizontalScrollOffset'),

  /** @private
    Whenever the vertical scroll offset changes, update the scrollers and
    edit the location of the contentView.
  */
  _scroll_verticalScrollOffsetDidChange: function() {
    this.invokeLast(this.adjustElementScroll);
  }.observes('verticalScrollOffset'),

  adjustElementScroll: function() {
    var container = this.get('containerView'),
        containerElement = container.$(),
        offset;

    offset = this.get('verticalScrollOffset');
    // containerElement[0].scrollTop = offset;
    offset = this.get('horizontalScrollOffset');
    // containerElement[0].scrollLeft = offset;
    container.notifyPropertyChange('clippingFrame');
  },

  forceDimensionsRecalculation: function (forceWidth, forceHeight, vOffSet, hOffSet) {
    var oldScrollHOffset = hOffSet;
    var oldScrollVOffset = vOffSet;
    this.scrollTo(0,0);
    if(forceWidth && forceHeight){
      this.scrollTo(this.get('maximumHorizontalScrollOffset'), this.get('maximumVerticalScrollOffset'));
    }
    if(forceWidth && !forceHeight){
      this.scrollTo(this.get('maximumHorizontalScrollOffset'), oldScrollVOffset);
    }
    if(!forceWidth && forceHeight){
      this.scrollTo(oldScrollHOffset ,this.get('maximumVerticalScrollOffset'));
    }
  }

});
<commit_msg>Remove TouchScrollView for merge back to mainline.<commit_after><|endoftext|>