<commit_before>const WXAPI = require('../../wxapi/main')
const regeneratorRuntime = require('../../utils/runtime')
//获取应用实例
var app = getApp()
Page({
  data: {
    pickerRegionRange: [],
    pickerSelect:[0, 0, 0],
    showRegionStr: '请选择'
  },
  initRegionPicker () {
    WXAPI.province().then(res => {
      if (res.code === 0) {
        let _pickerRegionRange = []
        _pickerRegionRange.push(res.data)
        _pickerRegionRange.push([{ name: '请选择' }])
        _pickerRegionRange.push([{ name: '请选择' }])
        this.setData({
          pickerRegionRange: _pickerRegionRange
        })
      }
    })
  },
  async initRegionDB (pname, cname, dname) {
    this.data.showRegionStr = pname + cname + dname
    let pObject = undefined
    let cObject = undefined
    let dObject = undefined
    if (pname) {
      const index = this.data.pickerRegionRange[0].findIndex(ele=>{
        return ele.name == pname
      })
      console.log('pindex', index)
      if (index >= 0) {
        this.data.pickerSelect[0] = index
        pObject = this.data.pickerRegionRange[0][index]
      }
    }
    if (!pObject) {
      return
    }
    const _cRes = await WXAPI.nextRegion(pObject.id)
    if (_cRes.code === 0) {
      this.data.pickerRegionRange[1] = _cRes.data
      if (cname) {
        const index = this.data.pickerRegionRange[1].findIndex(ele => {
          return ele.name == cname
        })
        if (index >= 0) {
          this.data.pickerSelect[1] = index
          cObject = this.data.pickerRegionRange[1][index]
        }
      }
    }
    if (!cObject) {
      return
    }
    const _dRes = await WXAPI.nextRegion(cObject.id)
    if (_dRes.code === 0) {
      this.data.pickerRegionRange[2] = _dRes.data
      if (dname) {
        const index = this.data.pickerRegionRange[2].findIndex(ele => {
          return ele.name == dname
        })
        if (index >= 0) {
          this.data.pickerSelect[2] = index
          dObject = this.data.pickerRegionRange[2][index]
        }
      }
    }
    this.setData({
      pickerRegionRange: this.data.pickerRegionRange,
      pickerSelect: this.data.pickerSelect,
      showRegionStr: this.data.showRegionStr,
      pObject: pObject,
      cObject: cObject,
      dObject: dObject
    })
  },
  bindchange: function(e) {
    console.log(e)
    const pObject = this.data.pickerRegionRange[0][e.detail.value[0]]
    const cObject = this.data.pickerRegionRange[1][e.detail.value[1]]
    const dObject = this.data.pickerRegionRange[2][e.detail.value[2]]
    const showRegionStr = pObject.name + cObject.name + dObject.name
    this.setData({
      pObject: pObject,
      cObject: cObject,
      dObject: dObject,
      showRegionStr: showRegionStr
    })
  },
  bindcolumnchange: function(e) {
    const column = e.detail.column
    const index = e.detail.value
    const regionObject = this.data.pickerRegionRange[column][index]
    console.log('bindcolumnchange', regionObject)
    if (column === 2) {
      return
    }
    if (column === 1) {
      this.data.pickerRegionRange[2] = [{ name: '请选择' }]
    }
    if (column === 0) {
      this.data.pickerRegionRange[1] = [{ name: '请选择' }]
      this.data.pickerRegionRange[2] = [{ name: '请选择' }]
    }
    // 后面的数组全部清空
    this.data.pickerRegionRange.splice(column+1)
    // 追加后面的一级数组
    WXAPI.nextRegion(regionObject.id).then(res => {
      if (res.code === 0) {
        this.data.pickerRegionRange[column + 1] = res.data
      }
      this.setData({
        pickerRegionRange: this.data.pickerRegionRange
      })
    })
  },
  bindSave: function(e) {
    WXAPI.addTempleMsgFormid({
      token: wx.getStorageSync('token'),
      type: 'form',
      formId: e.detail.formId
    })
    var that = this;
    var linkMan = e.detail.value.linkMan;
    var address = e.detail.value.address;
    var mobile = e.detail.value.mobile;
    var code = e.detail.value.code;
    if (linkMan == ""){
      wx.showModal({
        title: '提示',
        content: '请填写联系人姓名',
        showCancel:false
      })
      return
    }
    if (mobile == ""){
      wx.showModal({
        title: '提示',
        content: '请填写手机号码',
        showCancel:false
      })
      return
    }
    if (!this.data.pObject || !this.data.cObject){
      wx.showModal({
        title: '提示',
        content: '请选择地区',
        showCancel:false
      })
      return
    }
    if (address == ""){
      wx.showModal({
        title: '提示',
        content: '请填写详细地址',
        showCancel:false
      })
      return
    }
    if (code == ""){
      wx.showModal({
        title: '提示',
        content: '请填写邮编',
        showCancel:false
      })
      return
    }
    let apiResult
    if (that.data.id) {
      apiResult = WXAPI.updateAddress({
        token: wx.getStorageSync('token'),
        id: that.data.id,
        provinceId: this.data.pObject.id,
        cityId: this.data.cObject.id,
        districtId: this.data.dObject ? this.data.dObject.id : '',
        linkMan: linkMan,
        address: address,
        mobile: mobile,
        code: code,
        isDefault: 'true'
      })
    } else {
      apiResult = WXAPI.addAddress({
        token: wx.getStorageSync('token'),
        provinceId: this.data.pObject.id,
        cityId: this.data.cObject.id,
        districtId: this.data.dObject ? this.data.dObject.id : '',
        linkMan: linkMan,
        address: address,
        mobile: mobile,
        code: code,
        isDefault: 'true'
      })
    }
    apiResult.then(function (res) {
      if (res.code != 0) {
        // 登录错误
        wx.hideLoading();
        wx.showModal({
          title: '失败',
          content: res.msg,
          showCancel: false
        })
        return;
      }
      // 跳转到结算页面
      wx.navigateBack({})
    })
  },
  onLoad: function (e) {
    const _this = this
    _this.initRegionPicker() // 初始化省市区选择器
    if (e.id) { // 修改初始化数据库数据
      WXAPI.addressDetail(e.id, wx.getStorageSync('token')).then(function (res) {
        if (res.code === 0) {
          _this.setData({
            id: e.id,
            addressData: res.data,
            showRegionStr: res.data.provinceStr + res.data.cityStr + res.data.areaStr
          });
          _this.initRegionDB(res.data.provinceStr, res.data.cityStr, res.data.areaStr)
          return;
        } else {
          wx.showModal({
            title: '提示',
            content: '无法获取快递地址数据',
            showCancel: false
          })
        }
      })
    }
  },
  deleteAddress: function (e) {
    var that = this;
    var id = e.currentTarget.dataset.id;
    wx.showModal({
      title: '提示',
      content: '确定要删除该收货地址吗？',
      success: function (res) {
        if (res.confirm) {
          WXAPI.deleteAddress(id, wx.getStorageSync('token')).then(function () {
            wx.navigateBack({})
          })
        } else {
          console.log('用户点击取消')
        }
      }
    })
  },
  readFromWx : function () {
    const _this = this
    wx.chooseAddress({
      success: function (res) {
        console.log(res)
        _this.initRegionDB(res.provinceName, res.cityName, res.countyName)
        _this.setData({
          wxaddress: res
        });
      }
    })
  }
})
<commit_msg>修复省市区选择直辖市时候的bug<commit_after>const WXAPI = require('../../wxapi/main')
const regeneratorRuntime = require('../../utils/runtime')
//获取应用实例
var app = getApp()
Page({
  data: {
    pickerRegionRange: [],
    pickerSelect:[0, 0, 0],
    showRegionStr: '请选择'
  },
  initRegionPicker () {
    WXAPI.province().then(res => {
      if (res.code === 0) {
        let _pickerRegionRange = []
        _pickerRegionRange.push(res.data)
        _pickerRegionRange.push([{ name: '请选择' }])
        _pickerRegionRange.push([{ name: '请选择' }])
        this.data.pickerRegionRange = _pickerRegionRange
        this.bindcolumnchange({ detail: { column: 0, value: 0 } })
      }
    })
  },
  async initRegionDB (pname, cname, dname) {
    this.data.showRegionStr = pname + cname + dname
    let pObject = undefined
    let cObject = undefined
    let dObject = undefined
    if (pname) {
      const index = this.data.pickerRegionRange[0].findIndex(ele=>{
        return ele.name == pname
      })
      console.log('pindex', index)
      if (index >= 0) {
        this.data.pickerSelect[0] = index
        pObject = this.data.pickerRegionRange[0][index]
      }
    }
    if (!pObject) {
      return
    }
    const _cRes = await WXAPI.nextRegion(pObject.id)
    if (_cRes.code === 0) {
      this.data.pickerRegionRange[1] = _cRes.data
      if (cname) {
        const index = this.data.pickerRegionRange[1].findIndex(ele => {
          return ele.name == cname
        })
        if (index >= 0) {
          this.data.pickerSelect[1] = index
          cObject = this.data.pickerRegionRange[1][index]
        }
      }
    }
    if (!cObject) {
      return
    }
    const _dRes = await WXAPI.nextRegion(cObject.id)
    if (_dRes.code === 0) {
      this.data.pickerRegionRange[2] = _dRes.data
      if (dname) {
        const index = this.data.pickerRegionRange[2].findIndex(ele => {
          return ele.name == dname
        })
        if (index >= 0) {
          this.data.pickerSelect[2] = index
          dObject = this.data.pickerRegionRange[2][index]
        }
      }
    }
    this.setData({
      pickerRegionRange: this.data.pickerRegionRange,
      pickerSelect: this.data.pickerSelect,
      showRegionStr: this.data.showRegionStr,
      pObject: pObject,
      cObject: cObject,
      dObject: dObject
    })
  },
  bindchange: function(e) {
    console.log(e)
    const pObject = this.data.pickerRegionRange[0][e.detail.value[0]]
    const cObject = this.data.pickerRegionRange[1][e.detail.value[1]]
    const dObject = this.data.pickerRegionRange[2][e.detail.value[2]]
    const showRegionStr = pObject.name + cObject.name + dObject.name
    this.setData({
      pObject: pObject,
      cObject: cObject,
      dObject: dObject,
      showRegionStr: showRegionStr
    })
  },
  bindcolumnchange: function(e) {
    const column = e.detail.column
    const index = e.detail.value
    const regionObject = this.data.pickerRegionRange[column][index]
    console.log('bindcolumnchange', regionObject)
    if (column === 2) {
      this.setData({
        pickerRegionRange: this.data.pickerRegionRange
      })
      return
    }
    if (column === 1) {
      this.data.pickerRegionRange[2] = [{ name: '请选择' }]
    }
    if (column === 0) {
      this.data.pickerRegionRange[1] = [{ name: '请选择' }]
      this.data.pickerRegionRange[2] = [{ name: '请选择' }]
    }
    // 后面的数组全部清空
    this.data.pickerRegionRange.splice(column+1)
    // 追加后面的一级数组
    WXAPI.nextRegion(regionObject.id).then(res => {
      if (res.code === 0) {
        this.data.pickerRegionRange[column + 1] = res.data
      }
      this.bindcolumnchange({ detail: { column: column + 1, value: 0 } })
    })
  },
  bindSave: function(e) {
    WXAPI.addTempleMsgFormid({
      token: wx.getStorageSync('token'),
      type: 'form',
      formId: e.detail.formId
    })
    var that = this;
    var linkMan = e.detail.value.linkMan;
    var address = e.detail.value.address;
    var mobile = e.detail.value.mobile;
    var code = e.detail.value.code;
    if (linkMan == ""){
      wx.showModal({
        title: '提示',
        content: '请填写联系人姓名',
        showCancel:false
      })
      return
    }
    if (mobile == ""){
      wx.showModal({
        title: '提示',
        content: '请填写手机号码',
        showCancel:false
      })
      return
    }
    if (!this.data.pObject || !this.data.cObject){
      wx.showModal({
        title: '提示',
        content: '请选择地区',
        showCancel:false
      })
      return
    }
    if (address == ""){
      wx.showModal({
        title: '提示',
        content: '请填写详细地址',
        showCancel:false
      })
      return
    }
    if (code == ""){
      wx.showModal({
        title: '提示',
        content: '请填写邮编',
        showCancel:false
      })
      return
    }
    let apiResult
    if (that.data.id) {
      apiResult = WXAPI.updateAddress({
        token: wx.getStorageSync('token'),
        id: that.data.id,
        provinceId: this.data.pObject.id,
        cityId: this.data.cObject.id,
        districtId: this.data.dObject ? this.data.dObject.id : '',
        linkMan: linkMan,
        address: address,
        mobile: mobile,
        code: code,
        isDefault: 'true'
      })
    } else {
      apiResult = WXAPI.addAddress({
        token: wx.getStorageSync('token'),
        provinceId: this.data.pObject.id,
        cityId: this.data.cObject.id,
        districtId: this.data.dObject ? this.data.dObject.id : '',
        linkMan: linkMan,
        address: address,
        mobile: mobile,
        code: code,
        isDefault: 'true'
      })
    }
    apiResult.then(function (res) {
      if (res.code != 0) {
        // 登录错误
        wx.hideLoading();
        wx.showModal({
          title: '失败',
          content: res.msg,
          showCancel: false
        })
        return;
      }
      // 跳转到结算页面
      wx.navigateBack({})
    })
  },
  onLoad: function (e) {
    const _this = this
    _this.initRegionPicker() // 初始化省市区选择器
    if (e.id) { // 修改初始化数据库数据
      WXAPI.addressDetail(e.id, wx.getStorageSync('token')).then(function (res) {
        if (res.code === 0) {
          _this.setData({
            id: e.id,
            addressData: res.data,
            showRegionStr: res.data.provinceStr + res.data.cityStr + res.data.areaStr
          });
          _this.initRegionDB(res.data.provinceStr, res.data.cityStr, res.data.areaStr)
          return;
        } else {
          wx.showModal({
            title: '提示',
            content: '无法获取快递地址数据',
            showCancel: false
          })
        }
      })
    }
  },
  deleteAddress: function (e) {
    var that = this;
    var id = e.currentTarget.dataset.id;
    wx.showModal({
      title: '提示',
      content: '确定要删除该收货地址吗？',
      success: function (res) {
        if (res.confirm) {
          WXAPI.deleteAddress(id, wx.getStorageSync('token')).then(function () {
            wx.navigateBack({})
          })
        } else {
          console.log('用户点击取消')
        }
      }
    })
  },
  readFromWx : function () {
    const _this = this
    wx.chooseAddress({
      success: function (res) {
        console.log(res)
        _this.initRegionDB(res.provinceName, res.cityName, res.countyName)
        _this.setData({
          wxaddress: res
        });
      }
    })
  }
})
<|endoftext|>


