<commit_before>window.onload = function() {
    /**
     * 主题颜色交互
     */
    var inColor = document.getElementById('color0');
    var colorGroup = document.getElementById('colorGroup');
    var colorShow = document.getElementById('colorShow');
    var picker = {
        init: function(){
            /**
             * 触发显示
             */
            var self = this
            self.focus(inColor);

            /**
             * hover事件
             */
            var themeCors = colorGroup.getElementsByTagName('li');
            var objEach = Array.prototype.forEach;
            objEach.call(themeCors,function(ele){
                self.corhover(ele);
                self.corselect(ele);
            });

            document.addEventListener('click',function(event){
                var eleid = event.target.id;
                var isColorWrap = eleid != 'color0' || eleid != 'colorGroup';
                // console.log(isColorWrap);
                eleid != 'color0' && eleid != 'colorGroup' ? colorGroup.style.display = 'none' : '';
            },false);
        },
        init_ui: function(){
            var progress = document.querySelectorAll('#tab-panel-1 .progressbar');
            for(var i=0; i<progress.length; i++){
                progress[i].style.width = '50%';
            }
        },
        focus: function(inele){
            var self = this;
            inele.addEventListener('focus', function(event){
                /**
                 * show colorGroup
                 */
                var et = event.target || event.srcElement;
                var getX = et.offsetLeft;
                var getY = et.offsetTop;
                var getWidth = parseInt(getComputedStyle(et,null).getPropertyValue('width'));
                var setLeft = getX + getWidth + 'px';
                var setTop = getY + 'px';

                var setStyle = {
                    display: "block",
                    left: setLeft,
                    top: setTop
                };
                for(var key in setStyle) {
                    colorGroup.style[key] = setStyle[key];
                }
                event.stopPropagation();
            });
        },
        corhover: function(ele){
            ele.addEventListener('mouseenter', function(event){
                var eleCor = ele.getAttribute('data-color');
                var eleRGB = 'rgb(' + eleCor + ')';
                colorShow.style.backgroundColor = eleRGB;
            },true);
        },
        corselect: function(ele){
            var self = this;
            ele.addEventListener('click', function(event){
                var eleCor = ele.getAttribute('data-color');
                var eleRGB = 'rgb(' + eleCor + ')';
                colorGroup.style.display = 'none';
                inColor.value = eleCor;
                self.uichange(eleRGB);

                event.stopPropagation();
            },true);

        },
        uichange: function(selColor){
            var uiObj = {
                "nav": "#tab-panel-1 .u-navbar-inverse",
                "button": "#tab-panel-1 .u-button",
                "progress": "#tab-panel-1 .progressbar",
                "switch": "#tab-panel-1 .u-switch-track",
                "pagination":"#tab-panel-1 #pagination .active a"
            };

            for(var key in uiObj) {
                var catUis = document.querySelectorAll(uiObj[key]);
                for(var i = 0; i<catUis.length; i++){
                    catUis[i].style.backgroundColor = selColor;
                }
            }

        }
    };
    picker.init_ui();
    picker.init();

    /**
     * 选中元素,执行ajax
     */
    var cs = {
        init: function(){

            this.selAll();
            this.charSend();
        },

        Dom: {
            downBottom: document.getElementById('button'),
            downTop: document.getElementById('buttonTop'),
            blockWrap: document.querySelectorAll('#tab-panel-2 .color-whole-div'),
        },

        /**
         * 定制 - 选中元素
         */
        selAll: function() {
            var contWrap = this.Dom.blockWrap;
            var selFun = function(ele, index, ary) {
                var selWrap = ele.querySelectorAll('.tree-parent')[0];
                var subCheckbox = ele.querySelectorAll('li.u-checkbox');
                selWrap.addEventListener('click', function() {
                    var isCheck = u.hasClass(this,"is-checked");

                    if(isCheck) {
                        subCheckbox.forEach(function(subele){
                            u.addClass(subele,'is-checked');
                        })
                    } else {
                        subCheckbox.forEach(function(subele){
                            u.removeClass(subele,'is-checked');
                        })
                    }

                })
            };
            contWrap.forEach(selFun);
        },

        /**
         * 数据整理
         */
        charFun: function(event) {
            var dataJson = {};
            var checkedUnit = document.querySelectorAll('#tab-panel-2 .coreModel li.is-checked');
            var checkedData = function(checkele) {
                // data-catlog对应不同类别组件，如polyfill,css组件
                var checkClass = checkele.getAttribute('data-catlog');
                if(!dataJson[checkClass]){
                    dataJson[checkClass] = [];
                }
                // 添加选中的组件进入相应类别
                var checkFile = checkele.getAttribute('data-file');
                dataJson[checkClass].push(checkFile);
            };
            checkedUnit.forEach(checkedData);

            // 增加主题颜色
            var colorVal = inColor.value;
            dataJson.themeColor = colorVal;
            console.log(dataJson);

            var options={
                hasback:true//不含有遮罩层
            };
            u.showLoader(options);

            $.ajax({
                type: 'post',
                dataType: 'text',
                data: dataJson,
                url: '/package',
                success: function (patch) {
                    u.hideLoader();
                    location.href = patch;
                },
                error: function (patch) {
                    console.error(patch);
                }
            });

            event.stopPropagation();

        },
        /**
         * 提交事件
         */
        charSend: function() {
            var self = this;
            var downAry = [];
            downAry.push(this.Dom.downBottom);
            downAry.push(this.Dom.downTop);
            var submitEvent = function(ele){
                ele.addEventListener('click',self.charFun);
            };
            downAry.forEach(submitEvent);
        }

    };
    cs.init();

}<commit_msg>fix: 定制下载border颜色问题<commit_after>window.onload = function() {
    /**
     * 主题颜色交互
     */
    var inColor = document.getElementById('color0');
    var colorGroup = document.getElementById('colorGroup');
    var colorShow = document.getElementById('colorShow');
    var picker = {
        init: function(){
            /**
             * 触发显示
             */
            var self = this
            self.focus(inColor);

            /**
             * hover事件
             */
            var themeCors = colorGroup.getElementsByTagName('li');
            var objEach = Array.prototype.forEach;
            objEach.call(themeCors,function(ele){
                self.corhover(ele);
                self.corselect(ele);
            });

            document.addEventListener('click',function(event){
                var eleid = event.target.id;
                var isColorWrap = eleid != 'color0' || eleid != 'colorGroup';
                // console.log(isColorWrap);
                eleid != 'color0' && eleid != 'colorGroup' ? colorGroup.style.display = 'none' : '';
            },false);
        },
        init_ui: function(){
            var progress = document.querySelectorAll('#tab-panel-1 .progressbar');
            for(var i=0; i<progress.length; i++){
                progress[i].style.width = '50%';
            }
        },
        focus: function(inele){
            var self = this;
            inele.addEventListener('focus', function(event){
                /**
                 * show colorGroup
                 */
                var et = event.target || event.srcElement;
                var getX = et.offsetLeft;
                var getY = et.offsetTop;
                var getWidth = parseInt(getComputedStyle(et,null).getPropertyValue('width'));
                var setLeft = getX + getWidth + 'px';
                var setTop = getY + 'px';

                var setStyle = {
                    display: "block",
                    left: setLeft,
                    top: setTop
                };
                for(var key in setStyle) {
                    colorGroup.style[key] = setStyle[key];
                }
                event.stopPropagation();
            });
        },
        corhover: function(ele){
            ele.addEventListener('mouseenter', function(event){
                var eleCor = ele.getAttribute('data-color');
                var eleRGB = 'rgb(' + eleCor + ')';
                colorShow.style.backgroundColor = eleRGB;
            },true);
        },
        corselect: function(ele){
            var self = this;
            ele.addEventListener('click', function(event){
                var eleCor = ele.getAttribute('data-color');
                var eleRGB = 'rgb(' + eleCor + ')';
                colorGroup.style.display = 'none';
                inColor.value = eleCor;
                self.uichange(eleRGB);

                event.stopPropagation();
            },true);

        },
        uichange: function(selColor){
            var uiObj = {
                "nav": "#tab-panel-1 .u-navbar-inverse",
                "button": "#tab-panel-1 .u-button",
                "progress": "#tab-panel-1 .progressbar",
                "switch": "#tab-panel-1 .u-switch-track",
                "pagination":"#tab-panel-1 #pagination .active a"
            };

            for(var key in uiObj) {
                var catUis = document.querySelectorAll(uiObj[key]);
                for(var i = 0; i<catUis.length; i++){
                    catUis[i].style.backgroundColor = selColor;
                    catUis[i].style.borderColor = selColor;
                }
            }

        }
    };
    picker.init_ui();
    picker.init();

    /**
     * 选中元素,执行ajax
     */
    var cs = {
        init: function(){

            this.selAll();
            this.charSend();
        },

        Dom: {
            downBottom: document.getElementById('button'),
            downTop: document.getElementById('buttonTop'),
            blockWrap: document.querySelectorAll('#tab-panel-2 .color-whole-div'),
        },

        /**
         * 定制 - 选中元素
         */
        selAll: function() {
            var contWrap = this.Dom.blockWrap;
            var selFun = function(ele, index, ary) {
                var selWrap = ele.querySelectorAll('.tree-parent')[0];
                var subCheckbox = ele.querySelectorAll('li.u-checkbox');
                selWrap.addEventListener('click', function() {
                    var isCheck = u.hasClass(this,"is-checked");

                    if(isCheck) {
                        subCheckbox.forEach(function(subele){
                            u.addClass(subele,'is-checked');
                        })
                    } else {
                        subCheckbox.forEach(function(subele){
                            u.removeClass(subele,'is-checked');
                        })
                    }

                })
            };
            contWrap.forEach(selFun);
        },

        /**
         * 数据整理
         */
        charFun: function(event) {
            var dataJson = {};
            var checkedUnit = document.querySelectorAll('#tab-panel-2 .coreModel li.is-checked');
            var checkedData = function(checkele) {
                // data-catlog对应不同类别组件，如polyfill,css组件
                var checkClass = checkele.getAttribute('data-catlog');
                if(!dataJson[checkClass]){
                    dataJson[checkClass] = [];
                }
                // 添加选中的组件进入相应类别
                var checkFile = checkele.getAttribute('data-file');
                dataJson[checkClass].push(checkFile);
            };
            checkedUnit.forEach(checkedData);

            // 增加主题颜色
            var colorVal = inColor.value;
            dataJson.themeColor = colorVal;
            console.log(dataJson);

            var options={
                hasback:true//不含有遮罩层
            };
            u.showLoader(options);

            $.ajax({
                type: 'post',
                dataType: 'text',
                data: dataJson,
                url: '/package',
                success: function (patch) {
                    u.hideLoader();
                    location.href = patch;
                },
                error: function (patch) {
                    console.error(patch);
                }
            });

            event.stopPropagation();

        },
        /**
         * 提交事件
         */
        charSend: function() {
            var self = this;
            var downAry = [];
            downAry.push(this.Dom.downBottom);
            downAry.push(this.Dom.downTop);
            var submitEvent = function(ele){
                ele.addEventListener('click',self.charFun);
            };
            downAry.forEach(submitEvent);
        }

    };
    cs.init();

}
<|endoftext|>


