<commit_before>var path = require('path');
var argv = require('yargs').argv;
process.env.BABEL_ENV = 'karma';

const coverage_reporters = [
  { type: 'text-summary' },
];
const reporters = [
 'spec',
 'coverage',
];
var browsers = ['PhantomJS']; // for local builds
var sauceLunchers = {
    sl_chrome: {
      base: 'SauceLabs',
      browserName: 'chrome',
      platform: 'Windows 7',
      version: '35'
    },
    sl_firefox: {
      base: 'SauceLabs',
      browserName: 'firefox',
      version: '30'
    },
    sl_ios_safari: {
      base: 'SauceLabs',
      browserName: 'iphone',
      platform: 'OS X 10.9',
      version: '7.1'
    },
    sl_ie_11: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 8.1',
      version: '11'
    }
  }

if (process.env.TRAVIS) {
  console.log('On Travis sending coveralls');
  coverage_reporters.push( { type : 'lcov', dir : 'coverage' } );
  reporters.push('coveralls');
} else {
  console.log('Not on Travis so not sending coveralls');
  coverage_reporters.push( { type : 'html', dir : 'coverage', 'subdir' : '.' } );
}
if (process.env.SAUCE_USERNAME) {
  console.log('Will use sauceLabs');
  reporters.push('saucelabs');
  browsers = Object.keys(sauceLunchers);
} else {
  console.log('No sauceLabs')
}

module.exports = function (config) {
  config.set({
    browsers: browsers,
    coverageReporter: {
      reporters: coverage_reporters,
    },
    files: [
      './node_modules/phantomjs-polyfill/bind-polyfill.js',
      './node_modules/babel-polyfill/dist/polyfill.js',
      'tests.webpack.js',
    ],
    singleRun: !argv.watch,
    frameworks: [
      'mocha',
      'chai-sinon',
      'chai-as-promised',
      'chai'
    ],
    preprocessors: {
      'tests.webpack.js': ['webpack', 'sourcemap'],
    },
    reporters: reporters,
    sauceLabs: {
        testName: 'es6 library boilerplate'
    },
    customeLaunchers: sauceLunchers,
    webpack: {
      cache: true,
      devtool: 'inline-source-map',
      debug: true,
      module: {
        preLoaders: [
          {
            test: /spec\.js$/,
            include: /src/,
            exclude: /(bower_components|node_modules)/,
            loader: 'babel',
            query: {
              cacheDirectory: true,
            },
          },
          {
            test: /\.js?$/,
            include: /src/,
            exclude: /(node_modules|bower_components|spec)/,
            loader: 'babel-istanbul',
            query: {
              cacheDirectory: true,
            },
          },
        ],
        loaders: [
          {
            test: /\.js$/,
            include: path.resolve(__dirname, '../src'),
            exclude: /(bower_components|node_modules|spec)/,
            loader: 'babel',
            query: {
              cacheDirectory: true,
            },
          },
        ],
      },
    },
  });
};
<commit_msg>Trying a suggested fix for sauceLabs<commit_after>var path = require('path');
var argv = require('yargs').argv;
process.env.BABEL_ENV = 'karma';

const coverage_reporters = [
  { type: 'text-summary' },
];
const reporters = [
 'spec',
 'coverage',
];
var browsers = ['PhantomJS']; // for local builds
var sauceLunchers = {
    sl_chrome: {
      base: 'SauceLabs',
      browserName: 'chrome',
      platform: 'Windows 7',
      version: '35'
    },
    sl_firefox: {
      base: 'SauceLabs',
      browserName: 'firefox',
      version: '30'
    },
    sl_ios_safari: {
      base: 'SauceLabs',
      browserName: 'iphone',
      platform: 'OS X 10.9',
      version: '7.1'
    },
    sl_ie_11: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 8.1',
      version: '11'
    }
  }

if (process.env.TRAVIS) {
  console.log('On Travis sending coveralls');
  coverage_reporters.push( { type : 'lcov', dir : 'coverage' } );
  reporters.push('coveralls');
} else {
  console.log('Not on Travis so not sending coveralls');
  coverage_reporters.push( { type : 'html', dir : 'coverage', 'subdir' : '.' } );
}
if (process.env.SAUCE_USERNAME) {
  console.log('Will use sauceLabs');
  reporters.push('saucelabs');
  browsers = Object.keys(sauceLunchers);
} else {
  console.log('No sauceLabs')
}

module.exports = function (config) {
  config.set({
    browsers: browsers,
    coverageReporter: {
      reporters: coverage_reporters,
    },
    files: [
      './node_modules/phantomjs-polyfill/bind-polyfill.js',
      './node_modules/babel-polyfill/dist/polyfill.js',
      'tests.webpack.js',
    ],
    singleRun: !argv.watch,
    frameworks: [
      'mocha',
      'chai-sinon',
      'chai-as-promised',
      'chai'
    ],
    preprocessors: {
      'tests.webpack.js': ['webpack', 'sourcemap'],
    },
    reporters: reporters,
    sauceLabs: {
        testName: 'es6 library boilerplate'
    },
    customeLaunchers: sauceLunchers,
    plugins: [
      'karma-chai',
      'karma-chai-as-promised',
      'karma-chai-sinon',
      'karma-chrome-launcher',
      'karma-coverage',
      'karma-coveralls',
      'karma-mocha',
      'karma-phantomjs-launcher',
      'karma-sauce-launcher',
      'karma-sourcemap-loader',
      'karma-spec-reporter',
      'karma-webpack',
    ],
    webpack: {
      cache: true,
      devtool: 'inline-source-map',
      debug: true,
      module: {
        preLoaders: [
          {
            test: /spec\.js$/,
            include: /src/,
            exclude: /(bower_components|node_modules)/,
            loader: 'babel',
            query: {
              cacheDirectory: true,
            },
          },
          {
            test: /\.js?$/,
            include: /src/,
            exclude: /(node_modules|bower_components|spec)/,
            loader: 'babel-istanbul',
            query: {
              cacheDirectory: true,
            },
          },
        ],
        loaders: [
          {
            test: /\.js$/,
            include: path.resolve(__dirname, '../src'),
            exclude: /(bower_components|node_modules|spec)/,
            loader: 'babel',
            query: {
              cacheDirectory: true,
            },
          },
        ],
      },
    },
  });
};
<|endoftext|>


<commit_before>/*
* Functions to create the mini modal maps
*/

// initialize map
function CDADModalMap(mapid, lat, lon, zoom, surveyid, type, numid) {

	//console.log(mapid);

    //where detroit is 42.377410, -83.093719
    this.map = new L.Map(mapid, {
		minZoom: 8,
		maxZoom: 16,
		attributionControl: false,
	});

	// add CartoDB tiles
	this.CartoDBLayer = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png');

	// add cartoDB tiles to start
	this.map.addLayer(this.CartoDBLayer);

	// create empty container for locations
	this.LOCATION = null;

	// create and empty container for detroit city boundary
	this.DETLAYER = null;
	this.CDOBCLAYER = null;

	if (type == 'locationAndSA') {
		// add location
		CDADModalMap.add_LOCATION(this, numid);

		// add SA
		CDADModalMap.add_SA(this, surveyid, numid);

	} else if (type == 'SA') {
		// add SA
		CDADModalMap.add_SA(this, surveyid, numid);

	} else if (type == 'location') {
		// add location
		CDADModalMap.add_LOCATION(this, numid);

		// set center and zoom
		this.map.setView([lat,lon], zoom);

		bounds[numid] = this.map.getBounds();

	} else {
		this.DETLAYER_style = L.geoJson(null, {
		    style: CDADModalMap.getStyleColorFor_DETLAYER,
		}).addTo(this.map);

		this.DETLAYER = omnivore.topojson(detlayer, null, this.DETLAYER_style);

		// set center and zoom
		this.map.setView([lat,lon], zoom);

		//var southWest = L.latLng(42.257746, -83.295593);
		//var northEast = L.latLng(42.489061, -82.853394);
		//bounds[numid] = L.latLngBounds(southWest, northEast);
		console.log(zoom);

		bounds[numid] = this.map.getBounds();

	}

}

CDADModalMap.add_LOCATION = function(sel, numid) {
	// define layer styles and oneachfeature popup styling
	sel.LOCATION = L.geoJson(locations, {
		pointToLayer: CDADModalMap.getStyleFor_LOCATION,
		filter: function(feature, layer) {
			if (feature.properties.counterId == numid) {
				return true;
			} else {
				return false;
			}
	    }
	});

	sel.map.addLayer(sel.LOCATION);
}

CDADModalMap.add_SA = function(sel, surveyid, numid) {
	$.ajax({
		type: "GET",
		url: "/getjsonformap/"+ surveyid +"/",
		success: function(data){
			// load the draw tools
			if (data) {
				var geojson = JSON.parse(data);

				sel.CDOBCLAYER = L.geoJson(geojson, {
			        style: CDADModalMap.getStyleColorFor_CDOBCLAYER,
			    });
			    sel.map.addLayer(sel.CDOBCLAYER);

			    // fit map to bounds of layer
				bounds[numid] = sel.CDOBCLAYER.getBounds();
				sel.map.fitBounds(bounds[numid]);

			}
        }
	});
}

CDADModalMap.getStyleFor_LOCATION = function(feature, latlng){
	var locationIcon = L.icon({
	    iconUrl: feature.properties.iconUrl,
	    iconSize: [24, 32],
		iconAnchor: [12, 30],
	});

	return L.marker(latlng, {icon: locationIcon});

}

CDADModalMap.getStyleColorFor_CDOBCLAYER = function (feature){
    return {
        weight: 2,
        opacity: 0.75,
        color: '#e8c51d',
        fillOpacity: 0.5,
        fill: '#e8c51d'
    }
}

CDADModalMap.getStyleColorFor_DETLAYER = function (feature){
    return {
        weight: 2,
        opacity: 1,
        color: '#252525',
        fillOpacity: 0
    }
}

<commit_msg>bounds?<commit_after>/*
* Functions to create the mini modal maps
*/

// initialize map
function CDADModalMap(mapid, lat, lon, zoom, surveyid, type, numid) {

	//console.log(mapid);

    //where detroit is 42.377410, -83.093719
    this.map = new L.Map(mapid, {
		minZoom: 8,
		maxZoom: 16,
		attributionControl: false,
	});

	// add CartoDB tiles
	this.CartoDBLayer = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png');

	// add cartoDB tiles to start
	this.map.addLayer(this.CartoDBLayer);

	// create empty container for locations
	this.LOCATION = null;

	// create and empty container for detroit city boundary
	this.DETLAYER = null;
	this.CDOBCLAYER = null;

	if (type == 'locationAndSA') {
		// add location
		CDADModalMap.add_LOCATION(this, numid);

		// add SA
		CDADModalMap.add_SA(this, surveyid, numid);

	} else if (type == 'SA') {
		// add SA
		CDADModalMap.add_SA(this, surveyid, numid);

	} else if (type == 'location') {
		// add location
		CDADModalMap.add_LOCATION(this, numid);

		// set center and zoom
		this.map.setView([lat,lon], zoom);

		bounds[numid] = this.map.getBounds();

	} else {
		this.DETLAYER_style = L.geoJson(null, {
		    style: CDADModalMap.getStyleColorFor_DETLAYER,
		}).addTo(this.map);

		this.DETLAYER = omnivore.topojson(detlayer, null, this.DETLAYER_style);

		// set center and zoom
		this.map.setView([lat,lon], zoom);

		//var southWest = L.latLng(42.257746, -83.295593);
		//var northEast = L.latLng(42.489061, -82.853394);
		//bounds[numid] = L.latLngBounds(southWest, northEast);
		console.log(this.map.getBounds());

		bounds[numid] = this.map.getBounds();

	}

}