<commit_before>const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
const TOOLS = require('../../utils/tools.js') // TOOLS.showTabBarBadge();

Page({
  /**
   * 页面的初始数据
   */
  data: {
    categories: [],
    activeCategory: 0,
    categorySelected: {
      name: '',
      id: ''
    },
    currentGoods: [],
    onLoadStatus: true,
    scrolltop: 0,

    skuCurGoods: undefined
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    wx.showShareMenu({
      withShareTicket: true
    })
    this.categories();
  },
  async categories() {
    wx.showLoading({
      title: '加载中',
    })
    const res = await WXAPI.goodsCategory()
    wx.hideLoading()
    let categories = [];
    let categoryName = '';
    let categoryId = '';
    let activeCategory = 0
    if (res.code == 0) {
      if (this.data.categorySelected.id) {
        activeCategory = res.data.findIndex(ele => {
          return ele.id == this.data.categorySelected.id
        })
        const _curCategory = res.data.find(ele => {
          return ele.id == this.data.categorySelected.id
        })
        categoryName = _curCategory.name;
        categoryId = _curCategory.id;
      }
      for (let i = 0; i < res.data.length; i++) {
        let item = res.data[i];
        categories.push(item);
        if (i == 0 && !this.data.categorySelected.id) {
          categoryName = item.name;
          categoryId = item.id;
        }
      }
    }
    this.setData({
      activeCategory,
      categories: categories,
      categorySelected: {
        name: categoryName,
        id: categoryId
      }
    });
    this.getGoodsList();
  },
  async getGoodsList() {
    wx.showLoading({
      title: '加载中',
    })
    const res = await WXAPI.goods({
      categoryId: this.data.categorySelected.id,
      page: 1,
      pageSize: 100000
    })
    wx.hideLoading()
    if (res.code == 700) {
      this.setData({
        currentGoods: null
      });
      return
    }
    this.setData({
      currentGoods: res.data
    });
  },
  onCategoryClick(e) {
    const idx = e.target.dataset.idx
    if (idx == this.data.activeCategory) {
      this.setData({
        scrolltop: 0,
      })
      return
    }
    this.setData({
      activeCategory: idx,
      categorySelected: this.data.categories[idx],
      scrolltop: 0
    });
    this.getGoodsList();
  },
  bindconfirm(e) {
    this.setData({
      inputVal: e.detail
    })
    wx.navigateTo({
      url: '/pages/goods/list?name=' + this.data.inputVal,
    })
  },
  onShareAppMessage() {
    return {
      title: '"' + wx.getStorageSync('mallName') + '" ' + wx.getStorageSync('share_profile'),
      path: '/pages/index/index?inviter_id=' + wx.getStorageSync('uid')
    }
  },
  onShow() {
    AUTH.checkHasLogined().then(isLogined => {
      if (isLogined) {
        this.setData({
          wxlogin: isLogined
        })
        TOOLS.showTabBarBadge() // 获取购物车数据，显示TabBarBadge
      }
    })
    const _categoryId = wx.getStorageSync('_categoryId')
    // wx.removeStorageSync('_categoryId')
    if (_categoryId) {
      this.data.categorySelected.id = _categoryId
      this.categories();
    } else {
      this.data.categorySelected.id = null
    }
  },
  async addShopCar(e) {
    const curGood = this.data.currentGoods.find(ele => {
      return ele.id == e.currentTarget.dataset.id
    })
    if (!curGood) {
      return
    }
    if (curGood.stores <= 0) {
      wx.showToast({
        title: '已售罄~',
        icon: 'none'
      })
      return
    }
    this.addShopCarCheck({
      goodsId: curGood.id,
      buyNumber: 1,
      sku: []
    })
  },
  async addShopCarCheck(options){
    AUTH.checkHasLogined().then(isLogined => {
      this.setData({
        wxlogin: isLogined
      })
      if (isLogined) {
        // 处理加入购物车的业务逻辑
        this.addShopCarDone(options)
      } else {
        AUTH.openLoginDialog()
      }
    })
  },
  async addShopCarDone(options){
    const res = await WXAPI.shippingCarInfoAddItem(wx.getStorageSync('token'), options.goodsId, options.buyNumber, options.sku)
    if (res.code == 30002) {
      // 需要选择规格尺寸
      const skuCurGoodsRes = await WXAPI.goodsDetail(options.goodsId)
      if (skuCurGoodsRes.code != 0) {
        wx.showToast({
          title: skuCurGoodsRes.msg,
          icon: 'none'
        })
        return
      }
      wx.hideTabBar()
      const skuCurGoods = skuCurGoodsRes.data
      skuCurGoods.basicInfo.storesBuy = 1
      this.setData({
        skuCurGoods,
        skuGoodsPic: skuCurGoods.basicInfo.pic,
        selectSizePrice: skuCurGoods.basicInfo.minPrice,
        selectSizeOPrice: skuCurGoods.basicInfo.originalPrice,
        skuCurGoodsShow: true
      })
      return
    }
    if (res.code != 0) {
      wx.showToast({
        title: res.msg,
        icon: 'none'
      })
      return
    }
    wx.showToast({
      title: '加入成功',
      icon: 'success'
    })
    this.setData({
      skuCurGoods: null,
      skuCurGoodsShow: false
    })
    wx.showTabBar()
    TOOLS.showTabBarBadge() // 获取购物车数据，显示TabBarBadge
  },
  storesJia(){
    const skuCurGoods = this.data.skuCurGoods
    if (skuCurGoods.basicInfo.storesBuy < skuCurGoods.basicInfo.stores) {
      skuCurGoods.basicInfo.storesBuy++
      this.setData({
        skuCurGoods
      })
    }
  },
  storesJian(){
    const skuCurGoods = this.data.skuCurGoods
    if (skuCurGoods.basicInfo.storesBuy > 1) {
      skuCurGoods.basicInfo.storesBuy--
      this.setData({
        skuCurGoods
      })
    }
  },
  closeSku(){
    this.setData({
      skuCurGoods: null,
      skuCurGoodsShow: false
    })
    wx.showTabBar()
  },
  skuSelect(e){
    const pid = e.currentTarget.dataset.pid
    const id = e.currentTarget.dataset.id
    // 处理选中
    const skuCurGoods = this.data.skuCurGoods
    const property = skuCurGoods.properties.find(ele => {return ele.id == pid})
    let child
    property.childsCurGoods.forEach(ele => {
      if (ele.id == id) {
        ele.active = true
        child = ele
      } else {
        ele.active = false
      }
    })
    // 显示图片
    let skuGoodsPic = this.data.skuGoodsPic
    if (skuCurGoods.subPics && skuCurGoods.subPics.length > 0) {
      const _subPic = skuCurGoods.subPics.find(ele => {
        return ele.optionValueId == child.id
      })
      if (_subPic) {
        skuGoodsPic = _subPic.pic
      }
    }
    this.setData({
      skuCurGoods,
      skuGoodsPic
    })
    // 计算价格
    this.calculateGoodsPrice()
  },
  async calculateGoodsPrice() {
    // 计算最终的商品价格
    let price = this.data.skuCurGoods.basicInfo.minPrice
    let originalPrice = this.data.skuCurGoods.basicInfo.originalPrice
    let totalScoreToPay = this.data.skuCurGoods.basicInfo.minScore
    let buyNumMax = this.data.skuCurGoods.basicInfo.stores
    let buyNumber = this.data.skuCurGoods.basicInfo.minBuyNumber
    // 计算 sku 价格
    const needSelectNum = this.data.skuCurGoods.properties.length
    let curSelectNum = 0;
    let propertyChildIds = "";
    let propertyChildNames = "";
    this.data.skuCurGoods.properties.forEach(p => {
      p.childsCurGoods.forEach(c => {
        if (c.active) {
          curSelectNum++;
          propertyChildIds = propertyChildIds + p.id + ":" + c.id + ",";
          propertyChildNames = propertyChildNames + p.name + ":" + c.name + "  ";
        }
      })
    })
    let canSubmit = false;
    if (needSelectNum == curSelectNum) {
      canSubmit = true;
    }
    if (canSubmit) {
      const res = await WXAPI.goodsPrice(this.data.skuCurGoods.basicInfo.id, propertyChildIds)
      if (res.code == 0) {
        price = res.data.price
        originalPrice = res.data.originalPrice
        totalScoreToPay = res.data.score
        buyNumMax = res.data.stores
      }
    }
    this.setData({
      selectSizePrice: price,
      selectSizeOPrice: originalPrice,
      totalScoreToPay: totalScoreToPay,
      buyNumMax,
      buyNumber: (buyNumMax > buyNumber) ? buyNumber : 0
    });
  },
  addCarSku(){
    const skuCurGoods = this.data.skuCurGoods
    const propertySize = skuCurGoods.properties.length // 有几组SKU
    const sku = []
    skuCurGoods.properties.forEach(p => {
      const o = p.childsCurGoods.find(ele => {return ele.active})
      if (!o) {
        return
      }
      sku.push({
        optionId: o.propertyId,
        optionValueId: o.id
      })
    })
    if (sku.length != propertySize) {
      wx.showToast({
        title: '请选择规格',
        icon: 'none'
      })
      return
    }
    const options = {
      goodsId: skuCurGoods.basicInfo.id,
      buyNumber: skuCurGoods.basicInfo.storesBuy,
      sku
    }
    this.addShopCarDone(options)
  },
  processLogin(e) {
    if (!e.detail.userInfo) {
      wx.showToast({
        title: '已取消',
        icon: 'none',
      })
      return;
    }
    AUTH.register(this);
  },
  onReachBottom: function() {

  },
})<commit_msg>修复首页分类点进分类页面左侧分类未选中的问题<commit_after>const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
const TOOLS = require('../../utils/tools.js') // TOOLS.showTabBarBadge();