<commit_before>/* @flow weak */

/**
 * OfflineMobile Android Index
 * Sustainable Solutions (NZ) Ltd. 2016
 */

import React, {
  Component,
  StyleSheet,
  Text,
  TextInput,
  View,
} from 'react-native';

import {
  Cell,
  DataTable,
  Expansion,
  Header,
  HeaderCell,
  Row,
} from '../widgets/DataTable';

import { getItemQuantity } from '../utilities';
import { ListView } from 'realm/react-native';
import globalStyles from '../globalStyles';

export default class StockPage extends Component {
  constructor(props) {
    super(props);
    const dataSource = new ListView.DataSource({
      rowHasChanged: (row1, row2) => row1 !== row2,
    });
    this.state = {
      dataSource: dataSource,
      items: props.database.objects('Item'),
      searchTerm: '',
      sortBy: 'name',
      reverseSort: false,
    };
    this.componentWillMount = this.componentWillMount.bind(this);
    this.onColumnSort = this.onColumnSort.bind(this);
    this.onSearchChange = this.onSearchChange.bind(this);
    this.refreshData = this.refreshData.bind(this);
    this.renderExpansion = this.renderExpansion.bind(this);
    this.renderHeader = this.renderHeader.bind(this);
    this.renderRow = this.renderRow.bind(this);
  }

  componentWillMount() {
    const data = this.state.items.sorted(this.state.sortBy);
    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(data),
    });
  }

  onSearchChange(event) {
    const term = event.nativeEvent.text;
    this.setState({
      searchTerm: term,
    });
    this.refreshData();
  }

  onColumnSort(sortBy) {
    if (this.state.sortBy === sortBy) {
      this.setState({ reverseSort: !this.state.reverseSort });
    } else {
      this.setState({ sortBy: sortBy });
    }
    this.refreshData();
  }

  refreshData() {
    const { items, sortBy, dataSource, reverseSort, searchTerm } = this.state;
    const data = items.filtered(`name CONTAINS[c] "${searchTerm}"`).sorted(sortBy, reverseSort);
    this.setState({ dataSource: dataSource.cloneWithRows(data) });
  }

  renderHeader() {
    return (
      <Header style={globalStyles.dataTableHeader}>
        <HeaderCell
          style={[globalStyles.dataTableCell, globalStyles.dataTableHeaderCell]}
          textStyle={[globalStyles.text, localStyles.text]}
          onPress={() => this.onColumnSort('code')}
          width={COLUMN_WIDTHS[0]}
          text={'ITEM CODE'}
        />
        <HeaderCell
          style={[globalStyles.dataTableCell, globalStyles.dataTableHeaderCell]}
          textStyle={[globalStyles.text, localStyles.text]}
          width={COLUMN_WIDTHS[1]}
          onPress={() => this.onColumnSort('name')}
          text={'ITEM NAME'}
        />
        <HeaderCell
          style={[globalStyles.dataTableHeaderCell]}
          textStyle={[globalStyles.text, localStyles.text]}
          width={COLUMN_WIDTHS[2]}
          text={'STOCK ON HAND'}
        />
      </Header>
    );
  }

  renderExpansion(item) {
    return (
      <Expansion>
        <View style={{ flex: COLUMN_WIDTHS[0] }} />
        <View style={{ flex: COLUMN_WIDTHS[1] + COLUMN_WIDTHS[2], flexDirection: 'row' }}>
          <View style={{ flex: 1, flexDirection: 'column', justifyContent: 'space-around' }}>
            <Text style={[globalStyles.text, localStyles.text]}>
              Category: {item.category.name}
            </Text>
            <Text style={[globalStyles.text, localStyles.text]}>
              Department: {item.department.name}
            </Text>
          </View>
          <View style={{ flex: 1, flexDirection: 'column', justifyContent: 'space-around' }}>
            <Text style={[globalStyles.text, localStyles.text]}>
              Number of batches: {item.lines.length}
            </Text>
            <Text style={[globalStyles.text, localStyles.text]}>
              Nearest expiry: value
            </Text>
          </View>
        </View>
      </Expansion>
    );
  }

  renderRow(item) {
    return (
      <Row style={globalStyles.dataTableRow} renderExpansion={() => this.renderExpansion(item)}>
        <Cell
          style={globalStyles.dataTableCell}
          textStyle={[globalStyles.text, localStyles.text]}
          width={COLUMN_WIDTHS[0]}
        >
          {item.code}
        </Cell>
        <Cell
          style={globalStyles.dataTableCell}
          textStyle={[globalStyles.text, localStyles.text]}
          width={COLUMN_WIDTHS[1]}
        >
          {item.name}
        </Cell>
        <Cell
          style={[globalStyles.dataTableCell, localStyles.rightMostCell]}
          textStyle={[globalStyles.text, localStyles.text]}
          width={COLUMN_WIDTHS[2]}
        >
          {getItemQuantity(item)}
        </Cell>
      </Row>
    );
  }

  render() {
    return (
      <View style={globalStyles.pageContentContainer}>
        <View style={localStyles.horizontalContainer}>
          <TextInput
            style={globalStyles.searchBar}
            onChange={(event) => this.onSearchChange(event)}
            placeholder="Search"
          />
        </View>
        <DataTable
          style={globalStyles.dataTable}
          listViewStyle={globalStyles.container}
          dataSource={this.state.dataSource}
          renderRow={this.renderRow}
          renderHeader={this.renderHeader}
        />
      </View>
    );
  }
}

StockPage.propTypes = {
  database: React.PropTypes.object,
  style: View.propTypes.style,
};
const COLUMN_WIDTHS = [1.3, 7.2, 1.6];
const localStyles = StyleSheet.create({
  horizontalContainer: {
    flexDirection: 'row',
  },
  text: {
    fontSize: 20,
    marginLeft: 20,
    textAlign: 'left',
  },
  rightMostCell: {
    borderRightWidth: 0,
  },
  dataTable: {
    flex: 1,
  },
});
<commit_msg>setState with one property now one line<commit_after>/* @flow weak */

/**
 * OfflineMobile Android Index
 * Sustainable Solutions (NZ) Ltd. 2016
 */

import React, {
  Component,
  StyleSheet,
  Text,
  TextInput,
  View,
} from 'react-native';

import {
  Cell,
  DataTable,
  Expansion,
  Header,
  HeaderCell,
  Row,
} from '../widgets/DataTable';

import { getItemQuantity } from '../utilities';
import { ListView } from 'realm/react-native';
import globalStyles from '../globalStyles';

export default class StockPage extends Component {
  constructor(props) {
    super(props);
    const dataSource = new ListView.DataSource({
      rowHasChanged: (row1, row2) => row1 !== row2,
    });
    this.state = {
      dataSource: dataSource,
      items: props.database.objects('Item'),
      searchTerm: '',
      sortBy: 'name',
      reverseSort: false,
    };
    this.componentWillMount = this.componentWillMount.bind(this);
    this.onColumnSort = this.onColumnSort.bind(this);
    this.onSearchChange = this.onSearchChange.bind(this);
    this.refreshData = this.refreshData.bind(this);
    this.renderExpansion = this.renderExpansion.bind(this);
    this.renderHeader = this.renderHeader.bind(this);
    this.renderRow = this.renderRow.bind(this);
  }

  componentWillMount() {
    const data = this.state.items.sorted(this.state.sortBy);
    this.setState({ dataSource: this.state.dataSource.cloneWithRows(data) });
  }

  onSearchChange(event) {
    const term = event.nativeEvent.text;
    this.setState({ searchTerm: term });
    this.refreshData();
  }

  onColumnSort(sortBy) {
    if (this.state.sortBy === sortBy) {
      this.setState({ reverseSort: !this.state.reverseSort });
    } else {
      this.setState({ sortBy: sortBy });
    }
    this.refreshData();
  }

  refreshData() {
    const { items, sortBy, dataSource, reverseSort, searchTerm } = this.state;
    const data = items.filtered(`name CONTAINS[c] "${searchTerm}"`).sorted(sortBy, reverseSort);
    this.setState({ dataSource: dataSource.cloneWithRows(data) });
  }

  renderHeader() {
    return (
      <Header style={globalStyles.dataTableHeader}>
        <HeaderCell
          style={[globalStyles.dataTableCell, globalStyles.dataTableHeaderCell]}
          textStyle={[globalStyles.text, localStyles.text]}
          onPress={() => this.onColumnSort('code')}
          width={COLUMN_WIDTHS[0]}
          text={'ITEM CODE'}
        />
        <HeaderCell
          style={[globalStyles.dataTableCell, globalStyles.dataTableHeaderCell]}
          textStyle={[globalStyles.text, localStyles.text]}
          width={COLUMN_WIDTHS[1]}
          onPress={() => this.onColumnSort('name')}
          text={'ITEM NAME'}
        />
        <HeaderCell
          style={[globalStyles.dataTableHeaderCell]}
          textStyle={[globalStyles.text, localStyles.text]}
          width={COLUMN_WIDTHS[2]}
          text={'STOCK ON HAND'}
        />
      </Header>
    );
  }

  renderExpansion(item) {
    return (
      <Expansion>
        <View style={{ flex: COLUMN_WIDTHS[0] }} />
        <View style={{ flex: COLUMN_WIDTHS[1] + COLUMN_WIDTHS[2], flexDirection: 'row' }}>
          <View style={{ flex: 1, flexDirection: 'column', justifyContent: 'space-around' }}>
            <Text style={[globalStyles.text, localStyles.text]}>
              Category: {item.category.name}
            </Text>
            <Text style={[globalStyles.text, localStyles.text]}>
              Department: {item.department.name}
            </Text>
          </View>
          <View style={{ flex: 1, flexDirection: 'column', justifyContent: 'space-around' }}>
            <Text style={[globalStyles.text, localStyles.text]}>
              Number of batches: {item.lines.length}
            </Text>
            <Text style={[globalStyles.text, localStyles.text]}>
              Nearest expiry: value
            </Text>
          </View>
        </View>
      </Expansion>
    );
  }

  renderRow(item) {
    return (
      <Row style={globalStyles.dataTableRow} renderExpansion={() => this.renderExpansion(item)}>
        <Cell
          style={globalStyles.dataTableCell}
          textStyle={[globalStyles.text, localStyles.text]}
          width={COLUMN_WIDTHS[0]}
        >
          {item.code}
        </Cell>
        <Cell
          style={globalStyles.dataTableCell}
          textStyle={[globalStyles.text, localStyles.text]}
          width={COLUMN_WIDTHS[1]}
        >
          {item.name}
        </Cell>
        <Cell
          style={[globalStyles.dataTableCell, localStyles.rightMostCell]}
          textStyle={[globalStyles.text, localStyles.text]}
          width={COLUMN_WIDTHS[2]}
        >
          {getItemQuantity(item)}
        </Cell>
      </Row>
    );
  }

  render() {
    return (
      <View style={globalStyles.pageContentContainer}>
        <View style={localStyles.horizontalContainer}>
          <TextInput
            style={globalStyles.searchBar}
            onChange={(event) => this.onSearchChange(event)}
            placeholder="Search"
          />
        </View>
        <DataTable
          style={globalStyles.dataTable}
          listViewStyle={globalStyles.container}
          dataSource={this.state.dataSource}
          renderRow={this.renderRow}
          renderHeader={this.renderHeader}
        />
      </View>
    );
  }
}

