<commit_before>//var allTags = document.body.getElementsByTagName('xvolutions_adminbundle_*');
//var tmp = document.body.document.getElementsByTagName("input");
//var ids = [];
//for (var tg = 0; tg< allTags.length; tg++) {
//    var tag = allTags[tg];
//    if (tag.id) {
//        ids[tag.id] = document.getElementById(tag.id).value;
//     }
//}
//console.log(tmp);
//document.getElementById('save').name = document.getElementById('save').name + '/' + (JSON.stringify(ids));

$(document).ready(function()
{
    $('a.btn.btn-info.btn-sm.save').click(function()
    {
        var url = $(this).attr('name');
        var inputs = document.getElementsByTagName("input");
        var textareas = document.getElementsByTagName("textarea");
        var selects = document.getElementsByTagName("select");
        var data = {};
        for (var i = 0; i < inputs.length; i++)
        {
            data[inputs[i].id.replace('xvolutions_adminbundle_page_','')] = inputs[i].value;
        }
        for (var i = 0; i < textareas.length; i++)
        {
            data[textareas[i].id.replace('xvolutions_adminbundle_page_','')] = textareas[i].value;
        }
        for (var i = 0; i < selects.length; i++)
        {
            data[selects[i].id.replace('xvolutions_adminbundle_page_','')] = selects[i].value;
        }
        $.ajax(
        {
            type: "POST",
            url: url,
            data: JSON.stringify(data),
            async: true,
            cache: false,
            success: function(data, result )
            {
                var text= result;
                $("#text").text(text);
                $("#status").fadeIn(
                        'slow',
                        function()
                        {
                            $("#status").css("display","block");
                            $("#status").delay(1500);
                            $("#status").fadeOut(
                                'slow',
                                function()
                                {
                                    $("#status").slideUp(1500);
                                }
                            );
                        }
                );
            },
            dataType: "json"
        }
        );
    }
    );
});
<commit_msg>- Fix fetch getContent from TinyMCE text areas<commit_after>$(document).ready(function()
{
    $('a.btn.btn-info.btn-sm.save').click(function()
    {
        var url = $(this).attr('name');
        var inputs = document.getElementsByTagName("input");
        var textareas = document.getElementsByTagName("textarea");
        var selects = document.getElementsByTagName("select");
        var data = {};
        for (var i = 0; i < inputs.length; i++)
        {
            data[inputs[i].id.replace('xvolutions_adminbundle_page_','')] = inputs[i].value;
        }
        for (var i = 0; i < textareas.length; i++)
        {
            data[textareas[i].id.replace('xvolutions_adminbundle_page_','')] = tinyMCE.get(textareas[i].id).getContent();
        }
        for (var i = 0; i < selects.length; i++)
        {
            data[selects[i].id.replace('xvolutions_adminbundle_page_','')] = selects[i].value;
        }
        $.ajax(
        {
            type: "POST",
            url: url,
            data: JSON.stringify(data),
            async: true,
            cache: false,
            success: function(data, result )
            {
                var text= result;
                $("#text").text(text);
                $("#status").fadeIn(
                        'slow',
                        function()
                        {
                            $("#status").css("display","block");
                            $("#status").delay(1500);
                            $("#status").fadeOut(
                                'slow',
                                function()
                                {
                                    $("#status").slideUp(1500);
                                }
                            );
                        }
                );
            },
            dataType: "json"
        }
        );
    }
    );
});
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, injectIntl, intlShape, defineMessages } from 'react-intl';
import { makeStyles } from '@material-ui/core/styles';
import Box from '@material-ui/core/Box';
import Typography from '@material-ui/core/Typography';
import IconButton from '@material-ui/core/IconButton';
import HelpIcon from '@material-ui/icons/HelpOutline';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import { SliderPicker } from 'react-color';
import ReportDesignerFormSection from './ReportDesignerFormSection';
import UploadImage from '../../UploadImage';
import { checkBlue } from '../../../styles/js/shared';

const useStyles = makeStyles(theme => ({
  root: {
    position: 'relative',
  },
  mask: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    background: 'white',
    opacity: 0.8,
    zIndex: 2,
  },
  helpIcon: {
    color: checkBlue,
  },
  colorPicker: {
    width: 400,
    margin: theme.spacing(3),
  },
  textField: {
    marginTop: theme.spacing(2),
    marginBottom: theme.spacing(2),
  },
}));

const messages = defineMessages({
  introductionPlaceholder: {
    id: 'reportDesigner.introductionPlaceholder',
    defaultMessage: 'Type your introduction here...',
  },
  textPlaceholder: {
    id: 'reportDesigner.textPlaceholder',
    defaultMessage: 'Type your report here...',
  },
});

const ReportDesignerForm = (props) => {
  const classes = useStyles();
  const { data, media } = props;

  const handleHelp = () => {
    window.open('http://help.checkmedia.org/en/articles/3627266-check-message-report');
  };

  const handleImageChange = (image) => {
    props.onUpdate('image', image);
  };

  const handleImageError = () => {
    props.onUpdate('image', null);
  };

  const handleDefaultImage = () => {
    if (media && media.media && media.media.picture) {
      props.onUpdate('image', media.media.picture);
    }
  };

  const textFieldProps = {
    className: classes.textField,
    variant: 'outlined',
    fullWidth: true,
  };

  return (
    <Box className={classes.root}>
      { props.disabled ? <Box className={classes.mask} /> : null }
      <Box display="flex" alignItems="center">
        <Typography variant="subtitle1">
          <FormattedMessage
            id="reportDesigner.reportEditorTitle"
            defaultMessage="Select the content to send in your report"
          />
        </Typography>
        <IconButton onClick={handleHelp}>
          <HelpIcon className={classes.helpIcon} />
        </IconButton>
      </Box>
      <Box>
        <ReportDesignerFormSection
          enabled={data.use_introduction}
          onToggle={(enabled) => { props.onUpdate('use_introduction', enabled); }}
          label={
            <FormattedMessage
              id="reportDesigner.introduction"
              defaultMessage="Introduction message"
            />
          }
        >
          <TextField
            key={`introduction-${data.language}`}
            value={data.introduction}
            onChange={(e) => { props.onUpdate('introduction', e.target.value); }}
            placeholder={props.intl.formatMessage(messages.introductionPlaceholder)}
            rows={10}
            multiline
            {...textFieldProps}
          />
          <Typography variant="caption">
            <FormattedMessage
              id="reportDesigner.introductionSub"
              defaultMessage="Use {query_date} placeholder to display the date of the original query. Use {status} to communicate the status of the article."
              values={{
                query_date: '{{query_date}}',
                status: '{{status}}',
              }}
            />
          </Typography>
        </ReportDesignerFormSection>

        <ReportDesignerFormSection
          enabled={data.use_visual_card}
          onToggle={(enabled) => { props.onUpdate('use_visual_card', enabled); }}
          label={
            <FormattedMessage
              id="reportDesigner.visualCard"
              defaultMessage="Report image"
            />
          }
        >
          <UploadImage onChange={handleImageChange} onError={handleImageError} type="image" />
          <Box>
            { media.media.picture ?
              <Button onClick={handleDefaultImage}>
                <FormattedMessage
                  id="reportDesigner.useDefaultImage"
                  defaultMessage="Use default image"
                />
              </Button> : null }
          </Box>
          <TextField
            key={`headline-${data.language}`}
            value={data.headline}
            onChange={(e) => { props.onUpdate('headline', e.target.value); }}
            inputProps={{ maxLength: 85 }}
            label={
              <FormattedMessage
                id="reportDesigner.headline"
                defaultMessage="Headline - {max} characters max"
                values={{ max: 85 }}
              />
            }
            {...textFieldProps}
          />
          <TextField
            key={`description-${data.language}`}
            value={data.description}
            onChange={(e) => { props.onUpdate('description', e.target.value); }}
            inputProps={{ maxLength: 240 }}
            label={
              <FormattedMessage
                id="reportDesigner.description"
                defaultMessage="Description - {max} characters max"
                values={{ max: 240 }}
              />
            }
            multiline
            rows={6}
            {...textFieldProps}
          />
          <TextField
            key={`status-${data.language}`}
            value={data.status_label}
            onChange={(e) => { props.onUpdate('status_label', e.target.value); }}
            inputProps={{ maxLength: 16 }}
            label={
              <FormattedMessage
                id="reportDesigner.statusLabel"
                defaultMessage="Status label - {max} characters max"
                values={{ max: 16 }}
              />
            }
            {...textFieldProps}
          />
          <Box display="flex">
            <TextField
              key={`color-${data.language}`}
              value={data.theme_color}
              onChange={(e) => { props.onUpdate('theme_color', e.target.value); }}
              inputProps={{ maxLength: 7 }}
              label={
                <FormattedMessage
                  id="reportDesigner.themeColor"
                  defaultMessage="Theme color"
                />
              }
              {...textFieldProps}
            />
            <Box className={classes.colorPicker}>
              <SliderPicker
                color={data.theme_color}
                onChangeComplete={(color) => { props.onUpdate('theme_color', color.hex); }}
              />
            </Box>
          </Box>
          <FormControlLabel
            control={
              <Checkbox
                key={`dark-overlay-${data.language}`}
                onChange={(e) => { props.onUpdate('dark_overlay', e.target.checked); }}
                checked={data.dark_overlay || false}
              />
            }
            label={
              <FormattedMessage
                id="reportDesigner.darkOverlay"
                defaultMessage="Dark overlay"
              />
            }
          />
          <TextField
            key={`url-${data.language}`}
            value={data.url}
            onChange={(e) => { props.onUpdate('url', e.target.value); }}
            inputProps={{ maxLength: 40 }}
            label={
              <FormattedMessage
                id="reportDesigner.url"
                defaultMessage="URL - {max} characters max"
                values={{ max: 40 }}
              />
            }
            {...textFieldProps}
          />
        </ReportDesignerFormSection>

        <ReportDesignerFormSection
          enabled={data.use_text_message}
          onToggle={(enabled) => { props.onUpdate('use_text_message', enabled); }}
          label={
            <FormattedMessage
              id="reportDesigner.textMessage"
              defaultMessage="Report text"
            />
          }
        >
          <TextField
            id="report-designer__text" // For integration test
            key={`text-${data.language}`}
            value={data.text}
            onChange={(e) => { props.onUpdate('text', e.target.value); }}
            placeholder={props.intl.formatMessage(messages.textPlaceholder)}
            rows={10}
            multiline
            error={data.use_text_message && data.text.length === 0}
            helperText={
              data.use_text_message && data.text.length === 0 ?
                <FormattedMessage
                  id="reportDesigner.textError"
                  defaultMessage="You must either provide text for the report or uncheck the 'Report text' box"
                /> : null
            }
            {...textFieldProps}
          />
          <Box>
            <FormControlLabel
              control={
                <Checkbox
                  key={`use-disclaimer-${data.language}`}
                  onChange={(e) => { props.onUpdate('use_disclaimer', e.target.checked); }}
                  checked={data.use_disclaimer}
                />
              }
              label={
                <FormattedMessage
                  id="reportDesigner.disclaimer"
                  defaultMessage="Disclaimer"
                />
              }
            />
          </Box>
          <TextField
            key={`disclaimer-${data.language}`}
            value={data.disclaimer}
            onChange={(e) => { props.onUpdate('disclaimer', e.target.value); }}
            {...textFieldProps}
          />
        </ReportDesignerFormSection>
      </Box>
    </Box>
  );
};

ReportDesignerForm.defaultProps = {
  disabled: false,
};

ReportDesignerForm.propTypes = {
  data: PropTypes.object.isRequired,
  media: PropTypes.object.isRequired,
  onUpdate: PropTypes.func.isRequired,
  disabled: PropTypes.bool,
  // https://github.com/yannickcr/eslint-plugin-react/issues/1389
  // eslint-disable-next-line react/no-typos
  intl: intlShape.isRequired,
};

