<commit_before>// Thing Sensor Reporting Protocol

var dgram       = require('dgram')
  , util        = require('util')
  , xml         = require('xml2json')
  , trsp		= require('./discovery-tsrp')
  , devices     = require('./../core/device')
  , things      = require('./../api/api-manage-thing')
  , utility     = require('./../core/utility')
  ;

var logger = utility.logger('discovery');

exports.start = function() {
 	var LOCAL_BROADCAST_HOST = '224.192.32.19';
	var LOCAL_BROADCAST_PORT = 22600;
	var bootTime = process.hrtime()[0] * 1000 + process.hrtime()[1] / 1000;
	var requestID = 0;

	var socket = dgram.createSocket('udp4');
	socket.bind(LOCAL_BROADCAST_PORT, function() {
		socket.addMembership(LOCAL_BROADCAST_HOST);
	});

	socket.on('message', function(message, rinfo) {
    	var report;

    	try {
			var json = xml.toJson( message );
			var buff = JSON.parse( json );
			var currTime = process.hrtime()[0] * 1000 + process.hrtime()[1] / 1000;
			requestID = requestID+1;

			if ( buff.electricity ) {
				logger.info('Recieved OWL electricity packet.');
				var battery = buff.electricity.battery.level.substring(0, buff.electricity.battery.level.length - 1);

				var channel0, channel1, channel2 = null;
				buff.electricity.chan.forEach(function(entry) {
				    if( entry.id === 0 ) {
						channel0 = [{'current':entry.curr.$t,'units':entry.curr.units},
									{'day':entry.day.$t,'units':entry.day.units}];
					}
					if( entry.id === 1 ) {
						channel1 = [{'current':entry.curr.$t,'units':entry.curr.units},
									{'day':entry.day.$t,'units':entry.day.units}];
					}
					if( entry.id === 2 ) {
						channel2 = [{'current':entry.curr.$t,'units':entry.curr.units},
									{'day':entry.day.$t,'units':entry.day.units}];
					}
				});

				report = {"path":"/api/v1/thing/reporting",
 		  		          "requestID":requestID.toString(),
				   		  "things":{
				      		"/device/sensor/owl/electricity":{
				         		"prototype":{
				            		"device":{
				               			"name":"OWL Micro+",
				               			"maker":"2 Save Energy Ltd"
				            		},
				            		"name":true,
				            		"status":[ "present", "absent", "recent"],
				            		"properties":{ "rssi":"dB", "lqi":"", "battery":"%", "currentUsage":"W", "dailyUsage":"Wh" }
				         		},
				         		"instances":[{
				               		"name":"OWL Micro+",
				               		"status":"present",
				               		"unit":{
				                  		"serial":buff.electricity.id,
				                  		"udn":"195a42b0-ef6b-11e2-99d0-UID"+buff.electricity.id+"-owl-micro+"
				               		},
				               		"info":{
				                  		"rssi":buff.electricity.signal.rssi,
										"lqi":buff.electricity.signal.lqi,
										"battery":battery,
				                  		"currentUsage":channel0[0].current,
				                  		"dailyUsage":channel0[1].day
				               		},
				               		"uptime":currTime-bootTime
				            	}]
							}
				   		}
						};

			} else if ( buff.heating ) {
				logger.info('Recieved OWL heating packet.');
				var battery = buff.heating.battery.level.substring(0, buff.heating.battery.level.length - 2);
				report = {"path":"/api/v1/thing/reporting",
 		  		  		  "requestID":requestID.toString(),
				   		  "things":{
				      		"/device/climate/owl/control":{
				         		"prototype":{
				            		"device":{
				               			"name":"OWL Intuition-c",
				               			"maker":"2 Save Energy Ltd"
				            		},
				            		"name":true,
				            		"status":[ "present", "absent", "recent"],
				            		"properties":{ "rssi":"dB", "lqi":"", "battery":"mV", "temperature":"celsius", "goalTemperature":"celsius",
				                                   "until":"","zone":"" }
				         		},
				         		"instances":[{
				               		"name":"OWL Intuition-c",
				               		"status":"present",
				               		"unit":{
				                  		"serial":buff.heating.id,
				                  		"udn":"195a42b0-ef6b-11e2-99d0-UID"+buff.heating.id+"-owl-thermostat"
				               		},
				               		"info":{
				                  		"rssi":buff.heating.signal.rssi,
										"lqi":buff.heating.signal.lqi,
										"battery":battery,
				                  		"temperature":buff.heating.temperature.current,
				                  		"goalTemperature":buff.heating.temperature.required,
										"until":buff.heating.temperature.until,
										"zone":buff.heating.temperature.zone.toString()
				               		},
				               		"uptime":currTime-bootTime
				            	}]
							}
				   		}
						};

		 	} else if ( buff.weather ) {
				logger.info('Recieved OWL weather packet.');
				report = {"path":"/api/v1/thing/reporting",
		   		  		  "requestID":requestID.toString(),
				   		  "things":{
				      		"/device/climate/owl/sensor":{
				         		"prototype":{
				            		"device":{
				               			"name":"Network OWL",
				               			"maker":"2 Save Energy Ltd"
				            		},
				            		"name":true,
				            		"status":[ "present", "absent", "recent"],
				            		"properties":{ "code":"", "temperature":"celsius", "text":"" }
				         		},
				         		"instances":[{
				               		"name":"OWL Weather",
				               		"status":"present",
				               		"unit":{
				                  		"serial":buff.weather.id,
				                  		"udn":"195a42b0-ef6b-11e2-99d0-UID"+buff.weather.id+"-owl-weather"
				               		},
				               		"info":{
				                  		"code":buff.weather.code,
				                  		"temperature":buff.weather.temperature,
				                  		"text":buff.weather.text
				               		},
				               		"uptime":currTime-bootTime
				            	}]
							}
				   		}
						};

			} else if ( buff.solar ) {
				logger.info('Recieved OWL solar packet.');
				report = {"path":"/api/v1/thing/reporting",
				  		  "requestID":requestID.toString(),
				   		  "things":{
				      		"/device/sensor/owl/solarpanels":{
				         		"prototype":{
				            		"device":{
				               			"name":"OWL Intuition-pv",
				               			"maker":"2 Save Energy Ltd"
				            		},
				            		"name":true,
				            		"status":[ "present", "absent", "recent"],
				            		"properties":{ "generating":"W", "exporting":"W" }
				         		},
				         		"instances":[{
				               		"name":"OWL Intuition-pv",
				               		"status":"present",
				               		"unit":{
				                  		"serial":buff.solar.id,
				                  		"udn":"195a42b0-ef6b-11e2-99d0-UID"+buff.solar.id+"-owl-solar"
				               		},
				               		"info":{
				                  		"generating":buff.solar.current.generating,
				                  		"exporting":buff.solar.current.exporting
				               		},
				               		"uptime":currTime-bootTime
				            	}]
							}
				   		}
						};
			}

			//console.log(util.inspect(report, false, null));
			trsp.handle(report, rinfo.address, 'udp ' + rinfo.address + ' ' + rinfo.port + ' ' + report.path);
	    } catch(ex) {
		    logger.error('reporting', { event: 'parsing', diagnostic: ex.message });
      		return;
    	}
  	});

  	socket.on('listening', function() {
    	var address = this.address();
		logger.info('OWL driver listening on udp://*:' + address.port);
  	});

	socket.on('error', function(err) {
    	logger.error('reporting', { event: 'socket', diagnostic: err.message });
  	})

};
<commit_msg>Modified naming convention<commit_after>// Thing Sensor Reporting Protocol

var dgram       = require('dgram')
  , util        = require('util')
  , xml         = require('xml2json')
  , trsp		= require('./discovery-tsrp')
  , devices     = require('./../core/device')
  , things      = require('./../api/api-manage-thing')
  , utility     = require('./../core/utility')
  ;

var logger = utility.logger('discovery');