Page({
  /**
   * 页面的初始数据
   */
  data: {
    categories: [],
    activeCategory: 0,
    categorySelected: {
      name: '',
      id: ''
    },
    currentGoods: [],
    onLoadStatus: true,
    scrolltop: 0,

    skuCurGoods: undefined
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    wx.showShareMenu({
      withShareTicket: true
    })
    this.categories();
  },
  async categories() {
    wx.showLoading({
      title: '加载中',
    })
    const res = await WXAPI.goodsCategory()
    wx.hideLoading()
    let categories = [];
    let categoryName = '';
    let categoryId = '';
    let activeCategory = 0
    if (res.code == 0) {
      if (this.data.categorySelected.id) {
        activeCategory = res.data.findIndex(ele => {
          return ele.id == this.data.categorySelected.id
        })
        const _curCategory = res.data.find(ele => {
          return ele.id == this.data.categorySelected.id
        })
        categoryName = _curCategory.name;
        categoryId = _curCategory.id;
      }
      for (let i = 0; i < res.data.length; i++) {
        let item = res.data[i];
        categories.push(item);
        if (i == 0 && !this.data.categorySelected.id) {
          categoryName = item.name;
          categoryId = item.id;
        }
      }
    }
    this.setData({
      activeCategory,
      categories: categories,
      categorySelected: {
        name: categoryName,
        id: categoryId
      }
    });
    this.getGoodsList();
  },
  async getGoodsList() {
    wx.showLoading({
      title: '加载中',
    })
    const res = await WXAPI.goods({
      categoryId: this.data.categorySelected.id,
      page: 1,
      pageSize: 100000
    })
    wx.hideLoading()
    if (res.code == 700) {
      this.setData({
        currentGoods: null
      });
      return
    }
    this.setData({
      currentGoods: res.data
    });
  },
  onCategoryClick(e) {
    const idx = e.target.dataset.idx
    if (idx == this.data.activeCategory) {
      this.setData({
        scrolltop: 0,
      })
      return
    }
    this.setData({
      activeCategory: idx,
      categorySelected: this.data.categories[idx],
      scrolltop: 0
    });
    this.getGoodsList();
  },
  bindconfirm(e) {
    this.setData({
      inputVal: e.detail
    })
    wx.navigateTo({
      url: '/pages/goods/list?name=' + this.data.inputVal,
    })
  },
  onShareAppMessage() {
    return {
      title: '"' + wx.getStorageSync('mallName') + '" ' + wx.getStorageSync('share_profile'),
      path: '/pages/index/index?inviter_id=' + wx.getStorageSync('uid')
    }
  },
  onShow() {
    AUTH.checkHasLogined().then(isLogined => {
      if (isLogined) {
        this.setData({
          wxlogin: isLogined
        })
        TOOLS.showTabBarBadge() // 获取购物车数据，显示TabBarBadge
      }
    })
    const _categoryId = wx.getStorageSync('_categoryId')
    wx.removeStorageSync('_categoryId')
    if (_categoryId) {
      this.data.categorySelected.id = _categoryId
      this.categories();
    } else {
      this.data.categorySelected.id = null
    }
  },
  async addShopCar(e) {
    const curGood = this.data.currentGoods.find(ele => {
      return ele.id == e.currentTarget.dataset.id
    })
    if (!curGood) {
      return
    }
    if (curGood.stores <= 0) {
      wx.showToast({
        title: '已售罄~',
        icon: 'none'
      })
      return
    }
    this.addShopCarCheck({
      goodsId: curGood.id,
      buyNumber: 1,
      sku: []
    })
  },
  async addShopCarCheck(options){
    AUTH.checkHasLogined().then(isLogined => {
      this.setData({
        wxlogin: isLogined
      })
      if (isLogined) {
        // 处理加入购物车的业务逻辑
        this.addShopCarDone(options)
      } else {
        AUTH.openLoginDialog()
      }
    })
  },
  async addShopCarDone(options){
    const res = await WXAPI.shippingCarInfoAddItem(wx.getStorageSync('token'), options.goodsId, options.buyNumber, options.sku)
    if (res.code == 30002) {
      // 需要选择规格尺寸
      const skuCurGoodsRes = await WXAPI.goodsDetail(options.goodsId)
      if (skuCurGoodsRes.code != 0) {
        wx.showToast({
          title: skuCurGoodsRes.msg,
          icon: 'none'
        })
        return
      }
      wx.hideTabBar()
      const skuCurGoods = skuCurGoodsRes.data
      skuCurGoods.basicInfo.storesBuy = 1
      this.setData({
        skuCurGoods,
        skuGoodsPic: skuCurGoods.basicInfo.pic,
        selectSizePrice: skuCurGoods.basicInfo.minPrice,
        selectSizeOPrice: skuCurGoods.basicInfo.originalPrice,
        skuCurGoodsShow: true
      })
      return
    }
    if (res.code != 0) {
      wx.showToast({
        title: res.msg,
        icon: 'none'
      })
      return
    }
    wx.showToast({
      title: '加入成功',
      icon: 'success'
    })
    this.setData({
      skuCurGoods: null,
      skuCurGoodsShow: false
    })
    wx.showTabBar()
    TOOLS.showTabBarBadge() // 获取购物车数据，显示TabBarBadge
  },
  storesJia(){
    const skuCurGoods = this.data.skuCurGoods
    if (skuCurGoods.basicInfo.storesBuy < skuCurGoods.basicInfo.stores) {
      skuCurGoods.basicInfo.storesBuy++
      this.setData({
        skuCurGoods
      })
    }
  },
  storesJian(){
    const skuCurGoods = this.data.skuCurGoods
    if (skuCurGoods.basicInfo.storesBuy > 1) {
      skuCurGoods.basicInfo.storesBuy--
      this.setData({
        skuCurGoods
      })
    }
  },
  closeSku(){
    this.setData({
      skuCurGoods: null,
      skuCurGoodsShow: false
    })
    wx.showTabBar()
  },
  skuSelect(e){
    const pid = e.currentTarget.dataset.pid
    const id = e.currentTarget.dataset.id
    // 处理选中
    const skuCurGoods = this.data.skuCurGoods
    const property = skuCurGoods.properties.find(ele => {return ele.id == pid})
    let child
    property.childsCurGoods.forEach(ele => {
      if (ele.id == id) {
        ele.active = true
        child = ele
      } else {
        ele.active = false
      }
    })
    // 显示图片
    let skuGoodsPic = this.data.skuGoodsPic
    if (skuCurGoods.subPics && skuCurGoods.subPics.length > 0) {
      const _subPic = skuCurGoods.subPics.find(ele => {
        return ele.optionValueId == child.id
      })
      if (_subPic) {
        skuGoodsPic = _subPic.pic
      }
    }
    this.setData({
      skuCurGoods,
      skuGoodsPic
    })
    // 计算价格
    this.calculateGoodsPrice()
  },
  async calculateGoodsPrice() {
    // 计算最终的商品价格
    let price = this.data.skuCurGoods.basicInfo.minPrice
    let originalPrice = this.data.skuCurGoods.basicInfo.originalPrice
    let totalScoreToPay = this.data.skuCurGoods.basicInfo.minScore
    let buyNumMax = this.data.skuCurGoods.basicInfo.stores
    let buyNumber = this.data.skuCurGoods.basicInfo.minBuyNumber
    // 计算 sku 价格
    const needSelectNum = this.data.skuCurGoods.properties.length
    let curSelectNum = 0;
    let propertyChildIds = "";
    let propertyChildNames = "";
    this.data.skuCurGoods.properties.forEach(p => {
      p.childsCurGoods.forEach(c => {
        if (c.active) {
          curSelectNum++;
          propertyChildIds = propertyChildIds + p.id + ":" + c.id + ",";
          propertyChildNames = propertyChildNames + p.name + ":" + c.name + "  ";
        }
      })
    })
    let canSubmit = false;
    if (needSelectNum == curSelectNum) {
      canSubmit = true;
    }
    if (canSubmit) {
      const res = await WXAPI.goodsPrice(this.data.skuCurGoods.basicInfo.id, propertyChildIds)
      if (res.code == 0) {
        price = res.data.price
        originalPrice = res.data.originalPrice
        totalScoreToPay = res.data.score
        buyNumMax = res.data.stores
      }
    }
    this.setData({
      selectSizePrice: price,
      selectSizeOPrice: originalPrice,
      totalScoreToPay: totalScoreToPay,
      buyNumMax,
      buyNumber: (buyNumMax > buyNumber) ? buyNumber : 0
    });
  },
  addCarSku(){
    const skuCurGoods = this.data.skuCurGoods
    const propertySize = skuCurGoods.properties.length // 有几组SKU
    const sku = []
    skuCurGoods.properties.forEach(p => {
      const o = p.childsCurGoods.find(ele => {return ele.active})
      if (!o) {
        return
      }
      sku.push({
        optionId: o.propertyId,
        optionValueId: o.id
      })
    })
    if (sku.length != propertySize) {
      wx.showToast({
        title: '请选择规格',
        icon: 'none'
      })
      return
    }
    const options = {
      goodsId: skuCurGoods.basicInfo.id,
      buyNumber: skuCurGoods.basicInfo.storesBuy,
      sku
    }
    this.addShopCarDone(options)
  },
  processLogin(e) {
    if (!e.detail.userInfo) {
      wx.showToast({
        title: '已取消',
        icon: 'none',
      })
      return;
    }
    AUTH.register(this);
  },
  onReachBottom: function() {

  },
})<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import {
    View,
    TouchableOpacity,
    StyleSheet,
    Text
} from 'react-native'

