<commit_before>import * as d3 from 'd3'
import * as commonComponents from './components/common'
import * as distributionChartComponents from './components/distribution-chart'
import * as utils from './utilities/distribution-chart'
import Chart from './chart'

export default class DistributionChart extends Chart {
  constructor (element, options = {}) {
    let defaultConfig = {
      pointType: 'regular-week',
      confidenceIntervals: [],
      margin: {
        top: 5,
        right: 50,
        bottom: 80,
        left: 5
      }
    }

    let elementSelection = d3.select(element)
        .attr('class', 'd3-foresight-chart d3-foresight-distribution-chart')
    super(elementSelection, 0, Object.assign({}, defaultConfig, options))

    // Initialize scales
    this.xScale = d3.scaleLinear().range([0, this.width])
    this.xScaleDate = d3.scaleTime().range([0, this.width])
    this.xScalePoint = d3.scalePoint().range([0, this.width])

    // Time axis for indicating current position
    this.xAxis = new commonComponents.XAxisDate(
      this.svg,
      this.width,
      this.height,
      0,
      this.onsetHeight,
      this.config.axes.x,
      this.infoTooltip
    )

    // create 4 panels and assign new svgs to them
    let panelMargin = {
      top: 5, right: 10, bottom: 70, left: 50
    }
    let panelHeight = this.height / 2
    let panelWidth = this.width / 2
    let panelPositions = [
      [0, 0],
      [0, panelHeight],
      [panelWidth, 0],
      [panelWidth, panelHeight]
    ]

    this.panels = panelPositions.map(pos => {
      let svg = this.svg.append('svg')
          .attr('x', pos[0])
          .attr('y', pos[1])
          .attr('width', panelWidth)
          .attr('height', panelHeight)
          .append('g')
          .attr('transform', `translate(${panelMargin.left}, ${panelMargin.top})`)

      return new distributionChartComponents.DistributionPanel(
        svg,
        panelWidth - panelMargin.left - panelMargin.right,
        panelHeight - panelMargin.top - panelMargin.bottom,
        this.infoTooltip
      )
    })

    // Add dropdowns for curve selection
    this.dropdowns = panelPositions.map(pos => {
      let wrapperWrapper = elementSelection.append('div')
      wrapperWrapper.style('text-align', 'center')

      let wrapper = wrapperWrapper.append('span')
      wrapper.attr('class', 'select is-small')
      let dd = wrapper.append('select')

      wrapperWrapper.style('position', 'absolute')
      wrapperWrapper.style('left', (pos[0] + panelMargin.left / 2) + 'px')
      wrapperWrapper.style('width', panelWidth + 'px')
      wrapperWrapper.style('top', (pos[1] + panelHeight - panelMargin.bottom + 30) + 'px')

      return dd
    })

    this.pointer = new distributionChartComponents.Pointer(this)

    this.eventHooks = []
    let showStats = this.config.statsMeta.length > 0
    let panelConfig = {
      actual: false,
      observed: false,
      history: false,
      ci: false,
      stats: showStats
    }

    // Control panel
    this.controlPanel = new commonComponents.ControlPanel(
      this, panelConfig,
      (event, payload) => {
        if (event === 'btn:next') {
          console.log('forward')
        } else if (event === 'btn:back') {
          console.log('backward')
        }
      }
    )
  }

  // plot data
  plot (data) {
    // NOTE
    // Data has the following props
    // timePoints -> to plot the time axis
    // currentIdx -> to plot the pointer in onsetOffset
    // models -> list of n items for n models, each with:
    //   id
    //   meta
    //   stats
    //   curves (or maybe use predictions) list of t items for t targets:
    //     name -> text naming the target
    //     data -> series of (x, y) tuples about the distribution
    //     actual -> actual value // Not planned

    let curveNames = data.models[0].curves.map(t => t.name)

    this.dropdowns.forEach(dd => {
      dd.selectAll('*').remove()
      curveNames.forEach((cn, idx) => {
        let option = dd.append('option')
        option.text(cn)
        option.attr('value', idx)
      })
    })

    this.timePoints = data.timePoints
    if (this.config.pointType.endsWith('-week')) {
      this.ticks = this.timePoints.map(tp => tp.week)
    } else {
      throw utils.UnknownPointTypeException()
    }
    this.xScaleDate.domain(utils.getXDateDomain(this.timePoints, this.config.pointType))
    this.xScalePoint.domain(this.ticks)
    this.xScale.domain([0, this.timePoints.length - 1])
    this.xAxis.plot(this.xScalePoint, this.xScaleDate)

    // Plot pointer position
    this.pointer.plot(data.currentIdx, this.xScale)

    let yLimits = utils.getYLimits(data)

    // Provide curve data to the panels
    this.panels.forEach((p, idx) => {
      if (!p.selectedCurveIdx) {
        p.selectedCurveIdx = idx
        this.dropdowns[idx].property('value', idx)
      } else {
        this.dropdowns[idx].property('value', p.selectedCurveIdx)
      }
      p.plot(data, yLimits)
    })

    // Add event listeners to dropdown
    this.dropdowns.forEach((dd, idx) => {
      let currentPanel = this.panels[idx]
      dd.on('change', function () {
        let selectedIdx = parseInt(d3.select(this).property('value'))
        currentPanel.selectedCurveIdx = selectedIdx
        currentPanel.plot(data, yLimits)
      })
    })

    // Update models shown in control panel
    this.controlPanel.plot(this.panels[0].predictions, (predictionId, hidePrediction) => {
      this.panels.forEach(p => {
        let predMarker = p.predictions[p.predictions.map(p => p.id).indexOf(predictionId)]
        predMarker.hidden = hidePrediction
      })
    })
  }
}
<commit_msg>Handle hooks for forward backward events<commit_after>import * as d3 from 'd3'
import * as commonComponents from './components/common'
import * as distributionChartComponents from './components/distribution-chart'
import * as utils from './utilities/distribution-chart'
import Chart from './chart'

export default class DistributionChart extends Chart {
  constructor (element, options = {}) {
    let defaultConfig = {
      pointType: 'regular-week',
      confidenceIntervals: [],
      margin: {
        top: 5,
        right: 50,
        bottom: 80,
        left: 5
      }
    }

    let elementSelection = d3.select(element)
        .attr('class', 'd3-foresight-chart d3-foresight-distribution-chart')
    super(elementSelection, 0, Object.assign({}, defaultConfig, options))

    // Initialize scales
    this.xScale = d3.scaleLinear().range([0, this.width])
    this.xScaleDate = d3.scaleTime().range([0, this.width])
    this.xScalePoint = d3.scalePoint().range([0, this.width])

    // Time axis for indicating current position
    this.xAxis = new commonComponents.XAxisDate(
      this.svg,
      this.width,
      this.height,
      0,
      this.onsetHeight,
      this.config.axes.x,
      this.infoTooltip
    )

    // create 4 panels and assign new svgs to them
    let panelMargin = {
      top: 5, right: 10, bottom: 70, left: 50
    }
    let panelHeight = this.height / 2
    let panelWidth = this.width / 2
    let panelPositions = [
      [0, 0],
      [0, panelHeight],
      [panelWidth, 0],
      [panelWidth, panelHeight]
    ]

    this.panels = panelPositions.map(pos => {
      let svg = this.svg.append('svg')
          .attr('x', pos[0])
          .attr('y', pos[1])
          .attr('width', panelWidth)
          .attr('height', panelHeight)
          .append('g')
          .attr('transform', `translate(${panelMargin.left}, ${panelMargin.top})`)

      return new distributionChartComponents.DistributionPanel(
        svg,
        panelWidth - panelMargin.left - panelMargin.right,
        panelHeight - panelMargin.top - panelMargin.bottom,
        this.infoTooltip
      )
    })

    // Add dropdowns for curve selection
    this.dropdowns = panelPositions.map(pos => {
      let wrapperWrapper = elementSelection.append('div')
      wrapperWrapper.style('text-align', 'center')

      let wrapper = wrapperWrapper.append('span')
      wrapper.attr('class', 'select is-small')
      let dd = wrapper.append('select')

      wrapperWrapper.style('position', 'absolute')
      wrapperWrapper.style('left', (pos[0] + panelMargin.left / 2) + 'px')
      wrapperWrapper.style('width', panelWidth + 'px')
      wrapperWrapper.style('top', (pos[1] + panelHeight - panelMargin.bottom + 30) + 'px')

      return dd
    })

    this.pointer = new distributionChartComponents.Pointer(this)

    this.eventHooks = []
    let showStats = this.config.statsMeta.length > 0
    let panelConfig = {
      actual: false,
      observed: false,
      history: false,
      ci: false,
      stats: showStats
    }

    // Control panel
    this.controlPanel = new commonComponents.ControlPanel(
      this, panelConfig,
      (event, payload) => {
        if (event === 'btn:next') {
          this.handleHook({
            type: 'forward'
          })
        } else if (event === 'btn:back') {
          this.handleHook({
            type: 'backward'
          })
        }
      }
    )
  }

  // plot data
  plot (data) {
    // NOTE
    // Data has the following props
    // timePoints -> to plot the time axis
    // currentIdx -> to plot the pointer in onsetOffset
    // models -> list of n items for n models, each with:
    //   id
    //   meta
    //   stats
    //   curves (or maybe use predictions) list of t items for t targets:
    //     name -> text naming the target
    //     data -> series of (x, y) tuples about the distribution
    //     actual -> actual value // Not planned

    let curveNames = data.models[0].curves.map(t => t.name)

    this.dropdowns.forEach(dd => {
      dd.selectAll('*').remove()
      curveNames.forEach((cn, idx) => {
        let option = dd.append('option')
        option.text(cn)
        option.attr('value', idx)
      })
    })

    this.timePoints = data.timePoints
    if (this.config.pointType.endsWith('-week')) {
      this.ticks = this.timePoints.map(tp => tp.week)
    } else {
      throw utils.UnknownPointTypeException()
    }
    this.xScaleDate.domain(utils.getXDateDomain(this.timePoints, this.config.pointType))
    this.xScalePoint.domain(this.ticks)
    this.xScale.domain([0, this.timePoints.length - 1])
    this.xAxis.plot(this.xScalePoint, this.xScaleDate)

    // Plot pointer position
    this.pointer.plot(data.currentIdx, this.xScale)

    let yLimits = utils.getYLimits(data)

    // Provide curve data to the panels
    this.panels.forEach((p, idx) => {
      if (!p.selectedCurveIdx) {
        p.selectedCurveIdx = idx
        this.dropdowns[idx].property('value', idx)
      } else {
        this.dropdowns[idx].property('value', p.selectedCurveIdx)
      }
      p.plot(data, yLimits)
    })

    // Add event listeners to dropdown
    this.dropdowns.forEach((dd, idx) => {
      let currentPanel = this.panels[idx]
      dd.on('change', function () {
        let selectedIdx = parseInt(d3.select(this).property('value'))
        currentPanel.selectedCurveIdx = selectedIdx
        currentPanel.plot(data, yLimits)
      })
    })

    // Update models shown in control panel
    this.controlPanel.plot(this.panels[0].predictions, (predictionId, hidePrediction) => {
      this.panels.forEach(p => {
        let predMarker = p.predictions[p.predictions.map(p => p.id).indexOf(predictionId)]
        predMarker.hidden = hidePrediction
      })
    })
  }