exports.start = function() {
 	var LOCAL_BROADCAST_HOST = '224.192.32.19';
	var LOCAL_BROADCAST_PORT = 22600;
	var bootTime = process.hrtime()[0] * 1000 + process.hrtime()[1] / 1000;
	var requestID = 0;

	var socket = dgram.createSocket('udp4');
	socket.bind(LOCAL_BROADCAST_PORT, function() {
		socket.addMembership(LOCAL_BROADCAST_HOST);
	});

	socket.on('message', function(message, rinfo) {
    	var report;

    	try {
			var json = xml.toJson( message );
			var buff = JSON.parse( json );
			var currTime = process.hrtime()[0] * 1000 + process.hrtime()[1] / 1000;
			requestID = requestID+1;

			if ( buff.electricity ) {
				logger.info('Recieved OWL electricity packet.');
				var battery = buff.electricity.battery.level.substring(0, buff.electricity.battery.level.length - 1);

				var channel0, channel1, channel2 = null;
				buff.electricity.chan.forEach(function(entry) {
				    if( entry.id === 0 ) {
						channel0 = [{'current':entry.curr.$t,'units':entry.curr.units},
									{'day':entry.day.$t,'units':entry.day.units}];
					}
					if( entry.id === 1 ) {
						channel1 = [{'current':entry.curr.$t,'units':entry.curr.units},
									{'day':entry.day.$t,'units':entry.day.units}];
					}
					if( entry.id === 2 ) {
						channel2 = [{'current':entry.curr.$t,'units':entry.curr.units},
									{'day':entry.day.$t,'units':entry.day.units}];
					}
				});

				report = {"path":"/api/v1/thing/reporting",
 		  		          "requestID":requestID.toString(),
				   		  "things":{
				      		"/device/sensor/owl/electricity":{
				         		"prototype":{
				            		"device":{
				               			"name":"OWL Intuition-e",
				               			"maker":"2 Save Energy Ltd"
				            		},
				            		"name":true,
				            		"status":[ "present", "absent", "recent"],
				            		"properties":{ "rssi":"dB", "lqi":"", "battery":"%", "currentUsage":"W", "dailyUsage":"Wh" }
				         		},
				         		"instances":[{
				               		"name":"OWL Intuition-e",
				               		"status":"present",
				               		"unit":{
				                  		"serial":buff.electricity.id,
				                  		"udn":"195a42b0-ef6b-11e2-99d0-UID"+buff.electricity.id+"-owl-electricity-monitor"
				               		},
				               		"info":{
				                  		"rssi":buff.electricity.signal.rssi,
										"lqi":buff.electricity.signal.lqi,
										"battery":battery,
				                  		"currentUsage":channel0[0].current,
				                  		"dailyUsage":channel0[1].day
				               		},
				               		"uptime":currTime-bootTime
				            	}]
							}
				   		}
						};

			} else if ( buff.heating ) {
				logger.info('Recieved OWL heating packet.');
				var battery = buff.heating.battery.level.substring(0, buff.heating.battery.level.length - 2);
				report = {"path":"/api/v1/thing/reporting",
 		  		  		  "requestID":requestID.toString(),
				   		  "things":{
				      		"/device/climate/owl/control":{
				         		"prototype":{
				            		"device":{
				               			"name":"OWL Intuition-c",
				               			"maker":"2 Save Energy Ltd"
				            		},
				            		"name":true,
				            		"status":[ "present", "absent", "recent"],
				            		"properties":{ "rssi":"dB", "lqi":"", "battery":"mV", "temperature":"celsius", "goalTemperature":"celsius",
				                                   "until":"","zone":"" }
				         		},
				         		"instances":[{
				               		"name":"OWL Intuition-c",
				               		"status":"present",
				               		"unit":{
				                  		"serial":buff.heating.id,
				                  		"udn":"195a42b0-ef6b-11e2-99d0-UID"+buff.heating.id+"-owl-thermostat"
				               		},
				               		"info":{
				                  		"rssi":buff.heating.signal.rssi,
										"lqi":buff.heating.signal.lqi,
										"battery":battery,
				                  		"temperature":buff.heating.temperature.current,
				                  		"goalTemperature":buff.heating.temperature.required,
										"until":buff.heating.temperature.until,
										"zone":buff.heating.temperature.zone.toString()
				               		},
				               		"uptime":currTime-bootTime
				            	}]
							}
				   		}
						};

		 	} else if ( buff.weather ) {
				logger.info('Recieved OWL weather packet.');
				report = {"path":"/api/v1/thing/reporting",
		   		  		  "requestID":requestID.toString(),
				   		  "things":{
				      		"/device/climate/owl/sensor":{
				         		"prototype":{
				            		"device":{
				               			"name":"Network OWL",
				               			"maker":"2 Save Energy Ltd"
				            		},
				            		"name":true,
				            		"status":[ "present", "absent", "recent"],
				            		"properties":{ "code":"", "temperature":"celsius", "text":"" }
				         		},
				         		"instances":[{
				               		"name":"OWL Weather",
				               		"status":"present",
				               		"unit":{
				                  		"serial":buff.weather.id,
				                  		"udn":"195a42b0-ef6b-11e2-99d0-UID"+buff.weather.id+"-owl-weather"
				               		},
				               		"info":{
				                  		"code":buff.weather.code,
				                  		"temperature":buff.weather.temperature,
				                  		"text":buff.weather.text
				               		},
				               		"uptime":currTime-bootTime
				            	}]
							}
				   		}
						};

			} else if ( buff.solar ) {
				logger.info('Recieved OWL solar packet.');
				report = {"path":"/api/v1/thing/reporting",
				  		  "requestID":requestID.toString(),
				   		  "things":{
				      		"/device/sensor/owl/solarpanels":{
				         		"prototype":{
				            		"device":{
				               			"name":"OWL Intuition-pv",
				               			"maker":"2 Save Energy Ltd"
				            		},
				            		"name":true,
				            		"status":[ "present", "absent", "recent"],
				            		"properties":{ "generating":"W", "exporting":"W" }
				         		},
				         		"instances":[{
				               		"name":"OWL Intuition-pv",
				               		"status":"present",
				               		"unit":{
				                  		"serial":buff.solar.id,
				                  		"udn":"195a42b0-ef6b-11e2-99d0-UID"+buff.solar.id+"-owl-solarpanel"
				               		},
				               		"info":{
				                  		"generating":buff.solar.current.generating,
				                  		"exporting":buff.solar.current.exporting
				               		},
				               		"uptime":currTime-bootTime
				            	}]
							}
				   		}
						};
			}

			//console.log(util.inspect(report, false, null));
			trsp.handle(report, rinfo.address, 'udp ' + rinfo.address + ' ' + rinfo.port + ' ' + report.path);
	    } catch(ex) {
		    logger.error('reporting', { event: 'parsing', diagnostic: ex.message });
      		return;
    	}
  	});

  	socket.on('listening', function() {
    	var address = this.address();
		logger.info('OWL driver listening on udp://*:' + address.port);
  	});

	socket.on('error', function(err) {
    	logger.error('reporting', { event: 'socket', diagnostic: err.message });
  	})

};
<|endoftext|>


<commit_before>Ext.define('devilry_subjectadmin.controller.guides.CreateNewAssignment', {
    extend: 'devilry_subjectadmin.controller.guides.Base',

    views: [
        'guides.CreateNewAssignment'
    ],

    steps: 4,
    title: gettext('Create new assignment'),

    refs: [{
        ref: 'guideView',
        selector: 'viewport guide-createnewassignment'
    }, {
        ref: 'createNewAssignmentBox',
        selector: 'viewport periodoverview #createNewAssignmentBox'
    }],

    init: function() {
        this.callParent(arguments);
        this.control({
            'viewport dashboard allactivewhereisadminlist': {
                render: this.ifActiveInterceptor(this.onFirstStep)
            },
            'viewport periodoverview #createNewAssignmentBox': {
                render: this.ifActiveInterceptor(this._onPeriodRender)
            },
            'viewport createnewassignment #pageOne': {
                render: this.ifActiveInterceptor(this._onCreateNewAssignmentPageOne),
                show: this.ifActiveInterceptor(this._onCreateNewAssignmentPageOne)
            },
            'viewport createnewassignment #pageTwo': {
                show: this.ifActiveInterceptor(this._onCreateNewAssignmentPageTwo)
            },
            'viewport createnewassignment #createButton': {
                click: this._onCreateAssignmentClick
            }
        });
    },

    onFirstStep: function() {
        this.getGuideView().getLayout().setActiveItem('dashboard');
        this.setStep('dashboard', 1);
    },

    _onPeriodRender: function() {
        this.setStep('period', 2);
        var element = this.getCreateNewAssignmentBox().getEl().down('a');
        this.guideSystem.pointAt(element);
    },

    _onCreateNewAssignmentPageOne: function() {
        this.setStep('createnewassignment1', 3);
    },
    _onCreateNewAssignmentPageTwo: function() {
        this.setStep('createnewassignment2', 4);
    },

    _onCreateAssignmentClick: function() {
        this.guideSystem.endGuide();
    }
});
<commit_msg>devilry_subjectadmin...guides.CreateNewAssignment: Wrap the last click.<commit_after>Ext.define('devilry_subjectadmin.controller.guides.CreateNewAssignment', {
    extend: 'devilry_subjectadmin.controller.guides.Base',

    views: [
        'guides.CreateNewAssignment'
    ],

    steps: 4,
    title: gettext('Create new assignment'),

    refs: [{
        ref: 'guideView',
        selector: 'viewport guide-createnewassignment'
    }, {
        ref: 'createNewAssignmentBox',
        selector: 'viewport periodoverview #createNewAssignmentBox'
    }],

    init: function() {
        this.callParent(arguments);
        this.control({
            'viewport dashboard allactivewhereisadminlist': {
                render: this.ifActiveInterceptor(this.onFirstStep)
            },
            'viewport periodoverview #createNewAssignmentBox': {
                render: this.ifActiveInterceptor(this._onPeriodRender)
            },
            'viewport createnewassignment #pageOne': {
                render: this.ifActiveInterceptor(this._onCreateNewAssignmentPageOne),
                show: this.ifActiveInterceptor(this._onCreateNewAssignmentPageOne)
            },
            'viewport createnewassignment #pageTwo': {
                show: this.ifActiveInterceptor(this._onCreateNewAssignmentPageTwo)
            },
            'viewport createnewassignment #createButton': {
                click: this.ifActiveInterceptor(this._onCreateAssignmentClick)
            }
        });
    },

    onFirstStep: function() {
        this.getGuideView().getLayout().setActiveItem('dashboard');
        this.setStep('dashboard', 1);
    },

    _onPeriodRender: function() {
        this.setStep('period', 2);
        var element = this.getCreateNewAssignmentBox().getEl().down('a');
        this.guideSystem.pointAt(element);
    },

    _onCreateNewAssignmentPageOne: function() {
        this.setStep('createnewassignment1', 3);
    },
    _onCreateNewAssignmentPageTwo: function() {
        this.setStep('createnewassignment2', 4);
    },

    _onCreateAssignmentClick: function() {
        this.guideSystem.endGuide();
    }
});
<|endoftext|>


<commit_before>/**
 * @file IXmlContentHandler interface
 */
/*#ifndef(UMD)*/
"use strict";
/*global _gpfDefineInterface*/ // Internal interface definition helper
/*global _gpfSyncReadSourceJSON*/ // Reads a source json file (only in source mode)
/*exported _gpfIXmlContentHandler*/ // gpf.interfaces.IXmlContentHandler
/*#endif*/

/**
 * Interface used to serialize XML files, the SAX way
 *
 * @interface gpf.interfaces.IXmlContentHandler
 */

/**
 * Signal character data
 *
 * @method gpf.interfaces.IXmlContentHandler#characters
 * @param {String} buffer characters
 */

/**
 * Signal the end of the document
 *
 * @method gpf.interfaces.IXmlContentHandler#endDocument
 * @return {Promise} Resolved when ready
 */

/**
 * Signal the end of an element
 *
 * @method gpf.interfaces.IXmlContentHandler#endElement
 * @return {Promise} Resolved when ready
 */

/**
 *  Signal the scope end of a prefix-URI namespace mapping
 *
 * @method gpf.interfaces.IXmlContentHandler#endPrefixMapping
 * @param {String} prefix Prefix of the prefix-URI mapping
 * @return {Promise} Resolved when ready
 */

/**
 * Signal a processing instruction
 *
 * @method gpf.interfaces.IXmlContentHandler#processingInstruction
 * @param {String} target Target of processing instruction
 * @param {String} data Data of processing instruction
 * @return {Promise} Resolved when ready
 */

/**
 * Signal the beginning of the document
 *
 * @method gpf.interfaces.IXmlContentHandler#startDocument
 * @return {Promise} Resolved when ready
 */

/**
 * Signal the beginning of an element
 *
 * @method gpf.interfaces.IXmlContentHandler#startElement
 * @param {String} qName Qualified name, [prefix:]localName
 * @param {String} uri Namespace URI associated with the name
 * @param {Object} attributes attribute dictionary (string/string)
 * @return {Promise} Resolved when ready
 */

/**
 * Signal the scope start a prefix-URI namespace mapping
 *
 * @param {String} prefix Prefix of the prefix-URI mapping
 * @param {String} uri Namespace URI associated with the prefix
 * @return {Promise} Resolved when ready
 */

/**
 * IXmlContentHandler interface specifier
 *
 * @type {gpf.interfaces.IXmlContentHandler}
 */
var _gpfIXmlContentHandler = _gpfDefineInterface("XmlContentHandler",
    _gpfSyncReadSourceJSON("interfaces/xmlcontenthandler.json"));