const handleTabPress = (index, multiple, selectedIndex, onTabPress) => {
    if (multiple) {
        onTabPress(index);
    }
    else if (selectedIndex !== index) {
        onTabPress(index);
    }
};

const TabOption = ({
    isTabActive, index, text,
    firstTabStyle, lastTabStyle,
    tabStyle, activeTabStyle,
    tabTextStyle, activeTabTextStyle,
    onTabPress,
}) => {
    return (
        <TouchableOpacity style={[
            styles.tabStyle,
            tabStyle,
            isTabActive ? [styles.activeTabStyle, activeTabStyle] : {},
            firstTabStyle,
            lastTabStyle]}
            onPress={() => onTabPress(index)}
            activeOpacity={1}>
            <Text style={[
                styles.textStyle,
                tabTextStyle,
                isTabActive ? [styles.activeTabTextStyle, activeTabTextStyle] : {}]}>
                {text}
            </Text>
        </TouchableOpacity>
    );
}

const SegmentedControlTab = ({
    multiple, selectedIndex, selectedIndices, values,
    borderRadius, tabsContainerStyle,
    tabStyle, activeTabStyle,
    tabTextStyle, activeTabTextStyle,
    onTabPress,
}) => {
    const firstTabStyle = [{ borderTopLeftRadius: borderRadius, borderBottomLeftRadius: borderRadius }];
    const lastTabStyle = [{ borderTopRightRadius: borderRadius, borderBottomRightRadius: borderRadius }];

    return (
        <View
            style={[styles.tabsContainerStyle, tabsContainerStyle]}
            removeClippedSubviews={true}>
            {
                values.map((item, index) => {
                    return (
                        <TabOption
                            key={index}
                            index={index}
                            isTabActive={multiple ? selectedIndices.includes(index) : selectedIndex === index}
                            text={item}
                            onTabPress={(index) => handleTabPress(index, multiple, selectedIndex, onTabPress)}
                            firstTabStyle={index === 0 ? firstTabStyle : {}}
                            lastTabStyle={index === values.length - 1 ? lastTabStyle : {}}
                            tabStyle={[tabStyle, index !== 0 && index !== values.length - 1 ? { marginHorizontal: -1 } : {}]}
                            activeTabStyle={activeTabStyle}
                            tabTextStyle={tabTextStyle}
                            activeTabTextStyle={activeTabTextStyle} />
                    );
                })
            }
        </View>
    );
};

SegmentedControlTab.propTypes = Object.assign({}, Component.propTypes, {
    values: PropTypes.array,
    multiple: PropTypes.bool,
    onTabPress: PropTypes.func,
    selectedIndex: PropTypes.number,
    selectedIndices: PropTypes.arrayOf(PropTypes.number),
    tabsContainerStyle: View.propTypes.style,
    tabStyle: View.propTypes.style,
    activeTabStyle: View.propTypes.style,
    tabTextStyle: Text.propTypes.style,
    activeTabTextStyle: Text.propTypes.style,
    borderRadius: PropTypes.number
})

SegmentedControlTab.defaultProps = Object.assign({}, Component.propTypes, {
    values: ['One', 'Two', 'Three'],
    multiple: false,
    selectedIndex: 0,
    selectedIndices: [0],
    onTabPress() { },
    tabsContainerStyle: {},
    tabStyle: {},
    activeTabStyle: {},
    textStyle: {},
    activeTextStyle: {},
    borderRadius: 5
})

const styles = StyleSheet.create({
    tabsContainerStyle: {
        backgroundColor: 'transparent',
        flexDirection: 'row',
    },
    tabStyle: {
        paddingVertical: 5,
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        borderColor: '#0076FF',
        borderWidth: 1,
        backgroundColor: 'white',
    },
    activeTabStyle: {
        backgroundColor: '#0076FF'
    },
    tabTextStyle: {
        color: '#0076FF'
    },
    activeTabTextStyle: {
        color: 'white'
    }
})

export default SegmentedControlTab
<commit_msg>Disable removeClippedSubviews<commit_after>import React, { Component, PropTypes } from 'react'
import {
    View,
    TouchableOpacity,
    StyleSheet,
    Text
} from 'react-native'

const handleTabPress = (index, multiple, selectedIndex, onTabPress) => {
    if (multiple) {
        onTabPress(index);
    }
    else if (selectedIndex !== index) {
        onTabPress(index);
    }
};

const TabOption = ({
    isTabActive, index, text,
    firstTabStyle, lastTabStyle,
    tabStyle, activeTabStyle,
    tabTextStyle, activeTabTextStyle,
    onTabPress,
}) => {
    return (
        <TouchableOpacity style={[
            styles.tabStyle,
            tabStyle,
            isTabActive ? [styles.activeTabStyle, activeTabStyle] : {},
            firstTabStyle,
            lastTabStyle]}
            onPress={() => onTabPress(index)}
            activeOpacity={1}>
            <Text style={[
                styles.textStyle,
                tabTextStyle,
                isTabActive ? [styles.activeTabTextStyle, activeTabTextStyle] : {}]}>
                {text}
            </Text>
        </TouchableOpacity>
    );
}

const SegmentedControlTab = ({
    multiple, selectedIndex, selectedIndices, values,
    borderRadius, tabsContainerStyle,
    tabStyle, activeTabStyle,
    tabTextStyle, activeTabTextStyle,
    onTabPress,
}) => {
    const firstTabStyle = [{ borderTopLeftRadius: borderRadius, borderBottomLeftRadius: borderRadius }];
    const lastTabStyle = [{ borderTopRightRadius: borderRadius, borderBottomRightRadius: borderRadius }];

    return (
        <View
            style={[styles.tabsContainerStyle, tabsContainerStyle]}
            removeClippedSubviews={false}>
            {
                values.map((item, index) => {
                    return (
                        <TabOption
                            key={index}
                            index={index}
                            isTabActive={multiple ? selectedIndices.includes(index) : selectedIndex === index}
                            text={item}
                            onTabPress={(index) => handleTabPress(index, multiple, selectedIndex, onTabPress)}
                            firstTabStyle={index === 0 ? firstTabStyle : {}}
                            lastTabStyle={index === values.length - 1 ? lastTabStyle : {}}
                            tabStyle={[tabStyle, index !== 0 && index !== values.length - 1 ? { marginHorizontal: -1 } : {}]}
                            activeTabStyle={activeTabStyle}
                            tabTextStyle={tabTextStyle}
                            activeTabTextStyle={activeTabTextStyle} />
                    );
                })
            }
        </View>
    );
};

SegmentedControlTab.propTypes = Object.assign({}, Component.propTypes, {
    values: PropTypes.array,
    multiple: PropTypes.bool,
    onTabPress: PropTypes.func,
    selectedIndex: PropTypes.number,
    selectedIndices: PropTypes.arrayOf(PropTypes.number),
    tabsContainerStyle: View.propTypes.style,
    tabStyle: View.propTypes.style,
    activeTabStyle: View.propTypes.style,
    tabTextStyle: Text.propTypes.style,
    activeTabTextStyle: Text.propTypes.style,
    borderRadius: PropTypes.number
})

SegmentedControlTab.defaultProps = Object.assign({}, Component.propTypes, {
    values: ['One', 'Two', 'Three'],
    multiple: false,
    selectedIndex: 0,
    selectedIndices: [0],
    onTabPress() { },
    tabsContainerStyle: {},
    tabStyle: {},
    activeTabStyle: {},
    textStyle: {},
    activeTextStyle: {},
    borderRadius: 5
})