CDADModalMap.add_LOCATION = function(sel, numid) {
	// define layer styles and oneachfeature popup styling
	sel.LOCATION = L.geoJson(locations, {
		pointToLayer: CDADModalMap.getStyleFor_LOCATION,
		filter: function(feature, layer) {
			if (feature.properties.counterId == numid) {
				return true;
			} else {
				return false;
			}
	    }
	});

	sel.map.addLayer(sel.LOCATION);
}

CDADModalMap.add_SA = function(sel, surveyid, numid) {
	$.ajax({
		type: "GET",
		url: "/getjsonformap/"+ surveyid +"/",
		success: function(data){
			// load the draw tools
			if (data) {
				var geojson = JSON.parse(data);

				sel.CDOBCLAYER = L.geoJson(geojson, {
			        style: CDADModalMap.getStyleColorFor_CDOBCLAYER,
			    });
			    sel.map.addLayer(sel.CDOBCLAYER);

			    // fit map to bounds of layer
				bounds[numid] = sel.CDOBCLAYER.getBounds();
				sel.map.fitBounds(bounds[numid]);

			}
        }
	});
}

CDADModalMap.getStyleFor_LOCATION = function(feature, latlng){
	var locationIcon = L.icon({
	    iconUrl: feature.properties.iconUrl,
	    iconSize: [24, 32],
		iconAnchor: [12, 30],
	});

	return L.marker(latlng, {icon: locationIcon});

}

CDADModalMap.getStyleColorFor_CDOBCLAYER = function (feature){
    return {
        weight: 2,
        opacity: 0.75,
        color: '#e8c51d',
        fillOpacity: 0.5,
        fill: '#e8c51d'
    }
}

CDADModalMap.getStyleColorFor_DETLAYER = function (feature){
    return {
        weight: 2,
        opacity: 1,
        color: '#252525',
        fillOpacity: 0
    }
}

<|endoftext|>


<commit_before>var React = require('react-native');
var FeedbackView = require('./display_feedback/feedbackView');
var api = require('./../../utils/api');
var NavBar = require('./../shared/navbar');
var Button = require('./../shared/button');

var {
  View,
  Text,
  StyleSheet,
  Navigator,
  TouchableOpacity,
  TouchableHighlight,
  Modal,
  TextInput,
  Dimensions,
} = React;

class RequestFeedbackView extends React.Component {
  constructor(props) {
    super(props);
    var {height, width} = Dimensions.get('window');
    this.state = {
      lessonId: this.props.route.lessonId,
      classId: this.props.route.classId,
      socket: this.props.route.socket,
      modal: false,
      height: height,
      width: width,
      feedbackOptions: [
        {
          id: 1,
          name: 'Thumbs Check',
          /*options:{for preset answers?}*/
        },
        {
          id: 2,
          name: 'Multiple Choice'
        }
      ],
      numberOfStudentHands: 0,
      raisedHandList: ['A','B','C'],
    };
    //populate feedbackOptions with anything custom from lesson
    this.state.socket.on('studentRaisedHand', function(student){
      var numberOfStudentHands = this.state.numberOfStudentHands + 1;
      var raisedHandList = this.state.raisedHandList;
      console.log('userId >>>>>>>>>>>>', student.userId);
      this.setState({
        numberOfStudentHands: numberOfStudentHands,
        raisedHandList: raisedHandList.push(student)
      });
      this.numberOfRaiseHand(this.state.numberOfStudentHands);
      console.log('numberOfRaiseHand >>>>>>>>>>>>>>>',this.numberOfRaiseHands)
    }.bind(this))

  }

  dismissClass() {
    // emit socket dismissClass
    this.state.socket.emit('dismiss');
    this.props.navigator.pop();
  }

  clickRaisedHand() {
    this.setState({
      modal: !this.state.modal,
    })
  }
  listStudent(list) {
    return list.map((student, index) => {
      return (
        <View key={index}>
          <Text style={styles.studentTextSize}>
            {student}
          </Text>
        </View>
      )
    })
  }

  selectFeebackOption(feedbackOption) {
    api.startPoll(feedbackOption, this.state.lessonId, this.state.classId)
    .then((response) => {
      if(response.status === 500) {
        console.error('Server error', response);
      } else if(response.status === 201) {
        var pollId = JSON.parse(response._bodyText).pollId;
        this.props.navigator.push({
          component: FeedbackView,
          lessonId: this.state.lessonId,
          pollId: pollId,
          feedbackOption: feedbackOption,
          socket: this.state.socket,
          sceneConfig: {
            ...Navigator.SceneConfigs.FloatFromRight,
            gestures: {}
          }
        });
      } else {
        console.error('Error getting poll data', response);
      }
    })
    .catch((err) => {
      console.error('Error starting poll', err);
    });
  }

  renderFeedbackOptions(feedbackOptions) {
    return feedbackOptions.map((feedbackOption, index) => {
      return (
        <Button key={index} onPress={this.selectFeebackOption.bind(this, feedbackOption)} text={feedbackOption.name} />
      )
    })
  }

  render() {
    //need end class / back button

    return (
      <View style={{flex: 1, backgroundColor: '#ededed'}}>
        <NavBar navi={this.props.navigator}>Request Feedback</NavBar>
        <View style={styles.viewContainer}>
          <Button onPress={this.dismissClass.bind(this)} text={'Dismiss Class'}/>
          {this.renderFeedbackOptions(this.state.feedbackOptions)}
        </View>
        <View style={{flexDirection: 'column', height:60, width: null}}>
          <TouchableOpacity onPress={this.clickRaisedHand.bind(this)} style={{ alignItems: 'center', justifyContent: 'center', flexDirection: 'column', backgroundColor:'yellow', height:60, width: 100, alignSelf:'flex-end'}}>
             <Text style={styles.textSize}>
                {this.state.numberOfStudentHands}
              </Text>
          </TouchableOpacity>
        </View>

        <Modal visible={this.state.modal} transparent={true} animated={true}>
          <View style={styles.modal}>
            <View style={{height:this.state.height * 0.8, width:this.state.width * 0.9}}>
              <View style={styles.modalBox}>
                <Text style={styles.textSizeModal}> Raised hand student: </Text>
                {this.listStudent(this.state.raisedHandList)}
              </View>
              <Button onPress={this.clickRaisedHand.bind(this)} text={'Close'}/>
            </View>
          </View>
        </Modal>

      </View>
    )
  }
}

const styles = StyleSheet.create({
  viewContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  modal: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.8)',
    justifyContent: 'center',
    alignItems: 'center',
  },
  modalBox: {
    flex: 1,
    borderRadius: 10,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white'
  },
  textSizeModal: {
    fontSize : 20,
    fontWeight: 'bold',
  },
  studentTextSize: {
    fontSize: 35,
    fontWeight: 'bold',
  },
  textSize: {
    fontSize : 25,
    fontWeight: 'bold',
  },
});

module.exports = RequestFeedbackView;
<commit_msg>refactor the modal<commit_after>var React = require('react-native');
var FeedbackView = require('./display_feedback/feedbackView');
var api = require('./../../utils/api');
var NavBar = require('./../shared/navbar');
var Button = require('./../shared/button');

var {
  View,
  Text,
  StyleSheet,
  Navigator,
  TouchableOpacity,
  TouchableHighlight,
  Modal,
  TextInput,
  Dimensions,
} = React;

class RequestFeedbackView extends React.Component {
  constructor(props) {
    super(props);
    var {height, width} = Dimensions.get('window');
    this.state = {
      lessonId: this.props.route.lessonId,
      classId: this.props.route.classId,
      socket: this.props.route.socket,
      modal: false,
      height: height,
      width: width,
      feedbackOptions: [
        {
          id: 1,
          name: 'Thumbs Check',
          /*options:{for preset answers?}*/
        },
        {
          id: 2,
          name: 'Multiple Choice'
        }
      ],
      numberOfStudentHands: 0,
      raisedHandList: ['A','B','C'],
    };
    //populate feedbackOptions with anything custom from lesson
    this.state.socket.on('studentRaisedHand', function(student){
      var numberOfStudentHands = this.state.numberOfStudentHands + 1;
      var raisedHandList = this.state.raisedHandList;
      console.log('userId >>>>>>>>>>>>', student.userId);
      this.setState({
        numberOfStudentHands: numberOfStudentHands,
        raisedHandList: raisedHandList.push(student),
      });
      this.numberOfRaiseHand(this.state.numberOfStudentHands);
      console.log('numberOfRaiseHand >>>>>>>>>>>>>>>',this.numberOfRaiseHands)
    }.bind(this))

  }

  dismissClass() {
    // emit socket dismissClass
    this.state.socket.emit('dismiss');
    this.props.navigator.pop();
  }

  clickRaisedHand() {
    this.setState({
      modal: !this.state.modal,
    })
  }

  listStudent(list) {
    return list.map((student, index) => {
      return (
        <View key={index}>
          <Text style={styles.studentTextSize}>
            {student}
          </Text>
        </View>
      )
    })
  }

  selectFeebackOption(feedbackOption) {
    api.startPoll(feedbackOption, this.state.lessonId, this.state.classId)
    .then((response) => {
      if(response.status === 500) {
        console.error('Server error', response);
      } else if(response.status === 201) {
        var pollId = JSON.parse(response._bodyText).pollId;
        this.props.navigator.push({
          component: FeedbackView,
          lessonId: this.state.lessonId,
          pollId: pollId,
          feedbackOption: feedbackOption,
          socket: this.state.socket,
          sceneConfig: {
            ...Navigator.SceneConfigs.FloatFromRight,
            gestures: {}
          }
        });
      } else {
        console.error('Error getting poll data', response);
      }
    })
    .catch((err) => {
      console.error('Error starting poll', err);
    });
  }

  renderFeedbackOptions(feedbackOptions) {
    return feedbackOptions.map((feedbackOption, index) => {
      return (
        <Button key={index} onPress={this.selectFeebackOption.bind(this, feedbackOption)} text={feedbackOption.name} />
      )
    })
  }