<commit_msg>'Optional' parameters (#264)<commit_after>/**
 * @file IXmlContentHandler interface
 */
/*#ifndef(UMD)*/
"use strict";
/*global _gpfDefineInterface*/ // Internal interface definition helper
/*global _gpfSyncReadSourceJSON*/ // Reads a source json file (only in source mode)
/*exported _gpfIXmlContentHandler*/ // gpf.interfaces.IXmlContentHandler
/*#endif*/

/**
 * Interface used to serialize XML files, the SAX way
 *
 * @interface gpf.interfaces.IXmlContentHandler
 */

/**
 * Signal character data
 *
 * @method gpf.interfaces.IXmlContentHandler#characters
 * @param {String} buffer characters
 */

/**
 * Signal the end of the document
 *
 * @method gpf.interfaces.IXmlContentHandler#endDocument
 * @return {Promise} Resolved when ready
 */

/**
 * Signal the end of an element
 *
 * @method gpf.interfaces.IXmlContentHandler#endElement
 * @return {Promise} Resolved when ready
 */

/**
 *  Signal the scope end of a prefix-URI namespace mapping
 *
 * @method gpf.interfaces.IXmlContentHandler#endPrefixMapping
 * @param {String} prefix Prefix of the prefix-URI mapping
 * @return {Promise} Resolved when ready
 */

/**
 * Signal a processing instruction
 *
 * @method gpf.interfaces.IXmlContentHandler#processingInstruction
 * @param {String} target Target of processing instruction
 * @param {String} data Data of processing instruction
 * @return {Promise} Resolved when ready
 */

/**
 * Signal the beginning of the document
 *
 * @method gpf.interfaces.IXmlContentHandler#startDocument
 * @return {Promise} Resolved when ready
 */

/**
 * Signal the beginning of an element
 *
 * @method gpf.interfaces.IXmlContentHandler#startElement
 * @param {String} qName Qualified name, [prefix:]localName
 * @param {String} [uri=""] Namespace URI associated with the name
 * @param {Object} [attributes={}] attribute dictionary (string/string)
 * @return {Promise} Resolved when ready
 */

/**
 * Signal the scope start a prefix-URI namespace mapping
 *
 * @param {String} prefix Prefix of the prefix-URI mapping
 * @param {String} uri Namespace URI associated with the prefix
 * @return {Promise} Resolved when ready
 */

/**
 * IXmlContentHandler interface specifier
 *
 * @type {gpf.interfaces.IXmlContentHandler}
 */
var _gpfIXmlContentHandler = _gpfDefineInterface("XmlContentHandler",
    _gpfSyncReadSourceJSON("interfaces/xmlcontenthandler.json"));
<|endoftext|>


<commit_before>import {
  isPlainObject
} from 'uni-shared'

const CLASS_RE = /^\s+|\s+$/g
const WXS_CLASS_RE = /\s+/

function getWxsClsArr (clsArr, classList, isAdd) {
  const wxsClsArr = []

  let checkClassList = function (cls) {
    if (isAdd) {
      checkClassList = function (cls) {
        return !classList.contains(cls)
      }
    } else {
      checkClassList = function (cls) {
        return classList.contains(cls)
      }
    }
    return checkClassList(cls)
  }

  clsArr.forEach(cls => {
    cls = cls.replace(CLASS_RE, '')
    checkClassList(cls) && wxsClsArr.push(cls)
  })
  return wxsClsArr
}

function parseStyleText (cssText) {
  const res = {}
  const listDelimiter = /;(?![^(]*\))/g
  const propertyDelimiter = /:(.+)/
  cssText.split(listDelimiter).forEach(function (item) {
    if (item) {
      const tmp = item.split(propertyDelimiter)
      tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim())
    }
  })
  return res
}

class ComponentDescriptor {
  constructor (vm) {
    this.$vm = vm
    this.$el = vm.$el
  }

  selectComponent (selector) {
    if (!this.$el || !selector) {
      return
    }
    const el = this.$el.querySelector(selector)
    return el && el.__vue__ && createComponentDescriptor(el.__vue__, false)
  }

  selectAllComponents (selector) {
    if (!this.$el || !selector) {
      return []
    }
    const descriptors = []
    const els = this.$el.querySelectorAll(selector)
    for (let i = 0; i < els.length; i++) {
      const el = els[i]
      el.__vue__ && descriptors.push(createComponentDescriptor(el.__vue__, false))
    }
    return descriptors
  }

  setStyle (style) {
    if (!this.$el || !style) {
      return this
    }
    if (typeof style === 'string') {
      style = parseStyleText(style)
    }
    if (isPlainObject(style)) {
      this.$el.__wxsStyle = style
      this.$vm.$forceUpdate()
    }
    return this
  }

  addClass (...clsArr) {
    if (!this.$el || !clsArr.length) {
      return this
    }

    const wxsClsArr = getWxsClsArr(clsArr, this.$el.classList, true)
    if (wxsClsArr.length) {
      const wxsClass = this.$el.__wxsAddClass || ''
      this.$el.__wxsAddClass = wxsClass + (wxsClass ? ' ' : '') + wxsClsArr.join(' ')
      this.$vm.$forceUpdate()
    }

    return this
  }

  removeClass (...clsArr) {
    if (!this.$el || !clsArr.length) {
      return this
    }
    const classList = this.$el.classList
    const addWxsClsArr = this.$el.__wxsAddClass ? this.$el.__wxsAddClass.split(WXS_CLASS_RE) : []
    const wxsClsArr = getWxsClsArr(clsArr, classList, false)
    if (wxsClsArr.length) {
      const removeWxsClsArr = []
      wxsClsArr.forEach(cls => {
        const clsIndex = addWxsClsArr.findIndex(oldCls => oldCls === cls)
        if (clsIndex !== -1) { // 在 addWxsClass 中
          addWxsClsArr.splice(clsIndex, 1)
        }
        removeWxsClsArr.push(cls)
      })
      this.$el.__wxsRemoveClass = removeWxsClsArr
      this.$el.__wxsAddClass = addWxsClsArr.join(' ')
      this.$vm.$forceUpdate()
    }

    return this
  }

  hasClass (cls) {
    return this.$el && this.$el.classList.contains(cls)
  }

  getComputedStyle () {
    if (this.$el) {
      return window.getComputedStyle(this.$el)
    }
    return {}
  }

  getDataset () {
    return this.$el && this.$el.dataset
  }

  callMethod (funcName, args = {}) {
    if (this.$vm[funcName]) {
      this.$vm[funcName](JSON.parse(JSON.stringify(args)))
    } else if (this.$vm._$id) {
      UniViewJSBridge.publishHandler('onWxsInvokeCallMethod', {
        cid: this.$vm._$id,
        method: funcName,
        args
      })
    }
  }

  requestAnimationFrame (callback) {
    return (global.requestAnimationFrame(callback), this)
  }

  getState () {
    return this.$el && (this.$el.__wxsState || (this.$el.__wxsState = {}))
  }

  triggerEvent (eventName, detail = {}, options = {}) {
    // TODO options
    return (this.$vm.$emit(eventName, detail), this)
  }
}

export function createComponentDescriptor (vm, isOwnerInstance = true) {
  if (isOwnerInstance && vm && vm.$options.name && vm.$options.name.indexOf('VUni') === 0) {
    // ownerInstance 内置组件需要使用父 vm
    vm = vm.$parent
  }
  if (vm && vm.$el) {
    if (!vm.$el.__wxsComponentDescriptor) {
      vm.$el.__wxsComponentDescriptor = new ComponentDescriptor(vm)
    }
    return vm.$el.__wxsComponentDescriptor
  }
}
<commit_msg>fix: 修复部分情况下获取 wxs 实例错误的问题 question/117097<commit_after>import {
  isPlainObject
} from 'uni-shared'

const CLASS_RE = /^\s+|\s+$/g
const WXS_CLASS_RE = /\s+/

function getWxsClsArr (clsArr, classList, isAdd) {
  const wxsClsArr = []

  let checkClassList = function (cls) {
    if (isAdd) {
      checkClassList = function (cls) {
        return !classList.contains(cls)
      }
    } else {
      checkClassList = function (cls) {
        return classList.contains(cls)
      }
    }
    return checkClassList(cls)
  }

  clsArr.forEach(cls => {
    cls = cls.replace(CLASS_RE, '')
    checkClassList(cls) && wxsClsArr.push(cls)
  })
  return wxsClsArr
}

function parseStyleText (cssText) {
  const res = {}
  const listDelimiter = /;(?![^(]*\))/g
  const propertyDelimiter = /:(.+)/
  cssText.split(listDelimiter).forEach(function (item) {
    if (item) {
      const tmp = item.split(propertyDelimiter)
      tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim())
    }
  })
  return res
}

class ComponentDescriptor {
  constructor (vm) {
    this.$vm = vm
    this.$el = vm.$el
  }

  selectComponent (selector) {
    if (!this.$el || !selector) {
      return
    }
    const el = this.$el.querySelector(selector)
    return el && el.__vue__ && createComponentDescriptor(el.__vue__, false)
  }

  selectAllComponents (selector) {
    if (!this.$el || !selector) {
      return []
    }
    const descriptors = []
    const els = this.$el.querySelectorAll(selector)
    for (let i = 0; i < els.length; i++) {
      const el = els[i]
      el.__vue__ && descriptors.push(createComponentDescriptor(el.__vue__, false))
    }
    return descriptors
  }

  setStyle (style) {
    if (!this.$el || !style) {
      return this
    }
    if (typeof style === 'string') {
      style = parseStyleText(style)
    }
    if (isPlainObject(style)) {
      this.$el.__wxsStyle = style
      this.$vm.$forceUpdate()
    }
    return this
  }

  addClass (...clsArr) {
    if (!this.$el || !clsArr.length) {
      return this
    }

    const wxsClsArr = getWxsClsArr(clsArr, this.$el.classList, true)
    if (wxsClsArr.length) {
      const wxsClass = this.$el.__wxsAddClass || ''
      this.$el.__wxsAddClass = wxsClass + (wxsClass ? ' ' : '') + wxsClsArr.join(' ')
      this.$vm.$forceUpdate()
    }

    return this
  }

  removeClass (...clsArr) {
    if (!this.$el || !clsArr.length) {
      return this
    }
    const classList = this.$el.classList
    const addWxsClsArr = this.$el.__wxsAddClass ? this.$el.__wxsAddClass.split(WXS_CLASS_RE) : []
    const wxsClsArr = getWxsClsArr(clsArr, classList, false)
    if (wxsClsArr.length) {
      const removeWxsClsArr = []
      wxsClsArr.forEach(cls => {
        const clsIndex = addWxsClsArr.findIndex(oldCls => oldCls === cls)
        if (clsIndex !== -1) { // 在 addWxsClass 中
          addWxsClsArr.splice(clsIndex, 1)
        }
        removeWxsClsArr.push(cls)
      })
      this.$el.__wxsRemoveClass = removeWxsClsArr
      this.$el.__wxsAddClass = addWxsClsArr.join(' ')
      this.$vm.$forceUpdate()
    }

    return this
  }