const styles = StyleSheet.create({
    tabsContainerStyle: {
        backgroundColor: 'transparent',
        flexDirection: 'row',
    },
    tabStyle: {
        paddingVertical: 5,
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        borderColor: '#0076FF',
        borderWidth: 1,
        backgroundColor: 'white',
    },
    activeTabStyle: {
        backgroundColor: '#0076FF'
    },
    tabTextStyle: {
        color: '#0076FF'
    },
    activeTabTextStyle: {
        color: 'white'
    }
})

export default SegmentedControlTab
<|endoftext|>


<commit_before>'use strict';

var http = require('http');
var https = require('https');
var url = require('url');
//var querystring = require('querystring');
var fs = require('fs');
var websocket = require('websocket');		// don't forget to run "npm install websocket"

/*
	SensorReader
*/
function SensorReader()
{
	this._interval = setInterval( this._onReceivedData.bind(this), 20 );
	this._onSensorDataReady = [];
}

SensorReader.prototype.dispose = function()
{
	clearInterval( this._interval );
};

SensorReader.prototype._onReceivedData = function()
{
	var now = new Date().getTime();
	var t0 = (now % 4000) / 4000;
	var t1 = (now % 1000) / 1000;
	var t2 = (now % 333) / 333;
	var t4 = (now % 1642) / 1642;

	var temperature = (t0*30 - 15) + 50  + Math.sin( t2 * Math.PI * 2) * 2;

	var angularSpeedX =
		Math.sin( t0 * Math.PI * 2) * 15 +
		Math.sin( t1 * Math.PI * 2) * (5*(Math.sin( t4 * Math.PI * 2)+1)) +
		Math.sin( t2 * Math.PI * 2) * 2 +
		50;

	var dataPoint = {
		temperature: temperature,
		angularSpeedX: angularSpeedX,
		timestamp: new Date().getTime()
	};

	//console.log("SensorReader: read point " + dataPoint.timestamp);

	for ( var i=0; i<this._onSensorDataReady.length; ++i )
	{
		var listener = this._onSensorDataReady[i];
		listener( dataPoint );
	}
};

/*
	SensorDataSender
*/
function SensorDataSender( sensorReader, connection )
{
	this._sensorReader = sensorReader;
	this._connection = connection;

	this._interval = setInterval( this._sendData.bind(this), 50 );

	this._maxNumDataPointsToSend = 2000;
	this._dataPointsToSend = [];

	this._onSensorDataReadyHandler = this._onSensorDataReady.bind(this);
	this._sensorReader._onSensorDataReady.push( this._onSensorDataReadyHandler );

	this._instanceID = SensorDataSender.numInstances;
	SensorDataSender.numInstances++;

	console.log("SensorDataSender#"+ this._instanceID + ": created");
}
SensorDataSender.numInstances = 0;

SensorDataSender.prototype.dispose = function()
{
	clearInterval( this._interval );

	var index = this._sensorReader._onSensorDataReady.indexOf( this._onSensorDataReadyHandler );
	if (index!==-1)
	{
		this._sensorReader._onSensorDataReady.splice(index, 1);
	}
	else
	{
		console.error("something's wrong");
	}

	console.log("SensorDataSender#"+ this._instanceID + ": dispose");
};

SensorDataSender.prototype._onSensorDataReady = function( dataPoint )
{
	this._dataPointsToSend.splice(0, 0, dataPoint);
	if ( this._dataPointsToSend.length>this._maxNumDataPointsToSend )
	{
		this._dataPointsToSend.shift();
		console.warn("buffer full");
	}
};

SensorDataSender.prototype._sendData = function()
{
	//console.log("SensorDataSender#"+ this._instanceID + ": sending " + this._dataPointsToSend.length);
	var jsonData = JSON.stringify(this._dataPointsToSend);
	this._connection.sendUTF(jsonData);
	this._dataPointsToSend = [];
};

/*
	SensorMonitorServer
*/
function SensorMonitorServer()
{
	this._sensorReader = new SensorReader();
	this._sensorDataSenders = [];

	// HTTP server
	this._httpServer = http.createServer(
		function(req, res)
		{
			var path = url.parse(req.url).pathname;
			var query = url.parse(req.url).query;

			if ( path==='/')
			{
				SensorMonitorServer._serveFile( 'SensorMonitor.html', res );
			}
			else if ( path.indexOf('/files/')===0 )
			{
				var filename = path.substr(1);
				SensorMonitorServer._serveFile( filename, res );
			}
			else
			{
				SensorMonitorServer._createHTMLErrorResponse( res, 404, "Page not found");
			}
		});
	this._httpServer.listen(8080);

	// Websocket server
	this._websocketServer = new websocket.server({
		httpServer: this._httpServer
	});
	this._websocketServer.on('request',
		function(request)
		{
    		var connection = request.accept(null, request.origin);

    		//console.log("adding sender..." );
    		var sensorDataSender = new SensorDataSender( this._sensorReader, connection );
    		this._sensorDataSenders.push( sensorDataSender );

    		console.log("SensorMonitor: " + this._sensorDataSenders.length + " connections in progress");

    		connection.on('close',
    			function(connection)
    			{
					//console.log('Websocket server connection closed' + connection);
					sensorDataSender.dispose();
					var index = this._sensorDataSenders.indexOf(sensorDataSender);
					if (index!==-1)
					{
					    this._sensorDataSenders.splice(index, 1);
					}
					else
					{
						console.warn("couldn't find sender for connection...");
					}

					console.log("SensorMonitor: " + this._sensorDataSenders.length + " connections in progress");
   				}.bind(this));
		}.bind(this));

	console.log("SensorMonitor: server started");
}

SensorMonitorServer.prototype.dispose = function()
{
	// Stop things here!
	console.log("dispose to implement here...")
};

SensorMonitorServer._serveFile = function( filename, res )
{
	console.log("Serving file: " + filename);
	fs.readFile(filename, 'utf8',
		function(err, data)
			{
		  		if ( err )
		  		{
		    		SensorMonitorServer._createHTMLErrorResponse( res, 500, err );
		  		}
		  		else
		  		{
		  			res.writeHead(200); //{"Content-Type:": "application/json"});	// The server should certainly provide content type based on file extension
					res.write(data);
					res.end();
				}
			});
};

SensorMonitorServer._createHTMLErrorResponse = function( res, code, message )
{
	res.writeHead(code, {"Content-Type:": "text/html"});
	res.write(
		'<!DOCTYPE html>'+
		''+
		'    '+
		'        <meta charset="utf-8" />'+
		'        <title>Error</title>'+
		'    '+
		'    '+
		'
' + message + '
'+
		'    '+
		'');
	res.end();
};

/*
	Main
*/
function Main()
{
	var sensorMonitorServer = new SensorMonitorServer();

	//http://stackoverflow.com/questions/10021373/what-is-the-windows-equivalent-of-process-onsigint-in-node-js/14861513#14861513
	//http://stackoverflow.com/questions/6958780/quitting-node-js-gracefully
	if (process.platform === "win32")
	{
		var rl = require("readline").createInterface(
			{
				input: process.stdin,
				output: process.stdout
			});
		rl.on("SIGINT", function ()
			{
				process.emit("SIGINT");
			});
	}
	process.on("SIGINT", function ()
		{
			console.log("Stopping server...");
			sensorMonitorServer.dispose();
			process.exit();
		});
}

Main();

<commit_msg>SensorMonitorServer.js now opens UPD socket<commit_after>'use strict';

var http = require('http');
var https = require('https');
var url = require('url');
//var querystring = require('querystring');
var fs = require('fs');
var websocket = require('websocket');		// don't forget to run "npm install websocket"

var dgram = require('dgram');

/*
	SensorReader
*/
function SensorReader()
{
	this._interval = setInterval( this._onReceivedData.bind(this), 20 );
	this._onSensorDataReady = [];
}

SensorReader.prototype.dispose = function()
{
	clearInterval( this._interval );
};

SensorReader.prototype._onReceivedData = function()
{
	var now = new Date().getTime();
	var t0 = (now % 4000) / 4000;
	var t1 = (now % 1000) / 1000;
	var t2 = (now % 333) / 333;
	var t4 = (now % 1642) / 1642;

	var temperature = (t0*30 - 15) + 50  + Math.sin( t2 * Math.PI * 2) * 2;

	var angularSpeedX =
		Math.sin( t0 * Math.PI * 2) * 15 +
		Math.sin( t1 * Math.PI * 2) * (5*(Math.sin( t4 * Math.PI * 2)+1)) +
		Math.sin( t2 * Math.PI * 2) * 2 +
		50;

	var dataPoint = {
		temperature: temperature,
		angularSpeedX: angularSpeedX,
		timestamp: new Date().getTime()
	};

	//console.log("SensorReader: read point " + dataPoint.timestamp);

	for ( var i=0; i<this._onSensorDataReady.length; ++i )
	{
		var listener = this._onSensorDataReady[i];
		listener( dataPoint );
	}
};

/*
	SensorDataSender
*/
function SensorDataSender( sensorReader, connection )
{
	this._sensorReader = sensorReader;
	this._connection = connection;

	this._interval = setInterval( this._sendData.bind(this), 50 );

	this._maxNumDataPointsToSend = 2000;
	this._dataPointsToSend = [];

	this._onSensorDataReadyHandler = this._onSensorDataReady.bind(this);
	this._sensorReader._onSensorDataReady.push( this._onSensorDataReadyHandler );

	this._instanceID = SensorDataSender.numInstances;
	SensorDataSender.numInstances++;

	console.log("SensorDataSender#"+ this._instanceID + ": created");
}
SensorDataSender.numInstances = 0;

SensorDataSender.prototype.dispose = function()
{
	clearInterval( this._interval );

	var index = this._sensorReader._onSensorDataReady.indexOf( this._onSensorDataReadyHandler );
	if (index!==-1)
	{
		this._sensorReader._onSensorDataReady.splice(index, 1);
	}
	else
	{
		console.error("something's wrong");
	}

	console.log("SensorDataSender#"+ this._instanceID + ": dispose");
};

SensorDataSender.prototype._onSensorDataReady = function( dataPoint )
{
	this._dataPointsToSend.splice(0, 0, dataPoint);
	if ( this._dataPointsToSend.length>this._maxNumDataPointsToSend )
	{
		this._dataPointsToSend.shift();
		console.warn("buffer full");
	}
};