export default injectIntl(ReportDesignerForm);
<commit_msg>Status label 25 chars #8455<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, injectIntl, intlShape, defineMessages } from 'react-intl';
import { makeStyles } from '@material-ui/core/styles';
import Box from '@material-ui/core/Box';
import Typography from '@material-ui/core/Typography';
import IconButton from '@material-ui/core/IconButton';
import HelpIcon from '@material-ui/icons/HelpOutline';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import { SliderPicker } from 'react-color';
import ReportDesignerFormSection from './ReportDesignerFormSection';
import UploadImage from '../../UploadImage';
import { checkBlue } from '../../../styles/js/shared';

const useStyles = makeStyles(theme => ({
  root: {
    position: 'relative',
  },
  mask: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    background: 'white',
    opacity: 0.8,
    zIndex: 2,
  },
  helpIcon: {
    color: checkBlue,
  },
  colorPicker: {
    width: 400,
    margin: theme.spacing(3),
  },
  textField: {
    marginTop: theme.spacing(2),
    marginBottom: theme.spacing(2),
  },
}));

const messages = defineMessages({
  introductionPlaceholder: {
    id: 'reportDesigner.introductionPlaceholder',
    defaultMessage: 'Type your introduction here...',
  },
  textPlaceholder: {
    id: 'reportDesigner.textPlaceholder',
    defaultMessage: 'Type your report here...',
  },
});

const ReportDesignerForm = (props) => {
  const classes = useStyles();
  const { data, media } = props;

  const handleHelp = () => {
    window.open('http://help.checkmedia.org/en/articles/3627266-check-message-report');
  };

  const handleImageChange = (image) => {
    props.onUpdate('image', image);
  };

  const handleImageError = () => {
    props.onUpdate('image', null);
  };

  const handleDefaultImage = () => {
    if (media && media.media && media.media.picture) {
      props.onUpdate('image', media.media.picture);
    }
  };

  const textFieldProps = {
    className: classes.textField,
    variant: 'outlined',
    fullWidth: true,
  };

  return (
    <Box className={classes.root}>
      { props.disabled ? <Box className={classes.mask} /> : null }
      <Box display="flex" alignItems="center">
        <Typography variant="subtitle1">
          <FormattedMessage
            id="reportDesigner.reportEditorTitle"
            defaultMessage="Select the content to send in your report"
          />
        </Typography>
        <IconButton onClick={handleHelp}>
          <HelpIcon className={classes.helpIcon} />
        </IconButton>
      </Box>
      <Box>
        <ReportDesignerFormSection
          enabled={data.use_introduction}
          onToggle={(enabled) => { props.onUpdate('use_introduction', enabled); }}
          label={
            <FormattedMessage
              id="reportDesigner.introduction"
              defaultMessage="Introduction message"
            />
          }
        >
          <TextField
            key={`introduction-${data.language}`}
            value={data.introduction}
            onChange={(e) => { props.onUpdate('introduction', e.target.value); }}
            placeholder={props.intl.formatMessage(messages.introductionPlaceholder)}
            rows={10}
            multiline
            {...textFieldProps}
          />
          <Typography variant="caption">
            <FormattedMessage
              id="reportDesigner.introductionSub"
              defaultMessage="Use {query_date} placeholder to display the date of the original query. Use {status} to communicate the status of the article."
              values={{
                query_date: '{{query_date}}',
                status: '{{status}}',
              }}
            />
          </Typography>
        </ReportDesignerFormSection>

        <ReportDesignerFormSection
          enabled={data.use_visual_card}
          onToggle={(enabled) => { props.onUpdate('use_visual_card', enabled); }}
          label={
            <FormattedMessage
              id="reportDesigner.visualCard"
              defaultMessage="Report image"
            />
          }
        >
          <UploadImage onChange={handleImageChange} onError={handleImageError} type="image" />
          <Box>
            { media.media.picture ?
              <Button onClick={handleDefaultImage}>
                <FormattedMessage
                  id="reportDesigner.useDefaultImage"
                  defaultMessage="Use default image"
                />
              </Button> : null }
          </Box>
          <TextField
            key={`headline-${data.language}`}
            value={data.headline}
            onChange={(e) => { props.onUpdate('headline', e.target.value); }}
            inputProps={{ maxLength: 85 }}
            label={
              <FormattedMessage
                id="reportDesigner.headline"
                defaultMessage="Headline - {max} characters max"
                values={{ max: 85 }}
              />
            }
            {...textFieldProps}
          />
          <TextField
            key={`description-${data.language}`}
            value={data.description}
            onChange={(e) => { props.onUpdate('description', e.target.value); }}
            inputProps={{ maxLength: 240 }}
            label={
              <FormattedMessage
                id="reportDesigner.description"
                defaultMessage="Description - {max} characters max"
                values={{ max: 240 }}
              />
            }
            multiline
            rows={6}
            {...textFieldProps}
          />
          <TextField
            key={`status-${data.language}`}
            value={data.status_label}
            onChange={(e) => { props.onUpdate('status_label', e.target.value); }}
            inputProps={{ maxLength: 25 }}
            label={
              <FormattedMessage
                id="reportDesigner.statusLabel"
                defaultMessage="Status label - {max} characters max"
                values={{ max: 25 }}
              />
            }
            {...textFieldProps}
          />
          <Box display="flex">
            <TextField
              key={`color-${data.language}`}
              value={data.theme_color}
              onChange={(e) => { props.onUpdate('theme_color', e.target.value); }}
              inputProps={{ maxLength: 7 }}
              label={
                <FormattedMessage
                  id="reportDesigner.themeColor"
                  defaultMessage="Theme color"
                />
              }
              {...textFieldProps}
            />
            <Box className={classes.colorPicker}>
              <SliderPicker
                color={data.theme_color}
                onChangeComplete={(color) => { props.onUpdate('theme_color', color.hex); }}
              />
            </Box>
          </Box>
          <FormControlLabel
            control={
              <Checkbox
                key={`dark-overlay-${data.language}`}
                onChange={(e) => { props.onUpdate('dark_overlay', e.target.checked); }}
                checked={data.dark_overlay || false}
              />
            }
            label={
              <FormattedMessage
                id="reportDesigner.darkOverlay"
                defaultMessage="Dark overlay"
              />
            }
          />
          <TextField
            key={`url-${data.language}`}
            value={data.url}
            onChange={(e) => { props.onUpdate('url', e.target.value); }}
            inputProps={{ maxLength: 40 }}
            label={
              <FormattedMessage
                id="reportDesigner.url"
                defaultMessage="URL - {max} characters max"
                values={{ max: 40 }}
              />
            }
            {...textFieldProps}
          />
        </ReportDesignerFormSection>

        <ReportDesignerFormSection
          enabled={data.use_text_message}
          onToggle={(enabled) => { props.onUpdate('use_text_message', enabled); }}
          label={
            <FormattedMessage
              id="reportDesigner.textMessage"
              defaultMessage="Report text"
            />
          }
        >
          <TextField
            id="report-designer__text" // For integration test
            key={`text-${data.language}`}
            value={data.text}
            onChange={(e) => { props.onUpdate('text', e.target.value); }}
            placeholder={props.intl.formatMessage(messages.textPlaceholder)}
            rows={10}
            multiline
            error={data.use_text_message && data.text.length === 0}
            helperText={
              data.use_text_message && data.text.length === 0 ?
                <FormattedMessage
                  id="reportDesigner.textError"
                  defaultMessage="You must either provide text for the report or uncheck the 'Report text' box"
                /> : null
            }
            {...textFieldProps}
          />
          <Box>
            <FormControlLabel
              control={
                <Checkbox
                  key={`use-disclaimer-${data.language}`}
                  onChange={(e) => { props.onUpdate('use_disclaimer', e.target.checked); }}
                  checked={data.use_disclaimer}
                />
              }
              label={
                <FormattedMessage
                  id="reportDesigner.disclaimer"
                  defaultMessage="Disclaimer"
                />
              }
            />
          </Box>
          <TextField
            key={`disclaimer-${data.language}`}
            value={data.disclaimer}
            onChange={(e) => { props.onUpdate('disclaimer', e.target.value); }}
            {...textFieldProps}
          />
        </ReportDesignerFormSection>
      </Box>
    </Box>
  );
};

ReportDesignerForm.defaultProps = {
  disabled: false,
};

ReportDesignerForm.propTypes = {
  data: PropTypes.object.isRequired,
  media: PropTypes.object.isRequired,
  onUpdate: PropTypes.func.isRequired,
  disabled: PropTypes.bool,
  // https://github.com/yannickcr/eslint-plugin-react/issues/1389
  // eslint-disable-next-line react/no-typos
  intl: intlShape.isRequired,
};

export default injectIntl(ReportDesignerForm);
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { format } from 'jsondiffpatch/src/formatters/html';
import styled from 'styled-components';

export const StyledContainer = styled.div`
  width: 100%;
  height: 100%;
  overflow-y: auto;

  .jsondiffpatch-delta {
    font-family: monaco, Consolas, "Lucida Console", monospace;
    font-size: 12px;
    padding: 12px;
    margin: 0;
    display: inline-block;
  }

  .jsondiffpatch-delta pre {
    font-family: monaco, Consolas, "Lucida Console", monospace;
    font-size: 12px;
    margin: 0;
    padding: 2px 3px;
    border-radius: 3px;
    position: relative;
    color: #FFFFFF;
    display: inline-block;
  }

  ul.jsondiffpatch-delta {
    list-style-type: none;
    padding: 0 0 0 20px;
    margin: 0;
  }

  .jsondiffpatch-delta ul {
    list-style-type: none;
    padding: 0 0 0 20px;
    margin: 0;
  }

  .jsondiffpatch-left-value, .jsondiffpatch-right-value {
    vertical-align: top;
  }

  .jsondiffpatch-modified .jsondiffpatch-right-value:before {
    vertical-align: top;
    padding: 2px;
    color: #D381C3;
    content: ' => ';
  }

  .jsondiffpatch-added .jsondiffpatch-value pre,
  .jsondiffpatch-modified .jsondiffpatch-right-value pre,
  .jsondiffpatch-textdiff-added {
    background: rgba(161, 198 ,89, 0.4);
  }

  .jsondiffpatch-deleted pre,
  .jsondiffpatch-modified .jsondiffpatch-left-value pre,
  .jsondiffpatch-textdiff-deleted {
    background: rgba(251, 159 ,177, 0.4);
    text-decoration: line-through;
  }

  .jsondiffpatch-unchanged,
  .jsondiffpatch-movedestination {
    color: gray;
  }

  .jsondiffpatch-unchanged,
  .jsondiffpatch-movedestination > .jsondiffpatch-value {
    transition: all 0.5s;
    -webkit-transition: all 0.5s;
    overflow-y: hidden;
  }

  .jsondiffpatch-unchanged-showing .jsondiffpatch-unchanged,
  .jsondiffpatch-unchanged-showing .jsondiffpatch-movedestination > .jsondiffpatch-value {
    max-height: 100px;
  }

  .jsondiffpatch-unchanged-hidden .jsondiffpatch-unchanged,
  .jsondiffpatch-unchanged-hidden .jsondiffpatch-movedestination > .jsondiffpatch-value {
    max-height: 0;
  }

  .jsondiffpatch-unchanged-hiding .jsondiffpatch-movedestination > .jsondiffpatch-value,
  .jsondiffpatch-unchanged-hidden .jsondiffpatch-movedestination > .jsondiffpatch-value {
    display: block;
  }

  .jsondiffpatch-unchanged-visible .jsondiffpatch-unchanged,
  .jsondiffpatch-unchanged-visible .jsondiffpatch-movedestination > .jsondiffpatch-value {
    max-height: 100px;
  }

  .jsondiffpatch-unchanged-hiding .jsondiffpatch-unchanged,
  .jsondiffpatch-unchanged-hiding .jsondiffpatch-movedestination > .jsondiffpatch-value {
    max-height: 0;
  }

  .jsondiffpatch-unchanged-showing .jsondiffpatch-arrow,
  .jsondiffpatch-unchanged-hiding .jsondiffpatch-arrow {
    display: none;
  }

  .jsondiffpatch-value {
    display: inline-block;
  }

  .jsondiffpatch-property-name {
    display: inline-block;
    padding: 2px 0;
    padding-right: 5px;
    vertical-align: top;
    color: rgb(111, 179, 210);
  }

  .jsondiffpatch-property-name:after {
    content: ': ';
  }

  .jsondiffpatch-child-node-type-array > .jsondiffpatch-property-name:after {
    content: ': [';
  }

  .jsondiffpatch-child-node-type-array:after {
    content: '],';
  }

  div.jsondiffpatch-child-node-type-array:before {
    content: '[';
  }

  div.jsondiffpatch-child-node-type-array:after {
    content: ']';
  }

  .jsondiffpatch-child-node-type-object > .jsondiffpatch-property-name:after {
    content: ': {';
  }

  .jsondiffpatch-child-node-type-object:after {
    content: '},';
  }

  div.jsondiffpatch-child-node-type-object:before {
    content: '{';
  }

  div.jsondiffpatch-child-node-type-object:after {
    content: '}';
  }

  .jsondiffpatch-value pre:after {
    content: ',';
  }

  li:last-child > .jsondiffpatch-value pre:after,
  .jsondiffpatch-modified > .jsondiffpatch-left-value pre:after {
    content: '';
  }

  .jsondiffpatch-modified .jsondiffpatch-value {
    display: inline-block;
  }

  .jsondiffpatch-modified .jsondiffpatch-right-value {
    margin-left: 5px;
  }

  .jsondiffpatch-moved .jsondiffpatch-value {
    display: none;
  }

  .jsondiffpatch-moved .jsondiffpatch-moved-destination {
    display: inline-block;
    background: #ffffbb;
    color: #888;
  }

  .jsondiffpatch-moved .jsondiffpatch-moved-destination:before {
    content: ' => ';
  }

  ul.jsondiffpatch-textdiff {
    padding: 0;
  }

  .jsondiffpatch-textdiff-location {
    color: #bbb;
    display: inline-block;
    min-width: 60px;
  }

  .jsondiffpatch-textdiff-line {
    display: inline-block;
  }

  .jsondiffpatch-textdiff-line-number:after {
    content: ',';
  }

  .jsondiffpatch-error {
    background: red;
    color: white;
    font-weight: bold;
  }
`;