StockPage.propTypes = {
  database: React.PropTypes.object,
  style: View.propTypes.style,
};
const COLUMN_WIDTHS = [1.3, 7.2, 1.6];
const localStyles = StyleSheet.create({
  horizontalContainer: {
    flexDirection: 'row',
  },
  text: {
    fontSize: 20,
    marginLeft: 20,
    textAlign: 'left',
  },
  rightMostCell: {
    borderRightWidth: 0,
  },
  dataTable: {
    flex: 1,
  },
});
<|endoftext|>


<commit_before>import { ActionsObservable } from 'redux-observable';
import {
  EXECUTE_CELL,
  ERROR_EXECUTING,
  CLEAR_OUTPUTS,
  UPDATE_CELL_STATUS,
  UPDATE_CELL_PAGERS,
 } from '../../../src/notebook/constants';

import { executeCell } from '../../../src/notebook/actions';
import {
  executeCellStream,
  executeCellEpic,
  updateDisplayEpic,
  createExecuteRequest,
  msgSpecToNotebookFormat,
  createPagerActions,
  createSourceUpdateAction,
  createCellAfterAction,
  createCellStatusAction,
  createExecuteCellStream,
  updateCellNumberingAction,
  createErrorActionObservable,
} from '../../../src/notebook/epics/execute';

const Immutable = require('immutable');
const Rx = require('rxjs/Rx');

const sinon = require('sinon');
const chai = require('chai');
const chaiImmutable = require('chai-immutable');

const expect = chai.expect;
chai.use(chaiImmutable);

const Observable = Rx.Observable;

describe('executeCell', () => {
  it('returns an executeCell action', () => {
    expect(executeCell('0-0-0-0', 'import random; random.random()'))
      .to.deep.equal({
        type: EXECUTE_CELL,
        id: '0-0-0-0',
        source: 'import random; random.random()',
      });
  });
});

describe('executeCellStream', () => {
  // TODO: Refactor executeCelStream into separate testable observables
  it('is entirely too insane for me to test this well right this second', (done) => {
    const frontendToShell = new Rx.Subject();
    const shellToFrontend = new Rx.Subject();
    const mockShell = Rx.Subject.create(frontendToShell, shellToFrontend);
    const mockIOPub = new Rx.Subject();

    const channels = {
      shell: mockShell,
      iopub: mockIOPub,
    };

    // Expect message to have been sent
    frontendToShell
      .subscribe(msg => {
        expect(msg.header.msg_type).to.equal('execute_request');
        expect(msg.content.code).to.equal('import this');
      });

    const action$ = executeCellStream(channels, '0', 'import this');

    action$
      .bufferCount(3)
      .subscribe(messages => {
        expect(messages).to.deep.equal([
          // TODO: Order doesn't actually matter here
          { type: 'CLEAR_OUTPUTS', id: '0' },
          { type: 'UPDATE_CELL_STATUS', id: '0', status: 'busy' },
          { type: 'UPDATE_CELL_PAGERS', id: '0', pagers: Immutable.List() },
        ]);
        done(); // TODO: Make sure message check above is called
      });
  });

  it('outright rejects a lack of channels.shell and iopub', (done) => {
    const obs = executeCellStream({}, '0', 'woo');
    obs.subscribe(null, (err) => {
      expect(err.message).to.equal('kernel not connected');
      done();
    });
  });
});

describe('createExecuteRequest', () => {
  it('creates an execute_request message', () => {
    const code = 'print("test")';
    const executeRequest = createExecuteRequest(code);

    expect(executeRequest.content.code).to.equal(code);
    expect(executeRequest.header.msg_type).to.equal('execute_request');
  });
});

describe('msgSpecToNotebookFormat', () => {
  it('converts a message to the notebook format', () => {
    const msg = { content: { data: 'test' }, header: { msg_type: 'test_header' } };
    const notebookSpecMsg = msgSpecToNotebookFormat(msg);

    expect(notebookSpecMsg).to.have.property('output_type');
    expect(notebookSpecMsg).to.have.property('data');
    expect(notebookSpecMsg.output_type).to.equal('test_header');
  });
});

describe('createPagerActions', () => {
  it('emits actions to set pagers', (done) => {
    const msgObs = Rx.Observable.from([{
      source: 'page',
      data: { 'text/html': 'this is a test' },
    }]);

    const pagerAction$ = createPagerActions('1', msgObs);

    pagerAction$.subscribe((action) => {
      const expected = [{ source: 'page', data: { 'text/html': 'this is a test' } }];
      expect(action.id).to.equal('1');
      expect(action.pagers.toJS()).to.deep.equal(expected);
      done();
    });
  });
});

describe('createCellAfterAction', () => {
  it('emits a createCellAfter action', (done) => {
    const msgObs = Rx.Observable.from([{
      source: 'set_next_input',
      text: 'This is some test text.',
      replace: false,
    }]);

    const cellAction$ = createCellAfterAction('1', msgObs);

    cellAction$.subscribe((action) => {
      expect(action.id).to.equal('1');
      done();
    });
  });
});

describe('createCellStatusAction', () => {
  it('emits an updateCellStatus action', (done) => {
    const msgObs = Rx.Observable.from([{
      header: {
        msg_id: '123',
        msg_type: 'status',
      },
      parent_header: {},
      content: {
        execution_state: 'idle',
      },
      metadata: {},
    }]);

    const cellAction$ = createCellStatusAction('1', msgObs);

    cellAction$.subscribe((action) => {
      expect(action.id).to.equal('1');
      expect(action.status).to.equal('idle');
      done();
    });
  });
});

describe('updateCellNumberingAction', () => {
  it('emits updateCellExecutionCount action', (done) => {
    const msgObs = Rx.Observable.from([{
      header: {
        msg_id: '123',
        msg_type: 'execute_input',
      },
      parent_header: {},
      content: {
        execution_count: 3,
      },
      metadata: {},
    }]);

    const cellAction$ = updateCellNumberingAction('1', msgObs);

    cellAction$.subscribe((action) => {
      expect(action.id).to.equal('1');
      expect(action.count).to.equal(3);
      done();
    });
  });
});

describe('createSourceUpdateAction', () => {
  it('emits updateCellSource action', (done) => {
    const msgObs = Rx.Observable.from([{
      source: 'set_next_input',
      text: 'This is some test text.',
      replace: true,
    }]);

    const cellAction$ = createSourceUpdateAction('1', msgObs);

    cellAction$.subscribe((action) => {
      expect(action.source).to.equal('This is some test text.');
      done();
    });
  });
});
describe('createExecuteCellStream', () => {
  it('errors if the kernel is not connected in create', (done) => {
    const frontendToShell = new Rx.Subject();
    const shellToFrontend = new Rx.Subject();
    const mockShell = Rx.Subject.create(frontendToShell, shellToFrontend);
    const mockIOPub = new Rx.Subject();
    const store = { getState() { return this.state; },
      state: {
        app: {
          executionState: 'not connected',
          channels: { iopub: mockIOPub,
            shell: mockShell,
          },
          notificationSystem: {
            addNotification: sinon.spy(),
          },
        },
      },
    };
    const action$ = ActionsObservable.of({ type: 'EXECUTE_CELL' });
    const observable = createExecuteCellStream(action$, store, 'source', 'id');
    const actionBuffer = [];
    observable.subscribe(
        (x) => actionBuffer.push(x.payload),
        (err) => expect.fail(err, null),
        () => {
          expect(actionBuffer).to.deep.equal(['Kernel not connected!']);
          done();
        },
      );
  });
  it('doesnt complete but does push until abort action', (done) => {
    const frontendToShell = new Rx.Subject();
    const shellToFrontend = new Rx.Subject();
    const mockShell = Rx.Subject.create(frontendToShell, shellToFrontend);
    const mockIOPub = new Rx.Subject();
    const store = { getState() { return this.state; },
      state: {
        app: {
          executionState: 'connected',
          channels: { iopub: mockIOPub,
            shell: mockShell,
          },
          notificationSystem: {
            addNotification: sinon.spy(),
          },
        },
      },
    };
    const action$ = ActionsObservable.of({ type: 'EXECUTE_CELL', id: 'id' },
                                         { type: 'EXECUTE_CELL', id: 'id_2' },
                                         { type: 'ABORT_EXECUTION', id: 'id_2' },
                                         { type: 'EXECUTE_CELL', id: 'id' });
    const observable = createExecuteCellStream(action$, store, 'source', 'id');
    const actionBuffer = [];
    observable.subscribe(
      (x) => actionBuffer.push(x.type),
      (err) => expect.fail(err, null),
    );
    expect(actionBuffer).to.deep.equal([CLEAR_OUTPUTS, UPDATE_CELL_STATUS, UPDATE_CELL_PAGERS]);
    done();
  });
});

describe('executeCellEpic', () => {
  const store = { getState() { return this.state; },
    state: {
      app: {
        executionState: 'idle',
        channels: 'errorInExecuteCellObservable',
        notificationSystem: {
          addNotification: sinon.spy(),
        },
        token: 'blah',
      },
    },
  };
  it('Errors on a bad action', (done) => {
    const badInput$ = Observable.of({ type: EXECUTE_CELL });
    const badAction$ = new ActionsObservable(badInput$);
    const actionBuffer = [];
    const responseActions = executeCellEpic(badAction$, store).catch(error => {
      expect(error.message).to.equal('execute cell needs an id');
    });
    responseActions.subscribe(
      // Every action that goes through should get stuck on an array
      (x) => actionBuffer.push(x.type),
      (err) => expect.fail(err, null), // It should not error in the stream
      () => {
        expect(actionBuffer).to.deep.equal([ERROR_EXECUTING]);
        done();
      },
    );
  });
  it('Errors on an action where source not a string', (done) => {
    const badInput$ = Observable.of(executeCell('id', 2));
    const badAction$ = new ActionsObservable(badInput$);
    const actionBuffer = [];
    const responseActions = executeCellEpic(badAction$, store).catch(error => {
      expect(error.message).to.equal('execute cell needs source string');
    });
    responseActions.subscribe(
      // Every action that goes through should get stuck on an array
      (x) => actionBuffer.push(x.type),
      (err) => expect.fail(err, null), // It should not error in the stream
      () => {
        expect(actionBuffer).to.deep.equal([ERROR_EXECUTING]);
        done();
      },
    );
  });
  it('Runs an epic with the appropriate flow with good action', (done) => {
    const input$ = Observable.of(executeCell('id', 'source'));
    const action$ = new ActionsObservable(input$);
    const actionBuffer = [];
    const responseActions = executeCellEpic(action$, store);
    responseActions.subscribe(
      // Every action that goes through should get stuck on an array
      (x) => actionBuffer.push(x.payload.toString()),
      (err) => expect.fail(err, null), // It should not error in the stream
      () => {
        expect(actionBuffer).to.deep.equal(['Error: kernel not connected']);
        done();
      },
    );
  });
});