SensorDataSender.prototype._sendData = function()
{
	//console.log("SensorDataSender#"+ this._instanceID + ": sending " + this._dataPointsToSend.length);
	var jsonData = JSON.stringify(this._dataPointsToSend);
	this._connection.sendUTF(jsonData);
	this._dataPointsToSend = [];
};

/*
	SensorMonitorServer
*/
function SensorMonitorServer()
{
	this._sensorReader = new SensorReader();
	this._sensorDataSenders = [];

	// HTTP server
	this._httpServer = http.createServer(
		function(req, res)
		{
			var path = url.parse(req.url).pathname;
			var query = url.parse(req.url).query;

			if ( path==='/')
			{
				SensorMonitorServer._serveFile( 'SensorMonitor.html', res );
			}
			else if ( path.indexOf('/files/')===0 )
			{
				var filename = path.substr(1);
				SensorMonitorServer._serveFile( filename, res );
			}
			else
			{
				SensorMonitorServer._createHTMLErrorResponse( res, 404, "Page not found");
			}
		});
	this._httpServer.listen(8080);

	// Websocket server
	this._websocketServer = new websocket.server({
		httpServer: this._httpServer
	});
	this._websocketServer.on('request',
		function(request)
		{
    		var connection = request.accept(null, request.origin);

    		//console.log("adding sender..." );
    		var sensorDataSender = new SensorDataSender( this._sensorReader, connection );
    		this._sensorDataSenders.push( sensorDataSender );

    		console.log("SensorMonitor: " + this._sensorDataSenders.length + " connections in progress");

    		connection.on('close',
    			function(connection)
    			{
					//console.log('Websocket server connection closed' + connection);
					sensorDataSender.dispose();
					var index = this._sensorDataSenders.indexOf(sensorDataSender);
					if (index!==-1)
					{
					    this._sensorDataSenders.splice(index, 1);
					}
					else
					{
						console.warn("couldn't find sender for connection...");
					}

					console.log("SensorMonitor: " + this._sensorDataSenders.length + " connections in progress");
   				}.bind(this));
		}.bind(this));

	// UDP socket
	var udpSocket = dgram.createSocket('udp4');
	udpSocket.on('listening',
		function()
		{
		    var address = udpSocket.address();
		    console.log('UDP Server listening on ' + address.address + ":" + address.port);
		});
	udpSocket.on('message',
		function(message, remote)
		{
	    	console.log('UDP socket received message: ' + remote.address + ':' + remote.port +' - ' + message);
	    	var uint8Array = new Uint8Array( message );
			for ( var i=0; i<uint8Array.length /* same as remote.size */; i++ )
			{
				//var byteAsHex = messageString.substr( i*2, 2 );
				//var byte = parseInt( byteAsHex, 16 );
				//uint8Array[i] = byte;
				console.log("byte " + i + ": " + uint8Array[i] );
			}
			return uint8Array;

	    });
	udpSocket.bind(8181, '127.0.0.1');

	console.log("SensorMonitor: server started");
}

SensorMonitorServer.prototype.dispose = function()
{
	// Stop things here!
	console.log("dispose to implement here...")
};

SensorMonitorServer._serveFile = function( filename, res )
{
	console.log("Serving file: " + filename);
	fs.readFile(filename, 'utf8',
		function(err, data)
			{
		  		if ( err )
		  		{
		    		SensorMonitorServer._createHTMLErrorResponse( res, 500, err );
		  		}
		  		else
		  		{
		  			res.writeHead(200); //{"Content-Type:": "application/json"});	// The server should certainly provide content type based on file extension
					res.write(data);
					res.end();
				}
			});
};

SensorMonitorServer._createHTMLErrorResponse = function( res, code, message )
{
	res.writeHead(code, {"Content-Type:": "text/html"});
	res.write(
		'<!DOCTYPE html>'+
		''+
		'    '+
		'        <meta charset="utf-8" />'+
		'        <title>Error</title>'+
		'    '+
		'    '+
		'
' + message + '
'+
		'    '+
		'');
	res.end();
};

/*
	Main
*/
function Main()
{
	var sensorMonitorServer = new SensorMonitorServer();

	//http://stackoverflow.com/questions/10021373/what-is-the-windows-equivalent-of-process-onsigint-in-node-js/14861513#14861513
	//http://stackoverflow.com/questions/6958780/quitting-node-js-gracefully
	if (process.platform === "win32")
	{
		var rl = require("readline").createInterface(
			{
				input: process.stdin,
				output: process.stdout
			});
		rl.on("SIGINT", function ()
			{
				process.emit("SIGINT");
			});
	}
	process.on("SIGINT", function ()
		{
			console.log("Stopping server...");
			sensorMonitorServer.dispose();
			process.exit();
		});
}

Main();

<|endoftext|>


<commit_before>/*
 Copyright 2008-present Shaiksphere, Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/**
 * A collection of useful static methods to deal with JavaScript URLs.
 *
 * @since 3.5.0
 *
 */
mindsmine.URL = class {
    /**
     * Returns true if the passed string is a valid URL, false otherwise.
     *
     * Example Usage:
     *
     *      mindsmine.URL.isValidURL("http://userid@example.com")       //  true
     *      mindsmine.URL.isValidURL("www.example.com/main.html")       //  false
     *
     * @see {@link @MDN_API_URI@/URL|URL}
     *
     * @param {String} url to check
     *
     * @returns {Boolean} if the string is a valid URL
     *
     * @since 3.5.0
     *
     */
    static isValidURL(url) {
        if (mindsmine.String.isEmpty(url)) {
            return false;
        }

        try {
            new URL(url);
        } catch (e) {
            return false;
        }

        return true;
    }

    /**
     * Appends content to the query string of a URL, handling logic for whether to place a question mark or ampersand.
     *
     * @see {@link @MDN_API_URI@/URL|URL}
     * @see {@link @MDN_API_URI@/URLSearchParams|URLSearchParams}
     *
     * @param {String} url The URL to append to.
     * @param {String} param The parameter key to append to the URL.
     * @param {Object} value The parameter value to append to the URL.
     *
     * @returns {String} The resulting URL
     *
     * @throws {TypeError} for Invalid URL or empty arguments
     *
     * @since 3.5.0
     *
     */
    static appendQuery(url, param, value) {
        if (!this.isValidURL(url)) {
            throw new TypeError("Fatal Error. 'url'. Invalid URL.");
        }

        if (mindsmine.String.isEmpty(param)) {
            throw new TypeError("Fatal Error. 'param'. @ERROR_PERMITTED_STRING@");
        }

        let _url = new URL(url);

        _url.searchParams.append(param, value);

        return _url.href;
    }
};
<commit_msg>Adding more URL specific functions<commit_after>/*
 Copyright 2008-present Shaiksphere, Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/**
 * A collection of useful static methods to deal with JavaScript URLs.
 *
 * @since 3.5.0
 *
 */
mindsmine.URL = class {
    /**
     * Returns true if the passed string is a valid URL, false otherwise.
     *
     * Example Usage:
     *
     *      mindsmine.URL.isValidURL("http://userid@example.com")       //  true
     *      mindsmine.URL.isValidURL("www.example.com/main.html")       //  false
     *
     * @see {@link @MDN_API_URI@/URL|URL}
     *
     * @param {String} url to check
     *
     * @returns {Boolean} if the string is a valid URL
     *
     * @since 3.5.0
     *
     */
    static isValidURL(url) {
        if (mindsmine.String.isEmpty(url)) {
            return false;
        }

        try {
            new URL(url);
        } catch (e) {
            return false;
        }

        return true;
    }

    /**
     * Appends content to the query string of a URL, handling logic for whether to place a question mark or ampersand.
     *
     * @see {@link @MDN_API_URI@/URL|URL}
     * @see {@link @MDN_API_URI@/URLSearchParams|URLSearchParams}
     *
     * @param {String} url The URL to append to.
     * @param {String} param The parameter key to append to the URL.
     * @param {Object} value The parameter value to append to the URL.
     *
     * @returns {String} The resulting URL
     *
     * @throws {TypeError} for Invalid URL or empty arguments
     *
     * @since 3.5.0
     *
     */
    static appendQuery(url, param, value = {}) {
        if (!this.isValidURL(url)) {
            throw new TypeError("Fatal Error. 'url'. Invalid URL.");
        }

        if (mindsmine.String.isEmpty(param)) {
            throw new TypeError("Fatal Error. 'param'. @ERROR_PERMITTED_STRING@");
        }

        let _url = new URL(url);

        _url.searchParams.append(param, encodeURIComponent(value));

        return _url.href;
    }

    /**
     * Returns an object containing the names of the search parameters as properties and values of the search parameters
     * as the property values.
     *
     * @param {String} url The URL to retrieve the search parameters from.
     *
     * @returns {Object|null} Returns null if no search parameters exist.
     *
     * @throws {TypeError} for Invalid URL or empty arguments
     *
     * @since 3.6.5
     *
     */
    static getAllQueryParameters(url) {
        if (!this.isValidURL(url)) {
            throw new TypeError("Fatal Error. 'url'. Invalid URL.");
        }

        let _url = new URL(url);

        if (!mindsmine.String.isEmpty(_url.search)) {
            let __queryParams = {};

            _url.search.substr(1).split("&").forEach(p => {
                const pairs = p.split("=");

                __queryParams[pairs[0]] = decodeURIComponent(pairs[1]);
            });

            return __queryParams;
        }

        return null;
    }

    /**
     * Retrieves the value of the query parameter.
     *
     * @param {String} url The URL to retrieve the search parameter from.
     * @param {String} queryParam The query parameter (case-sensitive) string whose value is to be retrieved.
     *
     * @returns {String|null} Returns null if unavailable.
     *
     * @throws {TypeError} for Invalid URL or empty arguments
     *
     * @since 3.6.5
     *
     */
    static getQueryParameter(url, queryParam) {
        if (!this.isValidURL(url)) {
            throw new TypeError("Fatal Error. 'url'. Invalid URL.");
        }

        if (mindsmine.String.isEmpty(queryParam)) {
            throw new TypeError("Fatal Error. 'queryParam'. @ERROR_PERMITTED_STRING@");
        }

        let __queryParams = this.getAllQueryParameters(url);

        if (__queryParams && __queryParams.hasOwnProperty(queryParam)) {
            return __queryParams[queryParam];
        }

        return null;
    }

    /**
     * Returns an object containing the names of the hash parameters as properties and values of the hash parameters
     * as the property values.
     *
     * If a hash parameter does not have an associated value, it is provided with a true value.
     *
     * @param {String} url The URL to retrieve the hash parameters from.
     *
     * @returns {Object|null} Returns null if no hash parameters exist.
     *
     * @throws {TypeError} for Invalid URL or empty arguments
     *
     * @since 3.6.5
     *
     */
    static getAllHashParameters(url) {
        if (!this.isValidURL(url)) {
            throw new TypeError("Fatal Error. 'url'. Invalid URL.");
        }

        let _url = new URL(url);

        if (!mindsmine.String.isEmpty(_url.hash)) {
            let __hashParams = {};

            _url.hash.substr(1).split("&").forEach(p => {
                const pairs = p.split("=");

                if (pairs.length === 1) {
                    __hashParams[pairs[0]] = true;
                } else {
                    __hashParams[pairs[0]] = decodeURIComponent(pairs[1]);
                }
            });

            return __hashParams;
        }

        return null;
    }

    /**
     * Retrieves the value of the hash parameter.
     *
     * @param {String} url The URL to retrieve the hash parameter from.
     * @param {String} hashParam The hash parameter (case-sensitive) string whose value is to be retrieved.
     *
     * @returns {String|null} Returns null if unavailable.
     *
     * @throws {TypeError} for Invalid URL or empty arguments
     *
     * @since 3.6.5
     *
     */
    static getHashParameter(url, hashParam) {
        if (!this.isValidURL(url)) {
            throw new TypeError("Fatal Error. 'url'. Invalid URL.");
        }

        if (mindsmine.String.isEmpty(hashParam)) {
            throw new TypeError("Fatal Error. 'hashParam'. @ERROR_PERMITTED_STRING@");
        }

        let __hashParams = this.getAllHashParameters();

        if (__hashParams && __hashParams.hasOwnProperty(hashParam)) {
            return __hashParams[hashParam];
        }

        return null;
    }
};
<|endoftext|>