  hasClass (cls) {
    return this.$el && this.$el.classList.contains(cls)
  }

  getComputedStyle () {
    if (this.$el) {
      return window.getComputedStyle(this.$el)
    }
    return {}
  }

  getDataset () {
    return this.$el && this.$el.dataset
  }

  callMethod (funcName, args = {}) {
    if (funcName in this.$vm) {
      this.$vm[funcName](JSON.parse(JSON.stringify(args)))
    } else if (this.$vm._$id) {
      UniViewJSBridge.publishHandler('onWxsInvokeCallMethod', {
        cid: this.$vm._$id,
        method: funcName,
        args
      })
    }
  }

  requestAnimationFrame (callback) {
    return (global.requestAnimationFrame(callback), this)
  }

  getState () {
    return this.$el && (this.$el.__wxsState || (this.$el.__wxsState = {}))
  }

  triggerEvent (eventName, detail = {}, options = {}) {
    // TODO options
    return (this.$vm.$emit(eventName, detail), this)
  }
}

export function createComponentDescriptor (vm, isOwnerInstance = true) {
  if (isOwnerInstance && vm && vm.$options.name && vm.$options.name.indexOf('VUni') === 0) {
    // ownerInstance 内置组件需要使用父 vm
    vm = vm.$parent
  }
  // 改为挂载到 vm 实例，不同 vm 实例的 $el 可能重复
  if (vm) {
    if (!('__wxsComponentDescriptor' in vm)) {
      vm.__wxsComponentDescriptor = new ComponentDescriptor(vm)
    }
    return vm.__wxsComponentDescriptor
  }
}
<|endoftext|>


<commit_before>'use strict';
const path = require('path');
const electron = require('electron');
const {app, shell} = require('electron');
const ipc = require('electron').ipcMain;

const tray = require('./tray');
const link = require ('./link_helper');
const {linkIsInternal} = link;

// adds debug features like hotkeys for triggering dev tools and reload
require('electron-debug')();
require('electron-context-menu')();

// prevent window being garbage collected
let mainWindow;

// Load this url in main window
const targetUrl = 'file://' + path.join(__dirname, '../renderer', 'index.html');
// let targetLink = data["domain"] || '';

let targetLink = function () {
	if (data["domain"] !== undefined) {
		return data["domain"]
	}
}

const APP_ICON = path.join(__dirname, '../resources', 'Icon');

const iconPath = () => {
  return process.platform === 'win32'
    ? APP_ICON + '.ico'
    : APP_ICON + '.png'
};

function onClosed() {
	// dereference the window
	// for multiple windows store them in an array
	mainWindow = null;
}

function createMainWindow() {
	const win = new electron.BrowserWindow({
		// This settings needs to be saved in config
		title: 'Zulip',
		width: 1000,
		height: 600,
		icon: iconPath(),
		minWidth: 800,
		minHeight: 600
	});

	win.loadURL(targetUrl);
	win.on('closed', onClosed);
	win.setTitle('Zulip');

	// stop page to update it's title
	win.on('page-title-updated', (e) => {
	e.preventDefault();
	});

	return win;
}

// TODO
app.commandLine.appendSwitch('ignore-certificate-errors', 'true');

app.on('window-all-closed', () => {
	if (process.platform !== 'darwin') {
		app.quit();
	}
});

app.on('activate', () => {
	if (!mainWindow) {
		mainWindow = createMainWindow();
	}
});

app.on('ready', () => {
	mainWindow = createMainWindow();
	tray.create(mainWindow);

	const page = mainWindow.webContents;

    page.on('new-window', (event, url) => {
        if (mainWindow.useDefaultWindowBehaviour) {
            mainWindow.useDefaultWindowBehaviour = false;
            return;
        }
        if (linkIsInternal(targetLink, url)) {
        	event.preventDefault();
			return mainWindow.loadURL(url);
        }
        event.preventDefault();
        electron.shell.openExternal(url);
    });
});

ipc.on('new-domain', function (e, domain) {
	mainWindow.loadURL(domain);
	targetLink = domain;
});
<commit_msg>:runner:  fixed issue #17<commit_after>'use strict';
const path = require('path');
const electron = require('electron');
const {app, shell} = require('electron');
const ipc = require('electron').ipcMain;
const tray = require('./tray');
const link = require ('./link_helper');
const {linkIsInternal} = link;

const JsonDB = require('node-json-db');
const db = new JsonDB("domain", true, true);
const data = db.getData("/");

// adds debug features like hotkeys for triggering dev tools and reload
require('electron-debug')();
require('electron-context-menu')();

// prevent window being garbage collected
let mainWindow;
let targetLink;

// Load this url in main window
const targetUrl = 'file://' + path.join(__dirname, '../renderer', 'index.html');

function checkWindowURL() {
	if (data["domain"] !== undefined) {
		return data["domain"]
	}
	return targetLink
}

const APP_ICON = path.join(__dirname, '../resources', 'Icon');

const iconPath = () => {
  return process.platform === 'win32'
    ? APP_ICON + '.ico'
    : APP_ICON + '.png'
};

function onClosed() {
	// dereference the window
	// for multiple windows store them in an array
	mainWindow = null;
}

function createMainWindow() {
	const win = new electron.BrowserWindow({
		// This settings needs to be saved in config
		title: 'Zulip',
		width: 1000,
		height: 600,
		icon: iconPath(),
		minWidth: 800,
		minHeight: 600
	});

	win.loadURL(targetUrl);
	win.on('closed', onClosed);
	win.setTitle('Zulip');

	// stop page to update it's title
	win.on('page-title-updated', (e) => {
	e.preventDefault();
	});

	return win;
}

// TODO
app.commandLine.appendSwitch('ignore-certificate-errors', 'true');

app.on('window-all-closed', () => {
	if (process.platform !== 'darwin') {
		app.quit();
	}
});

app.on('activate', () => {
	if (!mainWindow) {
		mainWindow = createMainWindow();
	}
});

app.on('ready', () => {
	mainWindow = createMainWindow();
	tray.create(mainWindow);

	const page = mainWindow.webContents;

    page.on('new-window', (event, url) => {
        if (mainWindow.useDefaultWindowBehaviour) {
            mainWindow.useDefaultWindowBehaviour = false;
            return;
        }
        if (linkIsInternal(checkWindowURL(), url)) {
        	event.preventDefault();
			return mainWindow.loadURL(url);
        }
        event.preventDefault();
        electron.shell.openExternal(url);
    });
});

ipc.on('new-domain', function (e, domain) {
	mainWindow.loadURL(domain);
	targetLink = domain;
});
<|endoftext|>


<commit_before>/*
 */
Ext.define('Rally.technicalservices.Logger',{
    constructor: function(config){
        Ext.apply(this,config);
    },
    log: function(args){
        var timestamp = "[ " + Ext.util.Format.date(new Date(), "Y-m-d H:i:s.u") + " ]";
        //var output_args = arguments;
        //output_args.unshift( [ "[ " + timestamp + " ]" ] );
        //output_args = Ext.Array.push(output_args,arguments);

        var output_args = [];
        output_args = Ext.Array.push(output_args,[timestamp]);
        output_args = Ext.Array.push(output_args, Ext.Array.slice(arguments,0));

        window.console && console.log.apply(console,output_args);
    }

});
<commit_msg>turn off logging<commit_after>/*
 */
Ext.define('Rally.technicalservices.Logger', {
    enableLogging: false,
    constructor: function(config) {
        Ext.apply(this, config);
    },
    log: function(args) {
        if (this.enableLogging) {
            var timestamp = "[ " + Ext.util.Format.date(new Date(), "Y-m-d H:i:s.u") + " ]";
            //var output_args = arguments;
            //output_args.unshift( [ "[ " + timestamp + " ]" ] );
            //output_args = Ext.Array.push(output_args,arguments);

            var output_args = [];
            output_args = Ext.Array.push(output_args, [timestamp]);
            output_args = Ext.Array.push(output_args, Ext.Array.slice(arguments, 0));

            window.console && console.log.apply(console, output_args);
        }
    }

});
<|endoftext|>


<commit_before>function updateAngleWheel() {
    angleWheel = document.getElementById('angleWheelRange').value;
    document.getElementById('angleWheel').innerHTML = parseFloat(angleWheel).toFixed(1);
}

function readAngleWheel() {
    document.getElementById('angleWheelRange').value = angleWheel;
    document.getElementById('angleWheel').innerHTML = parseFloat(angleWheel).toFixed(1);
}

function updateMotion() {
    if (run) {
        var phi = degreeToRadian(angleCar);
        var delta = degreeToRadian(angleWheel);
        deltaX = (Math.cos(phi + delta) + Math.sin(delta) * Math.sin(phi)) * 0.1;
        deltaY = (Math.sin(phi + delta) - Math.sin(delta) * Math.cos(phi)) * 0.1;
        posX = posX + deltaX;
        posY = posY + deltaY;
        rotY = rotY + 0.1 * deltaX;
        rotX = rotX - 0.1 * deltaY;
        phi = phi - (Math.asin((2.0 * Math.sin(delta)) / 6.0)) * 0.1;
        angleCar = 180.0 * phi / Math.PI;
        if (angleCar > 270)
            angleCar -= 360;
        else if (angleCar < -90)
            angleCar += 360;
        distanceCenter = getDistance(posX, posY, angleCar, 'center');
        distanceRight = getDistance(posX, posY, angleCar, 'right');
        distanceLeft = getDistance(posX, posY, angleCar, 'left');
        document.getElementById('x').innerHTML = posX.toFixed(4);
        document.getElementById('y').innerHTML = posY.toFixed(4);
        document.getElementById('angleCar').innerHTML = angleCar.toFixed(1);
        document.getElementById('distanceCenter').innerHTML = distanceCenter.toFixed(4);
        document.getElementById('distanceRight').innerHTML = distanceRight.toFixed(4);
        document.getElementById('distanceLeft').innerHTML = distanceLeft.toFixed(4);
        if (failure || distanceCenter == -1 || distanceRight == -1 || distanceLeft == -1) {
            document.getElementById('success').style.display = 'none';
            document.getElementById('failure').style.display = 'block';
            failure = true;
        } else if (posY >= 37 && posX <= 30 && posX >= 18) {
            document.getElementById('success').style.display = 'block';
            document.getElementById('failure').style.display = 'none';
            startMotion('stop');
        } else {
            document.getElementById('success').style.display = 'none';
            document.getElementById('failure').style.display = 'none';
        }
    }
    setTimeout(updateMotion, 1000 / speed);
}