describe('updateDisplayEpic', () => {
  it('creates an epic that handles update_display_data messages', (done) => {
    const messages = [
      // Should be processed
      { header: { msg_type: 'update_display_data' },
        content: {
          data: { 'text/html': '<marquee>wee</marquee>' },
          transient: { display_id: '1234' },
        },
      },
      // Should not be processed
      { header: { msg_type: 'display_data' },
        content: {
          data: { 'text/html': '<marquee>wee</marquee>' },
          transient: { display_id: '5555' },
        },
      },
      { header: { msg_type: 'ignored' },
        content: {
          data: { 'text/html': '<marquee>wee</marquee>' },
        },
      },
      // Should be processed
      { header: { msg_type: 'update_display_data' },
        content: {
          data: { 'text/plain': 'i am text' },
          transient: { display_id: 'here' },
        },
      },
    ];

    const channels = {
      iopub: Observable.from(messages),
    };
    const kernel$ = Observable.of({ type: 'NEW_KERNEL', channels });
    const action$ = new ActionsObservable(kernel$);

    const epic = updateDisplayEpic(action$);

    const responseActions = [];
    epic.subscribe(
      (action) => responseActions.push(action),
      (err) => { throw err; },
      () => {
        expect(responseActions).to.deep.equal([
          { type: 'UPDATE_DISPLAY',
            output: {
              output_type: 'display_data',
              data: { 'text/html': '<marquee>wee</marquee>' },
              transient: { display_id: '1234' },
            },
          },
          { type: 'UPDATE_DISPLAY',
            output: {
              output_type: 'display_data',
              data: { 'text/plain': 'i am text' },
              transient: { display_id: 'here' },
            },
          },
        ]);
        done();
      },
    );
  });
});

describe('createErrorActionObservable', () => {
  it('returns a function that creates an observable', (done) => {
    const func = createErrorActionObservable('TEST_IT');
    const err = new Error('HEY');
    const obs = func(err);

    obs.subscribe(x => {
      expect(x.type).to.equal('TEST_IT');
      expect(x.payload).to.equal(err);
      expect(x.error).to.equal(true);
    }, (e) => { throw e; },
    () => {
      done();
    });
  });
});
<commit_msg>test: execute cell now recovers from errors<commit_after>import { ActionsObservable } from 'redux-observable';
import {
  EXECUTE_CELL,
  ERROR_EXECUTING,
  CLEAR_OUTPUTS,
  UPDATE_CELL_STATUS,
  UPDATE_CELL_PAGERS,
 } from '../../../src/notebook/constants';

import { executeCell } from '../../../src/notebook/actions';
import {
  executeCellStream,
  executeCellEpic,
  updateDisplayEpic,
  createExecuteRequest,
  msgSpecToNotebookFormat,
  createPagerActions,
  createSourceUpdateAction,
  createCellAfterAction,
  createCellStatusAction,
  createExecuteCellStream,
  updateCellNumberingAction,
  createErrorActionObservable,
} from '../../../src/notebook/epics/execute';

const Immutable = require('immutable');
const Rx = require('rxjs/Rx');

const sinon = require('sinon');
const chai = require('chai');
const chaiImmutable = require('chai-immutable');

const expect = chai.expect;
chai.use(chaiImmutable);

const Observable = Rx.Observable;

describe('executeCell', () => {
  it('returns an executeCell action', () => {
    expect(executeCell('0-0-0-0', 'import random; random.random()'))
      .to.deep.equal({
        type: EXECUTE_CELL,
        id: '0-0-0-0',
        source: 'import random; random.random()',
      });
  });
});

describe('executeCellStream', () => {
  // TODO: Refactor executeCelStream into separate testable observables
  it('is entirely too insane for me to test this well right this second', (done) => {
    const frontendToShell = new Rx.Subject();
    const shellToFrontend = new Rx.Subject();
    const mockShell = Rx.Subject.create(frontendToShell, shellToFrontend);
    const mockIOPub = new Rx.Subject();

    const channels = {
      shell: mockShell,
      iopub: mockIOPub,
    };

    // Expect message to have been sent
    frontendToShell
      .subscribe(msg => {
        expect(msg.header.msg_type).to.equal('execute_request');
        expect(msg.content.code).to.equal('import this');
      });

    const action$ = executeCellStream(channels, '0', 'import this');

    action$
      .bufferCount(3)
      .subscribe(messages => {
        expect(messages).to.deep.equal([
          // TODO: Order doesn't actually matter here
          { type: 'CLEAR_OUTPUTS', id: '0' },
          { type: 'UPDATE_CELL_STATUS', id: '0', status: 'busy' },
          { type: 'UPDATE_CELL_PAGERS', id: '0', pagers: Immutable.List() },
        ]);
        done(); // TODO: Make sure message check above is called
      });
  });

  it('outright rejects a lack of channels.shell and iopub', (done) => {
    const obs = executeCellStream({}, '0', 'woo');
    obs.subscribe(null, (err) => {
      expect(err.message).to.equal('kernel not connected');
      done();
    });
  });
});

describe('createExecuteRequest', () => {
  it('creates an execute_request message', () => {
    const code = 'print("test")';
    const executeRequest = createExecuteRequest(code);

    expect(executeRequest.content.code).to.equal(code);
    expect(executeRequest.header.msg_type).to.equal('execute_request');
  });
});

describe('msgSpecToNotebookFormat', () => {
  it('converts a message to the notebook format', () => {
    const msg = { content: { data: 'test' }, header: { msg_type: 'test_header' } };
    const notebookSpecMsg = msgSpecToNotebookFormat(msg);

    expect(notebookSpecMsg).to.have.property('output_type');
    expect(notebookSpecMsg).to.have.property('data');
    expect(notebookSpecMsg.output_type).to.equal('test_header');
  });
});

describe('createPagerActions', () => {
  it('emits actions to set pagers', (done) => {
    const msgObs = Rx.Observable.from([{
      source: 'page',
      data: { 'text/html': 'this is a test' },
    }]);

    const pagerAction$ = createPagerActions('1', msgObs);

    pagerAction$.subscribe((action) => {
      const expected = [{ source: 'page', data: { 'text/html': 'this is a test' } }];
      expect(action.id).to.equal('1');
      expect(action.pagers.toJS()).to.deep.equal(expected);
      done();
    });
  });
});

describe('createCellAfterAction', () => {
  it('emits a createCellAfter action', (done) => {
    const msgObs = Rx.Observable.from([{
      source: 'set_next_input',
      text: 'This is some test text.',
      replace: false,
    }]);

    const cellAction$ = createCellAfterAction('1', msgObs);

    cellAction$.subscribe((action) => {
      expect(action.id).to.equal('1');
      done();
    });
  });
});

describe('createCellStatusAction', () => {
  it('emits an updateCellStatus action', (done) => {
    const msgObs = Rx.Observable.from([{
      header: {
        msg_id: '123',
        msg_type: 'status',
      },
      parent_header: {},
      content: {
        execution_state: 'idle',
      },
      metadata: {},
    }]);

    const cellAction$ = createCellStatusAction('1', msgObs);

    cellAction$.subscribe((action) => {
      expect(action.id).to.equal('1');
      expect(action.status).to.equal('idle');
      done();
    });
  });
});

describe('updateCellNumberingAction', () => {
  it('emits updateCellExecutionCount action', (done) => {
    const msgObs = Rx.Observable.from([{
      header: {
        msg_id: '123',
        msg_type: 'execute_input',
      },
      parent_header: {},
      content: {
        execution_count: 3,
      },
      metadata: {},
    }]);

    const cellAction$ = updateCellNumberingAction('1', msgObs);

    cellAction$.subscribe((action) => {
      expect(action.id).to.equal('1');
      expect(action.count).to.equal(3);
      done();
    });
  });
});

describe('createSourceUpdateAction', () => {
  it('emits updateCellSource action', (done) => {
    const msgObs = Rx.Observable.from([{
      source: 'set_next_input',
      text: 'This is some test text.',
      replace: true,
    }]);

    const cellAction$ = createSourceUpdateAction('1', msgObs);

    cellAction$.subscribe((action) => {
      expect(action.source).to.equal('This is some test text.');
      done();
    });
  });
});
describe('createExecuteCellStream', () => {
  it('errors if the kernel is not connected in create', (done) => {
    const frontendToShell = new Rx.Subject();
    const shellToFrontend = new Rx.Subject();
    const mockShell = Rx.Subject.create(frontendToShell, shellToFrontend);
    const mockIOPub = new Rx.Subject();
    const store = { getState() { return this.state; },
      state: {
        app: {
          executionState: 'not connected',
          channels: { iopub: mockIOPub,
            shell: mockShell,
          },
          notificationSystem: {
            addNotification: sinon.spy(),
          },
        },
      },
    };
    const action$ = ActionsObservable.of({ type: 'EXECUTE_CELL' });
    const observable = createExecuteCellStream(action$, store, 'source', 'id');
    const actionBuffer = [];
    observable.subscribe(
        (x) => actionBuffer.push(x.payload),
        (err) => expect.fail(err, null),
        () => {
          expect(actionBuffer).to.deep.equal(['Kernel not connected!']);
          done();
        },
      );
  });
  it('doesnt complete but does push until abort action', (done) => {
    const frontendToShell = new Rx.Subject();
    const shellToFrontend = new Rx.Subject();
    const mockShell = Rx.Subject.create(frontendToShell, shellToFrontend);
    const mockIOPub = new Rx.Subject();
    const store = { getState() { return this.state; },
      state: {
        app: {
          executionState: 'connected',
          channels: { iopub: mockIOPub,
            shell: mockShell,
          },
          notificationSystem: {
            addNotification: sinon.spy(),
          },
        },
      },
    };
    const action$ = ActionsObservable.of({ type: 'EXECUTE_CELL', id: 'id' },
                                         { type: 'EXECUTE_CELL', id: 'id_2' },
                                         { type: 'ABORT_EXECUTION', id: 'id_2' },
                                         { type: 'EXECUTE_CELL', id: 'id' });
    const observable = createExecuteCellStream(action$, store, 'source', 'id');
    const actionBuffer = [];
    observable.subscribe(
      (x) => actionBuffer.push(x.type),
      (err) => expect.fail(err, null),
    );
    expect(actionBuffer).to.deep.equal([CLEAR_OUTPUTS, UPDATE_CELL_STATUS, UPDATE_CELL_PAGERS]);
    done();
  });
});