<commit_before>/* global window */
import getElements from '../utilities/getElements';

// all the role=tab get aria-selected=false, get active class removed, hide all panels
const resetTabs = (tabs, tabpanels, activeClass) => {
  tabs.forEach((tab) => {
    const isStepper = tab.hasAttribute('data-sprk-stepper');
    tab.classList.remove(activeClass);
    if (isStepper) {
      const tabTrigger = tab.querySelector('[role="tab]"');
      tabTrigger.setAttribute('aria-selected', 'false');
    } else {
      tab.setAttribute('aria-selected', 'false');
    }
    tabpanels.forEach((panel) => {
      panel.classList.add('sprk-u-HideWhenJs');
    });
  });
};

// correct role=tab get aria-selected=true, get active class added, show correct panel
const setActiveTab = (tab, tabpanel, activeClass) => {
  const isStepper = tab.hasAttribute('data-sprk-stepper');
  tab.classList.add(activeClass);
  if (tabpanel) tabpanel.classList.remove('sprk-u-HideWhenJs');

  if (isStepper) {
    const tabTrigger = tab.querySelector('[role="tab]"');
    tabTrigger.setAttribute('aria-selected', 'true');
    tabTrigger.focus();
  } else {
    tab.setAttribute('aria-selected', 'true');
    tab.focus();
  }
};

const getActiveTabIndex = (tabs, activeClass) => {
  let activeIndex = null;
  tabs.forEach((tab, index) => {
    if (tab.classList.contains(activeClass)) {
      activeIndex = index;
    }
  });

  return activeIndex;
};

const advanceTab = (tabs, tabpanels, activeClass) => {
  const activeIndex = getActiveTabIndex(tabs, activeClass);
  resetTabs(tabs, tabpanels, activeClass);

  if (activeIndex + 1 <= tabs.length - 1) {
    setActiveTab(tabs[activeIndex + 1], tabpanels[activeIndex + 1], activeClass);
  } else {
    setActiveTab(tabs[0], tabpanels[0], activeClass);
  }
};

const retreatTab = (tabs, tabpanels, activeClass) => {
  const activeIndex = getActiveTabIndex(tabs, activeClass);

  resetTabs(tabs, tabpanels, activeClass);

  if (activeIndex - 1 === -1) {
    setActiveTab(tabs[tabs.length - 1], tabpanels[tabs.length - 1], activeClass);
  } else {
    setActiveTab(tabs[activeIndex - 1], tabpanels[activeIndex - 1], activeClass);
  }
};

const ariaOrientation = (width, element) => {
  // switch aria-orientation to vertical on mobile (based on _tabs.scss breakpoint)
  if (width <= 736) {
    element.setAttribute('aria-orientation', 'vertical');
  } else {
    element.setAttribute('aria-orientation', 'horizontal');
  }
};

const handleTabKeydown = (event, tabs, tabpanels, activeClass) => {
  const keys = {
    end: 35,
    home: 36,
    left: 37,
    up: 38,
    right: 39,
    down: 40,
    tab: 9,
  };

  if (event.keyCode === keys.left || event.keyCode === keys.up) {
    event.preventDefault();
    retreatTab(tabs, tabpanels, activeClass);
  } else if (event.keyCode === keys.right || event.keyCode === keys.down) {
    event.preventDefault();
    advanceTab(tabs, tabpanels, activeClass);
  } else if (event.keyCode === keys.tab) {
    event.preventDefault();
    tabpanels[getActiveTabIndex(tabs, activeClass)].focus();
  } else if (event.keyCode === keys.home) {
    event.preventDefault();
    resetTabs(tabs, tabpanels, activeClass);
    setActiveTab(tabs[0], tabpanels[0], activeClass);
  } else if (event.keyCode === keys.end) {
    event.preventDefault();
    resetTabs(tabs, tabpanels, activeClass);
    setActiveTab(tabs[tabs.length - 1], tabpanels[tabpanels.length - 1], activeClass);
  }
};

const bindUIEvents = (element) => {
  ariaOrientation(window.innerWidth, element);

  const tabContainer = element.querySelector('.sprk-c-Tabs__buttons');
  const tabs = element.querySelectorAll('[role="tab"]');
  const tabpanels = element.querySelectorAll('[role="tabpanel"]');
  const activeClass = 'sprk-c-Tabs__button--active';

  tabs.forEach((tab, index) => {
    tab.addEventListener('click', () => {
      resetTabs(tabs, tabpanels, activeClass);
      setActiveTab(tab, tabpanels[index], activeClass);
    });
  });

  tabContainer.addEventListener('keydown', (event) => {
    handleTabKeydown(event, tabs, tabpanels, activeClass);
  });
};

const tabs = () => {
  getElements('[data-sprk-navigation="tabs"]', bindUIEvents);
};

export {
  tabs,
  bindUIEvents,
  ariaOrientation,
  resetTabs,
  setActiveTab,
  handleTabKeydown,
  advanceTab,
  retreatTab,
  getActiveTabIndex,
};
<commit_msg>fix safari selector issue<commit_after>/* global window */
import getElements from '../utilities/getElements';

// all the role=tab get aria-selected=false, get active class removed, hide all panels
const resetTabs = (tabs, tabpanels, activeClass) => {
  tabs.forEach((tab) => {
    const isStepper = tab.hasAttribute('data-sprk-stepper');
    tab.classList.remove(activeClass);
    if (isStepper) {
      const tabTrigger = tab.querySelector('[role="tab"]');
      tabTrigger.setAttribute('aria-selected', 'false');
    } else {
      tab.setAttribute('aria-selected', 'false');
    }
    tabpanels.forEach((panel) => {
      panel.classList.add('sprk-u-HideWhenJs');
    });
  });
};

// correct role=tab get aria-selected=true, get active class added, show correct panel
const setActiveTab = (tab, tabpanel, activeClass) => {
  const isStepper = tab.hasAttribute('data-sprk-stepper');
  tab.classList.add(activeClass);
  if (tabpanel) tabpanel.classList.remove('sprk-u-HideWhenJs');

  if (isStepper) {
    const tabTrigger = tab.querySelector('[role="tab"]');
    tabTrigger.setAttribute('aria-selected', 'true');
    tabTrigger.focus();
  } else {
    tab.setAttribute('aria-selected', 'true');
    tab.focus();
  }
};

const getActiveTabIndex = (tabs, activeClass) => {
  let activeIndex = null;
  tabs.forEach((tab, index) => {
    if (tab.classList.contains(activeClass)) {
      activeIndex = index;
    }
  });

  return activeIndex;
};

const advanceTab = (tabs, tabpanels, activeClass) => {
  const activeIndex = getActiveTabIndex(tabs, activeClass);
  resetTabs(tabs, tabpanels, activeClass);

  if (activeIndex + 1 <= tabs.length - 1) {
    setActiveTab(tabs[activeIndex + 1], tabpanels[activeIndex + 1], activeClass);
  } else {
    setActiveTab(tabs[0], tabpanels[0], activeClass);
  }
};

const retreatTab = (tabs, tabpanels, activeClass) => {
  const activeIndex = getActiveTabIndex(tabs, activeClass);

  resetTabs(tabs, tabpanels, activeClass);

  if (activeIndex - 1 === -1) {
    setActiveTab(tabs[tabs.length - 1], tabpanels[tabs.length - 1], activeClass);
  } else {
    setActiveTab(tabs[activeIndex - 1], tabpanels[activeIndex - 1], activeClass);
  }
};

const ariaOrientation = (width, element) => {
  // switch aria-orientation to vertical on mobile (based on _tabs.scss breakpoint)
  if (width <= 736) {
    element.setAttribute('aria-orientation', 'vertical');
  } else {
    element.setAttribute('aria-orientation', 'horizontal');
  }
};

const handleTabKeydown = (event, tabs, tabpanels, activeClass) => {
  const keys = {
    end: 35,
    home: 36,
    left: 37,
    up: 38,
    right: 39,
    down: 40,
    tab: 9,
  };

  if (event.keyCode === keys.left || event.keyCode === keys.up) {
    event.preventDefault();
    retreatTab(tabs, tabpanels, activeClass);
  } else if (event.keyCode === keys.right || event.keyCode === keys.down) {
    event.preventDefault();
    advanceTab(tabs, tabpanels, activeClass);
  } else if (event.keyCode === keys.tab) {
    event.preventDefault();
    tabpanels[getActiveTabIndex(tabs, activeClass)].focus();
  } else if (event.keyCode === keys.home) {
    event.preventDefault();
    resetTabs(tabs, tabpanels, activeClass);
    setActiveTab(tabs[0], tabpanels[0], activeClass);
  } else if (event.keyCode === keys.end) {
    event.preventDefault();
    resetTabs(tabs, tabpanels, activeClass);
    setActiveTab(tabs[tabs.length - 1], tabpanels[tabpanels.length - 1], activeClass);
  }
};