function startMotion(parameter) {
    switch (parameter) {
        case 'start':
            run = true;
            break;
        case 'stop':
            run = false;
            break;
        default:
            run = !run;
    }
    if (run) {
        document.getElementById('startMotion').innerHTML = 'Stop Motion (Space / M)';
        run = true;
    } else {
        document.getElementById('startMotion').innerHTML = 'Start Motion (Space / M)';
        run = false;
    }
}

function reset() {
    posX = posY = rotX = rotY = angleWheel = 0.0;
    angleCar = 90.0;
    distanceCenter = 22;
    distanceRight = 8.4853;
    distanceLeft = 8.4853;
    drawCount = 0;
    failure = false;
    document.getElementById('success').style.display = 'none';
    document.getElementById('failure').style.display = 'none';
    readAngleWheel();
}

document.onkeydown = function (e) {
    switch (e.keyCode) {
        case 37:
            // Left
            --posX;
            rotY += 0.1;
            break;
        case 65:
            // A
            if (angleWheel > -40) {
                --angleWheel;
                readAngleWheel();
            }
            break;

        case 38:
        case 87:
            // Up & W
            ++posY;
            rotX += 0.1;
            break;

        case 39:
            // Right
            ++posX;
            rotY += 0.1;
            break;
        case 68:
            // D
            if (angleWheel < 40) {
                ++angleWheel;
                readAngleWheel();
            }
            break;

        case 40:
        case 83:
            // Down & S
            --posY;
            rotX += 0.1;
            break;

        case 49:
            // First Person Camera (1)
            document.getElementById('firstPerson').click();
            break;

        case 51:
            // Third Person Camera (3)
            document.getElementById('thirdPerson').click();
            break;

        case 32:
        case 77:
            // Start/Stop (Space & M)
            startMotion();
            break;

        case 82:
            // Reset (R)
            reset();
            break;
    }
};

window.addEventListener('deviceorientation', function (event) {
    var beta = event.beta;
    beta = Math.max(Math.min(beta, 60), -60);
    angleWheel = beta * 2.0 / 3.0;
    readAngleWheel();
    var gamma = event.gamma;
    if (gamma > 30 && gamma < 50) {
        startMotion();
    } else if (gamma > -30 && gamma < -20) {
        reset();
    }
}, false);

setTimeout(updateMotion, 1000 / speed);
<commit_msg>Fix button description<commit_after>function updateAngleWheel() {
    angleWheel = document.getElementById('angleWheelRange').value;
    document.getElementById('angleWheel').innerHTML = parseFloat(angleWheel).toFixed(1);
}

function readAngleWheel() {
    document.getElementById('angleWheelRange').value = angleWheel;
    document.getElementById('angleWheel').innerHTML = parseFloat(angleWheel).toFixed(1);
}

function updateMotion() {
    if (run) {
        var phi = degreeToRadian(angleCar);
        var delta = degreeToRadian(angleWheel);
        deltaX = (Math.cos(phi + delta) + Math.sin(delta) * Math.sin(phi)) * 0.1;
        deltaY = (Math.sin(phi + delta) - Math.sin(delta) * Math.cos(phi)) * 0.1;
        posX = posX + deltaX;
        posY = posY + deltaY;
        rotY = rotY + 0.1 * deltaX;
        rotX = rotX - 0.1 * deltaY;
        phi = phi - (Math.asin((2.0 * Math.sin(delta)) / 6.0)) * 0.1;
        angleCar = 180.0 * phi / Math.PI;
        if (angleCar > 270)
            angleCar -= 360;
        else if (angleCar < -90)
            angleCar += 360;
        distanceCenter = getDistance(posX, posY, angleCar, 'center');
        distanceRight = getDistance(posX, posY, angleCar, 'right');
        distanceLeft = getDistance(posX, posY, angleCar, 'left');
        document.getElementById('x').innerHTML = posX.toFixed(4);
        document.getElementById('y').innerHTML = posY.toFixed(4);
        document.getElementById('angleCar').innerHTML = angleCar.toFixed(1);
        document.getElementById('distanceCenter').innerHTML = distanceCenter.toFixed(4);
        document.getElementById('distanceRight').innerHTML = distanceRight.toFixed(4);
        document.getElementById('distanceLeft').innerHTML = distanceLeft.toFixed(4);
        if (failure || distanceCenter == -1 || distanceRight == -1 || distanceLeft == -1) {
            document.getElementById('success').style.display = 'none';
            document.getElementById('failure').style.display = 'block';
            failure = true;
        } else if (posY >= 37 && posX <= 30 && posX >= 18) {
            document.getElementById('success').style.display = 'block';
            document.getElementById('failure').style.display = 'none';
            startMotion('stop');
        } else {
            document.getElementById('success').style.display = 'none';
            document.getElementById('failure').style.display = 'none';
        }
    }
    setTimeout(updateMotion, 1000 / speed);
}

function startMotion(parameter) {
    switch (parameter) {
        case 'start':
            run = true;
            break;
        case 'stop':
            run = false;
            break;
        default:
            run = !run;
    }
    if (run) {
        document.getElementById('startMotion').innerHTML = 'Stop Motion (Look up)';
        run = true;
    } else {
        document.getElementById('startMotion').innerHTML = 'Start Motion (Look up)';
        run = false;
    }
}

function reset() {
    posX = posY = rotX = rotY = angleWheel = 0.0;
    angleCar = 90.0;
    distanceCenter = 22;
    distanceRight = 8.4853;
    distanceLeft = 8.4853;
    drawCount = 0;
    failure = false;
    document.getElementById('success').style.display = 'none';
    document.getElementById('failure').style.display = 'none';
    readAngleWheel();
}

document.onkeydown = function (e) {
    switch (e.keyCode) {
        case 37:
            // Left
            --posX;
            rotY += 0.1;
            break;
        case 65:
            // A
            if (angleWheel > -40) {
                --angleWheel;
                readAngleWheel();
            }
            break;

        case 38:
        case 87:
            // Up & W
            ++posY;
            rotX += 0.1;
            break;

        case 39:
            // Right
            ++posX;
            rotY += 0.1;
            break;
        case 68:
            // D
            if (angleWheel < 40) {
                ++angleWheel;
                readAngleWheel();
            }
            break;

        case 40:
        case 83:
            // Down & S
            --posY;
            rotX += 0.1;
            break;

        case 49:
            // First Person Camera (1)
            document.getElementById('firstPerson').click();
            break;

        case 51:
            // Third Person Camera (3)
            document.getElementById('thirdPerson').click();
            break;

        case 32:
        case 77:
            // Start/Stop (Space & M)
            startMotion();
            break;

        case 82:
            // Reset (R)
            reset();
            break;
    }
};

window.addEventListener('deviceorientation', function (event) {
    var beta = event.beta;
    beta = Math.max(Math.min(beta, 60), -60);
    angleWheel = beta * 2.0 / 3.0;
    readAngleWheel();
    var gamma = event.gamma;
    if (gamma > 30 && gamma < 50) {
        startMotion();
    } else if (gamma > -30 && gamma < -20) {
        reset();
    }
}, false);

setTimeout(updateMotion, 1000 / speed);
<|endoftext|>


<commit_before><commit_msg>rework LinkHints.getVisibleElements, so that less temp array will be created<commit_after><|endoftext|>