describe('executeCellEpic', () => {
  const store = { getState() { return this.state; },
    state: {
      app: {
        executionState: 'idle',
        channels: 'errorInExecuteCellObservable',
        notificationSystem: {
          addNotification: sinon.spy(),
        },
        token: 'blah',
      },
    },
  };
  it('Errors on a bad action', (done) => {
    // Make one hot action
    const badInput$ = Observable.of({ type: EXECUTE_CELL }).share();
    const badAction$ = new ActionsObservable(badInput$);
    const responseActions = executeCellEpic(badAction$, store).catch(error => {
      expect(error.message).to.equal('execute cell needs an id');
    });
    responseActions.subscribe(
      // Every action that goes through should get stuck on an array
      (x) => {
        expect(x.type).to.equal(ERROR_EXECUTING);
        done();
      },
      (err) => expect.fail(err, null), // It should not error in the stream
      () => {
        expect.fail('It should not complete');
      },
    );
  });
  it('Errors on an action where source not a string', (done) => {
    const badInput$ = Observable.of(executeCell('id', 2));
    const badAction$ = new ActionsObservable(badInput$);
    const actionBuffer = [];
    const responseActions = executeCellEpic(badAction$, store).catch(error => {
      expect(error.message).to.equal('execute cell needs source string');
    });
    responseActions.subscribe(
      // Every action that goes through should get stuck on an array
      (x) => actionBuffer.push(x.type),
      (err) => expect.fail(err, null), // It should not error in the stream
      () => {
        expect(actionBuffer).to.deep.equal([ERROR_EXECUTING]);
        done();
      },
    );
  });
  it('Runs an epic with the appropriate flow with good action', (done) => {
    const input$ = Observable.of(executeCell('id', 'source'));
    const action$ = new ActionsObservable(input$);
    const actionBuffer = [];
    const responseActions = executeCellEpic(action$, store);
    responseActions.subscribe(
      // Every action that goes through should get stuck on an array
      (x) => actionBuffer.push(x.payload.toString()),
      (err) => expect.fail(err, null), // It should not error in the stream
      () => {
        expect(actionBuffer).to.deep.equal(['Error: kernel not connected']);
        done();
      },
    );
  });
});

describe('updateDisplayEpic', () => {
  it('creates an epic that handles update_display_data messages', (done) => {
    const messages = [
      // Should be processed
      { header: { msg_type: 'update_display_data' },
        content: {
          data: { 'text/html': '<marquee>wee</marquee>' },
          transient: { display_id: '1234' },
        },
      },
      // Should not be processed
      { header: { msg_type: 'display_data' },
        content: {
          data: { 'text/html': '<marquee>wee</marquee>' },
          transient: { display_id: '5555' },
        },
      },
      { header: { msg_type: 'ignored' },
        content: {
          data: { 'text/html': '<marquee>wee</marquee>' },
        },
      },
      // Should be processed
      { header: { msg_type: 'update_display_data' },
        content: {
          data: { 'text/plain': 'i am text' },
          transient: { display_id: 'here' },
        },
      },
    ];

    const channels = {
      iopub: Observable.from(messages),
    };
    const kernel$ = Observable.of({ type: 'NEW_KERNEL', channels });
    const action$ = new ActionsObservable(kernel$);

    const epic = updateDisplayEpic(action$);

    const responseActions = [];
    epic.subscribe(
      (action) => responseActions.push(action),
      (err) => { throw err; },
      () => {
        expect(responseActions).to.deep.equal([
          { type: 'UPDATE_DISPLAY',
            output: {
              output_type: 'display_data',
              data: { 'text/html': '<marquee>wee</marquee>' },
              transient: { display_id: '1234' },
            },
          },
          { type: 'UPDATE_DISPLAY',
            output: {
              output_type: 'display_data',
              data: { 'text/plain': 'i am text' },
              transient: { display_id: 'here' },
            },
          },
        ]);
        done();
      },
    );
  });
});

describe('createErrorActionObservable', () => {
  it('returns a function that creates an observable', (done) => {
    const func = createErrorActionObservable('TEST_IT');
    const err = new Error('HEY');
    const obs = func(err);

    obs.subscribe(x => {
      expect(x.type).to.equal('TEST_IT');
      expect(x.payload).to.equal(err);
      expect(x.error).to.equal(true);
    }, (e) => { throw e; },
    () => {
      done();
    });
  });
});
<|endoftext|>


<commit_before>'use strict';

var DataGrid  = require('../DataGrid')
var React     = require('react/addons')
var TestUtils = React.addons.TestUtils

var TABLE_CLASS         = 'z-table'
var ROW_CLASS           = 'z-row'
var CELL_CLASS			= 'z-cell'
var CELL_TEXT_CLASS		= 'z-text'

var testUtils = require('../utils')

var render        = testUtils.render
var findWithClass = testUtils.findWithClass
var tryWithClass  = testUtils.tryWithClass
var generateMockData = testUtils.generateMockData

var columns = [
    { name: 'index', title: '#', width: 50 },
    { name: 'firstName'},
    { name: 'lastName'  },
    { name: 'city' },
    { name: 'email' }
];

describe('DataGrid Test Suite -  Row Style',function() {

	it('check rowStyle as object works',function() {

		var ROW_COLOR = 'blue'
		var data = generateMockData({type : 'local', len : 3})

		var rowStyle = {color : ROW_COLOR}

		// table
        var table = render(
            DataGrid({
                idProperty: 'id',
                dataSource: data,
                columns   : columns,
                style     : {height:400},
                rowStyle  : rowStyle
            })
        );

        var rows = tryWithClass(table,ROW_CLASS)
		rows.forEach(function(row) {
			window.getComputedStyle(row.getDOMNode()).getPropertyValue('color').should.equal(ROW_COLOR)
        })

	})

	it('check rowStyle as function works',function() {

		var ROW_COLOR = 'blue'
		var ROW_COLOR_INDEX = 4
		var data = generateMockData({type : 'local', len : 10})

		var rowStyle = function(data, props){
			var style = {}
			if (props.index % ROW_COLOR_INDEX == 0){
				style.color = ROW_COLOR
			}
			return style
		}

		// table
        var table = render(
            DataGrid({
                idProperty: 'id',
                dataSource: data,
                columns   : columns,
                style     : {height:400},
                rowStyle  : rowStyle
            })
        );

        var rows = tryWithClass(table,ROW_CLASS)
		rows.forEach(function(row,index) {
			if(index % ROW_COLOR_INDEX == 0)
				window.getComputedStyle(row.getDOMNode()).getPropertyValue('color').should.equal(ROW_COLOR)
        })

	})

	it('check column style works',function() {

		var COL_COLOR = 'blue'
		var COL_COLOR_INDEX = 4
		var data = generateMockData({type : 'local', len : 10})

		columns = [
		    { name: 'index', title: '#', width: 50 },
		    { name: 'firstName'},
		    { name: 'lastName'  },
		    { name: 'city' },
		    { name: 'email', style : { color : COL_COLOR } }
		]

		// table
        var table = render(
            DataGrid({
                idProperty: 'id',
                dataSource: data,
                columns   : columns,
                style     : {height:400}
            })
        );

        var rows = tryWithClass(table,ROW_CLASS)
		rows.forEach(function(row) {
			var cells = tryWithClass(row,CELL_CLASS)
			cells.forEach(function(cell,index) {
				if(index == COL_COLOR_INDEX)
					window.getComputedStyle(cell.getDOMNode()).getPropertyValue('color').should.equal(COL_COLOR)
			})
        })

	})

})<commit_msg>Added textAlign check test case<commit_after>'use strict';

var DataGrid  = require('../DataGrid')
var React     = require('react/addons')
var TestUtils = React.addons.TestUtils

var TABLE_CLASS         = 'z-table'
var ROW_CLASS           = 'z-row'
var CELL_CLASS			= 'z-cell'
var CELL_TEXT_CLASS		= 'z-text'
var ALIGN_RIGHT_CLASS	= 'z-align-right'

var testUtils = require('../utils')

var render        = testUtils.render
var findWithClass = testUtils.findWithClass
var tryWithClass  = testUtils.tryWithClass
var generateMockData = testUtils.generateMockData

var columns = [
    { name: 'index', title: '#', width: 50 },
    { name: 'firstName'},
    { name: 'lastName'  },
    { name: 'city' },
    { name: 'email' }
];

describe('DataGrid Test Suite -  Row Style',function() {

	it('check rowStyle as object works',function() {

		var ROW_COLOR = 'blue'
		var data = generateMockData({type : 'local', len : 3})

		var rowStyle = {color : ROW_COLOR}

		// table
        var table = render(
            DataGrid({
                idProperty: 'id',
                dataSource: data,
                columns   : columns,
                style     : {height:400},
                rowStyle  : rowStyle
            })
        );

        var rows = tryWithClass(table,ROW_CLASS)
		rows.forEach(function(row) {
			window.getComputedStyle(row.getDOMNode()).getPropertyValue('color').should.equal(ROW_COLOR)
        })

	})

	it('check rowStyle as function works',function() {

		var ROW_COLOR = 'blue'
		var ROW_COLOR_INDEX = 4
		var data = generateMockData({type : 'local', len : 10})

		var rowStyle = function(data, props){
			var style = {}
			if (props.index % ROW_COLOR_INDEX == 0){
				style.color = ROW_COLOR
			}
			return style
		}

		// table
        var table = render(
            DataGrid({
                idProperty: 'id',
                dataSource: data,
                columns   : columns,
                style     : {height:400},
                rowStyle  : rowStyle
            })
        );

        var rows = tryWithClass(table,ROW_CLASS)
		rows.forEach(function(row,index) {
			if(index % ROW_COLOR_INDEX == 0)
				window.getComputedStyle(row.getDOMNode()).getPropertyValue('color').should.equal(ROW_COLOR)
        })

	})

	it('check column style works',function() {

		var COL_COLOR = 'blue'
		var COL_COLOR_INDEX = 4
		var data = generateMockData({type : 'local', len : 10})

		columns = [
		    { name: 'index', title: '#', width: 50 },
		    { name: 'firstName'},
		    { name: 'lastName'  },
		    { name: 'city' },
		    { name: 'email', style : { color : COL_COLOR } }
		]

		// table
        var table = render(
            DataGrid({
                idProperty: 'id',
                dataSource: data,
                columns   : columns,
                style     : {height:400}
            })
        );

        var rows = tryWithClass(table,ROW_CLASS)
		rows.forEach(function(row) {
			var cells = tryWithClass(row,CELL_CLASS)
			cells.forEach(function(cell,index) {
				if(index == COL_COLOR_INDEX)
					window.getComputedStyle(cell.getDOMNode()).getPropertyValue('color').should.equal(COL_COLOR)
			})
        })

	})

	it('check column textAlign works',function() {

		var TEXT_ALIGN = 'right'
		var COL_ALIGN_INDEX = 2
		var data = generateMockData({type : 'local', len : 10})

		columns = [
		    { name: 'index', title: '#', width: 50 },
		    { name: 'firstName'},
		    { name: 'lastName' , textAlign : TEXT_ALIGN },
		    { name: 'city' },
		    { name: 'email'}
		]

		// table
        var table = render(
            DataGrid({
                idProperty: 'id',
                dataSource: data,
                columns   : columns,
                style     : {height:400}
            })
        );

		var rows = tryWithClass(table,ROW_CLASS)
		rows.forEach(function(row) {
			var cells = tryWithClass(row,CELL_CLASS)
			cells.forEach(function(cell,index) {
				if(index == COL_ALIGN_INDEX)
					cell.props.className.should.containEql(ALIGN_RIGHT_CLASS)
			})
        })

	})

})<|endoftext|>


<commit_before>import React, { Fragment, Component } from 'react'
import {
  Box,
  Flex,
  Container,
  Heading,
  Text,
  Section,
  Link,
  Card,
  Button,
  Icon
} from '@hackclub/design-system'
import Helmet from 'react-helmet'
import Nav from 'components/Nav'
import IconButton from 'components/IconButton'
import Form from 'components/challenge/Form'
import Ended from 'components/challenge/Ended'
import Posts from 'components/challenge/Posts'
import { Modal, Overlay, CloseButton } from 'components/Modal'
import { dt, tinyDt } from 'helpers'
import { isEmpty } from 'lodash'
import api from 'api'
import storage from 'storage'