const bindUIEvents = (element) => {
  ariaOrientation(window.innerWidth, element);

  const tabContainer = element.querySelector('.sprk-c-Tabs__buttons');
  const tabs = element.querySelectorAll('[role="tab"]');
  const tabpanels = element.querySelectorAll('[role="tabpanel"]');
  const activeClass = 'sprk-c-Tabs__button--active';

  tabs.forEach((tab, index) => {
    tab.addEventListener('click', () => {
      resetTabs(tabs, tabpanels, activeClass);
      setActiveTab(tab, tabpanels[index], activeClass);
    });
  });

  tabContainer.addEventListener('keydown', (event) => {
    handleTabKeydown(event, tabs, tabpanels, activeClass);
  });
};

const tabs = () => {
  getElements('[data-sprk-navigation="tabs"]', bindUIEvents);
};

export {
  tabs,
  bindUIEvents,
  ariaOrientation,
  resetTabs,
  setActiveTab,
  handleTabKeydown,
  advanceTab,
  retreatTab,
  getActiveTabIndex,
};
<|endoftext|>


<commit_before>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import { COMMENTS } from '../consts/literals';

const
	comments = Object.keys(COMMENTS);

/**
 * Returns a comment type for the specified position of a string
 *
 * @param {string} str - source string
 * @param {number} pos - position
 * @return {(string|boolean)}
 */
export function getCommentType(str, pos) {
	if (!str) {
		return false;
	}

	for (let i = 0; i < comments.length; i++) {
		const
			el = comments[i],
			chunk = str.substr(pos, el.length);

		if (COMMENTS[chunk] && chunk === el) {
			return el || false;
		}
	}
}

/**
 * Returns a string of property concatenation for the specified value
 *
 * @param {string} val - source value
 * @return {string}
 */
export function concatProp(val) {
	return val[0] === '[' ? val : `.${val}`;
}
<commit_msg>:wrench:<commit_after>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import { COMMENTS } from '../consts/literals';

const
	comments = Object.keys(COMMENTS);

/**
 * Returns a comment type for the specified position of a string
 *
 * @param {string} str - source string
 * @param {number} pos - position
 * @return {(string|boolean)}
 */
export function getCommentType(str, pos) {
	if (!str) {
		return false;
	}

	for (let i = 0; i < comments.length; i++) {
		const
			el = comments[i],
			chunk = str.substr(pos, el.length);

		if (COMMENTS[chunk] && chunk === el) {
			return el;
		}
	}

	return false;
}

/**
 * Returns a string of property concatenation for the specified value
 *
 * @param {string} val - source value
 * @return {string}
 */
export function concatProp(val) {
	return val[0] === '[' ? val : `.${val}`;
}
<|endoftext|>


<commit_before>import React, { Component } from "react";
import { Button } from "reactstrap";
import { Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap";
import { UncontrolledTooltip } from "reactstrap";

import AceEditor from "react-ace";
import brace from "brace";
import "brace/mode/json";
import "brace/mode/text";
import "brace/ext/searchbox";
import "brace/theme/github";

import "./InstanceBtnSettings.css";

class InstanceBtnSettings extends Component {
  constructor(props) {
    super(props);
    this.state = {
      modalIsOpen: false,
      modalIsFS: false,
      code: ""
    };
    this.currentCode = "";
    this.toggleIsOpen = this.toggleIsOpen.bind(this);
    this.toggleIsFS = this.toggleIsFS.bind(this);
    this.onCodeChange = this.onCodeChange.bind(this);
  }

  toggleIsOpen() {
    this.setState({
      modalIsOpen: !this.state.modalIsOpen
    });
  }

  toggleIsFS() {
    this.setState({
      modalIsFS: !this.state.modalIsFS,
      code: this.currentCode
    });

    // need also to resize the ACE editor of it will truncate the text
    // we also re-focus to the edit area
    setImmediate(
      function() {
        this.refs[this.props.instance.technicalName + "-ace"].editor.resize();
        this.refs[this.props.instance.technicalName + "-ace"].editor.focus();
      }.bind(this)
    );
  }

  onCodeChange(newValue) {
    // Do not store the new value in the store now because it will
    // re-render the react component and it will generates stranges error
    // in the ace editor.
    // This is why we use the currentCode temp variable and push it in
    // the store just when switching to fullscreen (because re-render will occurs).
    this.currentCode = newValue;
  }

  render() {
    return (

        <Button
          color="link"
          className={this.props.classNameBtn + " ezmaster-a-cog"}
          onClick={this.toggleIsOpen}
        >

        </Button>

        <Modal
          isOpen={this.state.modalIsOpen}
          toggle={this.toggleIsOpen}
          className={this.state.modalIsFS ? "modal-fullscreen" : ""}
        >
          <ModalHeader toggle={this.toggleIsOpen}>
            Edit the {this.props.instance.technicalName}{" "}
            configuration{" "}
          </ModalHeader>
          <ModalBody>
            <AceEditor
              mode={Math.random() > 0.5 ? "text" : "json"}
              theme="github"
              width="100%"
              height=""
              focus={true}
              wrapEnabled={true}
              tabSize={2}
              ref={this.props.instance.technicalName + "-ace"}
              name={this.props.instance.technicalName + "-ace"}
              enableBasicAutocompletion={true}
              enableLiveAutocompletion={true}
              enableSnippets={true}
              fontSize={"1.5rem"}
              onChange={this.onCodeChange}
              value={this.state.code}
            />
          </ModalBody>
          <ModalFooter>
            <Button
              color="link"
              onClick={this.toggleIsFS}
              className="modal-fullscreen-btn"
            >

            </Button>
            <UncontrolledTooltip
              placement="top"
              target={this.props.instance.technicalName + "-settings-fs"}
            >
              Edit the configuration in fullscreen mode.
            </UncontrolledTooltip>
            <Button color="primary" onClick={this.toggleIsOpen}>
              XXXX
            </Button>{" "}
            <Button color="secondary" onClick={this.toggleIsOpen}>
              YYY
            </Button>
          </ModalFooter>
        </Modal>

        <UncontrolledTooltip
          placement="top"
          target={this.props.instance.technicalName + "-cog"}
        >
          Edit settings of {this.props.instance.technicalName}
        </UncontrolledTooltip>

    );
  }
}

export default InstanceBtnSettings;
<commit_msg>add better FS toggle icon<commit_after>import React, { Component } from "react";
import { Button } from "reactstrap";
import { Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap";
import { UncontrolledTooltip } from "reactstrap";

import AceEditor from "react-ace";
import brace from "brace";
import "brace/mode/json";
import "brace/mode/text";
import "brace/ext/searchbox";
import "brace/theme/github";

import "./InstanceBtnSettings.css";

class InstanceBtnSettings extends Component {
  constructor(props) {
    super(props);
    this.state = {
      modalIsOpen: false,
      modalIsFS: false,
      code: ""
    };
    this.currentCode = "";
    this.toggleIsOpen = this.toggleIsOpen.bind(this);
    this.toggleIsFS = this.toggleIsFS.bind(this);
    this.onCodeChange = this.onCodeChange.bind(this);
  }

  toggleIsOpen() {
    this.setState({
      modalIsOpen: !this.state.modalIsOpen
    });
  }

  toggleIsFS() {
    this.setState({
      modalIsFS: !this.state.modalIsFS,
      code: this.currentCode
    });

    // need also to resize the ACE editor of it will truncate the text
    // we also re-focus to the edit area
    setImmediate(
      function() {
        this.refs[this.props.instance.technicalName + "-ace"].editor.resize();
        this.refs[this.props.instance.technicalName + "-ace"].editor.focus();
      }.bind(this)
    );
  }

  onCodeChange(newValue) {
    // Do not store the new value in the store now because it will
    // re-render the react component and it will generates stranges error
    // in the ace editor.
    // This is why we use the currentCode temp variable and push it in
    // the store just when switching to fullscreen (because re-render will occurs).
    this.currentCode = newValue;
  }

  render() {
    return (

        <Button
          color="link"
          className={this.props.classNameBtn + " ezmaster-a-cog"}
          onClick={this.toggleIsOpen}
        >

        </Button>

        <Modal
          isOpen={this.state.modalIsOpen}
          toggle={this.toggleIsOpen}
          className={this.state.modalIsFS ? "modal-fullscreen" : ""}
        >
          <ModalHeader toggle={this.toggleIsOpen}>
            Edit the {this.props.instance.technicalName}{" "}
            configuration{" "}
          </ModalHeader>
          <ModalBody>
            <AceEditor
              mode={Math.random() > 0.5 ? "text" : "json"}
              theme="github"
              width="100%"
              height=""
              focus={true}
              wrapEnabled={true}
              tabSize={2}
              ref={this.props.instance.technicalName + "-ace"}
              name={this.props.instance.technicalName + "-ace"}
              enableBasicAutocompletion={true}
              enableLiveAutocompletion={true}
              enableSnippets={true}
              fontSize={"1.5rem"}
              onChange={this.onCodeChange}
              value={this.state.code}
            />
          </ModalBody>
          <ModalFooter>
            <Button
              color="link"
              onClick={this.toggleIsFS}
              className="modal-fullscreen-btn"
            >

            </Button>
            <UncontrolledTooltip
              placement="top"
              target={this.props.instance.technicalName + "-settings-fs"}
            >
              Edit the configuration in fullscreen mode.
            </UncontrolledTooltip>
            <Button color="primary" onClick={this.toggleIsOpen}>
              Update
            </Button>{" "}
            <Button color="secondary" onClick={this.toggleIsOpen}>
              Cancel
            </Button>
          </ModalFooter>
        </Modal>

        <UncontrolledTooltip
          placement="top"
          target={this.props.instance.technicalName + "-cog"}
        >
          Edit settings of {this.props.instance.technicalName}
        </UncontrolledTooltip>

    );
  }
}

export default InstanceBtnSettings;
<|endoftext|>