<commit_before><commit_msg>handle missing 'fly-client-ip' (#7814)<commit_after><|endoftext|>


<commit_before>(function(window, angular, chrome) {
    'use strict';

    angular.module('app.wallet')
        .controller('WalletCtrl', WalletCtrl);

    WalletCtrl.$inject = ['$scope', '$timeout', 'MAX_WALLETS', 'Wallet', 'Toast', 'hidapi', '$ionicHistory', 'profileService',  'ongoingProcess', 'walletService', 'popupService', 'gettextCatalog', 'derivationPathHelper', 'bwcService'];

    function WalletCtrl($scope, $timeout, MAX_WALLETS, Wallet, Toast, hidapi, $ionicHistory, profileService, ongoingProcess, walletService, popupService, gettextCatalog, derivationPathHelper, bwcService) {
        var vm = this;

        // dave says this comes from the import.js file by copay, with edits
        var _importExtendedPublicKey = function(wallet) {

          var opts = {};
          opts.externalSource = 'bitlox'
          opts.extendedPublicKey = wallet.xpub
          opts.derivationPath = derivationPathHelper.default
          opts.derivationStrategy = 'BIP44'
          opts.hasPassphrase = false;
          opts.name = wallet.name;
          opts.account = 0

          var b = bwcService.getBitcore();
          var x = b.HDPublicKey(wallet.xpub);
          opts.entropySource = x.publicKey.toString(); //"40c13cfdbafeccc47b4685d6e7f6a27c";
          opts.account = 0;
          opts.networkName = 'livenet';

          opts.network = true
          opts.bwsurl = 'https://bws.bitpay.com/bws/api'
          ongoingProcess.set('importingWallet', true);
          console.warn("START IMPORTING")
          profileService.importExtendedPublicKey(opts, function(err, walletId) {
            ongoingProcess.set('importingWallet', false);
            console.warn("DONE IMPORTING")
            if (err) {
              console.error(err)
              popupService.showAlert(gettextCatalog.getString('Error'), err);
              return;
            }

            walletService.updateRemotePreferences(wallet);
            profileService.setBackupFlag(wallet.credentials.walletId);
            $ionicHistory.removeBackView();
            $state.go('tabs.home');

          });
          // $timeout(function() {
          //
          // }, 100);
        };

        if(chrome && chrome.hid) {
          chrome.hid.onDeviceAdded.addListener(function() {
              vm.readWallets();
          });
        }
        vm.readWallets = function() {
            vm.readingWallets = true;
            return Wallet.list()
                .then(function(wallets) {
                    vm.wallets = wallets;
                    vm.openWallet = null;
                    refreshAvailableNumbers(wallets);
                }, Toast.errorHandler)
                .finally(function() {
                    vm.readingWallets = false;
                });
        };

        vm.loadWallet = function(wallet) {
            vm.openWallet = null;
            vm.loadingXpub = true;
            // console.debug("loading wallet", wallet.number);
            vm.openingWallet = wallet.number;
            wallet.open()
                .then(function() {
                    vm.openWallet = wallet;
                }, Toast.errorHandler, function(status) {
                    // console.debug("open notify", status);
                    // dave says, I think this is not needed any more
                    // if (status === Wallet.NOTIFY_XPUB_LOADED) {
                    //     vm.loadingXpub = false;
                    // }
                })
                .finally(function() {
                    console.debug("done loading wallet", wallet.number);
                    vm.openingWallet = null; // changed from -99 because I think it's fucking things up
                    console.log("WALLET LOADED", wallet.xpub)
                    _importExtendedPublicKey(wallet)
                });
        };

        vm.refreshBalance = function() {
            vm.refreshingBalance = true;
            vm.openWallet.updateBalance().catch(Toast.errorHandler)
                .finally(function() {
                    vm.refreshingBalance = false;
                });
        };

        vm.directOpenNumber = 0;
        vm.directLoad = function() {
            var wallet;
            vm.wallets.forEach(function(w) {
                if (w.number === vm.directOpenNumber) {
                    wallet = w;
                }
            });
            if (!wallet) {
                wallet = new Wallet({
                    wallet_number: vm.directOpenNumber,
                    version: 4,
                    wallet_name: "HIDDEN",
                    wallet_uuid: "HIDDEN",
                });
            }
            vm.loadWallet(wallet);
        };

        vm.prepForFlash = function() {
            vm.flashing = true;
            hidapi.flash().catch(Toast.errorHandler)
                .finally(function() {
                    vm.flashing = false;
                });
        };

        function refreshAvailableNumbers(wallets) {
            if (!wallets) {
                return;
            }
            // assemble array of wallet numbers
            var available = [];
            for(var i = 0; i < (MAX_WALLETS + 1); i++) {
                available.push(i);
            }
            // now loop through the wallets and remove existing
            // numbers
            wallets.forEach(function(wallet) {
                available.splice(available.indexOf(wallet.number), 1);
            });
            // set to the vm for the new wallet form
            vm.availableWalletNumbers = available;
        }

        function reset() {
            // status variables
            vm.readingWallets = true;
            vm.openingWallet = -99;
            vm.scanningWallet = false;
            vm.creatingWallet = false;
            vm.refreshingBalance = false;
            vm.openWallet = null;
            // read after a timeout, so angular does not hang and show
            // garbage while the browser is locked form readin the device
            $timeout(vm.readWallets.bind(vm), 100);
        }

        reset();
    }

})(window, window.angular, window.chrome);
<commit_msg>finally walk around the import issue and use createWallet call, works now<commit_after>(function(window, angular, chrome) {
    'use strict';

    angular.module('app.wallet')
        .controller('WalletCtrl', WalletCtrl);

    WalletCtrl.$inject = ['$scope', '$timeout', 'MAX_WALLETS', 'Wallet', 'Toast', 'hidapi', '$ionicHistory', 'profileService',  'ongoingProcess', 'walletService', 'popupService', 'gettextCatalog', 'derivationPathHelper', 'bwcService'];

    function WalletCtrl($scope, $timeout, MAX_WALLETS, Wallet, Toast, hidapi, $ionicHistory, profileService, ongoingProcess, walletService, popupService, gettextCatalog, derivationPathHelper, bwcService) {
        var vm = this;

        // dave says this comes from the import.js file by copay, with edits
        var _importExtendedPublicKey = function(wallet) {

          var opts = {};
          opts.externalSource = 'bitlox'
          opts.extendedPublicKey = wallet.xpub
          opts.derivationPath = derivationPathHelper.default
          opts.derivationStrategy = 'BIP44'
          opts.hasPassphrase = false;
          opts.name = wallet.name;
          opts.account = 0

          var b = bwcService.getBitcore();
          var x = b.HDPublicKey(wallet.xpub);
          opts.entropySource = x.publicKey.toString(); //"40c13cfdbafeccc47b4685d6e7f6a27c";
          opts.account = 0;
          opts.networkName = 'livenet';
          opts.m = 1;
          opts.n = 1;
          opts.singleAddress = false;

          opts.network = true
          opts.bwsurl = 'https://bws.bitpay.com/bws/api'
          ongoingProcess.set('importingWallet', true);
          console.warn("START IMPORTING")
          profileService.createWallet(opts, function(err, walletId) {
            ongoingProcess.set('importingWallet', false);
            console.warn("DONE IMPORTING")
            if (err) {
              console.error(err)
              popupService.showAlert(gettextCatalog.getString('Error'), err);
              return;
            }

            walletService.updateRemotePreferences(walletId);
            $ionicHistory.removeBackView();
            $state.go('tabs.home');

          });
          // $timeout(function() {
          //
          // }, 100);
        };

        if(chrome && chrome.hid) {
          chrome.hid.onDeviceAdded.addListener(function() {
              vm.readWallets();
          });
        }
        vm.readWallets = function() {
            vm.readingWallets = true;
            return Wallet.list()
                .then(function(wallets) {
                    vm.wallets = wallets;
                    vm.openWallet = null;
                    refreshAvailableNumbers(wallets);
                }, Toast.errorHandler)
                .finally(function() {
                    vm.readingWallets = false;
                });
        };

        vm.loadWallet = function(wallet) {
            vm.openWallet = null;
            vm.loadingXpub = true;
            // console.debug("loading wallet", wallet.number);
            vm.openingWallet = wallet.number;
            wallet.open()
                .then(function() {
                    vm.openWallet = wallet;
                }, Toast.errorHandler, function(status) {
                    // console.debug("open notify", status);
                    // dave says, I think this is not needed any more
                    // if (status === Wallet.NOTIFY_XPUB_LOADED) {
                    //     vm.loadingXpub = false;
                    // }
                })
                .finally(function() {
                    console.debug("done loading wallet", wallet.number);
                    vm.openingWallet = null; // changed from -99 because I think it's fucking things up
                    console.log("WALLET LOADED", wallet.xpub)
                    _importExtendedPublicKey(wallet)
                });
        };

        vm.refreshBalance = function() {
            vm.refreshingBalance = true;
            vm.openWallet.updateBalance().catch(Toast.errorHandler)
                .finally(function() {
                    vm.refreshingBalance = false;
                });
        };

        vm.directOpenNumber = 0;
        vm.directLoad = function() {
            var wallet;
            vm.wallets.forEach(function(w) {
                if (w.number === vm.directOpenNumber) {
                    wallet = w;
                }
            });
            if (!wallet) {
                wallet = new Wallet({
                    wallet_number: vm.directOpenNumber,
                    version: 4,
                    wallet_name: "HIDDEN",
                    wallet_uuid: "HIDDEN",
                });
            }
            vm.loadWallet(wallet);
        };

        vm.prepForFlash = function() {
            vm.flashing = true;
            hidapi.flash().catch(Toast.errorHandler)
                .finally(function() {
                    vm.flashing = false;
                });
        };

        function refreshAvailableNumbers(wallets) {
            if (!wallets) {
                return;
            }
            // assemble array of wallet numbers
            var available = [];
            for(var i = 0; i < (MAX_WALLETS + 1); i++) {
                available.push(i);
            }
            // now loop through the wallets and remove existing
            // numbers
            wallets.forEach(function(wallet) {
                available.splice(available.indexOf(wallet.number), 1);
            });
            // set to the vm for the new wallet form
            vm.availableWalletNumbers = available;
        }

        function reset() {
            // status variables
            vm.readingWallets = true;
            vm.openingWallet = -99;
            vm.scanningWallet = false;
            vm.creatingWallet = false;
            vm.refreshingBalance = false;
            vm.openWallet = null;
            // read after a timeout, so angular does not hang and show
            // garbage while the browser is locked form readin the device
            $timeout(vm.readWallets.bind(vm), 100);
        }

        reset();
    }

})(window, window.angular, window.chrome);
<|endoftext|>


<commit_before>import template from './add-user.template.html'
import controller from './add-user.controller.js'

export default {
  template,
  controller,
  bindings: {editedUser: '='}
}
<commit_msg>change bindings<commit_after>import template from './add-user.template.html'
import controller from './add-user.controller.js'

export default {
  template,
  controller,
  bindings: {editedUser: '<'}
}
<|endoftext|>


<commit_before>'use strict';

var request  = require('axios');
var React    = require('react');
var classSet = require('classnames');
import StripeCheckout from 'react-stripe-checkout';

var api      = require('../api');
var config   = require('../../config.js')();

module.exports = React.createClass({
  getInitialState() {
    return {
      error:   null,
      sending: false
    };
  },

  onSubmit(token) {
    this.setState({
      error:   null,
      sending: true
    });

    request.post(api('membership'), {
      email:       this.props.payerEmail,
      stripeToken: token.id
    })
    .then(() => {
      this.setState({
        sending: false
      });
      this.props.onPaymentSuccess();
    })
    .catch((e) => {
      this.setState({
        error: e,
        sending: false
      });
    });
  },

  render() {
    if (this.state.error) {
      return
Virhe maksaessa! Ota yhteyttä info@koodiklinikka.fi

    } else if (this.state.sending) {
      return
    } else {
      return (<StripeCheckout
        amount      = { 1000 }
        currency    = 'EUR'
        description = 'Jäsenmaksu'
        email       = { this.props.userInfo.email }
        image       = 'https://avatars3.githubusercontent.com/u/10520119?v = 3&s = 200'
        locale      = "en"
        name        = 'Koodiklinikka ry'
        stripeKey   = { config.stripe.publicKey }
        token       = { this.onSubmit }
      >
        <button className="btn btn-primary">
          Maksa kortilla
        </button>
      </StripeCheckout>)
    }
  }
});
<commit_msg>fix koodiklinikka image url for stripecheckout<commit_after>'use strict';

var request  = require('axios');
var React    = require('react');
var classSet = require('classnames');
import StripeCheckout from 'react-stripe-checkout';

var api      = require('../api');
var config   = require('../../config.js')();

module.exports = React.createClass({
  getInitialState() {
    return {
      error:   null,
      sending: false
    };
  },

  onSubmit(token) {
    this.setState({
      error:   null,
      sending: true
    });

    request.post(api('membership'), {
      email:       this.props.payerEmail,
      stripeToken: token.id
    })
    .then(() => {
      this.setState({
        sending: false
      });
      this.props.onPaymentSuccess();
    })
    .catch((e) => {
      this.setState({
        error: e,
        sending: false
      });
    });
  },

  render() {
    if (this.state.error) {
      return
Virhe maksaessa! Ota yhteyttä info@koodiklinikka.fi

    } else if (this.state.sending) {
      return
    } else {
      return (<StripeCheckout
        amount      = { 1000 }
        currency    = 'EUR'
        description = 'Jäsenmaksu'
        email       = { this.props.userInfo.email }
        image       = 'https://avatars3.githubusercontent.com/u/10520119?v=3&s=200'
        locale      = "en"
        name        = 'Koodiklinikka ry'
        stripeKey   = { config.stripe.publicKey }
        token       = { this.onSubmit }
      >
        <button className="btn btn-primary">
          Maksa kortilla
        </button>
      </StripeCheckout>)
    }
  }
});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013-2015 Memba Sarl. All rights reserved.
 * Sources at https://github.com/Memba
 */

/* jshint browser: true, jquery: true */
/* globals define: false */

(function (f, define) {
    'use strict';
    define([
        './vendor/codemirror/lib/codemirror.js',
        './vendor/codemirror/mode/javascript/javascript.js',
        './vendor/codemirror/addon/lint/lint.js',
        './vendor/codemirror/addon/lint/jshint.js',
        './vendor/codemirror/addon/lint/javascript-lint.js',
        './vendor/kendo/kendo.binder',
        './vendor/kendo/kendo.dropdownlist',
        './vendor/kendo/kendo.multiselect', // required because of a test in kendo.binder.js
        './window.assert',
        './window.log'
    ], f);
})(function (CodeMirror) {

    'use strict';

    // Depending how codemirror.js is loaded
    // We need `CodeMirror` for webpack and `window.CodeMirror` for grunt mocha
    CodeMirror = CodeMirror || window.CodeMirror;

    (function ($, undefined) {

        var kendo = window.kendo;
        var Widget = kendo.ui.Widget;
        var assert = window.assert;
        var logger = new window.Log('kidoju.widgets.codeeditor');
        var STRING = 'string';
        var UNDEFINED = 'undefined';
        var BEFORECHANGE = 'beforeChange';
        var CHANGE = 'change';
        var JS_COMMENT = '// ';
        // var NS = '.kendoCodeEditor',
        var WIDGET_CLASS = 'k-widget kj-codeeditor';
        var RX_LIBRARY = /^\/\/ ([^\n]+)$/;
        var RX_CUSTOM = /^function[\s]+validate[\s]*\([\s]*value[\s]*,[\s]*solution[\s]*(,[\s]*all[\s]*)?\)[\s]*\{[\s\S]*\}$/;

        /*********************************************************************************
         * Widget
         *********************************************************************************/

        /**
         * @class CodeEditor Widget (kendoCodeEditor)
         */
        var CodeEditor = Widget.extend({

            // TODO: Add testing of user value against solution
            // Quite complex, because we need to bring in kidoju.library.js + web workers execution (currently in kidoju.tools)

            /**
             * Initializes the widget
             * @param element
             * @param options
             */
            init: function (element, options) {
                var that = this;
                options = options || {};
                Widget.fn.init.call(that, element, options);
                logger.debug('widget initialized');
                that._layout();
                that._dataSource();
                if ($.type(options.value) === STRING) {
                    that.value(options.value);
                } else if (that.dataSource.total()) {  // TODO
                    that.value(JS_COMMENT + options.default);
                }
                // kendo.notify(that);
            },

            /**
             * Widget options
             * @property options
             */
            options: {
                name: 'CodeEditor',
                autoBind: true,
                // dataSource: [],
                custom: 'custom',
                default: 'equal',
                solution: '',
                value: null
            },

            /**
             * Widget events
             * @property events
             */
            events: [
                CHANGE
            ],

            /**
             * Value for MVVM binding
             * Takes/returns either a JS function as a string or a library formula name prefixed by '// '
             * @param value
             */
            value: function (value) {
                var that = this;
                if ($.type(value) === STRING) {
                    that._toggle(value);
                } else if ($.type(value) === UNDEFINED) {
                    var formula = that.dropDownList.text();
                    if ($.type(formula) !== STRING || !formula.length) {
                        return undefined;
                    } else if (formula === that.options.custom) {
                        return that.codeMirror.getDoc().getValue();
                    } else {
                        return JS_COMMENT + that.dropDownList.text();
                    }
                } else {
                    throw new TypeError('`value` is expected to be a string if not undefined');
                }
            },

            /**
             * Check that value refers to a custom function not in the code library
             *
             * @param value
             * @returns {*}
             * @private
             */
            _isCustom: function (value) {
                assert.type(STRING, value, kendo.format(assert.messages.type.default, value, STRING));
                var customMatches = value.match(RX_CUSTOM);
                if ($.isArray(customMatches) && customMatches.length === 2) {
                    return value;
                }
            },

            /**
             * Check that value refers to a piece of code from the library (dataSource)
             * Returns the name of the library item (without `// `) if found, otherwise undefined
             * @param value
             * @returns {*}
             * @private
             */
            _isInLibrary: function (value) {
                assert.type(STRING, value, kendo.format(assert.messages.type.default, value, STRING));
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                assert.instanceof(kendo.data.DataSource, this.dataSource, kendo.format(assert.messages.instanceof.default, 'this.dataSource', 'kendo.data.DataSource'));
                assert.equal(this.dropDownList.dataSource, this.dataSource, 'this.dropDownList.dataSource and this.dataSource are expected to be the same');
                var libraryMatches = value.match(RX_LIBRARY);
                if ($.isArray(libraryMatches) && libraryMatches.length === 2) {
                    var found = this.dataSource.data().filter(function (item) {
                        return item.name === libraryMatches[1];
                    });
                    if ($.isArray(found) && found.length) {
                        return libraryMatches[1];
                    }
                }
            },

            /**
             * toggle UI for custom vs library code
             * @param value
             * @private
             */
            _toggle: function (value) {
                assert.type(STRING, value, kendo.format(assert.messages.type.default, value, STRING));
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                assert.instanceof(CodeMirror, this.codeMirror, kendo.format(assert.messages.instanceof.default, 'this.codeMirror', 'CodeMirror'));
                var that = this;
                if (that._isCustom(value)) {
                    // If value is in the form `function validate(value, solution[, all]) { ... }`, it is custom
                    that.codeMirror.getDoc().setValue(value);
                } else {
                    // Otherwise, search the library
                    var name = that._isInLibrary(value);
                    if ($.type(name) === UNDEFINED) {
                        // and use default if not found
                        name = that._isInLibrary(JS_COMMENT + that.options.default);
                        assert.type(STRING, name, '`this.options.default` is expected to exist in the library');
                    }
                    that.dropDownList.text(name);
                    that._onDropDownListChange();
                }
            },

            /**
             * Builds the widget layout
             * @private
             */
            _layout: function () {
                var that = this;
                that.wrapper = that.element;
                that.element.addClass(WIDGET_CLASS);
                that._setHeader();
                that._setCodeMirror();
            },

            /**
             * Set drop down list with code library and value input
             * @private
             */
            _setHeader: function () {
                var that = this;
                var header = $('

').appendTo(that.element);
                var left = header.find('div').first();
                var right = header.find('div').last();

                // Create the dropDownList
                that.dropDownList = $('<select/>')
                    .appendTo(left)
                    .kendoDropDownList({
                        autoBind: that.options.autoBind,
                        change: $.proxy(that._onDropDownListChange, that), // change is not triggered by dropDownList api calls incl. value(), text(), ...
                        dataTextField: 'name',
                        dataValueField: 'formula',
                        dataSource: that.options.dataSource
                    })
                    .data('kendoDropDownList');

                // create the input field to display solution
                that.input = $('<input class="k-textbox k-state-disabled" disabled>')
                    .appendTo(right)
                    .val(that.options.solution);
            },

            /**
             * Event handler triggered when changing the value of the drop down list in the header
             * @private
             */
            _onDropDownListChange: function () {
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                assert.instanceof(CodeMirror, this.codeMirror, kendo.format(assert.messages.instanceof.default, 'this.codeMirror', 'CodeMirror'));
                this.codeMirror.getDoc().setValue(this.dropDownList.value());
            },

            /**
             * Set CodeMirror editor
             * @private
             */
            _setCodeMirror: function () {
                var that = this;
                var div = $('

')
                        .appendTo(that.element)
                        .get(0);
                assert.instanceof(window.HTMLElement, div, kendo.format(assert.messages.instanceof.default, 'div', 'HTMLElement'));
                that.codeMirror = CodeMirror(div, {
                    gutters: ['CodeMirror-lint-markers'],
                    lineNumbers: true,
                    lint: true,
                    mode: 'javascript',
                    value: ''
                });

                // Prevent from modifying first lines and last line
                that.codeMirror.on(BEFORECHANGE, function (cm, change) {
                    if (change.origin === 'setValue') {
                        return; // updated using this.value(value)
                    }
                    // if updated by typing into the code editor
                    if ((change.from.line === 0) || // prevent changing the first line
                        (change.from.line === cm.display.renderedView.length - 1) || // prevent changing the last line
                        (change.origin === '+delete' && change.to.line === cm.display.renderedView.length - 1)) { // prevent backspace on the last line or suppr on the previous line
                        // cancel change
                        change.cancel();
                    }
                });

                // Synchronize drop down list with code editor to display `custom` upon any change
                that.codeMirror.on(CHANGE, function (cm, change) {
                    if (that.dropDownList.text() !== that.options.custom) {
                        if (that.codeMirror.getDoc().getValue() !== that.dropDownList.value()) {
                            that.dropDownList.text(that.options.custom);
                        }
                    }
                    // trigger a change event for MVVM value binding
                    that.trigger(CHANGE, { value: that.value() });
                });

            },

            /**
             * _dataSource function to bind refresh to the change event
             * @private
             */
            _dataSource: function () {
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                assert.instanceof(kendo.data.DataSource, this.dropDownList.dataSource, kendo.format(assert.messages.instanceof.default, 'this.dropDownList.dataSource', 'kendo.data.DataSource'));
                var that = this;
                var dropDownList = that.dropDownList;
                // MVVM bindings require that.dataSource
                that.dataSource = that.dropDownList.dataSource;
                if (that._refreshHandler) {
                    that.dataSource.unbind(CHANGE, that._refreshHandler);
                }
                that._refreshHandler = $.proxy(that.refresh, that);
                that.dataSource.bind(CHANGE, that._refreshHandler);
            },

            /**
             * sets the dataSource for source binding
             * @param dataSource
             */
            setDataSource: function (dataSource) {
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                var that = this;
                var dropDownList = that.dropDownList;
                if (dropDownList.dataSource !== dataSource) {
                    dropDownList.setDataSource(dataSource);
                    that._dataSource();
                }
            },

            /**
             * Refresh
             * @param e
             */
            refresh: function (e) {
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                this.dropDownList.refresh(e);
            },

            /**
             * Clears the widget
             * @method _clear
             * @private
             */
            _clear: function () {
                var that = this;
                // unbind kendo
                kendo.unbind(that.element);
                // unbind all other events
                that.element.find('*').off();
                that.element.off();
                // remove descendants
                that.element.empty();
                // remove element classes
                that.element.removeClass(WIDGET_CLASS);
            },

            /**
             * Destroys the widget including all DOM modifications
             * @method destroy
             */
            destroy: function () {
                var that = this;
                Widget.fn.destroy.call(that);
                that._clear();
                kendo.destroy(that.element);
            }

        });

        kendo.ui.plugin(CodeEditor);

    }(window.jQuery));

    return window.kendo;

}, typeof define === 'function' && define.amd ? define : function (_, f) { 'use strict'; f(); });
<commit_msg>Removed TODO<commit_after>/**
 * Copyright (c) 2013-2015 Memba Sarl. All rights reserved.
 * Sources at https://github.com/Memba
 */

/* jshint browser: true, jquery: true */
/* globals define: false */

(function (f, define) {
    'use strict';
    define([
        './vendor/codemirror/lib/codemirror.js',
        './vendor/codemirror/mode/javascript/javascript.js',
        './vendor/codemirror/addon/lint/lint.js',
        './vendor/codemirror/addon/lint/jshint.js',
        './vendor/codemirror/addon/lint/javascript-lint.js',
        './vendor/kendo/kendo.binder',
        './vendor/kendo/kendo.dropdownlist',
        './vendor/kendo/kendo.multiselect', // required because of a test in kendo.binder.js
        './window.assert',
        './window.log'
    ], f);
})(function (CodeMirror) {

    'use strict';

    // Depending how codemirror.js is loaded
    // We need `CodeMirror` for webpack and `window.CodeMirror` for grunt mocha
    CodeMirror = CodeMirror || window.CodeMirror;

    (function ($, undefined) {

        var kendo = window.kendo;
        var Widget = kendo.ui.Widget;
        var assert = window.assert;
        var logger = new window.Log('kidoju.widgets.codeeditor');
        var STRING = 'string';
        var UNDEFINED = 'undefined';
        var BEFORECHANGE = 'beforeChange';
        var CHANGE = 'change';
        var JS_COMMENT = '// ';
        // var NS = '.kendoCodeEditor',
        var WIDGET_CLASS = 'k-widget kj-codeeditor';
        var RX_LIBRARY = /^\/\/ ([^\n]+)$/;
        var RX_CUSTOM = /^function[\s]+validate[\s]*\([\s]*value[\s]*,[\s]*solution[\s]*(,[\s]*all[\s]*)?\)[\s]*\{[\s\S]*\}$/;

        /*********************************************************************************
         * Widget
         *********************************************************************************/

        /**
         * @class CodeEditor Widget (kendoCodeEditor)
         */
        var CodeEditor = Widget.extend({

            // TODO: Add testing of user value against solution
            // Quite complex, because we need to bring in kidoju.library.js + web workers execution (currently in kidoju.tools)

            /**
             * Initializes the widget
             * @param element
             * @param options
             */
            init: function (element, options) {
                var that = this;
                options = options || {};
                Widget.fn.init.call(that, element, options);
                logger.debug('widget initialized');
                that._layout();
                that._dataSource();
                if ($.type(options.value) === STRING) {
                    that.value(options.value);
                } else if (that.dataSource.total()) {
                    that.value(JS_COMMENT + options.default);
                }
                // kendo.notify(that);
            },

            /**
             * Widget options
             * @property options
             */
            options: {
                name: 'CodeEditor',
                autoBind: true,
                // dataSource: [],
                custom: 'custom',
                default: 'equal',
                solution: '',
                value: null
            },

            /**
             * Widget events
             * @property events
             */
            events: [
                CHANGE
            ],

            /**
             * Value for MVVM binding
             * Takes/returns either a JS function as a string or a library formula name prefixed by '// '
             * @param value
             */
            value: function (value) {
                var that = this;
                if ($.type(value) === STRING) {
                    that._toggle(value);
                } else if ($.type(value) === UNDEFINED) {
                    var formula = that.dropDownList.text();
                    if ($.type(formula) !== STRING || !formula.length) {
                        return undefined;
                    } else if (formula === that.options.custom) {
                        return that.codeMirror.getDoc().getValue();
                    } else {
                        return JS_COMMENT + that.dropDownList.text();
                    }
                } else {
                    throw new TypeError('`value` is expected to be a string if not undefined');
                }
            },

            /**
             * Check that value refers to a custom function not in the code library
             *
             * @param value
             * @returns {*}
             * @private
             */
            _isCustom: function (value) {
                assert.type(STRING, value, kendo.format(assert.messages.type.default, value, STRING));
                var customMatches = value.match(RX_CUSTOM);
                if ($.isArray(customMatches) && customMatches.length === 2) {
                    return value;
                }
            },

            /**
             * Check that value refers to a piece of code from the library (dataSource)
             * Returns the name of the library item (without `// `) if found, otherwise undefined
             * @param value
             * @returns {*}
             * @private
             */
            _isInLibrary: function (value) {
                assert.type(STRING, value, kendo.format(assert.messages.type.default, value, STRING));
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                assert.instanceof(kendo.data.DataSource, this.dataSource, kendo.format(assert.messages.instanceof.default, 'this.dataSource', 'kendo.data.DataSource'));
                assert.equal(this.dropDownList.dataSource, this.dataSource, 'this.dropDownList.dataSource and this.dataSource are expected to be the same');
                var libraryMatches = value.match(RX_LIBRARY);
                if ($.isArray(libraryMatches) && libraryMatches.length === 2) {
                    var found = this.dataSource.data().filter(function (item) {
                        return item.name === libraryMatches[1];
                    });
                    if ($.isArray(found) && found.length) {
                        return libraryMatches[1];
                    }
                }
            },

            /**
             * toggle UI for custom vs library code
             * @param value
             * @private
             */
            _toggle: function (value) {
                assert.type(STRING, value, kendo.format(assert.messages.type.default, value, STRING));
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                assert.instanceof(CodeMirror, this.codeMirror, kendo.format(assert.messages.instanceof.default, 'this.codeMirror', 'CodeMirror'));
                var that = this;
                if (that._isCustom(value)) {
                    // If value is in the form `function validate(value, solution[, all]) { ... }`, it is custom
                    that.codeMirror.getDoc().setValue(value);
                } else {
                    // Otherwise, search the library
                    var name = that._isInLibrary(value);
                    if ($.type(name) === UNDEFINED) {
                        // and use default if not found
                        name = that._isInLibrary(JS_COMMENT + that.options.default);
                        assert.type(STRING, name, '`this.options.default` is expected to exist in the library');
                    }
                    that.dropDownList.text(name);
                    that._onDropDownListChange();
                }
            },

            /**
             * Builds the widget layout
             * @private
             */
            _layout: function () {
                var that = this;
                that.wrapper = that.element;
                that.element.addClass(WIDGET_CLASS);
                that._setHeader();
                that._setCodeMirror();
            },

            /**
             * Set drop down list with code library and value input
             * @private
             */
            _setHeader: function () {
                var that = this;
                var header = $('

').appendTo(that.element);
                var left = header.find('div').first();
                var right = header.find('div').last();

                // Create the dropDownList
                that.dropDownList = $('<select/>')
                    .appendTo(left)
                    .kendoDropDownList({
                        autoBind: that.options.autoBind,
                        change: $.proxy(that._onDropDownListChange, that), // change is not triggered by dropDownList api calls incl. value(), text(), ...
                        dataTextField: 'name',
                        dataValueField: 'formula',
                        dataSource: that.options.dataSource
                    })
                    .data('kendoDropDownList');

                // create the input field to display solution
                that.input = $('<input class="k-textbox k-state-disabled" disabled>')
                    .appendTo(right)
                    .val(that.options.solution);
            },

            /**
             * Event handler triggered when changing the value of the drop down list in the header
             * @private
             */
            _onDropDownListChange: function () {
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                assert.instanceof(CodeMirror, this.codeMirror, kendo.format(assert.messages.instanceof.default, 'this.codeMirror', 'CodeMirror'));
                this.codeMirror.getDoc().setValue(this.dropDownList.value());
            },

            /**
             * Set CodeMirror editor
             * @private
             */
            _setCodeMirror: function () {
                var that = this;
                var div = $('

')
                        .appendTo(that.element)
                        .get(0);
                assert.instanceof(window.HTMLElement, div, kendo.format(assert.messages.instanceof.default, 'div', 'HTMLElement'));
                that.codeMirror = CodeMirror(div, {
                    gutters: ['CodeMirror-lint-markers'],
                    lineNumbers: true,
                    lint: true,
                    mode: 'javascript',
                    value: ''
                });

                // Prevent from modifying first lines and last line
                that.codeMirror.on(BEFORECHANGE, function (cm, change) {
                    if (change.origin === 'setValue') {
                        return; // updated using this.value(value)
                    }
                    // if updated by typing into the code editor
                    if ((change.from.line === 0) || // prevent changing the first line
                        (change.from.line === cm.display.renderedView.length - 1) || // prevent changing the last line
                        (change.origin === '+delete' && change.to.line === cm.display.renderedView.length - 1)) { // prevent backspace on the last line or suppr on the previous line
                        // cancel change
                        change.cancel();
                    }
                });

                // Synchronize drop down list with code editor to display `custom` upon any change
                that.codeMirror.on(CHANGE, function (cm, change) {
                    if (that.dropDownList.text() !== that.options.custom) {
                        if (that.codeMirror.getDoc().getValue() !== that.dropDownList.value()) {
                            that.dropDownList.text(that.options.custom);
                        }
                    }
                    // trigger a change event for MVVM value binding
                    that.trigger(CHANGE, { value: that.value() });
                });

            },

            /**
             * _dataSource function to bind refresh to the change event
             * @private
             */
            _dataSource: function () {
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                assert.instanceof(kendo.data.DataSource, this.dropDownList.dataSource, kendo.format(assert.messages.instanceof.default, 'this.dropDownList.dataSource', 'kendo.data.DataSource'));
                var that = this;
                var dropDownList = that.dropDownList;
                // MVVM bindings require that.dataSource
                that.dataSource = that.dropDownList.dataSource;
                if (that._refreshHandler) {
                    that.dataSource.unbind(CHANGE, that._refreshHandler);
                }
                that._refreshHandler = $.proxy(that.refresh, that);
                that.dataSource.bind(CHANGE, that._refreshHandler);
            },

            /**
             * sets the dataSource for source binding
             * @param dataSource
             */
            setDataSource: function (dataSource) {
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                var that = this;
                var dropDownList = that.dropDownList;
                if (dropDownList.dataSource !== dataSource) {
                    dropDownList.setDataSource(dataSource);
                    that._dataSource();
                }
            },

            /**
             * Refresh
             * @param e
             */
            refresh: function (e) {
                assert.instanceof(kendo.ui.DropDownList, this.dropDownList, kendo.format(assert.messages.instanceof.default, 'this.dropDownList', 'kendo.ui.DropDownList'));
                this.dropDownList.refresh(e);
            },

            /**
             * Clears the widget
             * @method _clear
             * @private
             */
            _clear: function () {
                var that = this;
                // unbind kendo
                kendo.unbind(that.element);
                // unbind all other events
                that.element.find('*').off();
                that.element.off();
                // remove descendants
                that.element.empty();
                // remove element classes
                that.element.removeClass(WIDGET_CLASS);
            },

            /**
             * Destroys the widget including all DOM modifications
             * @method destroy
             */
            destroy: function () {
                var that = this;
                Widget.fn.destroy.call(that);
                that._clear();
                kendo.destroy(that.element);
            }

        });

        kendo.ui.plugin(CodeEditor);

    }(window.jQuery));

    return window.kendo;

}, typeof define === 'function' && define.amd ? define : function (_, f) { 'use strict'; f(); });
<|endoftext|>