export default class VisualDiffTab extends Component {
  shouldComponentUpdate(nextProps) {
    return this.props.data !== nextProps.data;
  }

  render() {
    let __html;
    const data = this.props.data;
    if (data) {
      __html = format(data);
    }

    return <StyledContainer dangerouslySetInnerHTML={{ __html }} />;
  }
}

VisualDiffTab.propTypes = {
  data: PropTypes.object
};
<commit_msg>Fix diff collor<commit_after>import React, { Component, PropTypes } from 'react';
import { format } from 'jsondiffpatch/src/formatters/html';
import styled from 'styled-components';

export const StyledContainer = styled.div`
  width: 100%;
  height: 100%;
  overflow-y: auto;

  .jsondiffpatch-delta {
    font-family: monaco, Consolas, "Lucida Console", monospace;
    font-size: 12px;
    padding: 12px;
    margin: 0;
    display: inline-block;
  }

  .jsondiffpatch-delta pre {
    font-family: monaco, Consolas, "Lucida Console", monospace;
    font-size: 12px;
    margin: 0;
    padding: 2px 3px;
    border-radius: 3px;
    position: relative;
    color: #FFFFFF;
    display: inline-block;
  }

  ul.jsondiffpatch-delta {
    list-style-type: none;
    padding: 0 0 0 20px;
    margin: 0;
  }

  .jsondiffpatch-delta ul {
    list-style-type: none;
    padding: 0 0 0 20px;
    margin: 0;
  }

  .jsondiffpatch-left-value, .jsondiffpatch-right-value {
    vertical-align: top;
  }

  .jsondiffpatch-modified .jsondiffpatch-right-value:before {
    vertical-align: top;
    padding: 2px;
    color: #D381C3;
    content: ' => ';
  }

  .jsondiffpatch-added .jsondiffpatch-value pre,
  .jsondiffpatch-modified .jsondiffpatch-right-value pre,
  .jsondiffpatch-textdiff-added {
    background: rgba(161, 198 ,89, 0.4);
  }

  .jsondiffpatch-deleted pre,
  .jsondiffpatch-modified .jsondiffpatch-left-value pre,
  .jsondiffpatch-textdiff-deleted {
    background: rgba(251, 159 ,177, 0.4);
    text-decoration: line-through;
  }

  .jsondiffpatch-unchanged,
  .jsondiffpatch-movedestination {
    color: gray;
  }

  .jsondiffpatch-unchanged,
  .jsondiffpatch-movedestination > .jsondiffpatch-value {
    transition: all 0.5s;
    -webkit-transition: all 0.5s;
    overflow-y: hidden;
  }

  .jsondiffpatch-unchanged-showing .jsondiffpatch-unchanged,
  .jsondiffpatch-unchanged-showing .jsondiffpatch-movedestination > .jsondiffpatch-value {
    max-height: 100px;
  }

  .jsondiffpatch-unchanged-hidden .jsondiffpatch-unchanged,
  .jsondiffpatch-unchanged-hidden .jsondiffpatch-movedestination > .jsondiffpatch-value {
    max-height: 0;
  }

  .jsondiffpatch-unchanged-hiding .jsondiffpatch-movedestination > .jsondiffpatch-value,
  .jsondiffpatch-unchanged-hidden .jsondiffpatch-movedestination > .jsondiffpatch-value {
    display: block;
  }

  .jsondiffpatch-unchanged-visible .jsondiffpatch-unchanged,
  .jsondiffpatch-unchanged-visible .jsondiffpatch-movedestination > .jsondiffpatch-value {
    max-height: 100px;
  }

  .jsondiffpatch-unchanged-hiding .jsondiffpatch-unchanged,
  .jsondiffpatch-unchanged-hiding .jsondiffpatch-movedestination > .jsondiffpatch-value {
    max-height: 0;
  }

  .jsondiffpatch-unchanged-showing .jsondiffpatch-arrow,
  .jsondiffpatch-unchanged-hiding .jsondiffpatch-arrow {
    display: none;
  }

  .jsondiffpatch-value {
    display: inline-block;
  }

  .jsondiffpatch-property-name {
    display: inline-block;
    padding: 2px 0;
    padding-right: 5px;
    vertical-align: top;
    color: rgb(111, 179, 210);
  }

  .jsondiffpatch-property-name:after {
    content: ': ';
    color: #FFFFFF;
  }

  .jsondiffpatch-child-node-type-array > .jsondiffpatch-property-name:after {
    content: ': [';
  }

  .jsondiffpatch-child-node-type-array:after {
    content: '],';
  }

  div.jsondiffpatch-child-node-type-array:before {
    content: '[';
  }

  div.jsondiffpatch-child-node-type-array:after {
    content: ']';
  }

  .jsondiffpatch-child-node-type-object > .jsondiffpatch-property-name:after {
    content: ': {';
  }

  .jsondiffpatch-child-node-type-object:after {
    content: '},';
  }

  div.jsondiffpatch-child-node-type-object:before {
    content: '{';
  }

  div.jsondiffpatch-child-node-type-object:after {
    content: '}';
  }

  .jsondiffpatch-value pre:after {
    content: ',';
  }

  li:last-child > .jsondiffpatch-value pre:after,
  .jsondiffpatch-modified > .jsondiffpatch-left-value pre:after {
    content: '';
  }

  .jsondiffpatch-modified .jsondiffpatch-value {
    display: inline-block;
  }

  .jsondiffpatch-modified .jsondiffpatch-right-value {
    margin-left: 5px;
  }

  .jsondiffpatch-moved .jsondiffpatch-value {
    display: none;
  }

  .jsondiffpatch-moved .jsondiffpatch-moved-destination {
    display: inline-block;
    background: #ffffbb;
    color: #888;
  }

  .jsondiffpatch-moved .jsondiffpatch-moved-destination:before {
    content: ' => ';
  }

  ul.jsondiffpatch-textdiff {
    padding: 0;
  }

  .jsondiffpatch-textdiff-location {
    color: #bbb;
    display: inline-block;
    min-width: 60px;
  }

  .jsondiffpatch-textdiff-line {
    display: inline-block;
  }

  .jsondiffpatch-textdiff-line-number:after {
    content: ',';
  }

  .jsondiffpatch-error {
    background: red;
    color: white;
    font-weight: bold;
  }
`;

export default class VisualDiffTab extends Component {
  shouldComponentUpdate(nextProps) {
    return this.props.data !== nextProps.data;
  }

  render() {
    let __html;
    const data = this.props.data;
    if (data) {
      __html = format(data);
    }

    return <StyledContainer dangerouslySetInnerHTML={{ __html }} />;
  }
}

VisualDiffTab.propTypes = {
  data: PropTypes.object
};
<|endoftext|>


<commit_before>import angular from 'angular';
import {Inject, Bind} from 'angular-es-utils';

@Inject('$scope', '$element')
export default class DropdownSelectCtrl {
	// 选项 item 字段映射
	static defaultMapping = {
		valueField: 'value',
		displayField: 'title'
	};

	constructor() {
		this.datalist = [];
		this._clampedDatalist = [];
		this.items = [];
		this.mapping = {};
		this.title = '';
		this.placeholder = '';
		this.searchable = false;
		this.model = null;
		this.focusIndex = 0;
		this.isOpen = false;
		this.isActive = false;

		this._openFn = null;
	}

	$onInit() {
		this._prepareOptions();
		this._prepareWatches();
	}

	$postLink() {
		this._prepareMouseEvents();
		this._prepareKeyboardEvents();
	}

	_prepareOptions() {
		const defaultMapping = DropdownSelectCtrl.defaultMapping;
		this.mapping = Object.assign({}, defaultMapping, this.mapping);

		if (typeof this.disabled === 'undefined') {
			this.disabled = false;
		}
	}

	_prepareWatches() {
		const scope = this.getScope();

		scope.$watch(() => this.datalist, (datalist, oldDatalist) => {
			this.items = this._clampedDatalist = this._getClampedDatalist(datalist || []);

			// 选中预设值
			this.setModelValue(this.model);
		});

		scope.$watch(() => this.model, (model, oldModel) => {
			if (!angular.equals(model, oldModel)) {
				this.setModelValue(this.model);
			}
		});

		if (this.disabled) {
			scope.$watch(() => this.isOpen, (openState, oldOpenstate) => {
				if (openState) {
					this.isOpen = false;
				}
			});
		}
	}

	_prepareMouseEvents() {
		let inputElement = this.getInputElement();

		if (!this.searchable) {
			inputElement.addEventListener('click', this.toggle);
		} else {
			this._openFn = this::(event => {
				let scope = this.getScope();
				this.open();
				scope.$root.$$phase || scope.$apply();
				inputElement.removeEventListener('click', this._openFn);
			});
			inputElement.addEventListener('click', this._openFn);
		}
	}

	_prepareKeyboardEvents() {
		let keydownFn = event => {
			let scope = this.getScope();
			let keyCode = event.keyCode;
			if (!this.isOpen) {
				// 下拉激活且关闭时，按 回车、上、下 键打开下拉
				if (keyCode === 13 || keyCode === 38 || keyCode === 40) {
					this.open();
				}
			} else {
				switch (keyCode) {
					case 13: // enter
						this.selectItemAt(this.focusIndex);
						break;
					case 38: // up
						this.focusUp();
						event.preventDefault();
						break;
					case 40: // down
						this.focusDown();
						event.preventDefault();
						break;
					default:
				}
			}
			scope.$root.$$phase || scope.$apply();
		};

		this.getScope().$watch(() => this.isActive, (isActive, oldState) => {
			if (isActive !== oldState) {
				let inputElement = this.getInputElement();
				if (isActive) {
					inputElement.addEventListener('keydown', keydownFn);
				} else {
					inputElement.removeEventListener('keydown', keydownFn);
				}
			}
		});
	}

	onSearchTextChange(text, oldText) {
		if (text !== oldText) {
			text = text.trim();
			if (!this.isOpen) {
				this.open();
			}
			if (text.length) {
				this._search(text);
			} else {
				this.setModelValue(null);
				this.items = this._clampedDatalist;
			}
			this.focusAt(0);
		}
	}