  render() {
    //need end class / back button

    return (
      <View style={{flex: 1, backgroundColor: '#ededed'}}>
        <NavBar navi={this.props.navigator}>Request Feedback</NavBar>
        <View style={styles.viewContainer}>
          <Button onPress={this.dismissClass.bind(this)} text={'Dismiss Class'}/>
          {this.renderFeedbackOptions(this.state.feedbackOptions)}
        </View>
        <View style={{flexDirection: 'column', height:60, width: null}}>
          <TouchableOpacity onPress={this.clickRaisedHand.bind(this)} style={{ alignItems: 'center', justifyContent: 'center', flexDirection: 'column', backgroundColor:'yellow', height:60, width: 100, alignSelf:'flex-end'}}>
             <Text style={styles.textSize}>
                {this.state.numberOfStudentHands}
              </Text>
          </TouchableOpacity>
        </View>

        <Modal visible={this.state.modal} transparent={true} animated={true}>
          <View style={styles.modal}>
            <View style={{height:this.state.height * 0.8, width:this.state.width * 0.9}}>
              <View style={styles.modalBox}>
                <Text style={styles.textSizeModal}> Raised hand student: </Text>
                {this.listStudent(this.state.raisedHandList)}
              </View>
              <Button onPress={this.clickRaisedHand.bind(this)} text={'Close'}/>
            </View>
          </View>
        </Modal>

      </View>
    )
  }
}

const styles = StyleSheet.create({
  viewContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  modal: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.8)',
    justifyContent: 'center',
    alignItems: 'center',
  },
  modalBox: {
    flex: 1,
    borderRadius: 10,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white'
  },
  textSizeModal: {
    fontSize : 20,
    fontWeight: 'bold',
  },
  studentTextSize: {
    fontSize: 35,
    fontWeight: 'bold',
  },
  textSize: {
    fontSize : 25,
    fontWeight: 'bold',
  },
});

module.exports = RequestFeedbackView;
<|endoftext|>


<commit_before>Fashion.Backend.VML = (function() {
  var Fashion = this;
  var window = Fashion.window;
  var _class = Fashion._lib._class;
  var _escapeXMLSpecialChars = Fashion._lib.escapeXMLSpecialChars;
  var __assert__ = Fashion._lib.__assert__;
  var _addPoint = Fashion._lib.addPoint;
  var _subtractPoint = Fashion._lib.subtractPoint;
  var _clipPoint = Fashion._lib.clipPoint;
  var Refresher = Fashion.Backend.Refresher;
  // checking browser.
  if (Fashion.browser.identifier !== 'ie') return null;

  var VML_PREFIX = 'v';
  var VML_NAMESPACE_URL = 'urn:schemas-microsoft-com:vml';
  var VML_BEHAVIOR_URL = '#default#VML';
  var VML_FLOAT_PRECISION = 1e4;

  function setup() {
    var namespaces = window.document.namespaces;
    if (Fashion.browser.version >= 8) {
      if (!namespaces[VML_PREFIX])
        namespaces.add(VML_PREFIX, VML_NAMESPACE_URL, VML_BEHAVIOR_URL);
    } else {
      if (!namespaces[VML_PREFIX])
        namespaces.add(VML_PREFIX, VML_NAMESPACE_URL);
      window.document.createStyleSheet().addRule(VML_PREFIX + '\\:*', "behavior:url(#default#VML)");
    }
  }

  function newElement(type) {
    var elem = window.document.createElement(VML_PREFIX + ':' + type);
    return elem;
  }

  function matrixString(m) {
    return [m.a, m.c, m.b, m.d, m.e, m.f].join(',');
  }

  function pathString(path) {
    var retval = [];
    for (var i = 0; i < path.length; i++) {
      var p = path[i];
      switch (p[0]) {
      case 'M':
        retval.push('m', (p[1] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[2] * VML_FLOAT_PRECISION).toFixed(0));
        break;
      case 'L':
        retval.push('l', (p[1] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[2] * VML_FLOAT_PRECISION).toFixed(0));
        break;
      case 'C':
        retval.push('c', (p[1] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[2] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[3] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[4] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[5] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[6] * VML_FLOAT_PRECISION).toFixed(0));
        break;
      case 'Z':
        retval.push('x');
        break;
      // TODO !!!!
      case 'R':
      case 'T':
      case 'S':
      case 'Q':
      case 'A':
      }
    }
    retval.push('e');
    return retval.join(' ');
  }

  function strokePattern(pattern) {
    return pattern.join(' ');
  }

  function appendPrologue(vml, id, tagName) {
    vml.push(
        '<', VML_PREFIX, ':', tagName,
        ' unselectable="on"',
        ' __fashion__id="', id, '"');
    return vml;
  }

  function appendEpilogue(vml, tagName) {
    vml.push('</', VML_PREFIX, ':', tagName, '>');
    return vml;
  }

  function appendStyles(vml, shape) {
    var position = shape.wrapper._position;
    var size = shape.wrapper._size;
    var fillAndStroke = new VMLFillAndStroke();
    shape._buildVMLStyle(fillAndStroke);
    fillAndStroke.setStyle({
      position: 'absolute',
      display: 'block',
      margin: 0,
      padding: 0,
      width: size.x + 'px',
      height: size.y + 'px',
      left: position.x + 'px',
      top: position.y + 'px'
    });
    fillAndStroke.appendHTML(vml);
    return vml;
  }

  function populateWithChildElements(elem) {
    var childNodes = elem.node.childNodes;
    for (var i = childNodes.length; --i >= 0;) {
      var node = childNodes[i];
      switch (node.tagName.toLowerCase()) {
      case 'fill':
        elem.fill = node;
        break;
      case 'stroke':
        elem.stroke = node;
        break;
      }
    }
    return elem;
  }

  function buildMouseEvt(impl, msieEvt) {
    var retval = new Fashion.MouseEvt();
    retval.type = msieEvt.type;
    retval.target = impl.wrapper;
    var which = msieEvt.which;
    var button = msieEvt.button;
    if (!which && button !== void(0)) {
      which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
    }
    switch(which) {
    case 0: retval.left = retval.middle = retval.right = false; break;
    case 1: retval.left = true; break;
    case 2: retval.middle = true; break;
    case 3: retval.right = true; break;
    }

    var physicalPagePosition;

    var doc = window.document, body = doc.body;
    physicalPagePosition = {
      x: msieEvt.clientX + body.scrollLeft,
      y: msieEvt.clientY + body.scrollTop
    };

    if (impl instanceof Drawable) {
      retval.screenPosition   = _subtractPoint(physicalPagePosition, impl.getViewportOffset());
      var physicalPosition    = _addPoint(impl.convertToPhysicalPoint(impl.scrollPosition()), retval.screenPosition);
      retval.logicalPosition  = impl.convertToLogicalPoint(physicalPosition);
      retval.physicalPosition = physicalPosition
    } else {
      retval.screenPosition   = _subtractPoint(physicalPagePosition, impl.drawable.getViewportOffset());
      var physicalPosition    = _addPoint(impl.drawable.convertToPhysicalPoint(impl.drawable.scrollPosition()), retval.screenPosition);
      retval.logicalPosition  = impl.drawable.convertToLogicalPoint(physicalPosition);
      retval.physicalPosition = physicalPosition;
      retval.offsetPosition   = _subtractPoint(retval.logicalPosition, impl.wrapper._position);
    }

    return retval;
  }

  include("Base.js");
  include("Circle.js");
  include("Rect.js");
  include("Path.js");
  include("Text.js");
  include("Drawable.js");

  setup();

  return {
    Circle: Circle,
    Rect: Rect,
    Path: Path,
    Text: Text,
    Drawable: Drawable
  };
}).call(Fashion);
/*
 * vim: sts=2 sw=2 ts=2 et
 */
<commit_msg>fix for ie8<commit_after>Fashion.Backend.VML = (function() {
  var Fashion = this;
  var window = Fashion.window;
  var _class = Fashion._lib._class;
  var _escapeXMLSpecialChars = Fashion._lib.escapeXMLSpecialChars;
  var __assert__ = Fashion._lib.__assert__;
  var _addPoint = Fashion._lib.addPoint;
  var _subtractPoint = Fashion._lib.subtractPoint;
  var _clipPoint = Fashion._lib.clipPoint;
  var Refresher = Fashion.Backend.Refresher;
  // checking browser.
  if (Fashion.browser.identifier !== 'ie') return null;

  var VML_PREFIX = 'v';
  var VML_NAMESPACE_URL = 'urn:schemas-microsoft-com:vml';
  var VML_BEHAVIOR_URL = '#default#VML';
  var VML_FLOAT_PRECISION = 1e4;

  function setup() {
    var namespaces = window.document.namespaces;
    if (Fashion.browser.version >= 8) {
      if (!namespaces[VML_PREFIX])
        namespaces.add(VML_PREFIX, VML_NAMESPACE_URL, VML_BEHAVIOR_URL);
      window.document.createStyleSheet().addRule(VML_PREFIX + '\\:line', "behavior:url(#default#VML)");
      window.document.createStyleSheet().addRule(VML_PREFIX + '\\:rect', "behavior:url(#default#VML)");
      window.document.createStyleSheet().addRule(VML_PREFIX + '\\:roundrect', "behavior:url(#default#VML)");
      window.document.createStyleSheet().addRule(VML_PREFIX + '\\:oval', "behavior:url(#default#VML)");
    } else {
      if (!namespaces[VML_PREFIX])
        namespaces.add(VML_PREFIX, VML_NAMESPACE_URL);
      window.document.createStyleSheet().addRule(VML_PREFIX + '\\:*', "behavior:url(#default#VML)");
    }
  }

  function newElement(type) {
    var elem = window.document.createElement(VML_PREFIX + ':' + type);
    return elem;
  }

  function matrixString(m) {
    return [m.a, m.c, m.b, m.d, m.e, m.f].join(',');
  }

  function pathString(path) {
    var retval = [];
    for (var i = 0; i < path.length; i++) {
      var p = path[i];
      switch (p[0]) {
      case 'M':
        retval.push('m', (p[1] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[2] * VML_FLOAT_PRECISION).toFixed(0));
        break;
      case 'L':
        retval.push('l', (p[1] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[2] * VML_FLOAT_PRECISION).toFixed(0));
        break;
      case 'C':
        retval.push('c', (p[1] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[2] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[3] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[4] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[5] * VML_FLOAT_PRECISION).toFixed(0),
                         (p[6] * VML_FLOAT_PRECISION).toFixed(0));
        break;
      case 'Z':
        retval.push('x');
        break;
      // TODO !!!!
      case 'R':
      case 'T':
      case 'S':
      case 'Q':
      case 'A':
      }
    }
    retval.push('e');
    return retval.join(' ');
  }

  function strokePattern(pattern) {
    return pattern.join(' ');
  }

  function appendPrologue(vml, id, tagName) {
    vml.push(
        '<', VML_PREFIX, ':', tagName,
        ' unselectable="on"',
        ' __fashion__id="', id, '"');
    return vml;
  }

  function appendEpilogue(vml, tagName) {
    vml.push('</', VML_PREFIX, ':', tagName, '>');
    return vml;
  }

  function appendStyles(vml, shape) {
    var position = shape.wrapper._position;
    var size = shape.wrapper._size;
    var fillAndStroke = new VMLFillAndStroke();
    shape._buildVMLStyle(fillAndStroke);
    fillAndStroke.setStyle({
      position: 'absolute',
      display: 'block',
      margin: 0,
      padding: 0,
      width: size.x + 'px',
      height: size.y + 'px',
      left: position.x + 'px',
      top: position.y + 'px'
    });
    fillAndStroke.appendHTML(vml);
    return vml;
  }

  function populateWithChildElements(elem) {
    var childNodes = elem.node.childNodes;
    for (var i = childNodes.length; --i >= 0;) {
      var node = childNodes[i];
      switch (node.tagName.toLowerCase()) {
      case 'fill':
        elem.fill = node;
        break;
      case 'stroke':
        elem.stroke = node;
        break;
      }
    }
    return elem;
  }

  function buildMouseEvt(impl, msieEvt) {
    var retval = new Fashion.MouseEvt();
    retval.type = msieEvt.type;
    retval.target = impl.wrapper;
    var which = msieEvt.which;
    var button = msieEvt.button;
    if (!which && button !== void(0)) {
      which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
    }
    switch(which) {
    case 0: retval.left = retval.middle = retval.right = false; break;
    case 1: retval.left = true; break;
    case 2: retval.middle = true; break;
    case 3: retval.right = true; break;
    }

    var physicalPagePosition;

    var doc = window.document, body = doc.body;
    physicalPagePosition = {
      x: msieEvt.clientX + body.scrollLeft,
      y: msieEvt.clientY + body.scrollTop
    };

    if (impl instanceof Drawable) {
      retval.screenPosition   = _subtractPoint(physicalPagePosition, impl.getViewportOffset());
      var physicalPosition    = _addPoint(impl.convertToPhysicalPoint(impl.scrollPosition()), retval.screenPosition);
      retval.logicalPosition  = impl.convertToLogicalPoint(physicalPosition);
      retval.physicalPosition = physicalPosition
    } else {
      retval.screenPosition   = _subtractPoint(physicalPagePosition, impl.drawable.getViewportOffset());
      var physicalPosition    = _addPoint(impl.drawable.convertToPhysicalPoint(impl.drawable.scrollPosition()), retval.screenPosition);
      retval.logicalPosition  = impl.drawable.convertToLogicalPoint(physicalPosition);
      retval.physicalPosition = physicalPosition;
      retval.offsetPosition   = _subtractPoint(retval.logicalPosition, impl.wrapper._position);
    }

    return retval;
  }

  include("Base.js");
  include("Circle.js");
  include("Rect.js");
  include("Path.js");
  include("Text.js");
  include("Drawable.js");

  setup();

  return {
    Circle: Circle,
    Rect: Rect,
    Path: Path,
    Text: Text,
    Drawable: Drawable
  };
}).call(Fashion);
/*
 * vim: sts=2 sw=2 ts=2 et
 */