class Help extends Component {
  state = { active: false }

  toggleRules = () => {
    this.setState(state => ({ active: !state.active }))
  }

  // Render a modal for challenge rules on button press
  render() {
    if (this.state.active) {
      return (
        <Fragment>
          <Modal align="left" my={4} p={[3, 4]}>
            <CloseButton onClick={this.toggleRules} />
            <Heading.h2>Challenge Rules</Heading.h2>
            <Text
              f={2}
              mt={3}
              color="info"
              py={2}
              px={3}
              bg="blue.0"
              style={{ borderRadius: 4 }}
            >
              For this challenge, your entry must be hosted on{' '}
              <Link href="https://repl.it" target="_blank" bold>
                repl.it
              </Link>.
            </Text>
            <Text f={2} my={3}>
              Challenge strictly follows Hack Club’s{' '}
              <Link href="https://conduct.hackclub.com" target="_blank">
                Code of Conduct
              </Link>. Anything breaking our Code of Conduct (ex. voter fraud)
              and contestants found cheating can be temporarily or permanently
              banned.
            </Text>
            <Text f={2}>
              If you think anyone has violated our Conduct or cheating policy,
              please reach out to us confidentially at{' '}
              <Link href="mailto:challenge@hackclub.com">
                challenge@hackclub.com
              </Link>.
            </Text>
          </Modal>
          <Overlay onClick={this.toggleRules} />
        </Fragment>
      )
    }
    return (
      <IconButton
        name="flag"
        size={16}
        children="Rules"
        inverted
        f={2}
        onClick={this.toggleRules}
        {...this.props}
      />
    )
  }
}

const Header = Section.withComponent('header').extend`
  padding-top: 0 !important;
  background-color: ${props => props.theme.colors.red[5]};
  background-image: linear-gradient(
    32deg,
    ${props => props.theme.colors.pink[5]},
    ${props => props.theme.colors.red[5]}
  );
  clip-path: polygon(0% 0%, 100% 0, 100% 100%, 0 98%);
  ${props => props.theme.mediaQueries.md} {
    clip-path: polygon(0% 0%, 100% 0, 100% 100%, 0 92%);
  }
`

const HeaderContainer = Container.extend`
  display: grid;
  grid-gap: ${props => props.theme.space[3]}px;
  ${props => props.theme.mediaQueries.md} {
    grid-template-columns: repeat(2, 1fr);
    grid-gap: ${props => props.theme.space[4]}px;
  }
`

const HeaderCard = Card.extend`
  min-height: 128px;
  position: relative;
  h2,
  p {
    color: ${props => props.theme.colors.black} !important;
  }
`

const Title = Flex.extend`
  border-bottom: 1px solid ${props => props.theme.colors.smoke};
`

const title = 'Hack Club Challenge'
const desc =
  'Join Hack Club’s high school coding challenge. Submit your entry to compete in our monthly programming contest and win prizes.'
const img = 'https://hackclub.com/challenge.png'

export default class extends Component {
  state = { status: 'loading' }

  componentDidMount() {
    if (storage.get('authToken')) {
      api
        .get(`v1/users/current`)
        .then(user => {
          this.setState({ status: 'success', userId: user.id })
        })
        .catch(err => {
          if (err.status === 401) {
            this.setState({ status: 'needsToAuth' })
          } else {
            this.setState({ status: 'error' })
          }
        })
    } else {
      this.setState({ status: 'needsToAuth' })
    }
  }

  render() {
    const { data } = this.props
    const { userId, status } = this.state
    if (isEmpty(data)) return null
    const challenge = data.publicJson
    const ended = Date.parse(new Date()) > Date.parse(challenge.end)
    return (
      <Fragment>
        <Helmet
          title={title}
          meta={[
            { name: 'description', content: desc },
            { name: 'twitter:title', content: title },
            { name: 'twitter:description', content: desc },
            { name: 'twitter:image', content: img },
            { property: 'og:title', content: title },
            { property: 'og:description', content: desc },
            { property: 'og:image', content: img },
            { property: 'og:url', content: 'https://hackclub.com/challenge' }
          ]}
        />

          <HeaderContainer maxWidth={56} p={0} mt={[0, 3]} align="left">
            <Box align={['center', null, 'right']}>
              <Text mb={[-2, -24]} f={3} bold caps>
                Hack Club
              </Text>
              <Heading.h1 f={[6, 7]} my={0}>
                Challenge
              </Heading.h1>
              <Heading.h2 f={3} mt={2} mb={3} regular>
                Join Hack Club’s high school coding contest
              </Heading.h2>
              <HeaderCard boxShadowSize="md" p={3} bg="pink.0" align="left">
                <Text f={2}>
                  🌟 Challenge of the month: {challenge.name}

                  🎁 {challenge.description}

                  📈 Upvote your favorites!

                  🏅 Top-voted 3 websites by {dt(challenge.end)} win!
                </Text>
              </HeaderCard>
            </Box>
            <HeaderCard boxShadowSize="md" p={3} bg="pink.0">
              <Form challengeId={challenge.id} status={status} />
            </HeaderCard>
          </HeaderContainer>

        <Container maxWidth={48} pt={4} pb={5} px={3}>
          {ended && <Ended />}
          <Title align="center" pb={2}>
            <Heading.h2 color="black" f={[4, 5]}>
              Submissions
            </Heading.h2>
            <Text.span f={2} color="muted" ml={3}>
              {tinyDt(challenge.start)}–{tinyDt(challenge.end)}
            </Text.span>
            <Help ml="auto" />
          </Title>
          <Posts challengeId={challenge.id} userId={userId} status={status} />
        </Container>
      </Fragment>
    )
  }
}
export const pageQuery = graphql`
  query ChallengeQuery {
    publicJson {
      id
      name
      description
      start
      end
    }
  }
`
<commit_msg>Challenges aren't monthly<commit_after>import React, { Fragment, Component } from 'react'
import {
  Box,
  Flex,
  Container,
  Heading,
  Text,
  Section,
  Link,
  Card,
  Button,
  Icon
} from '@hackclub/design-system'
import Helmet from 'react-helmet'
import Nav from 'components/Nav'
import IconButton from 'components/IconButton'
import Form from 'components/challenge/Form'
import Ended from 'components/challenge/Ended'
import Posts from 'components/challenge/Posts'
import { Modal, Overlay, CloseButton } from 'components/Modal'
import { dt, tinyDt } from 'helpers'
import { isEmpty } from 'lodash'
import api from 'api'
import storage from 'storage'

class Help extends Component {
  state = { active: false }

  toggleRules = () => {
    this.setState(state => ({ active: !state.active }))
  }

  // Render a modal for challenge rules on button press
  render() {
    if (this.state.active) {
      return (
        <Fragment>
          <Modal align="left" my={4} p={[3, 4]}>
            <CloseButton onClick={this.toggleRules} />
            <Heading.h2>Challenge Rules</Heading.h2>
            <Text
              f={2}
              mt={3}
              color="info"
              py={2}
              px={3}
              bg="blue.0"
              style={{ borderRadius: 4 }}
            >
              For this challenge, your entry must be hosted on{' '}
              <Link href="https://repl.it" target="_blank" bold>
                repl.it
              </Link>.
            </Text>
            <Text f={2} my={3}>
              Challenge strictly follows Hack Club’s{' '}
              <Link href="https://conduct.hackclub.com" target="_blank">
                Code of Conduct
              </Link>. Anything breaking our Code of Conduct (ex. voter fraud)
              and contestants found cheating can be temporarily or permanently
              banned.
            </Text>
            <Text f={2}>
              If you think anyone has violated our Conduct or cheating policy,
              please reach out to us confidentially at{' '}
              <Link href="mailto:challenge@hackclub.com">
                challenge@hackclub.com
              </Link>.
            </Text>
          </Modal>
          <Overlay onClick={this.toggleRules} />
        </Fragment>
      )
    }
    return (
      <IconButton
        name="flag"
        size={16}
        children="Rules"
        inverted
        f={2}
        onClick={this.toggleRules}
        {...this.props}
      />
    )
  }
}

const Header = Section.withComponent('header').extend`
  padding-top: 0 !important;
  background-color: ${props => props.theme.colors.red[5]};
  background-image: linear-gradient(
    32deg,
    ${props => props.theme.colors.pink[5]},
    ${props => props.theme.colors.red[5]}
  );
  clip-path: polygon(0% 0%, 100% 0, 100% 100%, 0 98%);
  ${props => props.theme.mediaQueries.md} {
    clip-path: polygon(0% 0%, 100% 0, 100% 100%, 0 92%);
  }
`

const HeaderContainer = Container.extend`
  display: grid;
  grid-gap: ${props => props.theme.space[3]}px;
  ${props => props.theme.mediaQueries.md} {
    grid-template-columns: repeat(2, 1fr);
    grid-gap: ${props => props.theme.space[4]}px;
  }
`

const HeaderCard = Card.extend`
  min-height: 128px;
  position: relative;
  h2,
  p {
    color: ${props => props.theme.colors.black} !important;
  }
`

const Title = Flex.extend`
  border-bottom: 1px solid ${props => props.theme.colors.smoke};
`

const title = 'Hack Club Challenge'
const desc =
  'Join Hack Club’s high school coding challenge. Submit your entry to compete in our monthly programming contest and win prizes.'
const img = 'https://hackclub.com/challenge.png'

export default class extends Component {
  state = { status: 'loading' }

  componentDidMount() {
    if (storage.get('authToken')) {
      api
        .get(`v1/users/current`)
        .then(user => {
          this.setState({ status: 'success', userId: user.id })
        })
        .catch(err => {
          if (err.status === 401) {
            this.setState({ status: 'needsToAuth' })
          } else {
            this.setState({ status: 'error' })
          }
        })
    } else {
      this.setState({ status: 'needsToAuth' })
    }
  }