	onOpen() {
		let scope = this.getScope();
		this.getInputElement().focus();
		if (this.searchable && this.title.length) {
			this._search(this.title);
			this.focusAt(0);
			scope.$root.$$phase || scope.$apply();
		}
	}

	onClose() {
		let scope = this.getScope();
		if (this.searchable) {
			this.getInputElement().addEventListener('click', this._openFn);
			this.setModelValue(this.model);
			scope.$root.$$phase || scope.$apply();
		}
	}

	setModelValue(modelValue) {
		if (modelValue !== null) {
			let valueField = this.mapping.valueField;
			let modelExisted = this.items.some(item => {
				if (angular.equals(item[valueField], this.model)) {
					this.title = item[this.mapping.displayField];
					return true;
				}
			});
			if (!modelExisted) {
				this.title = '';
				this.model = null;
			}
		} else {
			this.title = '';
			this.model = null;
		}
	}

	clear() {
		this.setModelValue(null);
		this.items = this._getClampedDatalist(this.datalist);
		this.getInputElement().focus();
		this.focusAt(0);
	}

	@Bind
	toggle() {
		let scope = this.getScope();
		if (this.isOpen) {
			this.close();
		} else {
			this.open();
		}
		scope.$root.$$phase || scope.$apply();
	}

	open() {
		this.isOpen = true;
	}

	close() {
		this.isOpen = false;
	}

	selectItemAt(index) {
		let item = this.items[index];
		if (item) {
			this.title = item[this.mapping.displayField];
			this.model = item[this.mapping.valueField];
			this.focusAt(index);
			this.close();
		}
	}

	focusAt(index) {
		this.focusIndex = index;
	}

	focusUp() {
		let index = this.focusIndex - 1;
		if (index < 0) {
			index = 0;
		}
		this.focusAt(index);

		let itemElement = this.getItemElementAt(index);
		if (itemElement) {
			itemElement.scrollIntoView(true);
		}
	}

	focusDown() {
		let listCount = this.items.length;
		let index = this.focusIndex + 1;
		if (index > listCount - 1) {
			index = listCount - 1;
		}
		this.focusAt(index);

		let itemElement = this.getItemElementAt(index);
		if (itemElement) {
			itemElement.scrollIntoView(false);
		}
	}

	getElement() {
		return this._$element[0];
	}

	getInputElement() {
		return this.getElement().querySelector('.dropdown-select-input');
	}

	getItemElementAt(index) {
		return this.getElement()
				.querySelector('.dropdown-list')
				.querySelectorAll('li:not(.empty-list-item)')[index];
	}

	getScope() {
		return this._$scope;
	}

	highlight(content, hiText) {
		if (!this.searchable || !hiText) {
			return content;
		}
		return content.replace(new RegExp(hiText, 'gi'), '$&');
	}

	_getClampedDatalist(datalist) {
		// 将每个 item 构造为对象
		// e.g. 将 ['北京', '上海'] 构造为
		// [{title: '北京', value: '北京'}, {title: '上海', value: '上海'}]
		return datalist.map(item => {
			if (typeof item !== 'object') {
				return {
					[this.mapping.displayField]: item,
					[this.mapping.valueField]: item
				};
			} else {
				return item;
			}
		});
	}

	_search(text) {
		let datalist = this._clampedDatalist;
		let mapping = this.mapping;
		let searchFields = [mapping.valueField, mapping.displayField];
		let filteredItems = [];

		searchFields.forEach(field => {
			datalist.forEach(item => {
				const fieldValue = item[field];
				if (fieldValue.toString().indexOf(text) !== -1 &&
						filteredItems.indexOf(item) === -1) {

					filteredItems.push(item);
				}
			});
		});

		this.items = filteredItems;
	}
};