<|endoftext|>


<commit_before>//= require vendor/jquery
//= require vendor/custom.modernizr
//= require vendor/shuffleelements
//= require vendor/fittext

//= require foundation/foundation
//= require foundation/foundation.joyride
//= require foundation/foundation.cookie
//= require foundation/foundation.alerts
//= require foundation/foundation.interchange
//= require foundation/foundation.magellan
//= require foundation/foundation.tooltips
//= require foundation/foundation.placeholder
//= require foundation/foundation.reveal
//= require foundation/foundation.clearing
//= require foundation/foundation.orbit
//= require foundation/foundation.dropdown
//= require foundation/foundation.forms
//= require foundation/foundation.topbar
//= require foundation/foundation.section
//= require_self

function equalizeBoxHeights() {
	$('.boxHeightContainer').each(function() {
		$('.boxHeightColumn', this).css("height", "");

		var highestBox = null;

		$('.boxHeightColumn', this).each(function() {
			if($(this).height() > $(highestBox).height())
				highestBox = $(this);
		});

		$('.boxHeightColumn', this).css("height", $(highestBox).height()
		 + (parseInt($(highestBox).css('padding-top').replace("px", ""))
		 + (parseInt($(highestBox).css('padding-bottom').replace("px", ""))
		 )));
	});
}

$(document).foundation();

$(document).ready(function() {
	$("#titleText").fitText(1.1, { maxFontSize: '60px' });
	$("#subtitleText").fitText(2.8, { minFontSize: '0px', maxFontSize: '27px' });
	$('.members .memberBox').shuffle();

	$(".memberBox img").mouseenter(function () {
		$(this).attr("src",$(this).data("profileurl"));
	});
	$(".memberBox img").mouseleave(function () {
		$(this).attr("src",$(this).data("baseurl"));
	});
});

$(window).load(function() {
	equalizeBoxHeights();
});

$(window).resize(function() {
	equalizeBoxHeights();
});

<commit_msg>preloading images via js<commit_after>//= require vendor/jquery
//= require vendor/custom.modernizr
//= require vendor/shuffleelements
//= require vendor/fittext

//= require foundation/foundation
//= require foundation/foundation.joyride
//= require foundation/foundation.cookie
//= require foundation/foundation.alerts
//= require foundation/foundation.interchange
//= require foundation/foundation.magellan
//= require foundation/foundation.tooltips
//= require foundation/foundation.placeholder
//= require foundation/foundation.reveal
//= require foundation/foundation.clearing
//= require foundation/foundation.orbit
//= require foundation/foundation.dropdown
//= require foundation/foundation.forms
//= require foundation/foundation.topbar
//= require foundation/foundation.section
//= require_self

function equalizeBoxHeights() {
	$('.boxHeightContainer').each(function() {
		$('.boxHeightColumn', this).css("height", "");

		var highestBox = null;

		$('.boxHeightColumn', this).each(function() {
			if($(this).height() > $(highestBox).height())
				highestBox = $(this);
		});

		$('.boxHeightColumn', this).css("height", $(highestBox).height()
		 + (parseInt($(highestBox).css('padding-top').replace("px", ""))
		 + (parseInt($(highestBox).css('padding-bottom').replace("px", ""))
		 )));
	});
}

$(document).foundation();

$(document).ready(function() {
	$("#titleText").fitText(1.1, { maxFontSize: '60px' });
	$("#subtitleText").fitText(2.8, { minFontSize: '0px', maxFontSize: '27px' });
	$('.members .memberBox').shuffle();

	// Preloading Images
	$(".memberBox img").each(function () {
		$('<img/>')[0].src = $(this).data("prifileurl");
	});

	$(".memberBox img").mouseenter(function () {
		$(this).attr("src",$(this).data("profileurl"));
	});
	$(".memberBox img").mouseleave(function () {
		$(this).attr("src",$(this).data("baseurl"));
	});
});

$(window).load(function() {
	equalizeBoxHeights();
});

$(window).resize(function() {
	equalizeBoxHeights();
});

<|endoftext|>


<commit_before>#!/bin/env node

'use strict';

const program = require('commander');
const config = require('../src/util/config');

program.usage('<key>[=<value>]');
program.parse(process.argv);

if (!program.args.length || !program.args[0]) {
    throw new Error('Invalid arguments');
}

let cmd = program.args[0].split('=');

if (cmd.length === 1) {
    console.log(config.get(cmd[0]));
} else {
    config.set(cmd[0], cmd[1]);
    console.log(`config: successfully set ${cmd[0]} to ${cmd[1]} in ${config.CONFIG_FILE}`)
}
<commit_msg>Make rest-on-couch-config executable<commit_after>#!/bin/env node

'use strict';

const program = require('commander');
const config = require('../src/util/config');

program.usage('<key>[=<value>]');
program.parse(process.argv);

if (!program.args.length || !program.args[0]) {
    throw new Error('Invalid arguments');
}

let cmd = program.args[0].split('=');

if (cmd.length === 1) {
    console.log(config.get(cmd[0]));
} else {
    config.set(cmd[0], cmd[1]);
    console.log(`config: successfully set ${cmd[0]} to ${cmd[1]} in ${config.CONFIG_FILE}`)
}
<|endoftext|>