  render() {
    const { data } = this.props
    const { userId, status } = this.state
    if (isEmpty(data)) return null
    const challenge = data.publicJson
    const ended = Date.parse(new Date()) > Date.parse(challenge.end)
    return (
      <Fragment>
        <Helmet
          title={title}
          meta={[
            { name: 'description', content: desc },
            { name: 'twitter:title', content: title },
            { name: 'twitter:description', content: desc },
            { name: 'twitter:image', content: img },
            { property: 'og:title', content: title },
            { property: 'og:description', content: desc },
            { property: 'og:image', content: img },
            { property: 'og:url', content: 'https://hackclub.com/challenge' }
          ]}
        />

          <HeaderContainer maxWidth={56} p={0} mt={[0, 3]} align="left">
            <Box align={['center', null, 'right']}>
              <Text mb={[-2, -24]} f={3} bold caps>
                Hack Club
              </Text>
              <Heading.h1 f={[6, 7]} my={0}>
                Challenge
              </Heading.h1>
              <Heading.h2 f={3} mt={2} mb={3} regular>
                Join Hack Club’s high school coding contest
              </Heading.h2>
              <HeaderCard boxShadowSize="md" p={3} bg="pink.0" align="left">
                <Text f={2}>
                  🌟 Current challenge: {challenge.name}

                  🎁 {challenge.description}

                  📈 Upvote your favorites!

                  🏅 Top-voted 3 websites by {dt(challenge.end)} win!
                </Text>
              </HeaderCard>
            </Box>
            <HeaderCard boxShadowSize="md" p={3} bg="pink.0">
              <Form challengeId={challenge.id} status={status} />
            </HeaderCard>
          </HeaderContainer>

        <Container maxWidth={48} pt={4} pb={5} px={3}>
          {ended && <Ended />}
          <Title align="center" pb={2}>
            <Heading.h2 color="black" f={[4, 5]}>
              Submissions
            </Heading.h2>
            <Text.span f={2} color="muted" ml={3}>
              {tinyDt(challenge.start)}–{tinyDt(challenge.end)}
            </Text.span>
            <Help ml="auto" />
          </Title>
          <Posts challengeId={challenge.id} userId={userId} status={status} />
        </Container>
      </Fragment>
    )
  }
}
export const pageQuery = graphql`
  query ChallengeQuery {
    publicJson {
      id
      name
      description
      start
      end
    }
  }
`
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2014 Glayzzle (BSD3 License)
 * @authors https://github.com/glayzzle/php-parser/graphs/contributors
 * @url http://glayzzle.com
 */

module.exports = {
  /**
   * checks if current token is a reference keyword
   */
  is_reference: function() {
    if (this.token == '&') {
      this.next();
      return true;
    }
    return false;
  }
  /**
   * checks if current token is a variadic keyword
   */
  ,is_variadic: function() {
    if (this.token === this.tok.T_ELLIPSIS) {
      this.next();
      return true;
    }
    return false;
  }
  /**
   * reading a function
   * <ebnf>
   * function ::= function_declaration code_block
   * </ebnf>
   */
  ,read_function: function(closure, flag) {
    var result = this.node(
      this.read_function_declaration(closure ? 1 : flag ? 2 : 0)
    );
    if (flag && flag[2] == 1) {
      result = result(flag);
      this.expect(';').nextWithComments();
    } else {
      var body = this.expect('{').read_code_block(false);
      if (flag) {
        result = result(body, flag);
      } else {
        result = result(body);
      }
    }
    return result;
  }
  /**
   * reads a function declaration (without his body)
   * <ebnf>
   * function_declaration ::= T_FUNCTION '&'?  T_STRING '(' parameter_list ')'
   * </ebnf>
   */
  ,read_function_declaration: function(type) {
    var nodeName = 'function';
    if (type === 1) {
      nodeName = 'closure';
    } else if (type === 2) {
      nodeName = 'method';
    }
    var result = this.node(nodeName);
    this.expect(this.tok.T_FUNCTION);
    var isRef = this.next().is_reference();
    var name = false, use = [], returnType = false;
    if (type !== 1) {
      name = this.expect(this.tok.T_STRING).text();
      this.next();
    }
    this.expect('(').next();
    var params = this.read_parameter_list();
    this.expect(')').next();
    if (type === 1 && this.token === this.tok.T_USE) {
      use = this.next().expect('(').next().read_list(this.read_lexical_var, ',');
      this.expect(')').next();
    }
    if (this.token === ':') {
      returnType = this.next().read_type();
    }
    if (type === 1) {
      return result(params, isRef, use, returnType);
    }
    return result(name, params, isRef, returnType);
  }
  /**
   * <ebnf>
   * lexical_var ::= '&'? T_VARIABLE
   * </ebnf>
   */
  ,read_lexical_var: function() {
    var result = [false, null];
    if (this.token === '&') {
      result[0] = true;
      this.next();
    }
    if (this.token === this.tok.T_VARIABLE) {
      result[1] = this.text();
      this.next();
    } else {
      this.expect(['&', this.tok.T_VARIABLE]);
    }
    return result;
  }
  /**
   * reads a list of parameters
   * <ebnf>
   *  parameter_list ::= (parameter ',')* parameter?
   * </ebnf>
   */
  ,read_parameter_list: function() {
    var result = [];
    if (this.token != ')') {
      while(this.token != this.EOF) {
        result.push(this.read_parameter());
        if (this.token == ',') {
          this.next();
        } else if (this.token == ')') {
          break;
        } else {
          this.error([',', ')']);
          break;
        }
      }
    }
    return result;
  }
  /**
   * <ebnf>
   *  parameter ::= type? '&'? T_ELLIPSIS? T_VARIABLE ('=' expr)?
   * </ebnf>
   * @see https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L640
   */
  ,read_parameter: function() {
    var type = this.read_type();
    var isRef = this.is_reference();
    var isVariadic = this.is_variadic();
    var name = this.expect(this.tok.T_VARIABLE).text();
    var value = [];
    if (this.next().token == '=') {
      value = this.next().read_expr();
    }
    return [name, type, value, isRef, isVariadic];
  }
  /**
   * <ebnf>
   *  function_argument_list ::= '(' (argument_list (',' argument_list)*)? ')'
   * </ebnf>
   */
  ,read_function_argument_list: function() {
    var result = [];
    this.expect('(').next();
    if (this.token !== ')') {
      while(this.token != this.EOF) {
        result.push(this.read_argument_list());
        if (this.token === ',') {
          this.next();
        } else break;
      }
    }
    this.expect(')').next();
    return result;
  }
  /**
   * <ebnf>
   *    argument_list ::= T_ELLIPSIS? expr
   * </ebnf>
   */
  ,read_argument_list: function() {
    if (this.token === this.tok.T_ELLIPSIS ) {
      return this.node('variadic')(this.next().read_expr());
    }
    return this.read_expr();
  }
  /**
   * read type hinting
   * <ebnf>
   *  type ::= T_ARRAY | T_CALLABLE | namespace_name
   * </ebnf>
   */
  ,read_type: function() {
    switch(this.token) {
      case this.tok.T_ARRAY:
        this.next();
        return 'array';
      case this.tok.T_NS_SEPARATOR:
      case this.tok.T_STRING:
        return this.read_namespace_name();
      case this.tok.T_CALLABLE:
        this.next();
        return 'callable';
      default:
        return 'mixed';
    }
  }
};
<commit_msg>https://github.com/glayzzle/php-parser/issues/41 make function AST more consistent<commit_after>/**
 * Copyright (C) 2014 Glayzzle (BSD3 License)
 * @authors https://github.com/glayzzle/php-parser/graphs/contributors
 * @url http://glayzzle.com
 */

module.exports = {
  /**
   * checks if current token is a reference keyword
   */
  is_reference: function() {
    if (this.token == '&') {
      this.next();
      return true;
    }
    return false;
  }
  /**
   * checks if current token is a variadic keyword
   */
  ,is_variadic: function() {
    if (this.token === this.tok.T_ELLIPSIS) {
      this.next();
      return true;
    }
    return false;
  }
  /**
   * reading a function
   * <ebnf>
   * function ::= function_declaration code_block
   * </ebnf>
   */
  ,read_function: function(closure, flag) {
    var result = this.node(
      this.read_function_declaration(closure ? 1 : flag ? 2 : 0)
    );
    if (flag && flag[2] == 1) {
      result = result(flag);
      this.expect(';').nextWithComments();
    } else {
      var body = this.expect('{').read_code_block(false);
      if (flag) {
        result = result(body, flag);
      } else {
        result = result(body);
      }
    }
    return result;
  }
  /**
   * reads a function declaration (without his body)
   * <ebnf>
   * function_declaration ::= T_FUNCTION '&'?  T_STRING '(' parameter_list ')'
   * </ebnf>
   */
  ,read_function_declaration: function(type) {
    var nodeName = 'function';
    if (type === 1) {
      nodeName = 'closure';
    } else if (type === 2) {
      nodeName = 'method';
    }
    var result = this.node(nodeName);
    this.expect(this.tok.T_FUNCTION);
    var isRef = this.next().is_reference();
    var name = false, use = [], returnType = false;
    if (type !== 1) {
      name = this.expect(this.tok.T_STRING).text();
      this.next();
    }
    this.expect('(').next();
    var params = this.read_parameter_list();
    this.expect(')').next();
    if (type === 1 && this.token === this.tok.T_USE) {
      use = this.next().expect('(').next().read_list(this.read_lexical_var, ',');
      this.expect(')').next();
    }
    if (this.token === ':') {
      returnType = this.next().read_type();
    }
    if (type === 1) {
      return result(params, isRef, use, returnType);
    }
    return result(name, params, isRef, returnType);
  }
  /**
   * <ebnf>
   * lexical_var ::= '&'? T_VARIABLE
   * </ebnf>
   */
  ,read_lexical_var: function() {
    var result = [false, null];
    if (this.token === '&') {
      result[0] = true;
      this.next();
    }
    if (this.token === this.tok.T_VARIABLE) {
      result[1] = this.text();
      this.next();
    } else {
      this.expect(['&', this.tok.T_VARIABLE]);
    }
    return result;
  }
  /**
   * reads a list of parameters
   * <ebnf>
   *  parameter_list ::= (parameter ',')* parameter?
   * </ebnf>
   */
  ,read_parameter_list: function() {
    var result = [];
    if (this.token != ')') {
      while(this.token != this.EOF) {
        result.push(this.read_parameter());
        if (this.token == ',') {
          this.next();
        } else if (this.token == ')') {
          break;
        } else {
          this.error([',', ')']);
          break;
        }
      }
    }
    return result;
  }
  /**
   * <ebnf>
   *  parameter ::= type? '&'? T_ELLIPSIS? T_VARIABLE ('=' expr)?
   * </ebnf>
   * @see https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L640
   */
  ,read_parameter: function() {
    var node = this.node('param');
    var type = this.read_type();
    var isRef = this.is_reference();
    var isVariadic = this.is_variadic();
    var name = this.expect(this.tok.T_VARIABLE).text();
    var value = null;
    if (this.next().token == '=') {
      value = this.next().read_expr();
    }
    return node(name, type, value, isRef, isVariadic);
  }
  /**
   * <ebnf>
   *  function_argument_list ::= '(' (argument_list (',' argument_list)*)? ')'
   * </ebnf>
   */
  ,read_function_argument_list: function() {
    var result = [];
    this.expect('(').next();
    if (this.token !== ')') {
      while(this.token != this.EOF) {
        result.push(this.read_argument_list());
        if (this.token === ',') {
          this.next();
        } else break;
      }
    }
    this.expect(')').next();
    return result;
  }
  /**
   * <ebnf>
   *    argument_list ::= T_ELLIPSIS? expr
   * </ebnf>
   */
  ,read_argument_list: function() {
    if (this.token === this.tok.T_ELLIPSIS ) {
      return this.node('variadic')(this.next().read_expr());
    }
    return this.read_expr();
  }
  /**
   * read type hinting
   * <ebnf>
   *  type ::= T_ARRAY | T_CALLABLE | namespace_name
   * </ebnf>
   */
  ,read_type: function() {
    switch(this.token) {
      case this.tok.T_ARRAY:
        this.next();
        return ['array'];
      case this.tok.T_NS_SEPARATOR:
      case this.tok.T_STRING:
        return this.read_namespace_name();
      case this.tok.T_CALLABLE:
        this.next();
        return ['callable'];
      default:
        return null;
    }
  }
};
<|endoftext|>