  handleHook (data) {
    this.eventHooks.forEach(hook => hook(data))
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import {graphql, createFragmentContainer} from 'react-relay';
import {EndpointPropType} from '../prop-types';
import IssueishListView from '../views/issueish-list-view';
import Issueish from '../models/issueish';
import {shell} from 'electron';

const StatePropType = PropTypes.oneOf(['EXPECTED', 'PENDING', 'SUCCESS', 'ERROR', 'FAILURE']);

export class BareIssueishListController extends React.Component {
  static propTypes = {
    results: PropTypes.arrayOf(
      PropTypes.shape({
        number: PropTypes.number.isRequired,
        title: PropTypes.string.isRequired,
        url: PropTypes.string.isRequired,
        author: PropTypes.shape({
          login: PropTypes.string.isRequired,
          avatarUrl: PropTypes.string.isRequired,
        }).isRequired,
        createdAt: PropTypes.string.isRequired,
        headRefName: PropTypes.string.isRequired,
        repository: PropTypes.shape({
          id: PropTypes.string.isRequired,
          name: PropTypes.string.isRequired,
          owner: PropTypes.shape({
            login: PropTypes.string.isRequired,
          }).isRequired,
        }).isRequired,
        commits: PropTypes.shape({
          nodes: PropTypes.arrayOf(PropTypes.shape({
            commit: PropTypes.shape({
              status: PropTypes.shape({
                contexts: PropTypes.arrayOf(
                  PropTypes.shape({
                    state: StatePropType.isRequired,
                  }).isRequired,
                ).isRequired,
              }),
            }),
          })),
        }),
      }),
    ),
    total: PropTypes.number.isRequired,
    isLoading: PropTypes.bool.isRequired,
    title: PropTypes.string.isRequired,
    error: PropTypes.object,

    resultFilter: PropTypes.func,
    onOpenIssueish: PropTypes.func.isRequired,
    onOpenReviews: PropTypes.func.isRequired,
    onOpenMore: PropTypes.func,

    emptyComponent: PropTypes.func,
    workspace: PropTypes.object,
    endpoint: EndpointPropType,
    workdir: PropTypes.string.isRequired,
    needReviewsButton: PropTypes.bool,
  };

  static defaultProps = {
    results: [],
    total: 0,
    resultFilter: () => true,
  }

  constructor(props) {
    super(props);

    this.state = {};
  }

  static getDerivedStateFromProps(props, state) {
    if (props.results === null) {
      return {
        lastResults: null,
        issueishes: [],
      };
    }

    if (props.results !== state.lastResults) {
      return {
        lastResults: props.results,
        issueishes: props.results.map(node => new Issueish(node)).filter(props.resultFilter),
      };
    }

    return null;
  }

  openOnGitHub = issueish => {
    return new Promise((resolve, reject) => {
      shell.openExternal(issueish.getGitHubURL(), {}, err => {
        if (err) { reject(err); } else { resolve(); }
      });
    });
  }

  render() {
    return (
      <IssueishListView
        title={this.props.title}
        isLoading={this.props.isLoading}
        total={this.props.total}
        issueishes={this.state.issueishes}
        error={this.props.error}
        needReviewsButton={this.props.needReviewsButton}
        onIssueishClick={this.props.onOpenIssueish}
        onMoreClick={this.props.onOpenMore}
        openReviews={this.props.onOpenReviews}
        openOnGitHub={this.openOnGitHub}
        emptyComponent={this.props.emptyComponent}
      />
    );
  }
}

export default createFragmentContainer(BareIssueishListController, {
  results: graphql`
    fragment issueishListController_results on PullRequest
    @relay(plural: true)
    {
      number
      title
      url
      author {
        login
        avatarUrl
      }
      createdAt
      headRefName

      repository {
        id
        name
        owner {
          login
        }
      }

      commits(last:1) {
        nodes {
          commit {
            status {
              contexts {
                state
              }
            }
          }
        }
      }
    }
  `,
});
<commit_msg>Add `open-issueish-in-browser` event and pass url instead of issueish<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import {graphql, createFragmentContainer} from 'react-relay';
import {EndpointPropType} from '../prop-types';
import IssueishListView from '../views/issueish-list-view';
import Issueish from '../models/issueish';
import {shell} from 'electron';
import {addEvent} from '../reporter-proxy';

const StatePropType = PropTypes.oneOf(['EXPECTED', 'PENDING', 'SUCCESS', 'ERROR', 'FAILURE']);

export class BareIssueishListController extends React.Component {
  static propTypes = {
    results: PropTypes.arrayOf(
      PropTypes.shape({
        number: PropTypes.number.isRequired,
        title: PropTypes.string.isRequired,
        url: PropTypes.string.isRequired,
        author: PropTypes.shape({
          login: PropTypes.string.isRequired,
          avatarUrl: PropTypes.string.isRequired,
        }).isRequired,
        createdAt: PropTypes.string.isRequired,
        headRefName: PropTypes.string.isRequired,
        repository: PropTypes.shape({
          id: PropTypes.string.isRequired,
          name: PropTypes.string.isRequired,
          owner: PropTypes.shape({
            login: PropTypes.string.isRequired,
          }).isRequired,
        }).isRequired,
        commits: PropTypes.shape({
          nodes: PropTypes.arrayOf(PropTypes.shape({
            commit: PropTypes.shape({
              status: PropTypes.shape({
                contexts: PropTypes.arrayOf(
                  PropTypes.shape({
                    state: StatePropType.isRequired,
                  }).isRequired,
                ).isRequired,
              }),
            }),
          })),
        }),
      }),
    ),
    total: PropTypes.number.isRequired,
    isLoading: PropTypes.bool.isRequired,
    title: PropTypes.string.isRequired,
    error: PropTypes.object,

    resultFilter: PropTypes.func,
    onOpenIssueish: PropTypes.func.isRequired,
    onOpenReviews: PropTypes.func.isRequired,
    onOpenMore: PropTypes.func,

    emptyComponent: PropTypes.func,
    workspace: PropTypes.object,
    endpoint: EndpointPropType,
    workdir: PropTypes.string.isRequired,
    needReviewsButton: PropTypes.bool,
  };

  static defaultProps = {
    results: [],
    total: 0,
    resultFilter: () => true,
  }

  constructor(props) {
    super(props);

    this.state = {};
  }

  static getDerivedStateFromProps(props, state) {
    if (props.results === null) {
      return {
        lastResults: null,
        issueishes: [],
      };
    }

    if (props.results !== state.lastResults) {
      return {
        lastResults: props.results,
        issueishes: props.results.map(node => new Issueish(node)).filter(props.resultFilter),
      };
    }

    return null;
  }

  openOnGitHub = url => {
    return new Promise((resolve, reject) => {
      shell.openExternal(url, {}, err => {
        if (err) { reject(err); } else {
          resolve();
          addEvent('open-issueish-in-browser', {package: 'github', component: this.constructor.name});
        }
      });
    });
  }

  render() {
    return (
      <IssueishListView
        title={this.props.title}
        isLoading={this.props.isLoading}
        total={this.props.total}
        issueishes={this.state.issueishes}
        error={this.props.error}
        needReviewsButton={this.props.needReviewsButton}
        onIssueishClick={this.props.onOpenIssueish}
        onMoreClick={this.props.onOpenMore}
        openReviews={this.props.onOpenReviews}
        openOnGitHub={this.openOnGitHub}
        emptyComponent={this.props.emptyComponent}
      />
    );
  }
}

export default createFragmentContainer(BareIssueishListController, {
  results: graphql`
    fragment issueishListController_results on PullRequest
    @relay(plural: true)
    {
      number
      title
      url
      author {
        login
        avatarUrl
      }
      createdAt
      headRefName

      repository {
        id
        name
        owner {
          login
        }
      }

      commits(last:1) {
        nodes {
          commit {
            status {
              contexts {
                state
              }
            }
          }
        }
      }
    }
  `,
});
<|endoftext|>


<commit_before>import { Template } from 'meteor/templating';
import * as RouteNames from '../../../startup/client/router.js';

Template.Mentor_Layout.helpers({
  secondMenuItems() {
    return [
      { label: 'Home',
        route: RouteNames.mentorHomePageRouteName },
      { label: 'Mentor Space',
        route: RouteNames.mentorMentorSpacePageRouteName },
      { label: 'Explorer',
        route: RouteNames.mentorExplorerPageRouteName },
    ];
  },
  secondMenuLength() {
    return 'three';
  },
});
<commit_msg>Added regex to the mentor layout<commit_after>import { Template } from 'meteor/templating';
import * as RouteNames from '../../../startup/client/router.js';

Template.Mentor_Layout.helpers({
  secondMenuItems() {
    return [
      { label: 'Home',
        route: RouteNames.mentorHomePageRouteName,
        regex: 'home',
      },
      { label: 'Mentor Space',
        route: RouteNames.mentorMentorSpacePageRouteName,
        regex: 'mentor-space',
      },
      { label: 'Explorer',
        route: RouteNames.mentorExplorerPageRouteName,
        regex: 'explorer',
      },
    ];
  },
  secondMenuLength() {
    return 'three';
  },
});
<|endoftext|>


<commit_before>/*
 * (C) Copyright 2014 Bill Hubauer <bill@hubauer.com>
 *
 * This file is part of Cricket  https://github.com/bhubauer/cricket
 *
 * This library is free software; you can redistribute it and/or modify it under the terms of the
 * GNU Lesser General Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this library;
 * if not, visit http://www.gnu.org/licenses/lgpl-2.1.html or write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

var _CRICKET_PAGE_INSTANCE_ = null;

var CRICKET_BUSY_INDICATOR = 'cricket_busy';
var CRICKET_AUTO_BUSY = false;
var CRICKET_ACTIVE_CHANNELS = {};

/* inlude the following CSS, along with the cricket busy indicator
 * body.cricket_busy, body.cricket_busy * {
    cursor: progress !important;
}
 */

function cricket_abort_ajax(inRequest) {
    if(inRequest) {
        inRequest.abort();
    }
}

// if inRequestChannel, the if there is any active ajax for this channel, it is aborted prior to issuing the new one

function cricket_ajax(inURL,inData,inIndicatorID,inConfirmation,inRequestChannel,inFailSilent) {

    if(inFailSilent == null) {
        inFailSilent = false;
    }

    if(inRequestChannel) {
        if(inRequestChannel in CRICKET_ACTIVE_CHANNELS) {
            cricket_abort_ajax(CRICKET_ACTIVE_CHANNELS[inRequestChannel]);
            delete CRICKET_ACTIVE_CHANNELS[inRequestChannel];
        }
    }

    var result = null;

    if(!inIndicatorID) {
        if(CRICKET_AUTO_BUSY) {
            inIndicatorID = CRICKET_BUSY_INDICATOR;
        }
    }

    if(!_CRICKET_PAGE_INSTANCE_){
        alert("Configuration error. _CRICKET_PAGE_INSTANCE_ not set");
        return;
    }

    // add page instance
    inData = jQuery.extend({'_CRICKET_PAGE_INSTANCE_':_CRICKET_PAGE_INSTANCE_},inData);

    var go = true;

    if(inConfirmation) {
        go = confirm(inConfirmation);
    }

    if(go) {
        // TODO: Activate this
        if(inIndicatorID) {
            if(cricket_indicator_active(inIndicatorID)) {
                return;
            }
            cricket_indicator_start(inIndicatorID);
        }
        result = jQuery.ajax({
            type: 'POST',
            url: inURL,
            data: inData,
            success: function(data,textStatus,request) {
//                if(inIndicatorID) {
//                    cricket_indicator_stop(inIndicatorID);
//                }
                if(data.redirect) {
                    document.location.href = data.redirect;
                    return;
                }

                if(data.message) {
                    alert(data.message);
                }

                for(var z = 0 ; z < data.scripts_pre.length ; z++) {
                    eval(data.scripts_pre[z]);
                }

                if(data.dialog) {
                    jQuery("

").dialog(
                        jQuery.extend(
                            data.dialog.options, {
                                close: function(e,ui) {
                                    cricket_ajax(data.dialog.closeUrl,{});
                                    jQuery("#" + data.dialog.id).dialog('destroy').remove();
                                }
                            }
                        )
                    );
                }

                for(var key in data.updates) {
                    if(data.replacements[key])
                        jQuery("#" + key).replaceWith(data.updates[key]);
                    else
                        jQuery("#" + key).html(data.updates[key]);
                }

                for(var key in data.append) {
                    jQuery("#" + key).append(data.append[key]);
                }

                for(var z = 0 ; z < data.scripts_post.length ; z++) {
                    eval(data.scripts_post[z]);
                }

                if(data.sounds.length) {
                    if(window.HTMLAudioElement) {
                        for(var key in data.sounds) {
                            var audio = new Audio(data.sounds[key]);
                            audio.play();
                        }
                    }
                }
            },
            complete: function(request,textStatus) {
                if(inRequestChannel) {
                    delete CRICKET_ACTIVE_CHANNELS[inRequestChannel];
                }

                if(inIndicatorID) cricket_indicator_stop(inIndicatorID);
            },
            error: function(request,textStatus,errorThrown) {
                if(!inFailSilent) {
                    jQuery("html").html(request.responseText);
                }
            },
            beforeSend: function(request) {
                request.setRequestHeader("x-cricket-ajax","true");
                return true;
            },
            dataType: 'json'
        });

        if(inRequestChannel) {
            CRICKET_ACTIVE_CHANNELS[inRequestChannel] = result;
        }
    }

//    return result;
}

var CRICKET_SELECTION = {};
function cricket_click_row(inTableID,inSelectURL,inRowID,inItemID, inUseID) {
    if(CRICKET_SELECTION[inTableID]) {
        jQuery("#" + CRICKET_SELECTION[inTableID]).removeClass("selected");
    }

    jQuery("#" + inRowID).addClass("selected");
    CRICKET_SELECTION[inTableID] = inRowID;

    var indicator = "ind_select_row";
    if (inUseID) {
    	indicator += "_" + inItemID;
    }

    cricket_ajax(inSelectURL,{id:inItemID,row_id:inRowID},indicator);
}

function cricket_clear_selection(inTableID) {
    if(CRICKET_SELECTION[inTableID]) {
        jQuery("#" + CRICKET_SELECTION[inTableID]).removeClass("selected");
        delete CRICKET_SELECTION[inTableID];
    }
}

function cricket_isArray(obj){
	if (typeof arguments[0] == 'object') {
		var criterion = arguments[0].constructor.toString().match(/array/i);
 		return (criterion != null);
	}
	return false;
}

function cricket_ajax_form(inFormOrChild,inSubmitURL,inInd,inConfirmation,inRequestChannel,inFailSilent)
{
    var values = cricket_serialize_form(inFormOrChild);
    cricket_ajax(inSubmitURL,values,inInd,inConfirmation,inRequestChannel,inFailSilent);
}

function cricket_serialize_form(inFormOrChild) {
    var     form = inFormOrChild;

    if(form.nodeName.toLowerCase() != 'form') {
        form = jQuery(form).parents('form').get();
    }

    var values = {};
    jQuery.each(jQuery(form).serializeArray(), function(i, field) {
    	if(values[field.name] != undefined) {
    		if(cricket_isArray(values[field.name])) {
    			values[field.name].push(field.value);
    		} else {
    			var tmp = values[field.name];
    			values[field.name] = [];
    			values[field.name].push(tmp);
    			values[field.name].push(field.value);
    		}
    	} else {
    		values[field.name] = field.value;
    	}
    });

    return values;
}

var cricket_indicators = {

};

var cricket_indicator_timeout = 250;

function cricket_indicator_start(inID,inRestart,inTimeout) {
    if(inRestart == null) {
        inRestart = false;
    }

    if(inTimeout == null) {
        inTimeout = cricket_indicator_timeout;
    }

    var rec = cricket_indicators[inID];
    if(!rec) {
        rec = {
            level: 0,
            timer: 0
        };

        cricket_indicators[inID] = rec;
    }else{
        rec.level = 1;
        cricket_indicator_stop(inID);
    }

    rec.level++;
    if(rec.level == 1) {
        rec.timer = setTimeout(function(){
            rec.timer = 0;

            if(inID == CRICKET_BUSY_INDICATOR) {
                jQuery('body').addClass('cricket_busy');
            }else{
                var i = document.getElementById(inID);
                if(i) {
                    i.style.visibility = "visible";
                }
            }
        },inTimeout);
    }
}

function cricket_indicator_active(inID) {
	var rec = cricket_indicators[inID];
	if(!rec) {
		return false;
	}

	return rec.level > 0;
}

function cricket_indicator_stop(inID) {
    var rec = cricket_indicators[inID];
	if(!rec) {
		return false;
	}
    rec.level--;
    if(rec.level == 0) {
        if(rec.timer != 0) {
            clearTimeout(rec.timer);
        }
        if(inID == CRICKET_BUSY_INDICATOR) {
            jQuery('body').removeClass('cricket_busy');
        }else{
            var i = document.getElementById(inID);
            if(i) {
                i.style.visibility = "hidden";
            }
        }
    }
}

function cricket_alert_position(inDLOGID,inMinTop) {
    var dlog = jQuery("#" + inDLOGID);
    var dlogHeight = dlog.height();
    var dlogWidth = dlog.width();

    var windowHeight = jQuery(window).height();
    var windowWidth = jQuery(window).width();

    var left = windowWidth / 2 - dlogWidth / 2;
    var top = windowHeight / 2 - dlogHeight / 2;

    top /= 2;

    var delta = (top + dlogHeight) - windowHeight;
    if(delta > 0) {
        top -= delta;
    }

    if(inMinTop) {
        if(top < inMinTop) {
            top = inMinTop;
        }
    }

    dlog.dialog({position:[left,top]});

//    dlog.dialog("option","position",[left,top]);
}

//function cricket_alert_position(inDLOGID) {
//    var dlogHeight = jQuery('#' + inDLOGID).height();
//    var screenHeight = window.screen.availHeight;
//
//    var dlogWidth = jQuery('#' + inDLOGID).width();
//    var screenWidth = window.screen.availWidth;
//
//    var top = (screenHeight - dlogHeight) / 5;
//    var left = (screenWidth - dlogWidth) / 3;
//
//    jQuery('#' + inDLOGID).dialog("option", "position", [left, top]);
//}<commit_msg>Added more human-readable console error. Malformed data (typically UTF-8 characters) results in null JSON data being sent over the wire. So, this is the attempt to let developers know that, when this occurs, they should check their data closely.<commit_after>/*
 * (C) Copyright 2014 Bill Hubauer <bill@hubauer.com>
 *
 * This file is part of Cricket  https://github.com/bhubauer/cricket
 *
 * This library is free software; you can redistribute it and/or modify it under the terms of the
 * GNU Lesser General Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this library;
 * if not, visit http://www.gnu.org/licenses/lgpl-2.1.html or write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

var _CRICKET_PAGE_INSTANCE_ = null;

var CRICKET_BUSY_INDICATOR = 'cricket_busy';
var CRICKET_AUTO_BUSY = false;
var CRICKET_ACTIVE_CHANNELS = {};

/* inlude the following CSS, along with the cricket busy indicator
 * body.cricket_busy, body.cricket_busy * {
    cursor: progress !important;
}
 */

function cricket_abort_ajax(inRequest) {
    if(inRequest) {
        inRequest.abort();
    }
}

// if inRequestChannel, the if there is any active ajax for this channel, it is aborted prior to issuing the new one

function cricket_ajax(inURL,inData,inIndicatorID,inConfirmation,inRequestChannel,inFailSilent) {

    if(inFailSilent == null) {
        inFailSilent = false;
    }

    if(inRequestChannel) {
        if(inRequestChannel in CRICKET_ACTIVE_CHANNELS) {
            cricket_abort_ajax(CRICKET_ACTIVE_CHANNELS[inRequestChannel]);
            delete CRICKET_ACTIVE_CHANNELS[inRequestChannel];
        }
    }

    var result = null;

    if(!inIndicatorID) {
        if(CRICKET_AUTO_BUSY) {
            inIndicatorID = CRICKET_BUSY_INDICATOR;
        }
    }

    if(!_CRICKET_PAGE_INSTANCE_){
        alert("Configuration error. _CRICKET_PAGE_INSTANCE_ not set");
        return;
    }

    // add page instance
    inData = jQuery.extend({'_CRICKET_PAGE_INSTANCE_':_CRICKET_PAGE_INSTANCE_},inData);

    var go = true;

    if(inConfirmation) {
        go = confirm(inConfirmation);
    }

    if(go) {
        // TODO: Activate this
        if(inIndicatorID) {
            if(cricket_indicator_active(inIndicatorID)) {
                return;
            }
            cricket_indicator_start(inIndicatorID);
        }
        result = jQuery.ajax({
            type: 'POST',
            url: inURL,
            data: inData,
            success: function(data, textStatus, request) {

                if(data) {

                    if (data.redirect) {
                        document.location.href = data.redirect;
                        return;
                    }

                    if (data.message) {
                        alert(data.message);
                    }

                    for (var z = 0; z < data.scripts_pre.length; z++) {
                        eval(data.scripts_pre[z]);
                    }

                    if (data.dialog) {
                        jQuery("

").dialog(
                            jQuery.extend(
                                data.dialog.options, {
                                    close: function (e, ui) {
                                        cricket_ajax(data.dialog.closeUrl, {});
                                        jQuery("#" + data.dialog.id).dialog('destroy').remove();
                                    }
                                }
                            )
                        );
                    }

                    for (var key in data.updates) {
                        if (data.replacements[key])
                            jQuery("#" + key).replaceWith(data.updates[key]);
                        else
                            jQuery("#" + key).html(data.updates[key]);
                    }

                    for (var key in data.append) {
                        jQuery("#" + key).append(data.append[key]);
                    }

                    for (var z = 0; z < data.scripts_post.length; z++) {
                        eval(data.scripts_post[z]);
                    }

                    if (data.sounds.length) {
                        if (window.HTMLAudioElement) {
                            for (var key in data.sounds) {
                                var audio = new Audio(data.sounds[key]);
                                audio.play();
                            }
                        }
                    }
                } else {
                    console.error('Cricket AJAX response is invalid. This can be caused by malformed data (often UTF-8 characters) pulled from a database.');
                }
            },
            complete: function(request,textStatus) {
                if(inRequestChannel) {
                    delete CRICKET_ACTIVE_CHANNELS[inRequestChannel];
                }

                if(inIndicatorID) cricket_indicator_stop(inIndicatorID);
            },
            error: function(request,textStatus,errorThrown) {
                if(!inFailSilent) {
                    jQuery("html").html(request.responseText);
                }
            },
            beforeSend: function(request) {
                request.setRequestHeader("x-cricket-ajax","true");
                return true;
            },
            dataType: 'json'
        });

        if(inRequestChannel) {
            CRICKET_ACTIVE_CHANNELS[inRequestChannel] = result;
        }
    }

//    return result;
}

var CRICKET_SELECTION = {};
function cricket_click_row(inTableID,inSelectURL,inRowID,inItemID, inUseID) {
    if(CRICKET_SELECTION[inTableID]) {
        jQuery("#" + CRICKET_SELECTION[inTableID]).removeClass("selected");
    }

    jQuery("#" + inRowID).addClass("selected");
    CRICKET_SELECTION[inTableID] = inRowID;

    var indicator = "ind_select_row";
    if (inUseID) {
    	indicator += "_" + inItemID;
    }

    cricket_ajax(inSelectURL,{id:inItemID,row_id:inRowID},indicator);
}

function cricket_clear_selection(inTableID) {
    if(CRICKET_SELECTION[inTableID]) {
        jQuery("#" + CRICKET_SELECTION[inTableID]).removeClass("selected");
        delete CRICKET_SELECTION[inTableID];
    }
}

function cricket_isArray(obj){
	if (typeof arguments[0] == 'object') {
		var criterion = arguments[0].constructor.toString().match(/array/i);
 		return (criterion != null);
	}
	return false;
}

function cricket_ajax_form(inFormOrChild,inSubmitURL,inInd,inConfirmation,inRequestChannel,inFailSilent)
{
    var values = cricket_serialize_form(inFormOrChild);
    cricket_ajax(inSubmitURL,values,inInd,inConfirmation,inRequestChannel,inFailSilent);
}

function cricket_serialize_form(inFormOrChild) {
    var     form = inFormOrChild;

    if(form.nodeName.toLowerCase() != 'form') {
        form = jQuery(form).parents('form').get();
    }

    var values = {};
    jQuery.each(jQuery(form).serializeArray(), function(i, field) {
    	if(values[field.name] != undefined) {
    		if(cricket_isArray(values[field.name])) {
    			values[field.name].push(field.value);
    		} else {
    			var tmp = values[field.name];
    			values[field.name] = [];
    			values[field.name].push(tmp);
    			values[field.name].push(field.value);
    		}
    	} else {
    		values[field.name] = field.value;
    	}
    });

    return values;
}

var cricket_indicators = {

};

var cricket_indicator_timeout = 250;

function cricket_indicator_start(inID,inRestart,inTimeout) {
    if(inRestart == null) {
        inRestart = false;
    }

    if(inTimeout == null) {
        inTimeout = cricket_indicator_timeout;
    }

    var rec = cricket_indicators[inID];
    if(!rec) {
        rec = {
            level: 0,
            timer: 0
        };

        cricket_indicators[inID] = rec;
    }else{
        rec.level = 1;
        cricket_indicator_stop(inID);
    }

    rec.level++;
    if(rec.level == 1) {
        rec.timer = setTimeout(function(){
            rec.timer = 0;

            if(inID == CRICKET_BUSY_INDICATOR) {
                jQuery('body').addClass('cricket_busy');
            }else{
                var i = document.getElementById(inID);
                if(i) {
                    i.style.visibility = "visible";
                }
            }
        },inTimeout);
    }
}

function cricket_indicator_active(inID) {
	var rec = cricket_indicators[inID];
	if(!rec) {
		return false;
	}

	return rec.level > 0;
}

function cricket_indicator_stop(inID) {
    var rec = cricket_indicators[inID];
	if(!rec) {
		return false;
	}
    rec.level--;
    if(rec.level == 0) {
        if(rec.timer != 0) {
            clearTimeout(rec.timer);
        }
        if(inID == CRICKET_BUSY_INDICATOR) {
            jQuery('body').removeClass('cricket_busy');
        }else{
            var i = document.getElementById(inID);
            if(i) {
                i.style.visibility = "hidden";
            }
        }
    }
}

function cricket_alert_position(inDLOGID,inMinTop) {
    var dlog = jQuery("#" + inDLOGID);
    var dlogHeight = dlog.height();
    var dlogWidth = dlog.width();

    var windowHeight = jQuery(window).height();
    var windowWidth = jQuery(window).width();

    var left = windowWidth / 2 - dlogWidth / 2;
    var top = windowHeight / 2 - dlogHeight / 2;

    top /= 2;

    var delta = (top + dlogHeight) - windowHeight;
    if(delta > 0) {
        top -= delta;
    }

    if(inMinTop) {
        if(top < inMinTop) {
            top = inMinTop;
        }
    }

    dlog.dialog({position:[left,top]});

//    dlog.dialog("option","position",[left,top]);
}

//function cricket_alert_position(inDLOGID) {
//    var dlogHeight = jQuery('#' + inDLOGID).height();
//    var screenHeight = window.screen.availHeight;
//
//    var dlogWidth = jQuery('#' + inDLOGID).width();
//    var screenWidth = window.screen.availWidth;
//
//    var top = (screenHeight - dlogHeight) / 5;
//    var left = (screenWidth - dlogWidth) / 3;
//
//    jQuery('#' + inDLOGID).dialog("option", "position", [left, top]);
//}<|endoftext|>


<commit_before>var FormData = this.FormData;
var cookiesMap = {};
//               /////  1   ////////// 2 /////// 3 ////    4  //
var domainReg = /^(?:(https?)\:)?\/\/(.*?)(?:\/(.*?))?([\?#].*)?$/i;
var { efrontURI, cross_host = efrontURI } = this;
var location_host = location.href.replace(domainReg, '$1://$2/');
if (cross_host) {
    if (!domainReg.test(cross_host)) {
        console.error("cross_host格式不正确", cross_host);
        cross_host = "/";
    } else {
        cross_host = (/^https/.test(location_host) ? "https://" : "http://") + cross_host.replace(domainReg, '$2/');
    }
}
var base = cross_host || (domainReg.test(location.href) ? '/' : "http://efront.cc/");
var HeadersKeys = ["Content-Type"];
var cookieItemsInSessionStorageKey = "--zimoli-coms-cross";
var cookiesData = sessionStorage.getItem(cookieItemsInSessionStorageKey);
var cors_hosts = [];
if (cookiesData) {
    try {
        extend(cookiesMap, JSON.parse(cookiesData));
    } catch (e) {
        console.warn("加载cookie出错！");
    }
}
function getDomainPath(url) {
    return url.replace(domainReg, "$2/$3");
}
function getRequestProtocol(url) {
    if (/^https:/i.test(url)) {
        return "https";
    }
    return "http";
}
function getCookies(domainPath) {
    var cookieObject = {};
    var splited = domainPath.split("/");
    var domain = splited[0];
    do {
        var copy = splited.slice(0);
        do {
            domainPath = copy.join("/");
            var cookie = cookiesMap[domainPath];
            if (cookie) {
                for (var k in cookie) {
                    if (!cookieObject[k]) {
                        cookieObject[k] = cookie[k];
                    }
                }
            }
            copy.pop();
        } while (copy.length);
        domain = domain.replace(/^.*?(\.|$)/, "");
        splited[0] = domain;
    } while (domain.length);
    return serialize(cookieObject, ";");
}
function addCookie(cookie, originDomain = "") {
    if (cookie) {
        clearTimeout(addCookie.save_timer);
        addCookie.save_timer = setTimeout(function () {
            sessionStorage.setItem(cookieItemsInSessionStorageKey, JSON.stringify(cookiesMap));
        }, 20);
        cookie.replace(/(^|;|,)\s*(expires)=(\w*),([^=]*)(;|$)/ig, "$1$2=$3.$4$5")
            .split(/,\s*/).map(function (cookie) {
                var cookieObject = {};
                var result = cookie.split(/;\s*/);
                result.slice(1).map(function (kev) {
                    var kvs = /^(.+?)\=(.+?)$/.exec(kev);
                    if (kvs) {
                        var [, k, v] = kvs;
                        cookieObject[k.toLowerCase()] = v;
                    }
                });
                var { path, domain } = cookieObject;
                if (!domain) {
                    domain = originDomain.replace(/[^\/]+$/, "");
                }
                if (/^\./.test(domain)) {
                    domain = domain.replace(/^\.+/, "");
                }
                var destPath;
                if (/^\//.test(path)) {
                    destPath = domain.replace(/\/.*$/, "") + path;
                } else {
                    destPath = domain;
                }
                destPath = destPath.replace(/\/+$/, "");
                if (originDomain.indexOf(destPath) >= 0) {
                    var cookieMap = parseKV(result[0], ";");
                    if (!cookiesMap[destPath]) {
                        cookiesMap[destPath] = cookieMap;
                    } else {
                        extend(cookiesMap[destPath], cookieMap);
                    }
                }
            });
    }
}
function isChildPath(relative, path) {
    return relative.replace(/^(.*\/)[^\/]*$/, path);
}
var digest = function () {
    if (cross.digest instanceof Function) cross.digest();
};

var getCrossUrl = function (domain, headers) {
    if (notCross(domain)) return domain;
    var originDomain = getDomainPath(domain);
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    var spliter = encodeURIComponent("/");
    return domain
        .replace(/^s?\/\//i, "http$&")
        .replace(domainReg, base + `%7B${/^(https\:|s\/\/)/i.test(domain) ? "s" : ""}${spliter + spliter}$2${spliter}${serialize(_headers)}%7D@$3$4`);
};
function cross(method, url, headers) {
    var originDomain = getDomainPath(url);
    if (!originDomain) throw new Error("Unsupposed url format!");
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    if (/^[mc]/i.test(method)) {
        _headers["User-Agent"] = /^m/i.test(method)
            ? "Efront/1.9 (iPhone) Safari/602.1"
            : "Efront/1.9 (Windows) Chrome/77.0.3865.90";
        method = method.slice(1);
    }
    var nocross = notCross(url);
    var xhr = new XMLHttpRequest;
    var abort = xhr.abort;
    xhr.abort = function () {
        xhr.onreadystatechange = null;
        abort.call(this);
    };
    HeadersKeys.map(function (k) {
        if (_headers[k]) xhr.setRequestHeader(k, _headers[k]);
        delete _headers[k];
    });

    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (xhr.getResponseHeader && !nocross) {
                var cookie = xhr.getResponseHeader("efront-cookie");
                addCookie(cookie, originDomain);
            }
            switch (xhr.status) {
                case 0:
                    if (!navigator.onLine) {
                        onerror({ status: "网络断开" });
                        break;
                    }
                    if (!navigator.response) {
                        onerror({ status: "服务器无响应" });
                        break;
                    }
                case 200:
                case 201:
                case 304:
                    onload(xhr);
                    break;
                case 302:
                case 301:
                    if (xhr.isRedirected > 2) break;
                    var location = xhr.getResponseHeader("efront-location");
                    if (!domainReg.test(location)) {
                        if (/^\//.test(location)) {
                            location = originDomain.replace(/\/.*$/, location);
                        } else {
                            location = originDomain.replace(/[^\/+]$/, location);
                        }
                        location = getRequestProtocol(url) + "://" + location;
                    }
                    var crs = cross("get", location, headers);
                    crs.isRedirected = (xhr.isRedirected || 0) + 1;
                    crs.done(onload, false);
                    crs.error(onerror, false);
                    break;
                default:
                    onerror(xhr);
            }
            dispatch(window, 'render');
        }
    };
    var setRequestHeader = xhr.setRequestHeader;
    var realHeaders = Object.create(null);
    xhr.setRequestHeader = function (key, value) {
        realHeaders[key] = value;
    };
    setTimeout(function () {
        var isform = /^f/i.test(method);
        if (isform) {
            if (method === 'form') method = 'post';
            else method = method.slice(1);
        }
        if (!isEmpty(jsondata) && isEmpty(datas)) {
            if (/^(get|head|trace)$/i.test(method)) {
                url = url.replace(/#[\s\S]*/, '');
                datas = serialize(jsondata);
                if (datas) url += (/\?/.test(url) ? "&" : "?") + datas;
            } else if (isform) {
                xhr.form(jsondata);
            } else {
                datas = JSON.stringify(jsondata);
                if (datas === "{}" || datas === "[]") {
                    datas = '';
                } else {
                    realHeaders["Content-Type"] = "application/json;charset=UTF-8";
                }
            }
        }
        if (nocross) {
            extend(realHeaders, _headers);
            xhr.open(method, url);
        } else {
            xhr.open(method, getCrossUrl(url, _headers));
        }
        Object.keys(realHeaders).forEach(key => setRequestHeader.call(xhr, key, realHeaders[key]));
        send.call(xhr, datas);
    }, 0);
    var onload = function (xhr) {
        if (xhr.decoder) {
            xhr = xhr.decoder(xhr);
        }
        onloads.map(e => e instanceof Function && e(xhr));
        digest();
    };
    var onerror = function (xhr) {
        onerrors.map(e => e instanceof Function && e(xhr));
        digest();
    };
    var onloads = [], onerrors = [];
    xhr.done = xhr.success = function (on, asqueue = true) {
        if (asqueue) {
            onloads.push(on);
        } else {
            onload = on;
        }
        return xhr;
    };
    var send = xhr.send;
    var datas = "";
    var jsondata = null;
    xhr.json = xhr.data = xhr.send = function (data, value) {
        if (!jsondata && !(isEmpty(data) && isEmpty(value))) jsondata = {};
        if (FormData && data instanceof FormData) {
            datas = data;
        } else if (data instanceof Object && !isFile(data)) {
            extend(jsondata, data);
        } else if (value) {
            extend(jsondata, { [data]: value });
        } else if (isString(data) && value !== false) {
            var data = /^\{/.test(data) ? JSON.parse(data) : parseKV(data, "&", "=");
            extend(jsondata, data);
        } else {
            datas = data;
        }
        return xhr;
    };
    xhr.form = function (data) {
        xhr.data(data);
        if (FormData) {
            datas = new FormData;
            for (var k in jsondata) {
                datas.append(k, jsondata[k]);
            }
        } else {
            realHeaders["Content-Type"] = "application/x-www-form-urlencoded";
            datas = serialize(jsondata, "&", "=");
        }
    };
    xhr.fail = xhr.error = function (on, asqueue = true) {
        if (asqueue) {
            onerrors.push(on);
        } else {
            onerror = on;
        }
        onerror = on;
        return xhr;
    };
    return xhr;
}
function addDirect(a) {
    if (typeof a === 'string' || a instanceof RegExp) cors_hosts.push(a);
}
function notCross(domain) {
    if (location_host === domain.slice(0, location_host.length)) return true;
    for (var cx = 0, dx = cors_hosts.length; cx < dx; cx++) {
        var host = cors_hosts[cx];
        if (host instanceof RegExp) {
            if (host.test(domain)) return true;
        } else {
            host = host.replace(domainReg, '$2/$3');
            if (domain.replace(domainReg, '$2/$3').slice(0, host.length) === host) return true;
        }
    }
    return false;
}
extend(cross, {
    getCookies,
    addCookie,
    addDirect,
    getCrossUrl
});<commit_msg>集成jsonp到cross<commit_after>var FormData = this.FormData;
var cookiesMap = {};
//               /////  1   ////////// 2 /////// 3 ////    4  //
var domainReg = /^(?:(https?)\:)?\/\/(.*?)(?:\/(.*?))?([\?#].*)?$/i;
var { efrontURI, cross_host = efrontURI } = this;
var location_host = location.href.replace(domainReg, '$1://$2/');
if (cross_host) {
    if (!domainReg.test(cross_host)) {
        console.error("cross_host格式不正确", cross_host);
        cross_host = "/";
    } else {
        cross_host = (/^https/.test(location_host) ? "https://" : "http://") + cross_host.replace(domainReg, '$2/');
    }
}
var base = cross_host || (domainReg.test(location.href) ? '/' : "http://efront.cc/");
var HeadersKeys = ["Content-Type"];
var cookieItemsInSessionStorageKey = "--zimoli-coms-cross";
var cookiesData = sessionStorage.getItem(cookieItemsInSessionStorageKey);
var cors_hosts = [];
if (cookiesData) {
    try {
        extend(cookiesMap, JSON.parse(cookiesData));
    } catch (e) {
        console.warn("加载cookie出错！");
    }
}
function getDomainPath(url) {
    return url.replace(domainReg, "$2/$3");
}
function getRequestProtocol(url) {
    if (/^https:/i.test(url)) {
        return "https";
    }
    return "http";
}
function getCookies(domainPath) {
    var cookieObject = {};
    var splited = domainPath.split("/");
    var domain = splited[0];
    do {
        var copy = splited.slice(0);
        do {
            domainPath = copy.join("/");
            var cookie = cookiesMap[domainPath];
            if (cookie) {
                for (var k in cookie) {
                    if (!cookieObject[k]) {
                        cookieObject[k] = cookie[k];
                    }
                }
            }
            copy.pop();
        } while (copy.length);
        domain = domain.replace(/^.*?(\.|$)/, "");
        splited[0] = domain;
    } while (domain.length);
    return serialize(cookieObject, ";");
}
function addCookie(cookie, originDomain = "") {
    if (cookie) {
        clearTimeout(addCookie.save_timer);
        addCookie.save_timer = setTimeout(function () {
            sessionStorage.setItem(cookieItemsInSessionStorageKey, JSON.stringify(cookiesMap));
        }, 20);
        cookie.replace(/(^|;|,)\s*(expires)=(\w*),([^=]*)(;|$)/ig, "$1$2=$3.$4$5")
            .split(/,\s*/).map(function (cookie) {
                var cookieObject = {};
                var result = cookie.split(/;\s*/);
                result.slice(1).map(function (kev) {
                    var kvs = /^(.+?)\=(.+?)$/.exec(kev);
                    if (kvs) {
                        var [, k, v] = kvs;
                        cookieObject[k.toLowerCase()] = v;
                    }
                });
                var { path, domain } = cookieObject;
                if (!domain) {
                    domain = originDomain.replace(/[^\/]+$/, "");
                }
                if (/^\./.test(domain)) {
                    domain = domain.replace(/^\.+/, "");
                }
                var destPath;
                if (/^\//.test(path)) {
                    destPath = domain.replace(/\/.*$/, "") + path;
                } else {
                    destPath = domain;
                }
                destPath = destPath.replace(/\/+$/, "");
                if (originDomain.indexOf(destPath) >= 0) {
                    var cookieMap = parseKV(result[0], ";");
                    if (!cookiesMap[destPath]) {
                        cookiesMap[destPath] = cookieMap;
                    } else {
                        extend(cookiesMap[destPath], cookieMap);
                    }
                }
            });
    }
}
function isChildPath(relative, path) {
    return relative.replace(/^(.*\/)[^\/]*$/, path);
}
var digest = function () {
    if (cross.digest instanceof Function) cross.digest();
};

var getCrossUrl = function (domain, headers) {
    if (notCross(domain)) return domain;
    var originDomain = getDomainPath(domain);
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    var spliter = encodeURIComponent("/");
    return domain
        .replace(/^s?\/\//i, "http$&")
        .replace(domainReg, base + `%7B${/^(https\:|s\/\/)/i.test(domain) ? "s" : ""}${spliter + spliter}$2${spliter}${serialize(_headers)}%7D@$3$4`);
};
function cross(method, url, headers) {
    var originDomain = getDomainPath(url);
    if (!originDomain) throw new Error("Unsupposed url format!");
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    if (/^[mc]/i.test(method)) {
        _headers["User-Agent"] = /^m/i.test(method)
            ? "Efront/1.9 (iPhone) Safari/602.1"
            : "Efront/1.9 (Windows) Chrome/77.0.3865.90";
        method = method.slice(1);
    }
    if (/^jsonp/i.test(method)) {
        var cb = method.split('\-')[1] || 'callback';
        setTimeout(function () {
            if (!isEmpty(jsondata) && isEmpty(datas)) {
                datas = serialize(jsondata);
            }
            if (datas) {
                xhr.src += "&" + datas;
            }
        });
        var xhr = jsonp(url, {
            [cb](a) {
                xhr.response = xhr.responseText = JSON.stringify(a);
                onload(xhr);
            }
        });
        xhr.onerror = function (e) {
            onerror(e);
        };
    } else {
        var nocross = notCross(url);
        var xhr = new XMLHttpRequest;
        var abort = xhr.abort;
        xhr.abort = function () {
            xhr.onreadystatechange = null;
            abort.call(this);
        };
        HeadersKeys.map(function (k) {
            if (_headers[k]) xhr.setRequestHeader(k, _headers[k]);
            delete _headers[k];
        });

        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.getResponseHeader && !nocross) {
                    var cookie = xhr.getResponseHeader("efront-cookie");
                    addCookie(cookie, originDomain);
                }
                switch (xhr.status) {
                    case 0:
                        if (!navigator.onLine) {
                            onerror({ status: "网络断开" });
                            break;
                        }
                        if (!navigator.response) {
                            onerror({ status: "服务器无响应" });
                            break;
                        }
                    case 200:
                    case 201:
                    case 304:
                        onload(xhr);
                        break;
                    case 302:
                    case 301:
                        if (xhr.isRedirected > 2) break;
                        var location = xhr.getResponseHeader("efront-location");
                        if (!domainReg.test(location)) {
                            if (/^\//.test(location)) {
                                location = originDomain.replace(/\/.*$/, location);
                            } else {
                                location = originDomain.replace(/[^\/+]$/, location);
                            }
                            location = getRequestProtocol(url) + "://" + location;
                        }
                        var crs = cross("get", location, headers);
                        crs.isRedirected = (xhr.isRedirected || 0) + 1;
                        crs.done(onload, false);
                        crs.error(onerror, false);
                        break;
                    default:
                        onerror(xhr);
                }
                dispatch(window, 'render');
            }
        };
        var setRequestHeader = xhr.setRequestHeader;
        var realHeaders = Object.create(null);
        xhr.setRequestHeader = function (key, value) {
            realHeaders[key] = value;
        };
        setTimeout(function () {
            var isform = /^f/i.test(method);
            if (isform) {
                if (method === 'form') method = 'post';
                else method = method.slice(1);
            }
            if (!isEmpty(jsondata) && isEmpty(datas)) {
                if (/^(get|head|trace)$/i.test(method)) {
                    url = url.replace(/#[\s\S]*/, '');
                    datas = serialize(jsondata);
                    if (datas) url += (/\?/.test(url) ? "&" : "?") + datas;
                } else if (isform) {
                    xhr.form(jsondata);
                } else {
                    datas = JSON.stringify(jsondata);
                    if (datas === "{}" || datas === "[]") {
                        datas = '';
                    } else {
                        realHeaders["Content-Type"] = "application/json;charset=UTF-8";
                    }
                }
            }
            if (nocross) {
                extend(realHeaders, _headers);
                xhr.open(method, url);
            } else {
                xhr.open(method, getCrossUrl(url, _headers));
            }
            Object.keys(realHeaders).forEach(key => setRequestHeader.call(xhr, key, realHeaders[key]));
            send.call(xhr, datas);
        }, 0);
    }
    var onload = function (xhr) {
        if (xhr.decoder) {
            xhr = xhr.decoder(xhr);
        }
        onloads.map(e => e instanceof Function && e(xhr));
        digest();
    };
    var onerror = function (xhr) {
        onerrors.map(e => e instanceof Function && e(xhr));
        digest();
    };
    var onloads = [], onerrors = [];
    xhr.done = xhr.success = function (on, asqueue = true) {
        if (asqueue) {
            onloads.push(on);
        } else {
            onload = on;
        }
        return xhr;
    };
    var send = xhr.send;
    var datas = "";
    var jsondata = null;
    xhr.json = xhr.data = xhr.send = function (data, value) {
        if (!jsondata && !(isEmpty(data) && isEmpty(value))) jsondata = {};
        if (FormData && data instanceof FormData) {
            datas = data;
        } else if (data instanceof Object && !isFile(data)) {
            extend(jsondata, data);
        } else if (value) {
            extend(jsondata, { [data]: value });
        } else if (isString(data) && value !== false) {
            var data = /^\{/.test(data) ? JSON.parse(data) : parseKV(data, "&", "=");
            extend(jsondata, data);
        } else {
            datas = data;
        }
        return xhr;
    };
    xhr.form = function (data) {
        xhr.data(data);
        if (FormData) {
            datas = new FormData;
            for (var k in jsondata) {
                datas.append(k, jsondata[k]);
            }
        } else {
            realHeaders["Content-Type"] = "application/x-www-form-urlencoded";
            datas = serialize(jsondata, "&", "=");
        }
    };
    xhr.fail = xhr.error = function (on, asqueue = true) {
        if (asqueue) {
            onerrors.push(on);
        } else {
            onerror = on;
        }
        onerror = on;
        return xhr;
    };
    return xhr;
}
function addDirect(a) {
    if (typeof a === 'string' || a instanceof RegExp) cors_hosts.push(a);
}
function notCross(domain) {
    if (location_host === domain.slice(0, location_host.length)) return true;
    for (var cx = 0, dx = cors_hosts.length; cx < dx; cx++) {
        var host = cors_hosts[cx];
        if (host instanceof RegExp) {
            if (host.test(domain)) return true;
        } else {
            host = host.replace(domainReg, '$2/$3');
            if (domain.replace(domainReg, '$2/$3').slice(0, host.length) === host) return true;
        }
    }
    return false;
}
extend(cross, {
    getCookies,
    addCookie,
    addDirect,
    getCrossUrl
});<|endoftext|>


<commit_before>"use strict";

const walk                        = require('acorn/dist/walk');
const extractCommonJSDependencies = require("./extract-commonJS-deps");

module.exports = (pAST, pDependencies) => {
    walk.simple(
        pAST,
        {
            "ExpressionStatement": pNode => {
                // module as a function (define(Array, function))
                // module with a name (define(string, Array, function))
                // 'root' require module (require(Array, function)
                if (pNode.expression.type === "CallExpression" &&
                     pNode.expression.callee.type === "Identifier" &&
                     (pNode.expression.callee.name === "define" ||
                       pNode.expression.callee.name === "require")){
                    pNode.expression.arguments
                        .filter(pArg => pArg.type === "ArrayExpression")
                        .forEach(arg =>
                            arg.elements.forEach(el => {
                                if (Boolean(el.value) && typeof el.value === "string") {
                                    el.value.split('!').forEach(pString =>
                                        pDependencies.push({
                                            moduleName: pString,
                                            moduleSystem: "amd"
                                        })
                                    );
                                }
                            })
                        );
                }
                // CommonJS-wrappers:
                //  (define(function(require, exports, module){
                //  define(["require", ...], function(require, ...){
                //      ... every 'require' call is a depencency
                // Won't work if someone decides to name the first parameter of
                // the function passed to the define something else from "require"
                if (pNode.expression.type === "CallExpression" &&
                     pNode.expression.callee.type === "Identifier" &&
                     pNode.expression.callee.name === "define") {
                    pNode.expression.arguments
                        .filter(pArg => pArg.type === "FunctionExpression")
                        .filter(pFunction => pFunction.params.some(pParam => pParam.name === "require"))
                        .forEach(pFunction => extractCommonJSDependencies(pFunction.body, pDependencies, "amd"));
                }
            }
        }
    );
};
<commit_msg>refactor(extract): break the anonymous call in the core AMD extractor in two functions<commit_after>"use strict";

const walk                        = require('acorn/dist/walk');
const extractCommonJSDependencies = require("./extract-commonJS-deps");

function extractRegularAMDDependencies(pNode, pDependencies) {
    if (pNode.expression.type === "CallExpression" &&
        pNode.expression.callee.type === "Identifier" &&
        (pNode.expression.callee.name === "define" ||
            pNode.expression.callee.name === "require")) {
        pNode.expression.arguments
            .filter(pArg => pArg.type === "ArrayExpression")
            .forEach(arg => arg.elements.forEach(el => {
                if (Boolean(el.value) && typeof el.value === "string") {
                    el.value.split('!').forEach(pString => pDependencies.push({
                        moduleName: pString,
                        moduleSystem: "amd"
                    }));
                }
            }));
    }
}

function extractCommonJSWrappers(pNode, pDependencies) {
    if (pNode.expression.type === "CallExpression" &&
        pNode.expression.callee.type === "Identifier" &&
        pNode.expression.callee.name === "define") {
        pNode.expression.arguments
            .filter(pArg => pArg.type === "FunctionExpression")
            .filter(pFunction => pFunction.params.some(pParam => pParam.name === "require"))
            .forEach(pFunction => extractCommonJSDependencies(pFunction.body, pDependencies, "amd"));
    }
}

module.exports = (pAST, pDependencies) => {
    walk.simple(
        pAST,
        {
            "ExpressionStatement": pNode => {
                // module as a function (define(Array, function))
                // module with a name (define(string, Array, function))
                // 'root' require module (require(Array, function)
                extractRegularAMDDependencies(pNode, pDependencies);
                // CommonJS-wrappers:
                //  (define(function(require, exports, module){
                //  define(["require", ...], function(require, ...){
                //      ... every 'require' call is a depencency
                // Won't work if someone decides to name the first parameter of
                // the function passed to the define something else from "require"
                extractCommonJSWrappers(pNode, pDependencies);
            }
        }
    );
};
<|endoftext|>


<commit_before>var FormData = this.FormData;
var cookiesMap = {};
//               /////  1   ////////// 2 /////// 3 ////    4  //
var domainReg = /^(?:(https?)\:)?\/\/(.*?)(?:\/(.*?))?([\?#].*)?$/i;
var base = domainReg.test(location.href) ? '/' : "http://efront.cc/";
var location_host = location.href.replace(domainReg, '$1://$2/');
var setHost = function (host) {
    var parsed = parseURL(host);
    if (!host) return console.error("cross_host格式不正确", host);
    var host = parsed.host + (parsed.pathname || '/');
    host = (/^https/.test(location_host) ? "https://" : "http://") + host;
    base = host;
};
var { efrontURI, cross_host = efrontURI } = this;
if (cross_host) setHost(cross_host);
var HeadersKeys = ["Content-Type"];
var cookieItemsInSessionStorageKey = "--zimoli-coms-cross";
var cookiesData = sessionStorage.getItem(cookieItemsInSessionStorageKey);
var cors_hosts = [];
if (cookiesData) {
    try {
        extend(cookiesMap, JSON.parse(cookiesData));
    } catch (e) {
        console.warn("加载cookie出错！");
    }
}
function getDomainPath(url) {
    return url.replace(domainReg, "$2/$3");
}
function getRequestProtocol(url) {
    if (/^https:/i.test(url)) {
        return "https:";
    }
    return "http:";
}
function getCookies(domainPath) {
    var cookieObject = {};
    var splited = domainPath.split("/");
    var domain = splited[0];
    do {
        var copy = splited.slice(0);
        do {
            domainPath = copy.join("/");
            var cookie = cookiesMap[domainPath];
            if (cookie) {
                for (var k in cookie) {
                    if (!cookieObject[k]) {
                        cookieObject[k] = cookie[k];
                    }
                }
            }
            copy.pop();
        } while (copy.length);
        domain = domain.replace(/^.*?(\.|$)/, "");
        splited[0] = domain;
    } while (domain.length);
    return serialize(cookieObject, ";");
}
function addCookie(cookie, originDomain = "") {
    if (cookie) {
        clearTimeout(addCookie.save_timer);
        addCookie.save_timer = setTimeout(function () {
            sessionStorage.setItem(cookieItemsInSessionStorageKey, JSON.stringify(cookiesMap));
        }, 20);
        cookie.replace(/(^|;|,)\s*(expires)=(\w*),([^=]*)(;|$)/ig, "$1$2=$3.$4$5")
            .split(/,\s*/).map(function (cookie) {
                var cookieObject = {};
                var result = cookie.split(/;\s*/);
                result.slice(1).map(function (kev) {
                    var kvs = /^(.+?)\=(.+?)$/.exec(kev);
                    if (kvs) {
                        var [, k, v] = kvs;
                        cookieObject[k.toLowerCase()] = v;
                    }
                });
                var { path, domain } = cookieObject;
                if (!domain) {
                    domain = originDomain.replace(/[^\/]+$/, "");
                }
                if (/^\./.test(domain)) {
                    domain = domain.replace(/^\.+/, "");
                }
                var destPath;
                if (/^\//.test(path)) {
                    destPath = domain.replace(/\/.*$/, "") + path;
                } else {
                    destPath = domain;
                }
                destPath = destPath.replace(/\/+$/, "");
                if (originDomain.indexOf(destPath) >= 0) {
                    var cookieMap = parseKV(result[0], ";");
                    if (!cookiesMap[destPath]) {
                        cookiesMap[destPath] = cookieMap;
                    } else {
                        extend(cookiesMap[destPath], cookieMap);
                    }
                }
            });
    }
}
function isChildPath(relative, path) {
    return relative.replace(/^(.*\/)[^\/]*$/, path);
}
var digest = function () {
    dispatch('render', window);
};

var getCrossUrl = function (domain, headers) {
    if (notCross(domain)) return domain;
    var originDomain = getDomainPath(domain);
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    _headers = serialize(_headers);
    if (_headers) _headers = "," + _headers;
    return domain
        .replace(/^(s?)(\/\/)/i, "http$1:$2")
        .replace(domainReg, base + `*${/^(https\:|s\/\/)/i.test(domain) ? "*" : ""}$2${_headers}/$3$4`);
};
function cross(method, url, headers) {
    var originDomain = getDomainPath(url);
    if (!originDomain) throw new Error("Unsupposed url format!");
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    if (/^[mc]/i.test(method)) {
        _headers["User-Agent"] = /^m/i.test(method)
            ? "Efront/1.9 (iPhone) Safari/602.1"
            : "Efront/1.9 (Windows) Chrome/77.0.3865.90";
        method = method.slice(1);
    }
    if (/^jsonp/i.test(method)) {
        var cb = method.split('\-')[1] || 'callback';
        setTimeout(function () {
            if (!isEmpty(jsondata) && isEmpty(datas)) {
                datas = serialize(jsondata);
            }
            if (datas) {
                xhr.src += "&" + datas;
            }
        });
        var xhr = jsonp(url, {
            [cb](a) {
                xhr.response = xhr.responseText = JSON.stringify(a);
                onload(xhr);
            }
        });
        xhr.onerror = function (e) {
            onerror(e);
        };
        xhr.abort = function () {
            removeFromList(requests, this);
            remove(this);
        };
    } else {
        var nocross = notCross(url);
        var xhr = new XMLHttpRequest;
        var abort = xhr.abort;
        xhr.abort = function () {
            xhr.onreadystatechange = null;
            removeFromList(requests, this);
            abort.call(this);
            clearTimeout(sendtimer);
        };

        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.getResponseHeader && !nocross) {
                    var cookie = xhr.getResponseHeader("efront-cookie");
                    addCookie(cookie, originDomain);
                }
                switch (xhr.status) {
                    case 0:
                        if (!navigator.onLine) {
                            onerror({ status: "网络断开" });
                            break;
                        }
                        if (!xhr.response) {
                            onerror({ status: "无法访问服务器" });
                            break;
                        }
                    case 200:
                    case 201:
                    case 304:
                        onload(xhr);
                        break;
                    case 302:
                    case 301:
                        if (xhr.isRedirected > 2 || nocross) break;
                        var location = xhr.getResponseHeader("efront-location");
                        if (!domainReg.test(location)) {
                            if (/^\//.test(location)) {
                                location = originDomain.replace(/\/.*$/, location);
                            } else {
                                location = originDomain.replace(/[^\/+]$/, location);
                            }
                            location = getRequestProtocol(url) + "//" + location;
                        }
                        var crs = cross("get", location, headers);
                        crs.isRedirected = (xhr.isRedirected || 0) + 1;
                        crs.done(onload, false);
                        crs.error(onerror, false);
                        break;
                    default:
                        onerror(xhr);
                }
                dispatch(window, 'render');
            }
        };
        var setRequestHeader = xhr.setRequestHeader;
        var realHeaders = Object.create(null);
        xhr.setRequestHeader = function (key, value) {
            realHeaders[key] = value;
        };
        xhr.then = function (ok, oh) {
            onloads.push(ok);
            onerrors.push(oh);
            flush();
        };
        var sendtimer = setTimeout(function () {
            digest();
            var isform = /^f/i.test(method);
            if (isform) {
                if (method === 'form') method = 'post';
                else method = method.slice(1);
            }
            if (!isEmpty(jsondata) && isEmpty(datas)) {
                if (/^(get|head|trace)$/i.test(method)) {
                    url = url.replace(/#[\s\S]*/, '');
                    datas = serialize(jsondata);
                    if (datas) url += (/\?/.test(url) ? "&" : "?") + datas;
                } else if (isform) {
                    xhr.form(jsondata);
                } else {
                    datas = JSON.stringify(jsondata);
                    if (datas === "{}" || datas === "[]") {
                        datas = '';
                    } else {
                        realHeaders["Content-Type"] = "application/json;charset=UTF-8";
                    }
                }
            }
            if (nocross) {
                extend(realHeaders, _headers);
                xhr.open(method, url);
            } else {
                xhr.open(method, getCrossUrl(url, _headers));
            }
            Object.keys(realHeaders).forEach(key => setRequestHeader.call(xhr, key, realHeaders[key]));
            send.call(xhr, datas);
        }, 0);
    }
    var loaded, errored;
    var onload = function (xhr) {
        removeFromList(requests, xhr);
        if (xhr.decoder) {
            xhr = xhr.decoder(xhr);
        }
        loaded = xhr;
        flush();
        digest();
    };
    var onerror = function (xhr) {
        removeFromList(requests, xhr);
        errored = xhr;
        flush();
        digest();
    };
    var flush = function () {
        var then = xhr.then;
        delete xhr.then;
        if (loaded) onloads.splice(0, onloads.length).map(e => e instanceof Function && e(xhr));
        if (errored) onerrors.splice(0, onerrors.length).map(e => e instanceof Function && e(errored));
        xhr.then = then;
    };
    var onloads = [], onerrors = [];
    xhr.done = xhr.success = function (on, asqueue = true) {
        if (!asqueue) onloads.splice(0, onloads.length);
        onloads.push(on);
        flush();
        return xhr;
    };
    var send = xhr.send;
    var datas = "";
    var jsondata = null;
    xhr.json = xhr.data = xhr.send = function (data, value) {
        if (!jsondata && !(isEmpty(data) && isEmpty(value))) jsondata = data instanceof Array ? [] : {};
        if (FormData && data instanceof FormData) {
            datas = data;
        } else if (isObject(data) && !isFile(data)) {
            extend(jsondata, data);
        } else if (!isEmpty(value)) {
            extend(jsondata, { [data]: value });
        } else if (isString(data) && value !== false && /^\s*\{|\=/.test(data)) {
            var data = /^\s*\{/.test(data) ? JSON.parse(data) : parseKV(data, "&", "=");
            extend(jsondata, data);
        } else {
            datas = data;
        }
        return xhr;
    };
    xhr.form = function (data) {
        xhr.data(data);
        if (FormData) {
            datas = new FormData;
            for (var k in jsondata) {
                datas.append(k, jsondata[k]);
            }
        } else {
            realHeaders["Content-Type"] = "application/x-www-form-urlencoded";
            datas = serialize(jsondata, "&", "=");
        }
    };
    xhr.fail = xhr.error = function (on, asqueue = true) {
        if (!asqueue) {
            onerrors.splice(0, onerrors.length);
        }
        onerrors.push(on);
        flush();
        return xhr;
    };
    requests.push(xhr);
    return xhr;
}
function addDirect(a) {
    if (typeof a === 'string' || a instanceof RegExp) cors_hosts.push(a);
}
function notCross(domain) {
    if (location_host === domain.slice(0, location_host.length) || !/^https?\:\/\/|^s?\/\//.test(domain)) return true;
    for (var cx = 0, dx = cors_hosts.length; cx < dx; cx++) {
        var host = cors_hosts[cx];
        if (host instanceof RegExp) {
            if (host.test(domain)) return true;
        } else {
            host = host.replace(domainReg, '$2/$3');
            if (domain.replace(domainReg, '$2/$3').slice(0, host.length) === host) return true;
        }
    }
    return false;
}

var requests = [];
extend(cross, {
    requests,
    abortAll() {
        var rs = requests.splice(0, requests.length);
        for (var r of rs) r.abort();
    },
    setHost,
    getCookies,
    addCookie,
    addDirect,
    getCrossUrl
});<commit_msg>防止重复添加相同的过滤器<commit_after>var FormData = this.FormData;
var cookiesMap = {};
//               /////  1   ////////// 2 /////// 3 ////    4  //
var domainReg = /^(?:(https?)\:)?\/\/(.*?)(?:\/(.*?))?([\?#].*)?$/i;
var base = domainReg.test(location.href) ? '/' : "http://efront.cc/";
var location_host = location.href.replace(domainReg, '$1://$2/');
var setHost = function (host) {
    var parsed = parseURL(host);
    if (!host) return console.error("cross_host格式不正确", host);
    var host = parsed.host + (parsed.pathname || '/');
    host = (/^https/.test(location_host) ? "https://" : "http://") + host;
    base = host;
};
var { efrontURI, cross_host = efrontURI } = this;
if (cross_host) setHost(cross_host);
var HeadersKeys = ["Content-Type"];
var cookieItemsInSessionStorageKey = "--zimoli-coms-cross";
var cookiesData = sessionStorage.getItem(cookieItemsInSessionStorageKey);
var cors_hosts = [];
if (cookiesData) {
    try {
        extend(cookiesMap, JSON.parse(cookiesData));
    } catch (e) {
        console.warn("加载cookie出错！");
    }
}
function getDomainPath(url) {
    return url.replace(domainReg, "$2/$3");
}
function getRequestProtocol(url) {
    if (/^https:/i.test(url)) {
        return "https:";
    }
    return "http:";
}
function getCookies(domainPath) {
    var cookieObject = {};
    var splited = domainPath.split("/");
    var domain = splited[0];
    do {
        var copy = splited.slice(0);
        do {
            domainPath = copy.join("/");
            var cookie = cookiesMap[domainPath];
            if (cookie) {
                for (var k in cookie) {
                    if (!cookieObject[k]) {
                        cookieObject[k] = cookie[k];
                    }
                }
            }
            copy.pop();
        } while (copy.length);
        domain = domain.replace(/^.*?(\.|$)/, "");
        splited[0] = domain;
    } while (domain.length);
    return serialize(cookieObject, ";");
}
function addCookie(cookie, originDomain = "") {
    if (cookie) {
        clearTimeout(addCookie.save_timer);
        addCookie.save_timer = setTimeout(function () {
            sessionStorage.setItem(cookieItemsInSessionStorageKey, JSON.stringify(cookiesMap));
        }, 20);
        cookie.replace(/(^|;|,)\s*(expires)=(\w*),([^=]*)(;|$)/ig, "$1$2=$3.$4$5")
            .split(/,\s*/).map(function (cookie) {
                var cookieObject = {};
                var result = cookie.split(/;\s*/);
                result.slice(1).map(function (kev) {
                    var kvs = /^(.+?)\=(.+?)$/.exec(kev);
                    if (kvs) {
                        var [, k, v] = kvs;
                        cookieObject[k.toLowerCase()] = v;
                    }
                });
                var { path, domain } = cookieObject;
                if (!domain) {
                    domain = originDomain.replace(/[^\/]+$/, "");
                }
                if (/^\./.test(domain)) {
                    domain = domain.replace(/^\.+/, "");
                }
                var destPath;
                if (/^\//.test(path)) {
                    destPath = domain.replace(/\/.*$/, "") + path;
                } else {
                    destPath = domain;
                }
                destPath = destPath.replace(/\/+$/, "");
                if (originDomain.indexOf(destPath) >= 0) {
                    var cookieMap = parseKV(result[0], ";");
                    if (!cookiesMap[destPath]) {
                        cookiesMap[destPath] = cookieMap;
                    } else {
                        extend(cookiesMap[destPath], cookieMap);
                    }
                }
            });
    }
}
function isChildPath(relative, path) {
    return relative.replace(/^(.*\/)[^\/]*$/, path);
}
var digest = function () {
    dispatch('render', window);
};

var getCrossUrl = function (domain, headers) {
    if (notCross(domain)) return domain;
    var originDomain = getDomainPath(domain);
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    _headers = serialize(_headers);
    if (_headers) _headers = "," + _headers;
    return domain
        .replace(/^(s?)(\/\/)/i, "http$1:$2")
        .replace(domainReg, base + `*${/^(https\:|s\/\/)/i.test(domain) ? "*" : ""}$2${_headers}/$3$4`);
};
function cross(method, url, headers) {
    var originDomain = getDomainPath(url);
    if (!originDomain) throw new Error("Unsupposed url format!");
    var _cookies = getCookies(originDomain);
    var _headers = {};
    if (_cookies) {
        _headers.Cookie = _cookies;
    }
    extend(_headers, headers);
    if (/^[mc]/i.test(method)) {
        _headers["User-Agent"] = /^m/i.test(method)
            ? "Efront/1.9 (iPhone) Safari/602.1"
            : "Efront/1.9 (Windows) Chrome/77.0.3865.90";
        method = method.slice(1);
    }
    if (/^jsonp/i.test(method)) {
        var cb = method.split('\-')[1] || 'callback';
        setTimeout(function () {
            if (!isEmpty(jsondata) && isEmpty(datas)) {
                datas = serialize(jsondata);
            }
            if (datas) {
                xhr.src += "&" + datas;
            }
        });
        var xhr = jsonp(url, {
            [cb](a) {
                xhr.response = xhr.responseText = JSON.stringify(a);
                onload(xhr);
            }
        });
        xhr.onerror = function (e) {
            onerror(e);
        };
        xhr.abort = function () {
            removeFromList(requests, this);
            remove(this);
        };
    } else {
        var nocross = notCross(url);
        var xhr = new XMLHttpRequest;
        var abort = xhr.abort;
        xhr.abort = function () {
            xhr.onreadystatechange = null;
            removeFromList(requests, this);
            abort.call(this);
            clearTimeout(sendtimer);
        };

        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.getResponseHeader && !nocross) {
                    var cookie = xhr.getResponseHeader("efront-cookie");
                    addCookie(cookie, originDomain);
                }
                switch (xhr.status) {
                    case 0:
                        if (!navigator.onLine) {
                            onerror({ status: "网络断开" });
                            break;
                        }
                        if (!xhr.response) {
                            onerror({ status: "无法访问服务器" });
                            break;
                        }
                    case 200:
                    case 201:
                    case 304:
                        onload(xhr);
                        break;
                    case 302:
                    case 301:
                        if (xhr.isRedirected > 2 || nocross) break;
                        var location = xhr.getResponseHeader("efront-location");
                        if (!domainReg.test(location)) {
                            if (/^\//.test(location)) {
                                location = originDomain.replace(/\/.*$/, location);
                            } else {
                                location = originDomain.replace(/[^\/+]$/, location);
                            }
                            location = getRequestProtocol(url) + "//" + location;
                        }
                        var crs = cross("get", location, headers);
                        crs.isRedirected = (xhr.isRedirected || 0) + 1;
                        crs.done(onload, false);
                        crs.error(onerror, false);
                        break;
                    default:
                        onerror(xhr);
                }
                dispatch(window, 'render');
            }
        };
        var setRequestHeader = xhr.setRequestHeader;
        var realHeaders = Object.create(null);
        xhr.setRequestHeader = function (key, value) {
            realHeaders[key] = value;
        };
        xhr.then = function (ok, oh) {
            onloads.push(ok);
            onerrors.push(oh);
            flush();
        };
        var sendtimer = setTimeout(function () {
            digest();
            var isform = /^f/i.test(method);
            if (isform) {
                if (method === 'form') method = 'post';
                else method = method.slice(1);
            }
            if (!isEmpty(jsondata) && isEmpty(datas)) {
                if (/^(get|head|trace)$/i.test(method)) {
                    url = url.replace(/#[\s\S]*/, '');
                    datas = serialize(jsondata);
                    if (datas) url += (/\?/.test(url) ? "&" : "?") + datas;
                } else if (isform) {
                    xhr.form(jsondata);
                } else {
                    datas = JSON.stringify(jsondata);
                    if (datas === "{}" || datas === "[]") {
                        datas = '';
                    } else {
                        realHeaders["Content-Type"] = "application/json;charset=UTF-8";
                    }
                }
            }
            if (nocross) {
                extend(realHeaders, _headers);
                xhr.open(method, url);
            } else {
                xhr.open(method, getCrossUrl(url, _headers));
            }
            Object.keys(realHeaders).forEach(key => setRequestHeader.call(xhr, key, realHeaders[key]));
            send.call(xhr, datas);
        }, 0);
    }
    var loaded, errored;
    var onload = function (xhr) {
        removeFromList(requests, xhr);
        if (xhr.decoder) {
            xhr = xhr.decoder(xhr);
        }
        loaded = xhr;
        flush();
        digest();
    };
    var onerror = function (xhr) {
        removeFromList(requests, xhr);
        errored = xhr;
        flush();
        digest();
    };
    var flush = function () {
        var then = xhr.then;
        delete xhr.then;
        if (loaded) onloads.splice(0, onloads.length).map(e => e instanceof Function && e(xhr));
        if (errored) onerrors.splice(0, onerrors.length).map(e => e instanceof Function && e(errored));
        xhr.then = then;
    };
    var onloads = [], onerrors = [];
    xhr.done = xhr.success = function (on, asqueue = true) {
        if (!asqueue) onloads.splice(0, onloads.length);
        onloads.push(on);
        flush();
        return xhr;
    };
    var send = xhr.send;
    var datas = "";
    var jsondata = null;
    xhr.json = xhr.data = xhr.send = function (data, value) {
        if (!jsondata && !(isEmpty(data) && isEmpty(value))) jsondata = data instanceof Array ? [] : {};
        if (FormData && data instanceof FormData) {
            datas = data;
        } else if (isObject(data) && !isFile(data)) {
            extend(jsondata, data);
        } else if (!isEmpty(value)) {
            extend(jsondata, { [data]: value });
        } else if (isString(data) && value !== false && /^\s*\{|\=/.test(data)) {
            var data = /^\s*\{/.test(data) ? JSON.parse(data) : parseKV(data, "&", "=");
            extend(jsondata, data);
        } else {
            datas = data;
        }
        return xhr;
    };
    xhr.form = function (data) {
        xhr.data(data);
        if (FormData) {
            datas = new FormData;
            for (var k in jsondata) {
                datas.append(k, jsondata[k]);
            }
        } else {
            realHeaders["Content-Type"] = "application/x-www-form-urlencoded";
            datas = serialize(jsondata, "&", "=");
        }
    };
    xhr.fail = xhr.error = function (on, asqueue = true) {
        if (!asqueue) {
            onerrors.splice(0, onerrors.length);
        }
        onerrors.push(on);
        flush();
        return xhr;
    };
    requests.push(xhr);
    return xhr;
}
function addDirect(a) {
    if (cors_hosts.indexOf(a) >= 0) return;
    if (typeof a === 'string' || a instanceof RegExp) cors_hosts.push(a);
}
function notCross(domain) {
    if (location_host === domain.slice(0, location_host.length) || !/^https?\:\/\/|^s?\/\//.test(domain)) return true;
    for (var cx = 0, dx = cors_hosts.length; cx < dx; cx++) {
        var host = cors_hosts[cx];
        if (host instanceof RegExp) {
            if (host.test(domain)) return true;
        } else {
            host = host.replace(domainReg, '$2/$3');
            if (domain.replace(domainReg, '$2/$3').slice(0, host.length) === host) return true;
        }
    }
    return false;
}

var requests = [];
extend(cross, {
    requests,
    abortAll() {
        var rs = requests.splice(0, requests.length);
        for (var r of rs) r.abort();
    },
    setHost,
    getCookies,
    addCookie,
    addDirect,
    getCrossUrl
});<|endoftext|>