<commit_before>/*jshint trailing:true, indent:4*/
/*
 * django-selectable UI widget
 * Source: https://bitbucket.org/mlavin/django-selectable
 * Docs: http://django-selectable.readthedocs.org/
 *
 * Depends:
 *   - jQuery 1.4.4+
 *   - jQuery UI 1.8 widget factory
 *
 * Copyright 2010-2012, Mark Lavin
 * BSD License
 *
*/
(function ($) {

	$.widget("ui.djselectable", {

        options: {
            removeIcon: "ui-icon-close",
            comboboxIcon: "ui-icon-triangle-1-s",
            prepareQuery: null,
            highlightMatch: true,
            formatLabel: null
        },

        _initDeck: function () {
            /* Create list display for currently selected items for multi-select */
            var self = this;
            var data = $(this.element).data();
            var style = data.selectablePosition || data['selectable-position'] || 'bottom';
            this.deck = $('
').addClass('ui-widget selectable-deck selectable-deck-' + style);
            if (style === 'bottom' || style === 'bottom-inline') {
                $(this.element).after(this.deck);
            } else {
                $(this.element).before(this.deck);
            }
            $(self.hiddenMultipleSelector).each(function (i, input) {
                self._addDeckItem(input);
            });
        },

        _addDeckItem: function (input) {
            /* Add new deck list item from a given hidden input */
            var self = this;
            var li = $('
')
            .text($(input).attr('title'))
            .addClass('selectable-deck-item');
            var item = {element: self.element, input: input, wrapper: li, deck: self.deck};
            if (self._trigger("add", null, item) === false) {
                input.remove();
            } else {
                var button = $('
')
                .addClass('selectable-deck-remove')
                .append(
                    $('')
                    .attr('href', '#')
                    .button({
                        icons: {
                            primary: self.options.removeIcon
                        },
                        text: false
                    })
                    .click(function (e) {
                        e.preventDefault();
                        if (self._trigger("remove", e, item) !== false) {
                            $(input).remove();
                            li.remove();
                        }
                    })
                );
                li.append(button).appendTo(this.deck);
            }
        },

        select: function (item, event) {
            /* Trigger selection of a given item.
            Item should contain two properties: id and value
            Event is the original select event if there is one.
            Event should not be passed if triggered manually.
            */
            var self = this,
            input = this.element;
            $(input).removeClass('ui-state-error');
            if (item) {
                if (self.allowMultiple) {
                    $(input).val("");
                    $(input).data("autocomplete").term = "";
                    if ($(self.hiddenMultipleSelector + '[value="' + item.id + '"]').length === 0) {
                        var newInput = $('<input />', {
                            'type': 'hidden',
                            'name': self.hiddenName,
                            'value': item.id,
                            'title': item.value,
                            'data-selectable-type': 'hidden-multiple'
                        });
                        $(input).after(newInput);
                        self._addDeckItem(newInput);
                    }
                    return false;
                } else {
                    $(input).val(item.value);
                    var ui = {item: item};
                    if (typeof(event) === 'undefined' || event.type !== "autocompleteselect") {
                        $(input).trigger('autocompleteselect', [ui ]);
                    }
                }
            }
        },

        _create: function () {
            /* Initialize a new selectable widget */
            var self = this,
            input = this.element,
            data = $(input).data();
            self.allowNew = data.selectableAllowNew || data['selectable-allow-new'];
            self.allowMultiple = data.selectableMultiple || data['selectable-multiple'];
            self.textName = $(input).attr('name');
            self.hiddenName = self.textName.replace('_0', '_1');
            self.hiddenSelector = ':input[data-selectable-type=hidden][name=' + self.hiddenName + ']';
            self.hiddenMultipleSelector = ':input[data-selectable-type=hidden-multiple][name=' + self.hiddenName + ']';
            if (self.allowMultiple) {
                self.allowNew = false;
                $(input).val("");
                this._initDeck();
            }

            function dataSource(request, response) {
                /* Custom data source to uses the lookup url with pagination
                Adds hook for adjusting query parameters.
                Includes timestamp to prevent browser caching the lookup. */
                var url = data.selectableUrl || data['selectable-url'];
                var now = new Date().getTime();
                var query = {term: request.term, timestamp: now};
                if (self.options.prepareQuery) {
                    self.options.prepareQuery(query);
                }
                var page = $(input).data("page");
                if (page) {
                    query.page = page;
                }
                function unwrapResponse(data) {
                    var results = data.data;
                    var meta = data.meta;
                    if (meta.next_page && meta.more) {
                        results.push({
                            id: '',
                            value: '',
                            label: meta.more,
                            page: meta.next_page
                        });
                    }
                    return response(results);
                }
				$.getJSON(url, query, unwrapResponse);
            }
            // Create base auto-complete lookup
            $(input).autocomplete({
                source: dataSource,
                change: function (event, ui) {
                    $(input).removeClass('ui-state-error');
                    if ($(input).val() && !ui.item) {
                        if (!self.allowNew) {
                            $(input).addClass('ui-state-error');
                        }
                    }
                    if (self.allowMultiple && !$(input).hasClass('ui-state-error')) {
                        $(input).val("");
                        $(input).data("autocomplete").term = "";
                    }
                },
                select: function (event, ui) {
                    $(input).removeClass('ui-state-error');
                    if (ui.item && ui.item.page) {
                        // Set current page value
                        $(input).data("page", ui.item.page);
                        $('.selectable-paginator', self.menu).remove();
                        // Search for next page of results
                        $(input).autocomplete("search");
                        return false;
                    }
                    return self.select(ui.item, event);
                }
            }).addClass("ui-widget ui-widget-content ui-corner-all");
            // Override the default auto-complete render.
            $(input).data("autocomplete")._renderItem = function (ul, item) {
                /* Adds hook for additional formatting, allows HTML in the label,
                highlights term matches and handles pagination. */
                var label = item.label;
                if (self.options.formatLabel) {
                    label = self.options.formatLabel(label, item);
                }
                if (self.options.highlightMatch && this.term) {
                    var re = new RegExp("(?![^&;]+;)(?!<[^<>]*)(" +
                    $.ui.autocomplete.escapeRegex(this.term) +
                    ")(?![^<>]*>)(?![^&;]+;)", "gi");
                    label = label.replace(re, "$1");
                }
                var li =  $("

")
                    .data("item.autocomplete", item)
                    .append($("").append(label))
                    .appendTo(ul);
                if (item.page) {
                    li.addClass('selectable-paginator');
                }
                return li;
            };
            // Override the default auto-complete suggest.
            $(input).data("autocomplete")._suggest = function (items) {
                /* Needed for handling pagination links */
                var page = $(input).data('page');
                var ul = this.menu.element;
                if (!page) {
                    ul.empty();
                }
                $(input).data('page', null);
                ul.zIndex(this.element.zIndex() + 1);
                this._renderMenu(ul, items);
                // jQuery UI menu does not define deactivate
                if (this.menu.deactivate) this.menu.deactivate();
                this.menu.refresh();
                // size and position menu
                ul.show();
                this._resizeMenu();
                ul.position($.extend({of: this.element}, this.options.position));
                if (this.options.autoFocus) {
                    this.menu.next(new $.Event("mouseover"));
                }
            };
            // Additional work for combobox widgets
            var selectableType = data.selectableType || data['selectable-type'];
            if (selectableType === 'combobox') {
                // Change auto-complete options
                $(input).autocomplete("option", {
                    delay: 0,
                    minLength: 0
                })
                .removeClass("ui-corner-all")
                .addClass("ui-corner-left ui-combo-input");
                // Add show all items button
                $("<button> </button>").attr("tabIndex", -1).attr("title", "Show All Items")
                .insertAfter($(input))
                .button({
                    icons: {
                        primary: self.options.comboboxIcon
                    },
                    text: false
                })
                .removeClass("ui-corner-all")
                .addClass("ui-corner-right ui-button-icon ui-combo-button")
                .click(function () {
                    // close if already visible
                    if ($(input).autocomplete("widget").is(":visible")) {
                        $(input).autocomplete("close");
                        return false;
                    }
                    // pass empty string as value to search for, displaying all results
                    $(input).autocomplete("search", "");
                    $(input).focus();
                    return false;
                });
            }
        }
	});

    window.bindSelectables = function (context) {
        /* Bind all selectable widgets in a given context.
        Automatically called on document.ready.
        Additional calls can be made for dynamically added widgets.
        */
        $(":input[data-selectable-type=text]", context).djselectable();
        $(":input[data-selectable-type=combobox]", context).djselectable();
        $(":input[data-selectable-type=hidden]", context).each(function (i, elem) {
            var hiddenName = $(elem).attr('name');
            var textName = hiddenName.replace('_1', '_0');
            $(":input[name=" + textName + "][data-selectable-url]").bind(
                "autocompletechange autocompleteselect",
                function (event, ui) {
                    if (ui.item && ui.item.id) {
                        $(elem).val(ui.item.id);
                    } else {
                        $(elem).val("");
                    }
                }
            );
        });
    };

    function djangoAdminPatches() {
        /* Monkey-patch Django's dynamic formset, if defined */
        if (typeof(django) !== "undefined" && typeof(django.jQuery) !== "undefined") {
            if (django.jQuery.fn.formset) {
                var oldformset = django.jQuery.fn.formset;
                django.jQuery.fn.formset = function (opts) {
                    var options = $.extend({}, opts);
                    var addedevent = function (row) {
                        bindSelectables($(row));
                    };
                    var added = null;
                    if (options.added) {
                        // Wrap previous added function and include call to bindSelectables
                        var oldadded = options.added;
                        added = function (row) { oldadded(row); addedevent(row); };
                    }
                    options.added = added || addedevent;
                    return oldformset.call(this, options);
                };
            }
        }

        /* Monkey-patch Django's dismissAddAnotherPopup(), if defined */
        if (typeof(dismissAddAnotherPopup) !== "undefined" &&
            typeof(windowname_to_id) !== "undefined" &&
            typeof(html_unescape) !== "undefined") {
            var django_dismissAddAnotherPopup = dismissAddAnotherPopup;
            dismissAddAnotherPopup = function (win, newId, newRepr) {
                /* See if the popup came from a selectable field.
                   If not, pass control to Django's code.
                   If so, handle it. */
                var fieldName = windowname_to_id(win.name); /* e.g. "id_fieldname" */
                var field = $('#' + fieldName);
                var multiField = $('#' + fieldName + '_0');
                /* Check for bound selectable */
                var singleWidget = field.data('djselectable');
                var multiWidget = multiField.data('djselectable');
                if (singleWidget || multiWidget) {
                    // newId and newRepr are expected to have previously been escaped by
                    // django.utils.html.escape.
                    var item =  {
                        id: html_unescape(newId),
                        value: html_unescape(newRepr)
                    };
                    if (singleWidget) {
                        field.djselectable('select', item);
                    }
                    if (multiWidget) {
                        multiField.djselectable('select', item);
                    }
                    win.close();
                } else {
                    /* Not ours, pass on to original function. */
                    return django_dismissAddAnotherPopup(win, newId, newRepr);
                }
            };
        }
    }

    $(document).ready(function () {
        // Patch the django admin JS
        if (typeof(djselectableAdminPatch) === "undefined" || djselectableAdminPatch) {
            djangoAdminPatches();
        }
        // Bind existing widgets on document ready
        if (typeof(djselectableAutoLoad) === "undefined" || djselectableAutoLoad) {
            bindSelectables('body');
        }
    });
})(jQuery);
<commit_msg>Fix double drop down button in dynamically added comboboxes<commit_after>/*jshint trailing:true, indent:4*/
/*
 * django-selectable UI widget
 * Source: https://bitbucket.org/mlavin/django-selectable
 * Docs: http://django-selectable.readthedocs.org/
 *
 * Depends:
 *   - jQuery 1.4.4+
 *   - jQuery UI 1.8 widget factory
 *
 * Copyright 2010-2012, Mark Lavin
 * BSD License
 *
*/
(function ($) {

	$.widget("ui.djselectable", {

        options: {
            removeIcon: "ui-icon-close",
            comboboxIcon: "ui-icon-triangle-1-s",
            prepareQuery: null,
            highlightMatch: true,
            formatLabel: null
        },

        _initDeck: function () {
            /* Create list display for currently selected items for multi-select */
            var self = this;
            var data = $(this.element).data();
            var style = data.selectablePosition || data['selectable-position'] || 'bottom';
            this.deck = $('
').addClass('ui-widget selectable-deck selectable-deck-' + style);
            if (style === 'bottom' || style === 'bottom-inline') {
                $(this.element).after(this.deck);
            } else {
                $(this.element).before(this.deck);
            }
            $(self.hiddenMultipleSelector).each(function (i, input) {
                self._addDeckItem(input);
            });
        },

        _addDeckItem: function (input) {
            /* Add new deck list item from a given hidden input */
            var self = this;
            var li = $('
')
            .text($(input).attr('title'))
            .addClass('selectable-deck-item');
            var item = {element: self.element, input: input, wrapper: li, deck: self.deck};
            if (self._trigger("add", null, item) === false) {
                input.remove();
            } else {
                var button = $('
')
                .addClass('selectable-deck-remove')
                .append(
                    $('')
                    .attr('href', '#')
                    .button({
                        icons: {
                            primary: self.options.removeIcon
                        },
                        text: false
                    })
                    .click(function (e) {
                        e.preventDefault();
                        if (self._trigger("remove", e, item) !== false) {
                            $(input).remove();
                            li.remove();
                        }
                    })
                );
                li.append(button).appendTo(this.deck);
            }
        },

        select: function (item, event) {
            /* Trigger selection of a given item.
            Item should contain two properties: id and value
            Event is the original select event if there is one.
            Event should not be passed if triggered manually.
            */
            var self = this,
            input = this.element;
            $(input).removeClass('ui-state-error');
            if (item) {
                if (self.allowMultiple) {
                    $(input).val("");
                    $(input).data("autocomplete").term = "";
                    if ($(self.hiddenMultipleSelector + '[value="' + item.id + '"]').length === 0) {
                        var newInput = $('<input />', {
                            'type': 'hidden',
                            'name': self.hiddenName,
                            'value': item.id,
                            'title': item.value,
                            'data-selectable-type': 'hidden-multiple'
                        });
                        $(input).after(newInput);
                        self._addDeckItem(newInput);
                    }
                    return false;
                } else {
                    $(input).val(item.value);
                    var ui = {item: item};
                    if (typeof(event) === 'undefined' || event.type !== "autocompleteselect") {
                        $(input).trigger('autocompleteselect', [ui ]);
                    }
                }
            }
        },

        _create: function () {
            /* Initialize a new selectable widget */
            var self = this,
            input = this.element,
            data = $(input).data();
            self.allowNew = data.selectableAllowNew || data['selectable-allow-new'];
            self.allowMultiple = data.selectableMultiple || data['selectable-multiple'];
            self.textName = $(input).attr('name');
            self.hiddenName = self.textName.replace('_0', '_1');
            self.hiddenSelector = ':input[data-selectable-type=hidden][name=' + self.hiddenName + ']';
            self.hiddenMultipleSelector = ':input[data-selectable-type=hidden-multiple][name=' + self.hiddenName + ']';
            if (self.allowMultiple) {
                self.allowNew = false;
                $(input).val("");
                this._initDeck();
            }

            function dataSource(request, response) {
                /* Custom data source to uses the lookup url with pagination
                Adds hook for adjusting query parameters.
                Includes timestamp to prevent browser caching the lookup. */
                var url = data.selectableUrl || data['selectable-url'];
                var now = new Date().getTime();
                var query = {term: request.term, timestamp: now};
                if (self.options.prepareQuery) {
                    self.options.prepareQuery(query);
                }
                var page = $(input).data("page");
                if (page) {
                    query.page = page;
                }
                function unwrapResponse(data) {
                    var results = data.data;
                    var meta = data.meta;
                    if (meta.next_page && meta.more) {
                        results.push({
                            id: '',
                            value: '',
                            label: meta.more,
                            page: meta.next_page
                        });
                    }
                    return response(results);
                }
				$.getJSON(url, query, unwrapResponse);
            }
            // Create base auto-complete lookup
            $(input).autocomplete({
                source: dataSource,
                change: function (event, ui) {
                    $(input).removeClass('ui-state-error');
                    if ($(input).val() && !ui.item) {
                        if (!self.allowNew) {
                            $(input).addClass('ui-state-error');
                        }
                    }
                    if (self.allowMultiple && !$(input).hasClass('ui-state-error')) {
                        $(input).val("");
                        $(input).data("autocomplete").term = "";
                    }
                },
                select: function (event, ui) {
                    $(input).removeClass('ui-state-error');
                    if (ui.item && ui.item.page) {
                        // Set current page value
                        $(input).data("page", ui.item.page);
                        $('.selectable-paginator', self.menu).remove();
                        // Search for next page of results
                        $(input).autocomplete("search");
                        return false;
                    }
                    return self.select(ui.item, event);
                }
            }).addClass("ui-widget ui-widget-content ui-corner-all");
            // Override the default auto-complete render.
            $(input).data("autocomplete")._renderItem = function (ul, item) {
                /* Adds hook for additional formatting, allows HTML in the label,
                highlights term matches and handles pagination. */
                var label = item.label;
                if (self.options.formatLabel) {
                    label = self.options.formatLabel(label, item);
                }
                if (self.options.highlightMatch && this.term) {
                    var re = new RegExp("(?![^&;]+;)(?!<[^<>]*)(" +
                    $.ui.autocomplete.escapeRegex(this.term) +
                    ")(?![^<>]*>)(?![^&;]+;)", "gi");
                    label = label.replace(re, "$1");
                }
                var li =  $("

")
                    .data("item.autocomplete", item)
                    .append($("").append(label))
                    .appendTo(ul);
                if (item.page) {
                    li.addClass('selectable-paginator');
                }
                return li;
            };
            // Override the default auto-complete suggest.
            $(input).data("autocomplete")._suggest = function (items) {
                /* Needed for handling pagination links */
                var page = $(input).data('page');
                var ul = this.menu.element;
                if (!page) {
                    ul.empty();
                }
                $(input).data('page', null);
                ul.zIndex(this.element.zIndex() + 1);
                this._renderMenu(ul, items);
                // jQuery UI menu does not define deactivate
                if (this.menu.deactivate) this.menu.deactivate();
                this.menu.refresh();
                // size and position menu
                ul.show();
                this._resizeMenu();
                ul.position($.extend({of: this.element}, this.options.position));
                if (this.options.autoFocus) {
                    this.menu.next(new $.Event("mouseover"));
                }
            };
            // Additional work for combobox widgets
            var selectableType = data.selectableType || data['selectable-type'];
            if (selectableType === 'combobox') {
                // Change auto-complete options
                $(input).autocomplete("option", {
                    delay: 0,
                    minLength: 0
                })
                .removeClass("ui-corner-all")
                .addClass("ui-corner-left ui-combo-input");
                // Add show all items button
                $("<button> </button>").attr("tabIndex", -1).attr("title", "Show All Items")
                .insertAfter($(input))
                .button({
                    icons: {
                        primary: self.options.comboboxIcon
                    },
                    text: false
                })
                .removeClass("ui-corner-all")
                .addClass("ui-corner-right ui-button-icon ui-combo-button")
                .click(function () {
                    // close if already visible
                    if ($(input).autocomplete("widget").is(":visible")) {
                        $(input).autocomplete("close");
                        return false;
                    }
                    // pass empty string as value to search for, displaying all results
                    $(input).autocomplete("search", "");
                    $(input).focus();
                    return false;
                });
            }
        }
	});

    window.bindSelectables = function (context) {
        /* Bind all selectable widgets in a given context.
        Automatically called on document.ready.
        Additional calls can be made for dynamically added widgets.
        */
        $(":input[data-selectable-type=text]", context).djselectable();
        $(":input[data-selectable-type=combobox]", context).djselectable();
        $(":input[data-selectable-type=hidden]", context).each(function (i, elem) {
            var hiddenName = $(elem).attr('name');
            var textName = hiddenName.replace('_1', '_0');
            $(":input[name=" + textName + "][data-selectable-url]").bind(
                "autocompletechange autocompleteselect",
                function (event, ui) {
                    if (ui.item && ui.item.id) {
                        $(elem).val(ui.item.id);
                    } else {
                        $(elem).val("");
                    }
                }
            );
        });
    };

    function djangoAdminPatches() {
        /* Monkey-patch Django's dynamic formset, if defined */
        if (typeof(django) !== "undefined" && typeof(django.jQuery) !== "undefined") {
            if (django.jQuery.fn.formset) {
                var oldformset = django.jQuery.fn.formset;
                django.jQuery.fn.formset = function (opts) {
                    var options = $.extend({}, opts);
                    var addedevent = function (row) {
                        $(row).find('button').remove();
                        bindSelectables($(row));
                    };
                    var added = null;
                    if (options.added) {
                        // Wrap previous added function and include call to bindSelectables
                        var oldadded = options.added;
                        added = function (row) { oldadded(row); addedevent(row); };
                    }
                    options.added = added || addedevent;
                    return oldformset.call(this, options);
                };
            }
        }

        /* Monkey-patch Django's dismissAddAnotherPopup(), if defined */
        if (typeof(dismissAddAnotherPopup) !== "undefined" &&
            typeof(windowname_to_id) !== "undefined" &&
            typeof(html_unescape) !== "undefined") {
            var django_dismissAddAnotherPopup = dismissAddAnotherPopup;
            dismissAddAnotherPopup = function (win, newId, newRepr) {
                /* See if the popup came from a selectable field.
                   If not, pass control to Django's code.
                   If so, handle it. */
                var fieldName = windowname_to_id(win.name); /* e.g. "id_fieldname" */
                var field = $('#' + fieldName);
                var multiField = $('#' + fieldName + '_0');
                /* Check for bound selectable */
                var singleWidget = field.data('djselectable');
                var multiWidget = multiField.data('djselectable');
                if (singleWidget || multiWidget) {
                    // newId and newRepr are expected to have previously been escaped by
                    // django.utils.html.escape.
                    var item =  {
                        id: html_unescape(newId),
                        value: html_unescape(newRepr)
                    };
                    if (singleWidget) {
                        field.djselectable('select', item);
                    }
                    if (multiWidget) {
                        multiField.djselectable('select', item);
                    }
                    win.close();
                } else {
                    /* Not ours, pass on to original function. */
                    return django_dismissAddAnotherPopup(win, newId, newRepr);
                }
            };
        }
    }

    $(document).ready(function () {
        // Patch the django admin JS
        if (typeof(djselectableAdminPatch) === "undefined" || djselectableAdminPatch) {
            djangoAdminPatches();
        }
        // Bind existing widgets on document ready
        if (typeof(djselectableAutoLoad) === "undefined" || djselectableAutoLoad) {
            bindSelectables('body');
        }
    });
})(jQuery);
<|endoftext|>


<commit_before>var util = require('util'),
    webdriver = require('selenium-webdriver');

var driver = new webdriver.Builder().
    usingServer('http://localhost:4444/wd/hub').
    withCapabilities({'browserName': 'chrome'}).
    build();

// driver.get('http://juliemr.github.io/webdriver-bugs/');
driver.get('http://localhost:8111/button.html');

driver.findElement(webdriver.By.css('button')).click();

driver.actions().sendKeys(webdriver.Key.RIGHT).perform();

driver.sleep(4000);

driver.quit();
<commit_msg>Fix address to work online<commit_after>var util = require('util'),
    webdriver = require('selenium-webdriver');

var driver = new webdriver.Builder().
    usingServer('http://localhost:4444/wd/hub').
    withCapabilities({'browserName': 'chrome'}).
    build();

driver.get('http://juliemr.github.io/webdriver-bugs/button.html');
// driver.get('http://localhost:8111/button.html');

driver.findElement(webdriver.By.css('button')).click();

driver.actions().sendKeys(webdriver.Key.RIGHT).perform();

driver.sleep(4000);

driver.quit();
<|endoftext|>


<commit_before>/* Chocolate Factory v0.6

DOM object builder. (Thanks to DeviCat for the name!)

Usage in HTML:
<script type=module src="https://rosuav.github.io/shed/chocfactory.js"></script>
<script defer src="/path/to/your/script.js"></script>

Usage in a module:
import choc, {set_content, on, DOM} from "https://rosuav.github.io/shed/chocfactory.js";

Once imported, the chocolate factory can be used in a number of ways:
* const {TAG} = choc; TAG(attr, contents) // recommended
* choc.TAG(attr, contents)
* choc("TAG", attr, contents)
* chocify("TAG"); TAG(attr, contents) // deprecated, non-module scripts only

Example:
const {FORM, LABEL, INPUT} = choc;
let el = FORM(LABEL(["Speak thy mind:", INPUT({name: "thought"})]))

Regardless of how it's called, choc will return a newly-created element with
the given tag, attributes, and contents. Both attributes and contents are
optional, but if both are given, must be in that order.

To replace the contents of a DOM element:
    set_content(element, contents);
The element can be either an actual DOM element or a selector. The contents
can be a DOM element (eg created by choc() above), or a text string, or an
array of elements and/or strings. Text strings will NOT be interpreted as
HTML, and thus can safely contain untrusted content. Note that this will
update a single element only, and will raise an error if multiple elements
match. (Changed in v0.2: Now raises if duplicates, instead of ignoring them.)

Hooking events can be done by selector. Internally this attaches the event
to the document, so dynamically-created objects can still respond to events.
    on("click", ".some-class", e => {console.log("Hello");});
To distinguish between multiple objects that potentially match, e.match
will be set to the object that received the event. (This is distinct from
e.target and e.currentTarget.) NOTE: e.match is wiped after the event
handler returns. For asynchronous use, capture it in a variable first.
Additional options can be set with another argument, eg passing true to have
the event handler attached to the capturing phase instead. Important for some
types of events, irrelevant for others. New in v0.6.

For other manipulations of DOM objects, start by locating one by its selector:
    DOM('input[name="thought"]').value = "..."
This is like document.querySelector(), but ensures that there is only one
matching element, thus avoiding the risk of catching the wrong one. (It's also
shorter. Way shorter.)

If you use the <dialog> tag, consider fix_dialogs(). It adds basic support to
browsers which lack it, and can optionally provide automatic behaviour for
close buttons and/or clicking outside the dialog to close it.
    fix_dialogs({close_selector: "button.close,input[type=submit]"});
    fix_dialogs({click_outside: true});
    //New in v0.5: Clicking outside dialogs closes them, but only if there is
    //no <form> inside the <dialog>. Guards against accidental closings.
    fix_dialogs({click_outside: "formless"});

The MIT License (MIT)

Copyright (c) 2020 Chris Angelico

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

export function DOM(sel) {
	const elems = document.querySelectorAll(sel);
	if (elems.length > 1) throw new Error("Expected a single element '" + sel + "' but got " + elems.length);
	return elems[0]; //Will return undefined if there are no matching elements.
}

export function set_content(elem, children) {
	if (typeof elem === "string") elem = DOM(elem);
	while (elem.lastChild) elem.removeChild(elem.lastChild);
	if (!Array.isArray(children)) children = [children];
	for (let child of children) {
		if (!child || child === "") continue;
		if (typeof child === "string" || typeof child === "number") child = document.createTextNode(child);
		elem.appendChild(child);
	}
	return elem;
}

const handlers = {};
export function on(event, selector, handler, options) {
	if (handlers[event]) return handlers[event].push([selector, handler]);
	handlers[event] = [[selector, handler]];
	document.addEventListener(event, e => {
		//Reimplement bubbling ourselves
		const top = e.currentTarget; //Generic in case we later allow this to attach to other than document
		let cur = e.target;
		while (cur && cur !== top) {
			e.match = cur; //We can't mess with e.currentTarget without synthesizing our own event object. Easier to make a new property.
			handlers[event].forEach(([s, h]) => cur.matches(s) && h(e));
			cur = cur.parentNode;
		}
		e.match = null; //Signal that you can't trust the match ref any more
	}, options);
	return 1;
}

//Apply some patches to <dialog> tags to make them easier to use. Accepts keyword args in a config object:
//	fix_dialogs({close_selector: ".dialog_cancel,.dialog_close", click_outside: true});
//For older browsers, this adds showModal() and close() methods
//If cfg.close_selector, will hook events from all links/buttons matching it to close the dialog
//If cfg.click_outside, any click outside a dialog will also close it. (May not work on older browsers.)
export function fix_dialogs(cfg) {
	if (!cfg) cfg = {};
	//For browsers with only partial support for the <dialog> tag, add the barest minimum.
	//On browsers with full support, there are many advantages to using dialog rather than
	//plain old div, but this way, other browsers at least have it pop up and down.
	let need_button_fix = false;
	document.querySelectorAll("dialog").forEach(dlg => {
		if (!dlg.showModal) {
			dlg.showModal = function() {this.style.display = "block";}
			dlg.close = function(ret) {
				if (ret) this.returnValue = ret;
				this.style.removeProperty("display");
				this.dispatchEvent(new CustomEvent("close", {bubbles: true}));
			};
			need_button_fix = true;
		}
	});
	//Ideally, I'd like to feature-detect whether form[method=dialog] actually
	//works, and do this if it doesn't; we assume that the lack of a showModal
	//method implies this being also unsupported. New in Choc Factory 0.4.
	if (need_button_fix) on("click", 'dialog form[method="dialog"] button', e => {
		e.match.closest("dialog").close(e.match.value);
		e.preventDefault();
	});
	if (cfg.click_outside) on("click", "dialog", e => {
		//NOTE: Sometimes, clicking on a <select> will give spurious clientX/clientY
		//values. Since clicking outside is always going to send the message directly
		//to the dialog (not to one of its children), check for that case.
		if (e.match !== e.target) return;
		if (cfg.click_outside === "formless" && e.match.querySelector("form")) return;
		let rect = e.match.getBoundingClientRect();
		if (e.clientY < rect.top || e.clientY > rect.top + rect.height
				|| e.clientX < rect.left || e.clientX > rect.left + rect.width)
		{
			e.match.close();
			e.preventDefault();
		}
	});
	if (cfg.close_selector) on("click", cfg.close_selector, e => e.match.closest("dialog").close());
}

let choc = function(tag, attributes, children) {
	const ret = document.createElement(tag);
	//If called as choc(tag, children), assume all attributes are defaults
	if (typeof attributes === "string" || attributes instanceof Array || attributes instanceof Element)
		return set_content(ret, attributes);
	if (attributes) for (let attr in attributes) {
		if (attr.startsWith("data-")) //Simplistic - we don't transform "data-foo-bar" into "fooBar" per HTML.
			ret.dataset[attr.slice(5)] = attributes[attr];
		else if (attr === "form") //Setting the form attribute on an element has to be done differently.
			ret.setAttribute("form", attributes[attr]);
		else ret[attr] = attributes[attr];
	}
	if (children) set_content(ret, children);
	return ret;
}
choc.__version__ = "0.6";

//Interpret choc.DIV(attr, chld) as choc("DIV", attr, chld)
//This is basically what Python would do as choc.__getattr__()
choc = new Proxy(choc, {get: function(obj, prop) {
	if (prop in obj) return obj[prop];
	return obj[prop] = (a, c) => obj(prop, a, c);
}});

//For modules, make the main entry-point easily available.
export default choc;

//For non-module scripts, allow some globals to be used
window.choc = choc; window.set_content = set_content; window.on = on; window.DOM = DOM; window.fix_dialogs = fix_dialogs;
window.chocify = tags => tags.split(" ").forEach(tag => window[tag] = choc[tag]);
<commit_msg>chocfac: Allow arrays inside arrays<commit_after>/* Chocolate Factory v0.6.1

DOM object builder. (Thanks to DeviCat for the name!)

Usage in HTML:
<script type=module src="https://rosuav.github.io/shed/chocfactory.js"></script>
<script defer src="/path/to/your/script.js"></script>

Usage in a module:
import choc, {set_content, on, DOM} from "https://rosuav.github.io/shed/chocfactory.js";

Once imported, the chocolate factory can be used in a number of ways:
* const {TAG} = choc; TAG(attr, contents) // recommended
* choc.TAG(attr, contents)
* choc("TAG", attr, contents)
* chocify("TAG"); TAG(attr, contents) // deprecated, non-module scripts only

Example:
const {FORM, LABEL, INPUT} = choc;
let el = FORM(LABEL(["Speak thy mind:", INPUT({name: "thought"})]))

Regardless of how it's called, choc will return a newly-created element with
the given tag, attributes, and contents. Both attributes and contents are
optional, but if both are given, must be in that order.

To replace the contents of a DOM element:
    set_content(element, contents);
The element can be either an actual DOM element or a selector. The contents
can be a DOM element (eg created by choc() above), or a text string, or an
array of elements and/or strings. Text strings will NOT be interpreted as
HTML, and thus can safely contain untrusted content. Note that this will
update a single element only, and will raise an error if multiple elements
match. (Changed in v0.2: Now raises if duplicates, instead of ignoring them.)

Hooking events can be done by selector. Internally this attaches the event
to the document, so dynamically-created objects can still respond to events.
    on("click", ".some-class", e => {console.log("Hello");});
To distinguish between multiple objects that potentially match, e.match
will be set to the object that received the event. (This is distinct from
e.target and e.currentTarget.) NOTE: e.match is wiped after the event
handler returns. For asynchronous use, capture it in a variable first.
Additional options can be set with another argument, eg passing true to have
the event handler attached to the capturing phase instead. Important for some
types of events, irrelevant for others. New in v0.6.

For other manipulations of DOM objects, start by locating one by its selector:
    DOM('input[name="thought"]').value = "..."
This is like document.querySelector(), but ensures that there is only one
matching element, thus avoiding the risk of catching the wrong one. (It's also
shorter. Way shorter.)

If you use the <dialog> tag, consider fix_dialogs(). It adds basic support to
browsers which lack it, and can optionally provide automatic behaviour for
close buttons and/or clicking outside the dialog to close it.
    fix_dialogs({close_selector: "button.close,input[type=submit]"});
    fix_dialogs({click_outside: true});
    //New in v0.5: Clicking outside dialogs closes them, but only if there is
    //no <form> inside the <dialog>. Guards against accidental closings.
    fix_dialogs({click_outside: "formless"});

The MIT License (MIT)

Copyright (c) 2020 Chris Angelico

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

export function DOM(sel) {
	const elems = document.querySelectorAll(sel);
	if (elems.length > 1) throw new Error("Expected a single element '" + sel + "' but got " + elems.length);
	return elems[0]; //Will return undefined if there are no matching elements.
}

//Append one child or an array of children
function append_child(elem, child) {
	if (!child || child === "") return;
	if (Array.isArray(child)) {
		//TODO maybe: prevent infinite nesting (array inside itself)
		for (let c of child) append_child(elem, c);
		return;
	}
	if (typeof child === "string" || typeof child === "number") child = document.createTextNode(child);
	elem.appendChild(child);
}

export function set_content(elem, children) {
	if (typeof elem === "string") elem = DOM(elem);
	while (elem.lastChild) elem.removeChild(elem.lastChild);
	append_child(elem, children);
	return elem;
}

const handlers = {};
export function on(event, selector, handler, options) {
	if (handlers[event]) return handlers[event].push([selector, handler]);
	handlers[event] = [[selector, handler]];
	document.addEventListener(event, e => {
		//Reimplement bubbling ourselves
		const top = e.currentTarget; //Generic in case we later allow this to attach to other than document
		let cur = e.target;
		while (cur && cur !== top) {
			e.match = cur; //We can't mess with e.currentTarget without synthesizing our own event object. Easier to make a new property.
			handlers[event].forEach(([s, h]) => cur.matches(s) && h(e));
			cur = cur.parentNode;
		}
		e.match = null; //Signal that you can't trust the match ref any more
	}, options);
	return 1;
}

//Apply some patches to <dialog> tags to make them easier to use. Accepts keyword args in a config object:
//	fix_dialogs({close_selector: ".dialog_cancel,.dialog_close", click_outside: true});
//For older browsers, this adds showModal() and close() methods
//If cfg.close_selector, will hook events from all links/buttons matching it to close the dialog
//If cfg.click_outside, any click outside a dialog will also close it. (May not work on older browsers.)
export function fix_dialogs(cfg) {
	if (!cfg) cfg = {};
	//For browsers with only partial support for the <dialog> tag, add the barest minimum.
	//On browsers with full support, there are many advantages to using dialog rather than
	//plain old div, but this way, other browsers at least have it pop up and down.
	let need_button_fix = false;
	document.querySelectorAll("dialog").forEach(dlg => {
		if (!dlg.showModal) {
			dlg.showModal = function() {this.style.display = "block";}
			dlg.close = function(ret) {
				if (ret) this.returnValue = ret;
				this.style.removeProperty("display");
				this.dispatchEvent(new CustomEvent("close", {bubbles: true}));
			};
			need_button_fix = true;
		}
	});
	//Ideally, I'd like to feature-detect whether form[method=dialog] actually
	//works, and do this if it doesn't; we assume that the lack of a showModal
	//method implies this being also unsupported. New in Choc Factory 0.4.
	if (need_button_fix) on("click", 'dialog form[method="dialog"] button', e => {
		e.match.closest("dialog").close(e.match.value);
		e.preventDefault();
	});
	if (cfg.click_outside) on("click", "dialog", e => {
		//NOTE: Sometimes, clicking on a <select> will give spurious clientX/clientY
		//values. Since clicking outside is always going to send the message directly
		//to the dialog (not to one of its children), check for that case.
		if (e.match !== e.target) return;
		if (cfg.click_outside === "formless" && e.match.querySelector("form")) return;
		let rect = e.match.getBoundingClientRect();
		if (e.clientY < rect.top || e.clientY > rect.top + rect.height
				|| e.clientX < rect.left || e.clientX > rect.left + rect.width)
		{
			e.match.close();
			e.preventDefault();
		}
	});
	if (cfg.close_selector) on("click", cfg.close_selector, e => e.match.closest("dialog").close());
}

let choc = function(tag, attributes, children) {
	const ret = document.createElement(tag);
	//If called as choc(tag, children), assume all attributes are defaults
	if (typeof attributes === "string" || attributes instanceof Array || attributes instanceof Element)
		return set_content(ret, attributes);
	if (attributes) for (let attr in attributes) {
		if (attr.startsWith("data-")) //Simplistic - we don't transform "data-foo-bar" into "fooBar" per HTML.
			ret.dataset[attr.slice(5)] = attributes[attr];
		else if (attr === "form") //Setting the form attribute on an element has to be done differently.
			ret.setAttribute("form", attributes[attr]);
		else ret[attr] = attributes[attr];
	}
	if (children) set_content(ret, children);
	return ret;
}
choc.__version__ = "0.6.1";

//Interpret choc.DIV(attr, chld) as choc("DIV", attr, chld)
//This is basically what Python would do as choc.__getattr__()
choc = new Proxy(choc, {get: function(obj, prop) {
	if (prop in obj) return obj[prop];
	return obj[prop] = (a, c) => obj(prop, a, c);
}});

//For modules, make the main entry-point easily available.
export default choc;

//For non-module scripts, allow some globals to be used
window.choc = choc; window.set_content = set_content; window.on = on; window.DOM = DOM; window.fix_dialogs = fix_dialogs;
window.chocify = tags => tags.split(" ").forEach(tag => window[tag] = choc[tag]);
<|endoftext|>


<commit_before>/**
 * @constructor
 */
function MenuController(tabs, fileTree) {
  this.tabs_ = tabs;
  this.fileTree_ = fileTree;
  this.dragItem_ = null;
  $('#file-menu-new').click(this.newTab_.bind(this));
  $('#file-menu-open').click(this.open_.bind(this));
  $('#file-menu-save').click(this.save_.bind(this));
  $('#file-menu-saveas').click(this.saveas_.bind(this));
  $('#file-menu-open-project').click(this.openProject_.bind(this));
  $(document).bind('newtab', this.onNewTab.bind(this));
  $(document).bind('switchtab', this.onSwitchTab.bind(this));
  $(document).bind('tabchange', this.onTabChange.bind(this));
  $(document).bind('tabclosed', this.onTabClosed.bind(this));
  $(document).bind('tabpathchange', this.onTabPathChange.bind(this));
  $(document).bind('tabrenamed', this.onTabRenamed.bind(this));
  $(document).bind('tabsave', this.onTabSave.bind(this));
}

MenuController.prototype.onNewTab = function(e, tab) {
  var id = tab.getId();
  var name = tab.getName();
  var listItem = $('
' +
                   '
' + name + '
' +
                   '

');
  listItem.bind('dragstart', this.onDragStart_.bind(this, listItem));
  listItem.bind('dragover', this.onDragOver_.bind(this, listItem));
  listItem.bind('dragend', this.onDragEnd_.bind(this, listItem));
  listItem.bind('drop', this.onDrop_.bind(this, listItem));
  listItem.appendTo($('#tabs-list'));
  listItem.click(this.tabButtonClicked_.bind(this, id));
  listItem.find('.close').click(this.closeTabClicked_.bind(this, id));
};

MenuController.prototype.onDragStart_ = function(listItem, e) {
  this.dragItem_ = listItem;
};

MenuController.prototype.onDragEnd_ = function(listItem, e) {
  this.dragItem_ = null;
  e.preventDefault();
  e.stopPropagation();
};

MenuController.prototype.onDrop_ = function(listItem, e) {
  e.stopPropagation();
};

MenuController.prototype.onDragOver_ = function(overItem, e) {
  e.preventDefault();
  if (!this.dragItem_ || overItem.attr('id') === this.dragItem_.attr('id'))
    return;

  if (this.dragItem_.index() < overItem.index()) {
    overItem.after(this.dragItem_);
  } else {
    overItem.before(this.dragItem_);
  }
  this.tabs_.reorder(this.dragItem_.index(), overItem.index());
};

MenuController.prototype.onTabRenamed = function(e, tab) {
  $('#tab' + tab.getId() + ' .filename').text(tab.getName());
};

MenuController.prototype.onTabPathChange = function(e, tab) {
  $('#tab' + tab.getId() + ' .filename').attr('title', tab.getPath());
};

MenuController.prototype.onTabChange = function(e, tab) {
  // TODO: Apply to file-tree node instead.
  $('#tab' + tab.getId()).addClass('unsaved');
};

MenuController.prototype.onTabClosed = function(e, tab) {
  $('#tab' + tab.getId()).remove();
};

MenuController.prototype.onTabSave = function(e, tab) {
  $('#tab' + tab.getId()).removeClass('unsaved');
};

MenuController.prototype.onSwitchTab = function(e, tab) {
  $('#tabs-list li.active').removeClass('active');
  $('#tab' + tab.getId()).addClass('active');
};

MenuController.prototype.newTab_ = function() {
  this.tabs_.newTab();
  return false;
};

MenuController.prototype.open_ = function() {
  this.tabs_.openFiles();
  return false;
};

MenuController.prototype.openProject_ = function() {
  this.fileTree_.openProject();
  return false;
};

MenuController.prototype.save_ = function() {
  this.tabs_.save();
  return false;
};

MenuController.prototype.saveas_ = function() {
  this.tabs_.saveAs();
  return false;
};

MenuController.prototype.tabButtonClicked_ = function(id) {
  this.tabs_.showTab(id);
  return false;
};

MenuController.prototype.closeTabClicked_ = function(id) {
  this.tabs_.close(id);
};
<commit_msg>Comments on legacy functionality.<commit_after>/**
 * @constructor
 */
function MenuController(tabs, fileTree) {
  this.tabs_ = tabs;
  this.fileTree_ = fileTree;
  this.dragItem_ = null;
  $('#file-menu-new').click(this.newTab_.bind(this));
  $('#file-menu-open').click(this.open_.bind(this));
  $('#file-menu-save').click(this.save_.bind(this));
  $('#file-menu-saveas').click(this.saveas_.bind(this));
  $('#file-menu-open-project').click(this.openProject_.bind(this));
  $(document).bind('newtab', this.onNewTab.bind(this));
  $(document).bind('switchtab', this.onSwitchTab.bind(this));
  $(document).bind('tabchange', this.onTabChange.bind(this));
  $(document).bind('tabclosed', this.onTabClosed.bind(this));
  $(document).bind('tabpathchange', this.onTabPathChange.bind(this));
  $(document).bind('tabrenamed', this.onTabRenamed.bind(this));
  $(document).bind('tabsave', this.onTabSave.bind(this));
}

MenuController.prototype.onNewTab = function(e, tab) {
  var id = tab.getId();
  var name = tab.getName();
  var listItem = $('
' +
                   '
' + name + '
' +
                   '

');
  listItem.bind('dragstart', this.onDragStart_.bind(this, listItem));
  listItem.bind('dragover', this.onDragOver_.bind(this, listItem));
  listItem.bind('dragend', this.onDragEnd_.bind(this, listItem));
  listItem.bind('drop', this.onDrop_.bind(this, listItem));
  listItem.appendTo($('#tabs-list'));
  listItem.click(this.tabButtonClicked_.bind(this, id));
  listItem.find('.close').click(this.closeTabClicked_.bind(this, id));
};

// TODO: What do these 'drag' do?
MenuController.prototype.onDragStart_ = function(listItem, e) {
  this.dragItem_ = listItem;
};

MenuController.prototype.onDragEnd_ = function(listItem, e) {
  this.dragItem_ = null;
  e.preventDefault();
  e.stopPropagation();
};

MenuController.prototype.onDrop_ = function(listItem, e) {
  e.stopPropagation();
};

MenuController.prototype.onDragOver_ = function(overItem, e) {
  e.preventDefault();
  if (!this.dragItem_ || overItem.attr('id') === this.dragItem_.attr('id'))
    return;

  if (this.dragItem_.index() < overItem.index()) {
    overItem.after(this.dragItem_);
  } else {
    overItem.before(this.dragItem_);
  }
  this.tabs_.reorder(this.dragItem_.index(), overItem.index());
};

MenuController.prototype.onTabRenamed = function(e, tab) {
  // TODO: Handle by file-tree instead.
  $('#tab' + tab.getId() + ' .filename').text(tab.getName());
};

MenuController.prototype.onTabPathChange = function(e, tab) {
  // TODO: Handle by file-tree instead.
  $('#tab' + tab.getId() + ' .filename').attr('title', tab.getPath());
};

MenuController.prototype.onTabChange = function(e, tab) {
  // TODO: Apply to file-tree node instead.
  $('#tab' + tab.getId()).addClass('unsaved');
};

MenuController.prototype.onTabClosed = function(e, tab) {
  // No longer needed, since we don't close files.
  $('#tab' + tab.getId()).remove();
};

MenuController.prototype.onTabSave = function(e, tab) {
  // TODO: Apply to file-tree instead.
  $('#tab' + tab.getId()).removeClass('unsaved');
};

MenuController.prototype.onSwitchTab = function(e, tab) {
  // No longer needed. Should be handled by file-tree instead.
  $('#tabs-list li.active').removeClass('active');
  $('#tab' + tab.getId()).addClass('active');
};

MenuController.prototype.newTab_ = function() {
  this.tabs_.newTab();
  return false;
};

MenuController.prototype.open_ = function() {
  this.tabs_.openFiles();
  return false;
};

MenuController.prototype.openProject_ = function() {
  this.fileTree_.openProject();
  return false;
};

MenuController.prototype.save_ = function() {
  this.tabs_.save();
  return false;
};

MenuController.prototype.saveas_ = function() {
  this.tabs_.saveAs();
  return false;
};

MenuController.prototype.tabButtonClicked_ = function(id) {
  this.tabs_.showTab(id);
  return false;
};

MenuController.prototype.closeTabClicked_ = function(id) {
  this.tabs_.close(id);
};
<|endoftext|>