<commit_msg>fix(dropdown): 初始化时, 下拉框 focus 位置不对 (#159)<commit_after>import angular from 'angular';
import {Inject, Bind} from 'angular-es-utils';

@Inject('$scope', '$element')
export default class DropdownSelectCtrl {
	// 选项 item 字段映射
	static defaultMapping = {
		valueField: 'value',
		displayField: 'title'
	};

	constructor() {
		this.datalist = [];
		this._clampedDatalist = [];
		this.items = [];
		this.mapping = {};
		this.title = '';
		this.placeholder = '';
		this.searchable = false;
		this.model = null;
		this.focusIndex = 0;
		this.isOpen = false;
		this.isActive = false;

		this._openFn = null;
	}

	$onInit() {
		this._prepareOptions();
		this._prepareWatches();
	}

	$postLink() {
		this._prepareMouseEvents();
		this._prepareKeyboardEvents();
	}

	_prepareOptions() {
		const defaultMapping = DropdownSelectCtrl.defaultMapping;
		this.mapping = Object.assign({}, defaultMapping, this.mapping);

		if (typeof this.disabled === 'undefined') {
			this.disabled = false;
		}
	}

	_prepareWatches() {
		const scope = this.getScope();

		scope.$watch(() => this.datalist, (datalist, oldDatalist) => {
			this.items = this._clampedDatalist = this._getClampedDatalist(datalist || []);

			// 选中预设值
			this.setModelValue(this.model);
			// 设置预设值的 focusIndex
			this.focusAt(this.getItemIndexByItemValue(this.model, this.items));
		});

		scope.$watch(() => this.model, (model, oldModel) => {
			if (!angular.equals(model, oldModel)) {
				this.setModelValue(this.model);
			}
		});

		if (this.disabled) {
			scope.$watch(() => this.isOpen, (openState, oldOpenstate) => {
				if (openState) {
					this.isOpen = false;
				}
			});
		}
	}

	_prepareMouseEvents() {
		let inputElement = this.getInputElement();

		if (!this.searchable) {
			inputElement.addEventListener('click', this.toggle);
		} else {
			this._openFn = this::(event => {
				let scope = this.getScope();
				this.open();
				scope.$root.$$phase || scope.$apply();
				inputElement.removeEventListener('click', this._openFn);
			});
			inputElement.addEventListener('click', this._openFn);
		}
	}

	_prepareKeyboardEvents() {
		let keydownFn = event => {
			let scope = this.getScope();
			let keyCode = event.keyCode;
			if (!this.isOpen) {
				// 下拉激活且关闭时，按 回车、上、下 键打开下拉
				if (keyCode === 13 || keyCode === 38 || keyCode === 40) {
					this.open();
				}
			} else {
				switch (keyCode) {
					case 13: // enter
						this.selectItemAt(this.focusIndex);
						break;
					case 38: // up
						this.focusUp();
						event.preventDefault();
						break;
					case 40: // down
						this.focusDown();
						event.preventDefault();
						break;
					default:
				}
			}
			scope.$root.$$phase || scope.$apply();
		};

		this.getScope().$watch(() => this.isActive, (isActive, oldState) => {
			if (isActive !== oldState) {
				let inputElement = this.getInputElement();
				if (isActive) {
					inputElement.addEventListener('keydown', keydownFn);
				} else {
					inputElement.removeEventListener('keydown', keydownFn);
				}
			}
		});
	}

	onSearchTextChange(text, oldText) {
		if (text !== oldText) {
			text = text.trim();
			if (!this.isOpen) {
				this.open();
			}
			if (text.length) {
				this._search(text);
			} else {
				this.setModelValue(null);
				this.items = this._clampedDatalist;
			}
			this.focusAt(0);
		}
	}

	onOpen() {
		let scope = this.getScope();
		this.getInputElement().focus();
		if (this.searchable && this.title.length) {
			this._search(this.title);
			this.focusAt(0);
			scope.$root.$$phase || scope.$apply();
		}
	}

	onClose() {
		let scope = this.getScope();
		if (this.searchable) {
			this.getInputElement().addEventListener('click', this._openFn);
			this.setModelValue(this.model);
			scope.$root.$$phase || scope.$apply();
		}
	}

	setModelValue(modelValue) {
		if (modelValue !== null) {
			let valueField = this.mapping.valueField;
			let modelExisted = this.items.some(item => {
				if (angular.equals(item[valueField], this.model)) {
					this.title = item[this.mapping.displayField];
					return true;
				}
			});
			if (!modelExisted) {
				this.title = '';
				this.model = null;
			}
		} else {
			this.title = '';
			this.model = null;
		}
	}

	clear() {
		this.setModelValue(null);
		this.items = this._getClampedDatalist(this.datalist);
		this.getInputElement().focus();
		this.focusAt(0);
	}

	@Bind
	toggle() {
		let scope = this.getScope();
		if (this.isOpen) {
			this.close();
		} else {
			this.open();
		}
		scope.$root.$$phase || scope.$apply();
	}

	open() {
		this.isOpen = true;
	}

	close() {
		this.isOpen = false;
	}

	selectItemAt(index) {
		let item = this.items[index];
		if (item) {
			this.title = item[this.mapping.displayField];
			this.model = item[this.mapping.valueField];
			this.focusAt(index);
			this.close();
		}
	}

	focusAt(index) {
		this.focusIndex = index;
	}

	focusUp() {
		let index = this.focusIndex - 1;
		if (index < 0) {
			index = 0;
		}
		this.focusAt(index);

		let itemElement = this.getItemElementAt(index);
		if (itemElement) {
			itemElement.scrollIntoView(true);
		}
	}

	focusDown() {
		let listCount = this.items.length;
		let index = this.focusIndex + 1;
		if (index > listCount - 1) {
			index = listCount - 1;
		}
		this.focusAt(index);

		let itemElement = this.getItemElementAt(index);
		if (itemElement) {
			itemElement.scrollIntoView(false);
		}
	}

	getElement() {
		return this._$element[0];
	}

	getInputElement() {
		return this.getElement().querySelector('.dropdown-select-input');
	}

	getItemElementAt(index) {
		return this.getElement()
				.querySelector('.dropdown-list')
				.querySelectorAll('li:not(.empty-list-item)')[index];
	}

	getScope() {
		return this._$scope;
	}

	highlight(content, hiText) {
		if (!this.searchable || !hiText) {
			return content;
		}
		return content.replace(new RegExp(hiText, 'gi'), '$&');
	}

	getItemIndexByItemValue(ItemValue, items) {
		return items.findIndex(item => {
			return item[this.mapping.valueField] === ItemValue;
		});
	}

	_getClampedDatalist(datalist) {
		// 将每个 item 构造为对象
		// e.g. 将 ['北京', '上海'] 构造为
		// [{title: '北京', value: '北京'}, {title: '上海', value: '上海'}]
		return datalist.map(item => {
			if (typeof item !== 'object') {
				return {
					[this.mapping.displayField]: item,
					[this.mapping.valueField]: item
				};
			} else {
				return item;
			}
		});
	}

	_search(text) {
		let datalist = this._clampedDatalist;
		let mapping = this.mapping;
		let searchFields = [mapping.valueField, mapping.displayField];
		let filteredItems = [];

		searchFields.forEach(field => {
			datalist.forEach(item => {
				const fieldValue = item[field];
				if (fieldValue.toString().indexOf(text) !== -1 &&
						filteredItems.indexOf(item) === -1) {

					filteredItems.push(item);
				}
			});
		});

		this.items = filteredItems;
	}
};

<|endoftext|>


<commit_before>/**
 * @author vincent loh <vincent.ml@gmail.com>
 * @update J Manuel Corona <jmcg92@gmail.com>
 * @update zhixin wen <wenzhixin2010@gmail.com>
 */

const Utils = $.fn.bootstrapTable.utils

$.extend($.fn.bootstrapTable.defaults, {
  stickyHeader: false,
  stickyHeaderOffsetY: 0,
  stickyHeaderOffsetLeft: 0,
  stickyHeaderOffsetRight: 0
})

const hiddenClass = {
  bootstrap3: 'hidden'
}[$.fn.bootstrapTable.theme] || 'd-none'

$.BootstrapTable = class extends $.BootstrapTable {
  initHeader (...args) {
    super.initHeader(...args)

    if (!this.options.stickyHeader) {
      return
    }

    this.$el.before('

')
    this.$el.before('

')
    this.$el.after('

')
    this.$header.addClass('sticky-header')

    // clone header just once, to be used as sticky header
    // deep clone header, using source header affects tbody>td width
    this.$stickyContainer = this.$tableBody.find('.sticky-header-container')
    this.$stickyBegin = this.$tableBody.find('.sticky_anchor_begin')
    this.$stickyEnd = this.$tableBody.find('.sticky_anchor_end')
    this.$stickyHeader = this.$header.clone(true, true)

    // render sticky on window scroll or resize
    $(window).on('resize.sticky-header-table', () => this.renderStickyHeader())
    $(window).on('scroll.sticky-header-table', () => this.renderStickyHeader())
    this.$tableBody.off('scroll').on('scroll', () => this.matchPositionX())
  }

  renderStickyHeader () {
    const top = $(window).scrollTop()
    // top anchor scroll position, minus header height
    const start = this.$stickyBegin.offset().top - this.options.stickyHeaderOffsetY
    // bottom anchor scroll position, minus header height, minus sticky height
    const end = this.$stickyEnd.offset().top - this.options.stickyHeaderOffsetY - this.$header.height()
    // show sticky when top anchor touches header, and when bottom anchor not exceeded
    if (top > start && top <= end) {
      // ensure clone and source column widths are the same
      this.$stickyHeader.find('tr:eq(0)').find('th').each((index, el) => {
        $(el).css('min-width', this.$header.find('tr:eq(0)').find('th').eq(index).css('width'))
      })
      // match bootstrap table style
      this.$stickyContainer.removeClass(hiddenClass).addClass('fix-sticky fixed-table-container')
      // stick it in position
      this.$stickyContainer.css('top', `${this.options.stickyHeaderOffsetY}`)
      this.$stickyContainer.css('left', `${this.options.stickyHeaderOffsetLeft}`)
      this.$stickyContainer.css('right', `${this.options.stickyHeaderOffsetRight}`)
      // create scrollable container for header
      this.$stickyTable = $('
')
      this.$stickyTable.addClass(this.options.classes)
      // append cloned header to dom
      this.$stickyContainer.html(this.$stickyTable.append(this.$stickyHeader))
      // match clone and source header positions when left-right scroll
      this.matchPositionX()
    } else {
      this.$stickyContainer.removeClass('fix-sticky').addClass(hiddenClass)
    }
  }

  matchPositionX () {
    this.$stickyContainer.scrollLeft(this.$tableBody.scrollLeft())
  }
}
<commit_msg>Fixed sticky header not work bug with fullscreen (#4717)<commit_after>/**
 * @author vincent loh <vincent.ml@gmail.com>
 * @update J Manuel Corona <jmcg92@gmail.com>
 * @update zhixin wen <wenzhixin2010@gmail.com>
 */

const Utils = $.fn.bootstrapTable.utils

$.extend($.fn.bootstrapTable.defaults, {
  stickyHeader: false,
  stickyHeaderOffsetY: 0,
  stickyHeaderOffsetLeft: 0,
  stickyHeaderOffsetRight: 0
})

const hiddenClass = {
  bootstrap3: 'hidden'
}[$.fn.bootstrapTable.theme] || 'd-none'

$.BootstrapTable = class extends $.BootstrapTable {
  initHeader (...args) {
    super.initHeader(...args)

    if (!this.options.stickyHeader) {
      return
    }

    this.$el.before('

')
    this.$el.before('

')
    this.$el.after('

')
    this.$header.addClass('sticky-header')

    // clone header just once, to be used as sticky header
    // deep clone header, using source header affects tbody>td width
    this.$stickyContainer = this.$tableBody.find('.sticky-header-container')
    this.$stickyBegin = this.$tableBody.find('.sticky_anchor_begin')
    this.$stickyEnd = this.$tableBody.find('.sticky_anchor_end')
    this.$stickyHeader = this.$header.clone(true, true)

    // render sticky on window scroll or resize
    $(window).off('resize.sticky-header-table')
      .on('resize.sticky-header-table', () => this.renderStickyHeader())
    $(window).off('scroll.sticky-header-table')
      .on('scroll.sticky-header-table', () => this.renderStickyHeader())
    this.$tableBody.off('scroll').on('scroll', () => this.matchPositionX())
  }

  resetView (...args) {
    super.resetView(...args)

    $('.bootstrap-table.fullscreen').off('scroll')
      .on('scroll', () => this.renderStickyHeader())
  }

  renderStickyHeader () {
    const top = $(window).scrollTop()
    // top anchor scroll position, minus header height
    const start = this.$stickyBegin.offset().top - this.options.stickyHeaderOffsetY
    // bottom anchor scroll position, minus header height, minus sticky height
    const end = this.$stickyEnd.offset().top - this.options.stickyHeaderOffsetY - this.$header.height()
    // show sticky when top anchor touches header, and when bottom anchor not exceeded
    if (top > start && top <= end) {
      // ensure clone and source column widths are the same
      this.$stickyHeader.find('tr:eq(0)').find('th').each((index, el) => {
        $(el).css('min-width', this.$header.find('tr:eq(0)').find('th').eq(index).css('width'))
      })
      // match bootstrap table style
      this.$stickyContainer.removeClass(hiddenClass).addClass('fix-sticky fixed-table-container')
      // stick it in position
      let stickyHeaderOffsetLeft = this.options.stickyHeaderOffsetLeft
      let stickyHeaderOffsetRight = this.options.stickyHeaderOffsetRight
      if (this.$el.closest('.bootstrap-table').hasClass('fullscreen')) {
        stickyHeaderOffsetLeft = 0
        stickyHeaderOffsetRight = 0
      }
      this.$stickyContainer.css('top', `${this.options.stickyHeaderOffsetY}`)
      this.$stickyContainer.css('left', `${stickyHeaderOffsetLeft}`)
      this.$stickyContainer.css('right', `${stickyHeaderOffsetRight}`)
      // create scrollable container for header
      this.$stickyTable = $('
')
      this.$stickyTable.addClass(this.options.classes)
      // append cloned header to dom
      this.$stickyContainer.html(this.$stickyTable.append(this.$stickyHeader))
      // match clone and source header positions when left-right scroll
      this.matchPositionX()
    } else {
      this.$stickyContainer.removeClass('fix-sticky').addClass(hiddenClass)
    }
  }

  matchPositionX () {
    this.$stickyContainer.scrollLeft(this.$tableBody.scrollLeft())
  }
}
<|endoftext|>


<commit_before>var cli = require('cli');
var exec = require('child_process').exec;
var fs = require('fs');
var knownCameras = require('./knownCameras.json');
var _ = require('underscore');
var q = require('q');

function getSerialIDForCamera(camera) {
  var defer  = q.defer();
  exec('udevadm info --query=all --name='+camera+' | grep ID_SERIAL_SHORT', function (err, result) {
    if(err) {
      cli.fatal(err);
    }
    if(result.indexOf('ID_SERIAL_SHORT=') > -1) {
      var justId = (result.match(/ID_SERIAL_SHORT=(.+)/))[1];
      defer.resolve(_.findWhere(knownCameras, { id: justId }));
    }
    else {
      defer.resolve(undefined);
    }
  });
  return defer.promise;
}

//I don't like any of this...
function generateVLCStreamCommands(options, cameras) {
  //like srsly kill me
  var vlcCommands = []
  cameras.forEach(function (camera) {
    var defer = q.defer();
    getSerialIDForCamera(camera).then(function startStream(cameraInfo) {
      //console.log(cameraInfo);
      if(cameraInfo && cameraInfo.name) {
        cli.info(cameraInfo.name + ' recognized with serial ' + cameraInfo.id + '.\n\tOpened on Port: ' + (parseInt(options.port) + cameraInfo.port_increment));
        var cmd = "cvlc "+ (options.verbose ? '-vvv' : '');
            cmd += "v4l2://"+camera+":width="+options.width+":height="+options.height+":fps="+options.fps + ' --live-caching 200 ';
            cmd += "--sout '#transcode{vcodec=h264,venc=x264{preset=ultrafast}vb="+options.bitrate;
            cmd += ",acodec=none}:duplicate{dst=file{dst=" + options.filename + '-' + cameraInfo.name.replace(/ /g, '') + ".mp4},dst=rtp{sdp=rtsp://:";
            cmd += (parseInt(options.port)+cameraInfo.port_increment)+"/}}'";
        cli.info(cmd)
        defer.resolve(cmd);
      }
      else {
        cli.warn('Unknown Camera ' + camera +'. Register in knownCameras.json');
        defer.resolve(undefined);
      }
    });
    vlcCommands.push(defer.promise);
  });
  return q.all(vlcCommands);
}

function killPID(pid) {
  if(pid.length > 0) {
    var command = 'kill ' + pid;
    exec(command, function callback(err, result) {
        var result = (err || result || 'success').toString();
        if(result.indexOf('No such process') > -1) {
          result = 'Was already deleted';
        }
        cli.info('Result of [' + command + ']: ' + result);
    });
  }
}

//Manually reads in the pids file and deletes all pids
function closeOpenStreams() {
  var file = 'do-not-delete-manually.hyperloop';
  if(fs.existsSync(file)) {
    var pids = fs.readFileSync('do-not-delete-manually.hyperloop');
    if(pids && pids.length > 1) {
      pids = pids.toString().split("\n");
      //cli.info('Manually Kiling the following pids: ' + pids);
      for(var index in pids) {
        killPID(pids[index]);
      }
    }
    else {
      cli.info('Could not read pids file (do-not-delete-manually)');
    }
  }

  return 0;
}

cli.parse({
  width: ['w', 'Width of video to streams', 'int', 640],
  height: ['h', 'Height of the video streams', 'int', 480],
  bitrate: ['b', 'Requested bitrate from streams', 'int', 4000],
  filename: ['f', 'Filename base to write the streams (test#.mp4)', 'string', 'test'],
  fps: ['fps', 'Frames per second that the camera should attempt to capture', 'int', 45],
  port: ['p', 'Default starting port to broadcast over -- increments by 1 for each camera', 'int', 8554],
  verbose: [false, 'If on, will log out all of VLCs garbage', 'bool', false],
  close: [false, 'When a stream is launched the Processs ID is tracked, if there is an interrupt of communication between client and server, this will explicitly close any opened streams']
});

cli.main(function mainEntryPoint(args, options) {

  //if the close option is set, we don't even bother with reading, we try to open
  //up pid file, and read in the pids, afterwards we delete the pid file and
  //move on
  if(options.close) {
    closeOpenStreams();
  }
  else {
    //start by grabbing all camera
    fs.readdir('/dev/', function getCameras(err, files) {
      if(err) {
        cli.fatal(err);
      }
      var cameras = [];
      files.forEach(function (file) {
        if(file.indexOf('video') > -1) {
          cameras.push('/dev/' + file);
        }
      });
      cli.info('Found Cameras: ' + cameras);
      return generateVLCStreamCommands(options, cameras).then(function runCommands(commands) {
        commands.forEach(function (command) {
          exec(command);
        });

        //just use a pipe so i don't have to launch an fs writer
        exec('pgrep -f vlc > do-not-delete-manually.hyperloop', function(err, pids, stderr) {
          if(err) {
             cli.fatal('Could not obtain the VLC pids');
          }
        });

      });
    });
  }
});

<commit_msg>Change stream type to hv32<commit_after>var cli = require('cli');
var exec = require('child_process').exec;
var fs = require('fs');
var knownCameras = require('./knownCameras.json');
var _ = require('underscore');
var q = require('q');

function getSerialIDForCamera(camera) {
  var defer  = q.defer();
  exec('udevadm info --query=all --name='+camera+' | grep ID_SERIAL_SHORT', function (err, result) {
    if(err) {
      cli.fatal(err);
    }
    if(result.indexOf('ID_SERIAL_SHORT=') > -1) {
      var justId = (result.match(/ID_SERIAL_SHORT=(.+)/))[1];
      defer.resolve(_.findWhere(knownCameras, { id: justId }));
    }
    else {
      defer.resolve(undefined);
    }
  });
  return defer.promise;
}

//I don't like any of this...
function generateVLCStreamCommands(options, cameras) {
  //like srsly kill me
  var vlcCommands = []
  cameras.forEach(function (camera) {
    var defer = q.defer();
    getSerialIDForCamera(camera).then(function startStream(cameraInfo) {
      //console.log(cameraInfo);
      if(cameraInfo && cameraInfo.name) {
        cli.info(cameraInfo.name + ' recognized with serial ' + cameraInfo.id + '.\n\tOpened on Port: ' + (parseInt(options.port) + cameraInfo.port_increment));
        var cmd = "cvlc "+ (options.verbose ? '-vvv' : '');
            cmd += "v4l2://"+camera+":width="+options.width+":height="+options.height+":fps="+options.fps + ' --live-caching 200 ';
            cmd += "--sout '#transcode{vcodec=hv32,venc=x264{preset=ultrafast}vb="+options.bitrate;
            cmd += ",acodec=none}:duplicate{dst=file{dst=" + options.filename + '-' + cameraInfo.name.replace(/ /g, '') + ".mp4},dst=rtp{sdp=rtsp://:";
            cmd += (parseInt(options.port)+cameraInfo.port_increment)+"/}}'";
        cli.info(cmd)
        defer.resolve(cmd);
      }
      else {
        cli.warn('Unknown Camera ' + camera +'. Register in knownCameras.json');
        defer.resolve(undefined);
      }
    });
    vlcCommands.push(defer.promise);
  });
  return q.all(vlcCommands);
}

//We don't use pkill here to avoid killing processess that aren't ours
function killPID(pid) {
  if(pid.length > 0) {
    var command = 'kill ' + pid;
    exec(command, function callback(err, result) {
        var result = (err || result || 'success').toString();
        if(result.indexOf('No such process') > -1) {
          result = 'Was already deleted';
        }
        cli.info('Result of [' + command + ']: ' + result);
    });
  }
}

//Manually reads in the pids file and deletes all pids
function closeOpenStreams() {
  var file = 'do-not-delete-manually.hyperloop';
  if(fs.existsSync(file)) {
    var pids = fs.readFileSync('do-not-delete-manually.hyperloop');
    if(pids && pids.length > 1) {
      pids = pids.toString().split("\n");
      //cli.info('Manually Kiling the following pids: ' + pids);
      for(var index in pids) {
        killPID(pids[index]);
      }
    }
    else {
      cli.info('Could not read pids file (do-not-delete-manually)');
    }
  }

  return 0;
}

cli.parse({
  width: ['w', 'Width of video to streams', 'int', 640],
  height: ['h', 'Height of the video streams', 'int', 480],
  bitrate: ['b', 'Requested bitrate from streams', 'int', 4000],
  filename: ['f', 'Filename base to write the streams (test#.mp4)', 'string', 'test'],
  fps: ['fps', 'Frames per second that the camera should attempt to capture', 'int', 45],
  port: ['p', 'Default starting port to broadcast over -- increments by 1 for each camera', 'int', 8554],
  verbose: [false, 'If on, will log out all of VLCs garbage', 'bool', false],
  close: [false, 'When a stream is launched the Processs ID is tracked, if there is an interrupt of communication between client and server, this will explicitly close any opened streams']
});

cli.main(function mainEntryPoint(args, options) {

  //if the close option is set, we don't even bother with reading, we try to open
  //up pid file, and read in the pids, afterwards we delete the pid file and
  //move on
  if(options.close) {
    closeOpenStreams();
  }
  else {
    //start by grabbing all camera
    fs.readdir('/dev/', function getCameras(err, files) {
      if(err) {
        cli.fatal(err);
      }
      var cameras = [];
      files.forEach(function (file) {
        if(file.indexOf('video') > -1) {
          cameras.push('/dev/' + file);
        }
      });
      cli.info('Found Cameras: ' + cameras);
      return generateVLCStreamCommands(options, cameras).then(function runCommands(commands) {
        commands.forEach(function (command) {
          exec(command);
        });

        //just use a pipe so i don't have to launch an fs writer
        exec('pgrep -f vlc > do-not-delete-manually.hyperloop', function(err, pids, stderr) {
          if(err) {
             cli.fatal('Could not obtain the VLC pids');
          }
        });

      });
    });
  }
});

<|endoftext|>


<commit_before>"use strict"

var ndarray = require("ndarray")
var createBuffer = require("gl-buffer")
var createVAO = require("gl-vao")
var createAOMesh = require("./mesh.js")
var ops = require("ndarray-ops")
var glm = require("gl-matrix")
var mat4 = glm.mat4

//Creates a mesh from a set of voxels
function createVoxelMesh(gl, voxels, voxelSideTextureIDs, voxelSideTextureSizes, position) {
  //Create mesh
  var vert_data = createAOMesh(voxels, voxelSideTextureIDs, voxelSideTextureSizes)
  if (vert_data === null) return null // no vertices allocated

  //Upload triangle mesh to WebGL
  var triangleVertexCount = Math.floor(vert_data.length/8)
  var vert_buf = createBuffer(gl, vert_data)
  var triangleVAO = createVAO(gl, [
    { "buffer": vert_buf,
      "type": gl.UNSIGNED_BYTE,
      "size": 4,
      "offset": 0,
      "stride": 8,
      "normalized": false
    },
    { "buffer": vert_buf,
      "type": gl.UNSIGNED_BYTE,
      "size": 4,
      "offset": 4,
      "stride": 8,
      "normalized": false
    }
  ])

  // move the chunk into place
  var modelMatrix = mat4.create()
  var translateVector = [
    position[2] * (voxels.shape[2] - 2),
    position[1] * (voxels.shape[1] - 2),
    position[0] * (voxels.shape[0] - 2)]

  mat4.translate(modelMatrix, modelMatrix, translateVector)

  //Bundle result and return
  var result = {
    triangleVertexCount: triangleVertexCount,
    triangleVAO: triangleVAO,
    center: [voxels.shape[0]>>1, voxels.shape[1]>>1, voxels.shape[2]>>1],
    radius: voxels.shape[2],
    modelMatrix: modelMatrix
  }

  if (this) this.emit('meshed', result, gl, vert_data, voxels)

  return result
}

module.exports = createVoxelMesh
<commit_msg>Change createVoxelMesh() to not return null for no vertices<commit_after>"use strict"

var ndarray = require("ndarray")
var createBuffer = require("gl-buffer")
var createVAO = require("gl-vao")
var createAOMesh = require("./mesh.js")
var ops = require("ndarray-ops")
var glm = require("gl-matrix")
var mat4 = glm.mat4

//Creates a mesh from a set of voxels
function createVoxelMesh(gl, voxels, voxelSideTextureIDs, voxelSideTextureSizes, position) {
  //Create mesh
  var vert_data = createAOMesh(voxels, voxelSideTextureIDs, voxelSideTextureSizes)
  var triangleVertexCount, triangleVAO

  if (vert_data === null) {
    // no vertices allocated
    triangleVertexCount = 0
    triangleVAO = null
  } else {
    //Upload triangle mesh to WebGL
    triangleVertexCount = Math.floor(vert_data.length/8)
    var vert_buf = createBuffer(gl, vert_data)
    triangleVAO = createVAO(gl, [
      { "buffer": vert_buf,
        "type": gl.UNSIGNED_BYTE,
        "size": 4,
        "offset": 0,
        "stride": 8,
        "normalized": false
      },
      { "buffer": vert_buf,
        "type": gl.UNSIGNED_BYTE,
        "size": 4,
        "offset": 4,
        "stride": 8,
        "normalized": false
      }
    ])
  }

  // move the chunk into place
  var modelMatrix = mat4.create()
  var translateVector = [
    position[2] * (voxels.shape[2] - 2),
    position[1] * (voxels.shape[1] - 2),
    position[0] * (voxels.shape[0] - 2)]

  mat4.translate(modelMatrix, modelMatrix, translateVector)

  //Bundle result and return
  var result = {
    triangleVertexCount: triangleVertexCount,
    triangleVAO: triangleVAO,
    center: [voxels.shape[0]>>1, voxels.shape[1]>>1, voxels.shape[2]>>1],
    radius: voxels.shape[2],
    modelMatrix: modelMatrix
  }

  if (this) this.emit('meshed', result, gl, vert_data, voxels)

  return result
}

module.exports = createVoxelMesh
<|endoftext|>


<commit_before>'use strict';

const Util = require('./Util.js');
const { define } = require('./decorators.js');

@define({
    chains: [ 'ctor', 'dtor' ],

    processors: {
        prototype: null,
        chains: 'prototype',
        mixins: 'chains',
        config: 'mixins'
    },

    properties: {
        isInstance: {
            value: true
        }
    },

    prototype: {
        configuring: false,
        constructing: true,
        destroying: false,
        destroyed: false
    }
})
class Base {
    constructor (...args) {
        let me = this;
        let C = me.constructor;
        let meta = me.$meta;

        if (meta.class !== C) {
            meta = C.getMeta();
        }

        // After the above code has executed "this.$meta" will always be valid for an
        // instance. This is a helpful performance gain since it allows us to avoid a
        // method call every time we want the meta class.

        if (!meta.instances++ && !meta.completed) {
            meta.complete();
        }

        me.construct(...args);
    }

    construct (config) {
        let me = this;
        let meta = me.$meta;

        if (config || meta.configs) {
            me.configuring = true;

            me.configure(config);

            me.configuring = false;
        }

        if (meta.liveChains.ctor) {
            meta.callChain(me, 'ctor');
        }
    }

    configure (config) {
        this.configure = Util.nullFn;
        this.$meta.configure(this, config);
    }

    destroy () {
        let me = this;

        me.destroy = Util.nullFn;
        me.destroying = true;

        me.destruct();

        me.destroyed = true;
    }

    destruct () {
        let meta = this.$meta;

        if (meta.liveChains.dtor) {
            meta.callChain(this, 'dtor', null, true);
        }
    }

    callChain (method, ...args) {
        this.$meta.callChain(this, method, args);
    }

    callChainRev (method, ...args) {
        this.$meta.callChain(this, method, args, true);
    }

    getMeta () {
        return this.$meta;
    }

    reconfigure (config) {
        let me = this;

        me.configuring = true;
        me.$meta.reconfigure(me, config);
        me.configuring = false;
    }
}

module.exports = Base;
<commit_msg>Use properties instead of prototype on Base<commit_after>'use strict';

const Util = require('./Util.js');
const { define } = require('./decorators.js');

@define({
    chains: [ 'ctor', 'dtor' ],

    processors: {
        prototype: null,
        chains: 'prototype',
        mixins: 'chains',
        config: 'mixins'
    },

    properties: {
        isInstance: {
            value: true
        },
        configuring: {
            value: false,
            writable: true
        },
        constructing: {
            value: true,
            writable: true
        },
        destroying: {
            value: false,
            writable: true
        },
        destroyed: {
            value: false,
            writable: true
        }
    }
})
class Base {
    constructor (...args) {
        let me = this;
        let C = me.constructor;
        let meta = me.$meta;

        if (meta.class !== C) {
            meta = C.getMeta();
        }

        // After the above code has executed "this.$meta" will always be valid for an
        // instance. This is a helpful performance gain since it allows us to avoid a
        // method call every time we want the meta class.

        if (!meta.instances++ && !meta.completed) {
            meta.complete();
        }

        me.construct(...args);
    }

    construct (config) {
        let me = this;
        let meta = me.$meta;

        if (config || meta.configs) {
            me.configuring = true;

            me.configure(config);

            me.configuring = false;
        }

        if (meta.liveChains.ctor) {
            meta.callChain(me, 'ctor');
        }
    }

    configure (config) {
        this.configure = Util.nullFn;
        this.$meta.configure(this, config);
    }

    destroy () {
        let me = this;

        me.destroy = Util.nullFn;
        me.destroying = true;

        me.destruct();

        me.destroyed = true;
    }

    destruct () {
        let meta = this.$meta;

        if (meta.liveChains.dtor) {
            meta.callChain(this, 'dtor', null, true);
        }
    }

    callChain (method, ...args) {
        this.$meta.callChain(this, method, args);
    }

    callChainRev (method, ...args) {
        this.$meta.callChain(this, method, args, true);
    }

    getMeta () {
        return this.$meta;
    }

    reconfigure (config) {
        let me = this;

        me.configuring = true;
        me.$meta.reconfigure(me, config);
        me.configuring = false;
    }
}

module.exports = Base;
<|endoftext|>


<commit_before>/**
 *
 *
 * MIT License
 * Copyright (c) 2015 notrubp@gmail.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
 * is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * @license MIT
 * @copyright notrubp@gmail.com 2015
 */
(function(global) {
  "use strict";

  /*
   * Imports
   */
  var Dom = global.Dom;
  var Property = global.Property;

  function Game() {
  }

  Game.prototype.load = function(success, failure) {
    this.sprites = Dom.createImage(null, "img/sprites.png");

    this.background = Dom.createImage(null, "img/board.png");
    Property.set(this.background, "display", "none");
    Dom.append(document.body, this.background);

    this.canvas = Dom.createCanvas(Rect.makeXywh(0, 0, 288, 322));
    Property.set(this.canvas, "display", "none");
    Dom.append(document.body, this.canvas);

    this.stage = new createjs.Stage(this.canvas);
    this.stage.enableMouseOver(10);

    // Wait for sprite sheet to load.

    Chain.append((function(success, failure) {
      this.sprites.onload = success;
      this.sprites.onerror = success;
    }).bind(this))

    // Create sprite sheet.

    .append((function(success, failure) {
      this.spriteSheet = new createjs.SpriteSheet({
        images: [ this.sprites ],
        frames: [
          // [ x, y, width, height ]
          [ 87, 0, 13, 23 ], // one
          [ 87, 23, 13, 23 ], // two
          [ 100, 0, 13, 23 ], // three
          [ 74, 0, 13, 23 ], // four
          [ 100, 23, 13, 23 ], // five
          [ 87, 69, 13, 23 ], // six
          [ 74, 69, 13, 23 ], // seven
          [ 87, 46, 13, 23 ], // eight
          [ 74, 23, 13, 23 ], // nine
          [ 74, 46, 13, 23 ], // zero
          [ 0, 78, 26, 26 ], // smiley
          [ 0, 0, 26, 26 ], // smiley_pressed
          [ 0, 26, 26, 26 ], // smiley_scared
          [ 26, 0, 26, 26 ], // smiley_cool
          [ 0, 52, 26, 26 ], // smiley_dead
          [ 52, 0, 16, 16 ], // node_blank
          [ 58, 64, 16, 16 ], // node_empty
          [ 42, 90, 16, 16 ], // node_flagged
          [ 58, 80, 16, 16 ], // node_question
          [ 42, 42, 16, 16 ], // node_question_pressed
          [ 26, 90, 16, 16 ], // node_mine
          [ 26, 42, 16, 16 ], // node_hit
          [ 26, 26, 16, 16 ], // node_minemarked
          [ 58, 16, 16, 16 ], // node_1
          [ 58, 48, 16, 16 ], // node_2
          [ 42, 58, 16, 16 ], // node_3
          [ 58, 32, 16, 16 ], // node_4
          [ 42, 74, 16, 16 ], // node_5
          [ 26, 74, 16, 16 ], // node_6
          [ 42, 26, 16, 16 ], // node_7
          [ 26, 58, 16, 16 ] // node_8
        ],
        animations: {
          "one": 0,
          "two": 1,
          "three": 2,
          "four": 3,
          "five": 4,
          "six": 5,
          "seven": 6,
          "eight": 7,
          "nine": 8,
          "zero": 9,
          "smiley": 10,
          "smiley_pressed": 11,
          "smiley_scared": 12,
          "smiley_cool": 13,
          "smiley_dead": 14,
          "node_blank": 15,
          "node_empty": 16,
          "node_flagged": 17,
          "node_question": 18,
          "node_question_pressed": 19,
          "node_mine": 20,
          "node_hit": 21,
          "node_minemarked": 22,
          "node_1": 23,
          "node_2": 24,
          "node_3": 25,
          "node_4": 26,
          "node_5": 27,
          "node_6": 28,
          "node_7": 29,
          "node_8": 30
        }
      });

      // Lookup table for number -> sprite sheet animation name
      this.spriteSheet.numbers = [
        "zero",
        "one",
        "two",
        "three",
        "four",
        "five",
        "six",
        "seven",
        "eight",
        "nine",
      ];

      // Next
      success();
    }).bind(this))

    // Initialize board.

    .append((function(success, failure) {
      this.board = new Board();
      this.board.load(this, success, failure);
    }).bind(this))

    // Initialize UI.

    .append((function(success, failure) {
      this.ui = new Ui();
      this.ui.load(this, success, failure);
    }).bind(this))

    // Show the game.

    .success((function() {
      // Draw (once).
      this.stage.update();

      Property.remove(this.background, "display");
      Property.remove(this.canvas, "display");

      // Signal that game has fully loaded.
      if (success) {
        success();
      }
    }).bind(this))

    .failure((function() {
      // Signal that game has failed to load.
      if (failure) {
        failure();
      }
    }).bind(this))

    // Start in order (non-async).

    .setOrdered(true)
    .commit();
  }

  /*
   * Exports
   */
  global.Game = Game;
})(window);

<commit_msg>Fixed order of loading sprite sheet<commit_after>/**
 *
 *
 * MIT License
 * Copyright (c) 2015 notrubp@gmail.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
 * is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * @license MIT
 * @copyright notrubp@gmail.com 2015
 */
(function(global) {
  "use strict";

  /*
   * Imports
   */
  var Dom = global.Dom;
  var Property = global.Property;

  function Game() {
  }

  Game.prototype.load = function(success, failure) {
    this.background = Dom.createImage(null, "img/board.png");
    Property.set(this.background, "display", "none");
    Dom.append(document.body, this.background);

    this.canvas = Dom.createCanvas(Rect.makeXywh(0, 0, 288, 322));
    Property.set(this.canvas, "display", "none");
    Dom.append(document.body, this.canvas);

    this.stage = new createjs.Stage(this.canvas);
    this.stage.enableMouseOver(10);

    // Wait for sprite sheet to load.

    Chain.append((function(success, failure) {
      this.sprites = Dom.createImage();
      this.sprites.onload = success;
      this.sprites.onerror = success;
      Dom.setImageSrc(this.sprites, "img/sprites.png");
    }).bind(this))

    // Create sprite sheet.

    .append((function(success, failure) {
      this.spriteSheet = new createjs.SpriteSheet({
        images: [ this.sprites ],
        frames: [
          // [ x, y, width, height ]
          [ 87, 0, 13, 23 ], // one
          [ 87, 23, 13, 23 ], // two
          [ 100, 0, 13, 23 ], // three
          [ 74, 0, 13, 23 ], // four
          [ 100, 23, 13, 23 ], // five
          [ 87, 69, 13, 23 ], // six
          [ 74, 69, 13, 23 ], // seven
          [ 87, 46, 13, 23 ], // eight
          [ 74, 23, 13, 23 ], // nine
          [ 74, 46, 13, 23 ], // zero
          [ 0, 78, 26, 26 ], // smiley
          [ 0, 0, 26, 26 ], // smiley_pressed
          [ 0, 26, 26, 26 ], // smiley_scared
          [ 26, 0, 26, 26 ], // smiley_cool
          [ 0, 52, 26, 26 ], // smiley_dead
          [ 52, 0, 16, 16 ], // node_blank
          [ 58, 64, 16, 16 ], // node_empty
          [ 42, 90, 16, 16 ], // node_flagged
          [ 58, 80, 16, 16 ], // node_question
          [ 42, 42, 16, 16 ], // node_question_pressed
          [ 26, 90, 16, 16 ], // node_mine
          [ 26, 42, 16, 16 ], // node_hit
          [ 26, 26, 16, 16 ], // node_minemarked
          [ 58, 16, 16, 16 ], // node_1
          [ 58, 48, 16, 16 ], // node_2
          [ 42, 58, 16, 16 ], // node_3
          [ 58, 32, 16, 16 ], // node_4
          [ 42, 74, 16, 16 ], // node_5
          [ 26, 74, 16, 16 ], // node_6
          [ 42, 26, 16, 16 ], // node_7
          [ 26, 58, 16, 16 ] // node_8
        ],
        animations: {
          "one": 0,
          "two": 1,
          "three": 2,
          "four": 3,
          "five": 4,
          "six": 5,
          "seven": 6,
          "eight": 7,
          "nine": 8,
          "zero": 9,
          "smiley": 10,
          "smiley_pressed": 11,
          "smiley_scared": 12,
          "smiley_cool": 13,
          "smiley_dead": 14,
          "node_blank": 15,
          "node_empty": 16,
          "node_flagged": 17,
          "node_question": 18,
          "node_question_pressed": 19,
          "node_mine": 20,
          "node_hit": 21,
          "node_minemarked": 22,
          "node_1": 23,
          "node_2": 24,
          "node_3": 25,
          "node_4": 26,
          "node_5": 27,
          "node_6": 28,
          "node_7": 29,
          "node_8": 30
        }
      });

      // Lookup table for number -> sprite sheet animation name
      this.spriteSheet.numbers = [
        "zero",
        "one",
        "two",
        "three",
        "four",
        "five",
        "six",
        "seven",
        "eight",
        "nine",
      ];

      // Next
      success();
    }).bind(this))

    // Initialize board.

    .append((function(success, failure) {
      this.board = new Board();
      this.board.load(this, success, failure);
    }).bind(this))

    // Initialize UI.

    .append((function(success, failure) {
      this.ui = new Ui();
      this.ui.load(this, success, failure);
    }).bind(this))

    // Show the game.

    .success((function() {
      // Draw (once).
      this.stage.update();

      Property.remove(this.background, "display");
      Property.remove(this.canvas, "display");

      // Signal that game has fully loaded.
      if (success) {
        success();
      }
    }).bind(this))

    .failure((function() {
      // Signal that game has failed to load.
      if (failure) {
        failure();
      }
    }).bind(this))

    // Start in order (non-async).

    .setOrdered(true)
    .commit();
  }

  /*
   * Exports
   */
  global.Game = Game;
})(window);

<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { add, remove } from 'eventlistener';
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';
import cx from 'classnames';

import parentScroll from './utils/parentScroll';
import inViewport from './utils/inViewport';

export class Lazy extends React.Component {

  static propTypes = {
    children: React.PropTypes.node.isRequired,
    className: React.PropTypes.string,
    debounce: React.PropTypes.bool,
    deferredLoadingClassName: React.PropTypes.string,
    elementType: React.PropTypes.string,
    initStyle: React.PropTypes.object,
    loadingClassName: React.PropTypes.string,
    mode: React.PropTypes.oneOf(['container', 'placeholder']),
    offset: React.PropTypes.number,
    offsetBottom: React.PropTypes.number,
    offsetHorizontal: React.PropTypes.number,
    offsetLeft: React.PropTypes.number,
    offsetRight: React.PropTypes.number,
    offsetTop: React.PropTypes.number,
    offsetVertical: React.PropTypes.number,
    threshold: React.PropTypes.number,
    throttle: React.PropTypes.number,
    visibleClassName: React.PropTypes.string,
    onContentVisible: React.PropTypes.func,
  };

  static defaultProps = {
    debounce: false,
    deferredLoadingClassName: 'isDeferredLoading',
    elementType: 'div',
    initStyle: null,
    loadingClassName: 'isLoading',
    mode: 'placeholder',
    offset: 0,
    offsetBottom: 0,
    offsetHorizontal: 0,
    offsetLeft: 0,
    offsetRight: 0,
    offsetTop: 0,
    offsetVertical: 0,
    throttle: 250,
    visibleClassName: 'isVisible',
  };

  static contextTypes = {
    redialContext: React.PropTypes.object,
  };

  constructor(props, context) {
    super(props, context);

    this.lazyLoadHandler = this.lazyLoadHandler.bind(this);

    if (props.throttle > 0) {
      if (props.debounce) {
        this.lazyLoadHandler = debounce(this.lazyLoadHandler, props.throttle);
      } else {
        this.lazyLoadHandler = throttle(this.lazyLoadHandler, props.throttle);
      }
    }

    this.state = { visible: false };
  }

  componentDidMount() {
    const eventNode = this.getEventNode();

    this.lazyLoadHandler();

    if (this.lazyLoadHandler.flush) {
      this.lazyLoadHandler.flush();
    }

    add(window, 'resize', this.lazyLoadHandler);
    add(eventNode, 'scroll', this.lazyLoadHandler);
  }

  componentWillReceiveProps() {
    if (!this.state.visible) {
      this.lazyLoadHandler();
    }
  }

  shouldComponentUpdate(_nextProps, nextState) {
    return nextState.visible;
  }

  componentWillUnmount() {
    if (this.lazyLoadHandler.cancel) {
      this.lazyLoadHandler.cancel();
    }

    this.detachListeners();
  }

  getEventNode() {
    return parentScroll(ReactDOM.findDOMNode(this));
  }

  getOffset() {
    const {
      offset, offsetVertical, offsetHorizontal,
      offsetTop, offsetBottom, offsetLeft, offsetRight, threshold,
    } = this.props;

    const realOffsetAll = threshold || offset;
    const realOffsetVertical = offsetVertical || realOffsetAll;
    const realOffsetHorizontal = offsetHorizontal || realOffsetAll;

    return {
      top: offsetTop || realOffsetVertical,
      bottom: offsetBottom || realOffsetVertical,
      left: offsetLeft || realOffsetHorizontal,
      right: offsetRight || realOffsetHorizontal,
    };
  }

  lazyLoadHandler() {
    const offset = this.getOffset();
    const node = ReactDOM.findDOMNode(this);
    const eventNode = this.getEventNode();

    if (node && eventNode && inViewport(node, eventNode, offset)) {
      const { onContentVisible } = this.props;

      this.setState({ visible: true });
      this.detachListeners();

      if (onContentVisible) {
        onContentVisible();
      }
    }
  }

  detachListeners() {
    const eventNode = this.getEventNode();

    remove(window, 'resize', this.lazyLoadHandler);
    remove(eventNode, 'scroll', this.lazyLoadHandler);
  }

  render() {
    const {
      children,
      className,
      elementType,
      initStyle,
      mode,
      visibleClassName,
      loadingClassName,
      deferredLoadingClassName,
    } = this.props;

    const restProps = {};
    Object.keys(this.props).filter(k => !Lazy.propTypes[k]).forEach(k => {
      restProps[k] = this.props[k];
    });

    const { visible } = this.state;
    const elClasses = cx('LazyLoad', className, {
      [visibleClassName]: visible,
      [loadingClassName]: this.context.redialContext &&
        this.context.redialContext.loading,
      [deferredLoadingClassName]: this.context.redialContext &&
        this.context.redialContext.deferredLoading,
    });
    const props = {
      ...restProps,
      className: elClasses,
    };
    if (!visible) {
      return React.createElement(
        elementType,
        {
          ...props,
          style: initStyle || props.style,
        }
      );
    }

    if (mode === 'container') {
      const loading = this.context.redialContext &&
        (this.context.redialContext.loading ||
          this.context.redialContext.deferredLoading);
      return React.createElement(
        elementType,
        {
          ...props,
          style: loading ? (initStyle || props.style) : props.style,
        },
        children
      );
    }
    return children;
  }
}
<commit_msg>use findDOMNode to confirm children<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { add, remove } from 'eventlistener';
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';
import cx from 'classnames';

import parentScroll from './utils/parentScroll';
import inViewport from './utils/inViewport';

const CHILD_KEY = 'RRR_LAZY_CHILD_KEY';

export class Lazy extends React.Component {

  static propTypes = {
    children: React.PropTypes.node.isRequired,
    className: React.PropTypes.string,
    debounce: React.PropTypes.bool,
    deferredLoadingClassName: React.PropTypes.string,
    elementType: React.PropTypes.string,
    initStyle: React.PropTypes.object,
    loadingClassName: React.PropTypes.string,
    mode: React.PropTypes.oneOf(['container', 'placeholder']),
    offset: React.PropTypes.number,
    offsetBottom: React.PropTypes.number,
    offsetHorizontal: React.PropTypes.number,
    offsetLeft: React.PropTypes.number,
    offsetRight: React.PropTypes.number,
    offsetTop: React.PropTypes.number,
    offsetVertical: React.PropTypes.number,
    threshold: React.PropTypes.number,
    throttle: React.PropTypes.number,
    visibleClassName: React.PropTypes.string,
    onContentVisible: React.PropTypes.func,
  };

  static defaultProps = {
    debounce: false,
    deferredLoadingClassName: 'isDeferredLoading',
    elementType: 'div',
    initStyle: null,
    loadingClassName: 'isLoading',
    mode: 'placeholder',
    offset: 0,
    offsetBottom: 0,
    offsetHorizontal: 0,
    offsetLeft: 0,
    offsetRight: 0,
    offsetTop: 0,
    offsetVertical: 0,
    throttle: 250,
    visibleClassName: 'isVisible',
  };

  static contextTypes = {
    redialContext: React.PropTypes.object,
  };

  constructor(props, context) {
    super(props, context);

    this.lazyLoadHandler = this.lazyLoadHandler.bind(this);

    if (props.throttle > 0) {
      if (props.debounce) {
        this.lazyLoadHandler = debounce(this.lazyLoadHandler, props.throttle);
      } else {
        this.lazyLoadHandler = throttle(this.lazyLoadHandler, props.throttle);
      }
    }

    if (React.Children.count(props.children) > 1) {
      console.warn('[rrr-lazy] Only one child is allowed');
    }

    this.state = {
      visible: false,
      mounted: false,
    };
  }

  componentDidMount() {
    const eventNode = this.getEventNode();

    this.lazyLoadHandler();

    if (this.lazyLoadHandler.flush) {
      this.lazyLoadHandler.flush();
    }

    add(window, 'resize', this.lazyLoadHandler);
    add(eventNode, 'scroll', this.lazyLoadHandler);
  }

  componentWillReceiveProps() {
    if (!this.state.visible) {
      this.lazyLoadHandler();
    }
  }

  shouldComponentUpdate(_nextProps, nextState) {
    return this.state.visible !== nextState.visible ||
      this.state.mounted !== nextState.mounted;
  }

  componentWillUnmount() {
    if (this.lazyLoadHandler.cancel) {
      this.lazyLoadHandler.cancel();
    }
    this.detachListeners();
  }

  getEventNode() {
    return parentScroll(ReactDOM.findDOMNode(this));
  }

  getOffset() {
    const {
      offset, offsetVertical, offsetHorizontal,
      offsetTop, offsetBottom, offsetLeft, offsetRight, threshold,
    } = this.props;

    const realOffsetAll = threshold || offset;
    const realOffsetVertical = offsetVertical || realOffsetAll;
    const realOffsetHorizontal = offsetHorizontal || realOffsetAll;

    return {
      top: offsetTop || realOffsetVertical,
      bottom: offsetBottom || realOffsetVertical,
      left: offsetLeft || realOffsetHorizontal,
      right: offsetRight || realOffsetHorizontal,
    };
  }

  lazyLoadHandler() {
    if (!this.state.visible) {
      const offset = this.getOffset();
      const node = ReactDOM.findDOMNode(this);
      const eventNode = this.getEventNode();
      if (node && eventNode && inViewport(node, eventNode, offset)) {
        this.setState({ visible: true });
        if (this.props.onContentVisible) {
          this.props.onContentVisible();
        }
      }
    } else {
      const dom = ReactDOM.findDOMNode(this.refs[CHILD_KEY]);
      const loading = this.context.redialContext &&
        (this.context.redialContext.loading || this.context.redialContext.deferredLoading);
      if (dom || !loading) {
        this.detachListeners();
        this.setState({ mounted: true });
      }
    }
  }

  detachListeners() {
    const eventNode = this.getEventNode();

    remove(window, 'resize', this.lazyLoadHandler);
    remove(eventNode, 'scroll', this.lazyLoadHandler);
  }

  render() {
    const restProps = {};
    Object.keys(this.props).filter(k => !Lazy.propTypes[k]).forEach(k => {
      restProps[k] = this.props[k];
    });

    const { visible, mounted } = this.state;
    const elClasses = cx('LazyLoad', this.props.className, {
      [this.props.visibleClassName]: visible && mounted,
      [this.props.loadingClassName]: this.context.redialContext &&
        this.context.redialContext.loading,
      [this.props.deferredLoadingClassName]: this.context.redialContext &&
        this.context.redialContext.deferredLoading,
    });

    const props = {
      ...restProps,
      className: elClasses,
    };

    const initStyle = this.props.initStyle || this.props.style;

    if (!visible) {
      return React.createElement(
        this.props.elementType,
        {
          ...props,
          style: initStyle,
        }
      );
    }

    const children = React.cloneElement(this.props.children, {
      ref: CHILD_KEY,
    });

    if (this.props.mode === 'container') {
      return React.createElement(
        this.props.elementType,
        {
          ...props,
          style: this.state.mounted ? props.style : initStyle,
        },
        children
      );
    }

    if (!this.state.mounted) {
      return React.createElement(
        this.props.elementType,
        {
          ...props,
          style: initStyle,
        },
        children,
      );
    }
    return children;
  }
}
<|endoftext|>


<commit_before>var Point = require('./Point');

// Line
// ----
//
// A line can be constructed by supplying
// the slope and a y-intercept.
var Line = function (slope, yIntercept) {
  this.slope      = slope;
  this.yIntercept = yIntercept;
  this._type = 'Line';

  // Returns a point that represents the
  // intersection of this line with
  // another line.
  var intersectionWithLine = function (line) {
    var x = (this.yIntercept - line.yIntercept) / (line.slope - this.slope);
    var y = this.slope * x + this.yIntercept;
    return new Point(x, y);
  }.bind(this);

  // Returns a point that represents
  // the intersection of this line with
  // another object
  this.intersectionWith = function (other) {
    switch (other._type) {
      case "Line":
        return intersectionWithLine(other);
        break;
    }
  };
};

// A line can also be constructed from
// a slope and a point on the line
Line.fromSlopeAndPoint = function (slope, point) {
  var yIntercept = point.y + slope * (-point.x);
  return new Line(slope, yIntercept);
};

// A line can also be constructed from two
// points
Line.fromPoints = function (p1, p2) {
  var slope = (p2.y - p1.y) / (p2.x - p1.x);
  return Line.fromSlopeAndPoint(slope, p1);
};

module.exports = Line;<commit_msg>capitalization!~<commit_after>var Point = require('./Point');

// Line
// ----
//
// A line can be constructed by supplying
// the slope and a y-intercept.
var Line = function (slope, yIntercept) {
  this.slope      = slope;
  this.yIntercept = yIntercept;
  this._type = 'Line';

  // Returns a point that represents the
  // intersection of this Line with
  // another Line.
  var intersectionWithLine = function (line) {
    var x = (this.yIntercept - line.yIntercept) / (line.slope - this.slope);
    var y = this.slope * x + this.yIntercept;
    return new Point(x, y);
  }.bind(this);

  // Returns a point that represents
  // the intersection of this line with
  // another object
  this.intersectionWith = function (other) {
    switch (other._type) {
      case "Line":
        return intersectionWithLine(other);
        break;
    }
  };
};

// A line can also be constructed from
// a slope and a point on the line
Line.fromSlopeAndPoint = function (slope, point) {
  var yIntercept = point.y + slope * (-point.x);
  return new Line(slope, yIntercept);
};

// A line can also be constructed from two
// points
Line.fromPoints = function (p1, p2) {
  var slope = (p2.y - p1.y) / (p2.x - p1.x);
  return Line.fromSlopeAndPoint(slope, p1);
};

module.exports = Line;<|endoftext|>


<commit_before><commit_msg>get rid of console.log cuz it was lagging the program<commit_after><|endoftext|>