<commit_before>/**
 * Patterns collapsible - Collapsible content
 *
 * Copyright 2012-2013 Florian Friesdorf
 * Copyright 2012-2013 Simplon B.V. - Wichert Akkerman
 * Copyright 2012 Markus Maier
 * Copyright 2013 Peter Lamut
 * Copyright 2012 Jonas Hoersch
 */
define([
    "jquery",
    "./inject",
    "../core/logger",
    "../core/parser",
    "../core/store",
    "../registry"
], function($, inject, logger, Parser, store, registry) {
    var log = logger.getLogger("pat.collapsible"),
        parser = new Parser("collapsible");

    parser.add_argument("load-content");
    parser.add_argument("store", "none", ["none", "session", "local"]);
    parser.add_argument("transition", "slide", ["none", "css", "fade", "slide"]);
    parser.add_argument("effect-duration", "fast");
    parser.add_argument("effect-easing", "swing");
    parser.add_argument("closed", false);
    parser.add_argument("trigger", "::first");

    var _ = {
        name: "collapsible",
        trigger: ".pat-collapsible",
        jquery_plugin: true,

        transitions: {
            none: {closed: "hide", open: "show"},
            fade: {closed: "fadeOut", open: "fadeIn"},
            slide: {closed: "slideUp", open: "slideDown"}
        },

        init: function($el, opts) {
            return $el.each(function() {
                var $el = $(this),
                    options = _._validateOptions(this, parser.parse($el, opts)),
                // create collapsible structure
                    $content, state, storage;

                if (options.trigger === "::first") {
                    options.$trigger = $el.children(":first");
                    $content = $el.children(":gt(0)");
                } else {
                    options.$trigger = $(options.trigger);
                    $content = $el.children();
                }

                if (options.$trigger.length===0) {
                    log.error("Collapsible has no trigger.", this);
                    return;
                }

                if ($content.length)
                    options.$panel = $content.wrapAll("
")
                        .parent();
                else
                    options.$panel = $("
").insertAfter(options.$trigger);

                $el.data("patternCollapsible", options);
                state=(options.closed || $el.hasClass("closed")) ? "closed" : "open";
                if (options.store!=="none") {
                    storage=(options.store==="local" ? store.local : store.session)(_.name);
                    state=storage.get(this.id) || state;
                }

                if (state==="closed") {
                    options.$trigger.removeClass("collapsible-open").addClass("collapsible-closed");
                    $el.removeClass("open").addClass("closed");
                    options.$panel.hide();
                } else {
                    if (options.loadContent)
                        _.loadContent($el, options.loadContent, options.$panel);
                    options.$trigger.removeClass("collapsible-closed").addClass("collapsible-open");
                    $el.removeClass("closed").addClass("open");
                    options.$panel.show();
                }

                options.$trigger
                    .off(".pat-collapsible")
                    .on("click.pat-collapsible", null, $el, _._onClick);

                return $el;
            });
        },

        _onClick: function(event) {
            _.toggle(event.data);
        },

        destroy: function($el) {
            $el.removeData("patternCollapsible");
            $el.children(":first").off(".pat-collapsible");
        },

        open: function($el) {
            if (!$el.hasClass("open"))
                _.toggle($el);
            return $el;
        },

        close: function($el) {
            if (!$el.hasClass("closed"))
                _.toggle($el);
            return $el;
        },

        _validateOptions: function(trigger, options) {
            if (options.store!=="none") {
                if (!trigger.id) {
                    log.warn("state persistance requested, but element has no id");
                    options.store="none";
                } else if (!store.supported) {
                    log.warn("state persistance requested, but browser does not support webstorage");
                    options.store="none";
                }
            }
            return options;
        },

        loadContent: function($el, url, $target) {
            var components = url.split("#"),
                base_url = components[0],
                id = components[1] ? "#" + components[1] : null,
                opts = [{
                    url: base_url,
                    source: id,
                    $target: $target,
                    dataType: "html"
                }];
            inject.execute(opts, $el);
        },

        toggle: function($el) {
            var options = $el.data("patternCollapsible"),
                new_state = $el.hasClass("closed") ? "open" : "closed";

            if (options.store!=="none") {
                var storage=(options.store==="local" ? store.local : store.session)(_.name);
                storage.set($el.attr("id"), new_state);
            }

            if (new_state==="open") {
                $el.trigger("patterns-collapsible-open");
                _._transit($el, "closed", "open", options);
            } else {
                $el.trigger("patterns-collapsible-close");
                _._transit($el, "open", "closed", options);
            }

            // allow for chaining
            return $el;
        },

        _transit: function($el, from_cls, to_cls, options) {
            if (to_cls === "open" && options.loadContent)
                _.loadContent($el, options.loadContent, options.$panel);

            var duration = (options.transition==="css" || options.transition==="none") ? null : options.effect.duration;

            if (!duration) {
                options.$trigger
                        .removeClass("collapsible-" + from_cls)
                        .addClass("collapsible-" + to_cls);
                $el
                    .removeClass(from_cls)
                    .addClass(to_cls);
            } else {
                var t = _.transitions[options.transition];
                $el.addClass("in-progress");
                options.$trigger.addClass("collapsible-in-progress");
                options.$panel[t[to_cls]](duration, options.effect.easing, function() {
                    options.$trigger
                            .removeClass("collapsible-" + from_cls)
                            .removeClass("collapsible-in-progress")
                            .addClass("collapsible-" + to_cls);
                    $el
                        .removeClass(from_cls)
                        .removeClass("in-progress")
                        .addClass(to_cls);
                });
            }
        }
    };

    registry.register(_);
    return _;
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>Collapsible: make loadContent private<commit_after>/**
 * Patterns collapsible - Collapsible content
 *
 * Copyright 2012-2013 Florian Friesdorf
 * Copyright 2012-2013 Simplon B.V. - Wichert Akkerman
 * Copyright 2012 Markus Maier
 * Copyright 2013 Peter Lamut
 * Copyright 2012 Jonas Hoersch
 */
define([
    "jquery",
    "./inject",
    "../core/logger",
    "../core/parser",
    "../core/store",
    "../registry"
], function($, inject, logger, Parser, store, registry) {
    var log = logger.getLogger("pat.collapsible"),
        parser = new Parser("collapsible");

    parser.add_argument("load-content");
    parser.add_argument("store", "none", ["none", "session", "local"]);
    parser.add_argument("transition", "slide", ["none", "css", "fade", "slide"]);
    parser.add_argument("effect-duration", "fast");
    parser.add_argument("effect-easing", "swing");
    parser.add_argument("closed", false);
    parser.add_argument("trigger", "::first");

    var _ = {
        name: "collapsible",
        trigger: ".pat-collapsible",
        jquery_plugin: true,

        transitions: {
            none: {closed: "hide", open: "show"},
            fade: {closed: "fadeOut", open: "fadeIn"},
            slide: {closed: "slideUp", open: "slideDown"}
        },

        init: function($el, opts) {
            return $el.each(function() {
                var $el = $(this),
                    options = _._validateOptions(this, parser.parse($el, opts)),
                // create collapsible structure
                    $content, state, storage;

                if (options.trigger === "::first") {
                    options.$trigger = $el.children(":first");
                    $content = $el.children(":gt(0)");
                } else {
                    options.$trigger = $(options.trigger);
                    $content = $el.children();
                }

                if (options.$trigger.length===0) {
                    log.error("Collapsible has no trigger.", this);
                    return;
                }

                if ($content.length)
                    options.$panel = $content.wrapAll("
")
                        .parent();
                else
                    options.$panel = $("
").insertAfter(options.$trigger);

                $el.data("patternCollapsible", options);
                state=(options.closed || $el.hasClass("closed")) ? "closed" : "open";
                if (options.store!=="none") {
                    storage=(options.store==="local" ? store.local : store.session)(_.name);
                    state=storage.get(this.id) || state;
                }

                if (state==="closed") {
                    options.$trigger.removeClass("collapsible-open").addClass("collapsible-closed");
                    $el.removeClass("open").addClass("closed");
                    options.$panel.hide();
                } else {
                    if (options.loadContent)
                        _._loadContent($el, options.loadContent, options.$panel);
                    options.$trigger.removeClass("collapsible-closed").addClass("collapsible-open");
                    $el.removeClass("closed").addClass("open");
                    options.$panel.show();
                }

                options.$trigger
                    .off(".pat-collapsible")
                    .on("click.pat-collapsible", null, $el, _._onClick);

                return $el;
            });
        },

        _onClick: function(event) {
            _.toggle(event.data);
        },

        destroy: function($el) {
            $el.removeData("patternCollapsible");
            $el.children(":first").off(".pat-collapsible");
        },

        open: function($el) {
            if (!$el.hasClass("open"))
                _.toggle($el);
            return $el;
        },

        close: function($el) {
            if (!$el.hasClass("closed"))
                _.toggle($el);
            return $el;
        },

        _validateOptions: function(trigger, options) {
            if (options.store!=="none") {
                if (!trigger.id) {
                    log.warn("state persistance requested, but element has no id");
                    options.store="none";
                } else if (!store.supported) {
                    log.warn("state persistance requested, but browser does not support webstorage");
                    options.store="none";
                }
            }
            return options;
        },

        _loadContent: function($el, url, $target) {
            var components = url.split("#"),
                base_url = components[0],
                id = components[1] ? "#" + components[1] : null,
                opts = [{
                    url: base_url,
                    source: id,
                    $target: $target,
                    dataType: "html"
                }];
            inject.execute(opts, $el);
        },

        toggle: function($el) {
            var options = $el.data("patternCollapsible"),
                new_state = $el.hasClass("closed") ? "open" : "closed";

            if (options.store!=="none") {
                var storage=(options.store==="local" ? store.local : store.session)(_.name);
                storage.set($el.attr("id"), new_state);
            }

            if (new_state==="open") {
                $el.trigger("patterns-collapsible-open");
                _._transit($el, "closed", "open", options);
            } else {
                $el.trigger("patterns-collapsible-close");
                _._transit($el, "open", "closed", options);
            }

            // allow for chaining
            return $el;
        },

        _transit: function($el, from_cls, to_cls, options) {
            if (to_cls === "open" && options.loadContent)
                _._loadContent($el, options.loadContent, options.$panel);

            var duration = (options.transition==="css" || options.transition==="none") ? null : options.effect.duration;

            if (!duration) {
                options.$trigger
                        .removeClass("collapsible-" + from_cls)
                        .addClass("collapsible-" + to_cls);
                $el
                    .removeClass(from_cls)
                    .addClass(to_cls);
            } else {
                var t = _.transitions[options.transition];
                $el.addClass("in-progress");
                options.$trigger.addClass("collapsible-in-progress");
                options.$panel[t[to_cls]](duration, options.effect.easing, function() {
                    options.$trigger
                            .removeClass("collapsible-" + from_cls)
                            .removeClass("collapsible-in-progress")
                            .addClass("collapsible-" + to_cls);
                    $el
                        .removeClass(from_cls)
                        .removeClass("in-progress")
                        .addClass(to_cls);
                });
            }
        }
    };

    registry.register(_);
    return _;
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>