<commit_before>define(["dojo/_base/lang", "dojo/_base/array", "dojo/dom-construct","dojo/_base/declare", "dojox/gfx", "dojox/gfx/shape"],
	function(lang, arr, domConstruct, declare, gfx, shape){

	return declare("dojox.charting.Element", null, {
		// summary:
		//		A base class that is used to build other elements of a chart, such as
		//		a series.
		// chart: dojox/charting/Chart
		//		The parent chart for this element.
		// group: dojox/gfx/shape.Group
		//		The visual GFX group representing this element.
		// htmlElement: Array
		//		Any DOMNodes used as a part of this element (such as HTML-based labels).
		// dirty: Boolean
		//		A flag indicating whether or not this element needs to be rendered.

		chart: null,
		group: null,
		htmlElements: null,
		dirty: true,

		constructor: function(chart){
			// summary:
			//		Creates a new charting element.
			// chart: dojox/charting/Chart
			//		The chart that this element belongs to.
			this.chart = chart;
			this.group = null;
			this.htmlElements = [];
			this.dirty = true;
			this.trailingSymbol = "...";
			this._events = [];
		},
		purgeGroup: function(){
			// summary:
			//		Clear any elements out of our group, and destroy the group.
			// returns: dojox/charting/Element
			//		A reference to this object for functional chaining.
			this.destroyHtmlElements();
			if(this.group){
				// since 1.7.x we need dispose shape otherwise there is a memoryleak
				this.group.removeShape();
				var children = this.group.children;
				for(var i = 0; i < children.length;++i){
					shape.dispose(children[i]);
				}
				this.group.clear();
				this.group = null;
			}
			this.dirty = true;
			if(this._events.length){
				arr.forEach(this._events, function(item){
					item.shape.disconnect(item.handle);
				});
				this._events = [];
			}
			return this;	//	dojox.charting.Element
		},
		cleanGroup: function(creator){
			// summary:
			//		Clean any elements (HTML or GFX-based) out of our group, and create a new one.
			// creator: dojox/gfx/shape.Surface?
			//		An optional surface to work with.
			// returns: dojox/charting/Element
			//		A reference to this object for functional chaining.
			this.destroyHtmlElements();
			if(!creator){ creator = this.chart.surface; }
			if(this.group){
				var children = this.group.children;
				for(var i = 0; i < children.length;++i){
					shape.dispose(children[i]);
				}
				this.group.clear();
			}else{
				this.group = creator.createGroup();
			}
			this.dirty = true;
			return this;	//	dojox.charting.Element
		},
		destroyHtmlElements: function(){
			// summary:
			//		Destroy any DOMNodes that may have been created as a part of this element.
			if(this.htmlElements.length){
				arr.forEach(this.htmlElements, domConstruct.destroy);
				this.htmlElements = [];
			}
		},
		destroy: function(){
			// summary:
			//		API addition to conform to the rest of the Dojo Toolkit's standard.
			this.purgeGroup();
		},
		//text utilities
		getTextWidth: function(s, font){
			return gfx._base._getTextBox(s, {font: font}).w || 0;
		},
		getTextWithLimitLength: function(s, font, limitWidth, truncated){
			// summary:
			//		Get the truncated string based on the limited width in px(dichotomy algorithm)
			// s: String?
			//		candidate text.
			// font: String?
			//		text's font style.
			// limitWidth: Number?
			//		text limited width in px.
			// truncated: Boolean?
			//		whether the input text(s) has already been truncated.
			// returns: Object
			// |	{
			// |		text: processed text, maybe truncated or not,
			// |		truncated: whether text has been truncated
			// |	}
			if(!s || s.length <= 0){
				return {
					text: "",
					truncated: truncated || false
				};
			}
			if(!limitWidth || limitWidth <= 0){
				return {
					text: s,
					truncated: truncated || false
				};
			}
			var delta = 2,
				//golden section for dichotomy algorithm
				trucPercentage = 0.618,
				minStr = s.substring(0,1) + this.trailingSymbol,
				minWidth = this.getTextWidth(minStr, font);
			if(limitWidth <= minWidth){
				return {
					text: minStr,
					truncated: true
				};
			}
			var width = this.getTextWidth(s, font);
			if(width <= limitWidth){
				return {
					text: s,
					truncated: truncated || false
				};
			}else{
				var begin = 0,
					end = s.length;
				while(begin < end){
					if(end - begin <= delta ){
						while (this.getTextWidth(s.substring(0, begin) + this.trailingSymbol, font) > limitWidth) {
							begin -= 1;
						}
						return {
							text: (s.substring(0,begin) + this.trailingSymbol),
							truncated: true
							};
					}
					var index = begin + Math.round((end - begin) * trucPercentage),
						widthIntercepted = this.getTextWidth(s.substring(0, index), font);
					if(widthIntercepted < limitWidth){
						begin = index;
						end = end;
					}else{
						begin = begin;
						end = index;
					}
				}
			}
		},
		getTextWithLimitCharCount: function(s, font, wcLimit, truncated){
			// summary:
			//		Get the truncated string based on the limited character count(dichotomy algorithm)
			// s: String?
			//		candidate text.
			// font: String?
			//		text's font style.
			// wcLimit: Number?
			//		text limited character count.
			// truncated: Boolean?
			//		whether the input text(s) has already been truncated.
			// returns: Object
			// |	{
			// |		text: processed text, maybe truncated or not,
			// |		truncated: whether text has been truncated
			// |	}
			if (!s || s.length <= 0) {
				return {
					text: "",
					truncated: truncated || false
				};
			}
			if(!wcLimit || wcLimit <= 0 || s.length <= wcLimit){
				return {
					text: s,
					truncated: truncated || false
				};
			}
			return {
				text: s.substring(0, wcLimit) + this.trailingSymbol,
				truncated: true
			};
		},
		// fill utilities
		_plotFill: function(fill, dim, offsets){
			// process a plot-wide fill
			if(!fill || !fill.type || !fill.space){
				return fill;
			}
			var space = fill.space, span;
			switch(fill.type){
				case "linear":
					if(space === "plot" || space === "shapeX" || space === "shapeY"){
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultLinearGradient, fill);
						fill.space = space;
						// process dimensions
						if(space === "plot" || space === "shapeX"){
							// process Y
							span = dim.height - offsets.t - offsets.b;
							fill.y1 = offsets.t + span * fill.y1 / 100;
							fill.y2 = offsets.t + span * fill.y2 / 100;
						}
						if(space === "plot" || space === "shapeY"){
							// process X
							span = dim.width - offsets.l - offsets.r;
							fill.x1 = offsets.l + span * fill.x1 / 100;
							fill.x2 = offsets.l + span * fill.x2 / 100;
						}
					}
					break;
				case "radial":
					if(space === "plot"){
						// this one is used exclusively for scatter charts
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultRadialGradient, fill);
						fill.space = space;
						// process both dimensions
						var spanX = dim.width  - offsets.l - offsets.r,
							spanY = dim.height - offsets.t - offsets.b;
						fill.cx = offsets.l + spanX * fill.cx / 100;
						fill.cy = offsets.t + spanY * fill.cy / 100;
						fill.r  = fill.r * Math.sqrt(spanX * spanX + spanY * spanY) / 200;
					}
					break;
				case "pattern":
					if(space === "plot" || space === "shapeX" || space === "shapeY"){
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultPattern, fill);
						fill.space = space;
						// process dimensions
						if(space === "plot" || space === "shapeX"){
							// process Y
							span = dim.height - offsets.t - offsets.b;
							fill.y = offsets.t + span * fill.y / 100;
							fill.height = span * fill.height / 100;
						}
						if(space === "plot" || space === "shapeY"){
							// process X
							span = dim.width - offsets.l - offsets.r;
							fill.x = offsets.l + span * fill.x / 100;
							fill.width = span * fill.width / 100;
						}
					}
					break;
			}
			return fill;
		},
		_shapeFill: function(fill, bbox){
			// process shape-specific fill
			if(!fill || !fill.space){
				return fill;
			}
			var space = fill.space, span;
			switch(fill.type){
				case "linear":
					if(space === "shape" || space === "shapeX" || space === "shapeY"){
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultLinearGradient, fill);
						fill.space = space;
						// process dimensions
						if(space === "shape" || space === "shapeX"){
							// process X
							span = bbox.width;
							fill.x1 = bbox.x + span * fill.x1 / 100;
							fill.x2 = bbox.x + span * fill.x2 / 100;
						}
						if(space === "shape" || space === "shapeY"){
							// process Y
							span = bbox.height;
							fill.y1 = bbox.y + span * fill.y1 / 100;
							fill.y2 = bbox.y + span * fill.y2 / 100;
						}
					}
					break;
				case "radial":
					if(space === "shape"){
						// this one is used exclusively for bubble charts and pie charts
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultRadialGradient, fill);
						fill.space = space;
						// process both dimensions
						fill.cx = bbox.x + bbox.width  / 2;
						fill.cy = bbox.y + bbox.height / 2;
						fill.r  = fill.r * bbox.width  / 200;
					}
					break;
				case "pattern":
					if(space === "shape" || space === "shapeX" || space === "shapeY"){
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultPattern, fill);
						fill.space = space;
						// process dimensions
						if(space === "shape" || space === "shapeX"){
							// process X
							span = bbox.width;
							fill.x = bbox.x + span * fill.x / 100;
							fill.width = span * fill.width / 100;
						}
						if(space === "shape" || space === "shapeY"){
							// process Y
							span = bbox.height;
							fill.y = bbox.y + span * fill.y / 100;
							fill.height = span * fill.height / 100;
						}
					}
					break;
			}
			return fill;
		},
		_pseudoRadialFill: function(fill, center, radius, start, end){
			// process pseudo-radial fills
			if(!fill || fill.type !== "radial" || fill.space !== "shape"){
				return fill;
			}
			// clone and normalize fill
			var space = fill.space;
			fill = gfx.makeParameters(gfx.defaultRadialGradient, fill);
			fill.space = space;
			if(arguments.length < 4){
				// process both dimensions
				fill.cx = center.x;
				fill.cy = center.y;
				fill.r  = fill.r * radius / 100;
				return fill;
			}
			// convert to a linear gradient
			var angle = arguments.length < 5 ? start : (end + start) / 2;
			return {
				type: "linear",
				x1: center.x,
				y1: center.y,
				x2: center.x + fill.r * radius * Math.cos(angle) / 100,
				y2: center.y + fill.r * radius * Math.sin(angle) / 100,
				colors: fill.colors
			};
			return fill;
		}
	});
});
<commit_msg>refs #14589. Disposes gfx element groups we don't use anymore to prevent leaking. !strict.<commit_after>define(["dojo/_base/lang", "dojo/_base/array", "dojo/dom-construct","dojo/_base/declare", "dojox/gfx", "dojox/gfx/shape"],
	function(lang, arr, domConstruct, declare, gfx, shape){

	return declare("dojox.charting.Element", null, {
		// summary:
		//		A base class that is used to build other elements of a chart, such as
		//		a series.
		// chart: dojox/charting/Chart
		//		The parent chart for this element.
		// group: dojox/gfx/shape.Group
		//		The visual GFX group representing this element.
		// htmlElement: Array
		//		Any DOMNodes used as a part of this element (such as HTML-based labels).
		// dirty: Boolean
		//		A flag indicating whether or not this element needs to be rendered.

		chart: null,
		group: null,
		htmlElements: null,
		dirty: true,

		constructor: function(chart){
			// summary:
			//		Creates a new charting element.
			// chart: dojox/charting/Chart
			//		The chart that this element belongs to.
			this.chart = chart;
			this.group = null;
			this.htmlElements = [];
			this.dirty = true;
			this.trailingSymbol = "...";
			this._events = [];
		},
		purgeGroup: function(){
			// summary:
			//		Clear any elements out of our group, and destroy the group.
			// returns: dojox/charting/Element
			//		A reference to this object for functional chaining.
			this.destroyHtmlElements();
			if(this.group){
				// since 1.7.x we need dispose shape otherwise there is a memoryleak
				this.group.removeShape();
				var children = this.group.children;
				for(var i = 0; i < children.length;++i){
					shape.dispose(children[i]);
				}
				this.group.clear();
				shape.dispose(this.group);
				this.group = null;
			}
			this.dirty = true;
			if(this._events.length){
				arr.forEach(this._events, function(item){
					item.shape.disconnect(item.handle);
				});
				this._events = [];
			}
			return this;	//	dojox.charting.Element
		},
		cleanGroup: function(creator){
			// summary:
			//		Clean any elements (HTML or GFX-based) out of our group, and create a new one.
			// creator: dojox/gfx/shape.Surface?
			//		An optional surface to work with.
			// returns: dojox/charting/Element
			//		A reference to this object for functional chaining.
			this.destroyHtmlElements();
			if(!creator){ creator = this.chart.surface; }
			if(this.group){
				var children = this.group.children;
				for(var i = 0; i < children.length;++i){
					shape.dispose(children[i]);
				}
				this.group.clear();
			}else{
				this.group = creator.createGroup();
			}
			this.dirty = true;
			return this;	//	dojox.charting.Element
		},
		destroyHtmlElements: function(){
			// summary:
			//		Destroy any DOMNodes that may have been created as a part of this element.
			if(this.htmlElements.length){
				arr.forEach(this.htmlElements, domConstruct.destroy);
				this.htmlElements = [];
			}
		},
		destroy: function(){
			// summary:
			//		API addition to conform to the rest of the Dojo Toolkit's standard.
			this.purgeGroup();
		},
		//text utilities
		getTextWidth: function(s, font){
			return gfx._base._getTextBox(s, {font: font}).w || 0;
		},
		getTextWithLimitLength: function(s, font, limitWidth, truncated){
			// summary:
			//		Get the truncated string based on the limited width in px(dichotomy algorithm)
			// s: String?
			//		candidate text.
			// font: String?
			//		text's font style.
			// limitWidth: Number?
			//		text limited width in px.
			// truncated: Boolean?
			//		whether the input text(s) has already been truncated.
			// returns: Object
			// |	{
			// |		text: processed text, maybe truncated or not,
			// |		truncated: whether text has been truncated
			// |	}
			if(!s || s.length <= 0){
				return {
					text: "",
					truncated: truncated || false
				};
			}
			if(!limitWidth || limitWidth <= 0){
				return {
					text: s,
					truncated: truncated || false
				};
			}
			var delta = 2,
				//golden section for dichotomy algorithm
				trucPercentage = 0.618,
				minStr = s.substring(0,1) + this.trailingSymbol,
				minWidth = this.getTextWidth(minStr, font);
			if(limitWidth <= minWidth){
				return {
					text: minStr,
					truncated: true
				};
			}
			var width = this.getTextWidth(s, font);
			if(width <= limitWidth){
				return {
					text: s,
					truncated: truncated || false
				};
			}else{
				var begin = 0,
					end = s.length;
				while(begin < end){
					if(end - begin <= delta ){
						while (this.getTextWidth(s.substring(0, begin) + this.trailingSymbol, font) > limitWidth) {
							begin -= 1;
						}
						return {
							text: (s.substring(0,begin) + this.trailingSymbol),
							truncated: true
							};
					}
					var index = begin + Math.round((end - begin) * trucPercentage),
						widthIntercepted = this.getTextWidth(s.substring(0, index), font);
					if(widthIntercepted < limitWidth){
						begin = index;
						end = end;
					}else{
						begin = begin;
						end = index;
					}
				}
			}
		},
		getTextWithLimitCharCount: function(s, font, wcLimit, truncated){
			// summary:
			//		Get the truncated string based on the limited character count(dichotomy algorithm)
			// s: String?
			//		candidate text.
			// font: String?
			//		text's font style.
			// wcLimit: Number?
			//		text limited character count.
			// truncated: Boolean?
			//		whether the input text(s) has already been truncated.
			// returns: Object
			// |	{
			// |		text: processed text, maybe truncated or not,
			// |		truncated: whether text has been truncated
			// |	}
			if (!s || s.length <= 0) {
				return {
					text: "",
					truncated: truncated || false
				};
			}
			if(!wcLimit || wcLimit <= 0 || s.length <= wcLimit){
				return {
					text: s,
					truncated: truncated || false
				};
			}
			return {
				text: s.substring(0, wcLimit) + this.trailingSymbol,
				truncated: true
			};
		},
		// fill utilities
		_plotFill: function(fill, dim, offsets){
			// process a plot-wide fill
			if(!fill || !fill.type || !fill.space){
				return fill;
			}
			var space = fill.space, span;
			switch(fill.type){
				case "linear":
					if(space === "plot" || space === "shapeX" || space === "shapeY"){
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultLinearGradient, fill);
						fill.space = space;
						// process dimensions
						if(space === "plot" || space === "shapeX"){
							// process Y
							span = dim.height - offsets.t - offsets.b;
							fill.y1 = offsets.t + span * fill.y1 / 100;
							fill.y2 = offsets.t + span * fill.y2 / 100;
						}
						if(space === "plot" || space === "shapeY"){
							// process X
							span = dim.width - offsets.l - offsets.r;
							fill.x1 = offsets.l + span * fill.x1 / 100;
							fill.x2 = offsets.l + span * fill.x2 / 100;
						}
					}
					break;
				case "radial":
					if(space === "plot"){
						// this one is used exclusively for scatter charts
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultRadialGradient, fill);
						fill.space = space;
						// process both dimensions
						var spanX = dim.width  - offsets.l - offsets.r,
							spanY = dim.height - offsets.t - offsets.b;
						fill.cx = offsets.l + spanX * fill.cx / 100;
						fill.cy = offsets.t + spanY * fill.cy / 100;
						fill.r  = fill.r * Math.sqrt(spanX * spanX + spanY * spanY) / 200;
					}
					break;
				case "pattern":
					if(space === "plot" || space === "shapeX" || space === "shapeY"){
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultPattern, fill);
						fill.space = space;
						// process dimensions
						if(space === "plot" || space === "shapeX"){
							// process Y
							span = dim.height - offsets.t - offsets.b;
							fill.y = offsets.t + span * fill.y / 100;
							fill.height = span * fill.height / 100;
						}
						if(space === "plot" || space === "shapeY"){
							// process X
							span = dim.width - offsets.l - offsets.r;
							fill.x = offsets.l + span * fill.x / 100;
							fill.width = span * fill.width / 100;
						}
					}
					break;
			}
			return fill;
		},
		_shapeFill: function(fill, bbox){
			// process shape-specific fill
			if(!fill || !fill.space){
				return fill;
			}
			var space = fill.space, span;
			switch(fill.type){
				case "linear":
					if(space === "shape" || space === "shapeX" || space === "shapeY"){
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultLinearGradient, fill);
						fill.space = space;
						// process dimensions
						if(space === "shape" || space === "shapeX"){
							// process X
							span = bbox.width;
							fill.x1 = bbox.x + span * fill.x1 / 100;
							fill.x2 = bbox.x + span * fill.x2 / 100;
						}
						if(space === "shape" || space === "shapeY"){
							// process Y
							span = bbox.height;
							fill.y1 = bbox.y + span * fill.y1 / 100;
							fill.y2 = bbox.y + span * fill.y2 / 100;
						}
					}
					break;
				case "radial":
					if(space === "shape"){
						// this one is used exclusively for bubble charts and pie charts
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultRadialGradient, fill);
						fill.space = space;
						// process both dimensions
						fill.cx = bbox.x + bbox.width  / 2;
						fill.cy = bbox.y + bbox.height / 2;
						fill.r  = fill.r * bbox.width  / 200;
					}
					break;
				case "pattern":
					if(space === "shape" || space === "shapeX" || space === "shapeY"){
						// clone a fill so we can modify properly directly
						fill = gfx.makeParameters(gfx.defaultPattern, fill);
						fill.space = space;
						// process dimensions
						if(space === "shape" || space === "shapeX"){
							// process X
							span = bbox.width;
							fill.x = bbox.x + span * fill.x / 100;
							fill.width = span * fill.width / 100;
						}
						if(space === "shape" || space === "shapeY"){
							// process Y
							span = bbox.height;
							fill.y = bbox.y + span * fill.y / 100;
							fill.height = span * fill.height / 100;
						}
					}
					break;
			}
			return fill;
		},
		_pseudoRadialFill: function(fill, center, radius, start, end){
			// process pseudo-radial fills
			if(!fill || fill.type !== "radial" || fill.space !== "shape"){
				return fill;
			}
			// clone and normalize fill
			var space = fill.space;
			fill = gfx.makeParameters(gfx.defaultRadialGradient, fill);
			fill.space = space;
			if(arguments.length < 4){
				// process both dimensions
				fill.cx = center.x;
				fill.cy = center.y;
				fill.r  = fill.r * radius / 100;
				return fill;
			}
			// convert to a linear gradient
			var angle = arguments.length < 5 ? start : (end + start) / 2;
			return {
				type: "linear",
				x1: center.x,
				y1: center.y,
				x2: center.x + fill.r * radius * Math.cos(angle) / 100,
				y2: center.y + fill.r * radius * Math.sin(angle) / 100,
				colors: fill.colors
			};
			return fill;
		}
	});
});
<|endoftext|>


<commit_before>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

async function main(parentId, displayName) {
  // [START dialogflow_set_agent_sample]
  const {AgentsClient} = require('@google-cloud/dialogflow');

  const parent = 'projects/' + parentId + '/locations/global';

  const agent = {
    parent: parent,
    displayName: displayName,
    defaultLanguageCode: 'en',
    timeZone: 'America/Los_Angeles',
  };

  const client = new AgentsClient();

  async function setAgent() {
    const request = {
      agent,
    };

    const [response] = await client.setAgent(request);
    console.log(`response: ${JSON.stringify(response, null, 2)}`);
  }
  await setAgent();
  // [END dialogflow_set_agent_sample]
}

process.on('unhandledRejection', err => {
  console.error(err.message);
  process.exitCode = 1;
});
main(...process.argv.slice(2));
<commit_msg>samples: Update set-agent.js (#947)<commit_after>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

// parentID is the projectID and displayName is customized by user
async function main(parentId, displayName) {
  // [START dialogflow_set_agent_sample]
  const {AgentsClient} = require('@google-cloud/dialogflow');

  // make sure to pass projectID as the input parameter
  const parent = 'projects/' + parentId + '/locations/global';

  const agent = {
    parent: parent,
    displayName: displayName,
    defaultLanguageCode: 'en',
    timeZone: 'America/Los_Angeles',
  };

  const client = new AgentsClient();

  async function setAgent() {
    const request = {
      agent,
    };

    const [response] = await client.setAgent(request);
    console.log(`response: ${JSON.stringify(response, null, 2)}`);
  }
  await setAgent();
  // [END dialogflow_set_agent_sample]
}

process.on('unhandledRejection', err => {
  console.error(err.message);
  process.exitCode = 1;
});
main(...process.argv.slice(2));
<|endoftext|>


<commit_before>;(function () {
    function initWatch(vm, watch) {
        vm._watchers || (vm._watchers = []);
        for (var key in watch) {
            var handler = watch[key];
            if (BI.isArray(handler)) {
                for (var i = 0; i < handler.length; i++) {
                    vm._watchers.push(createWatcher(vm, key, handler[i]));
                }
            } else {
                vm._watchers.push(createWatcher(vm, key, handler));
            }
        }
    }

    function createWatcher(vm, keyOrFn, handler) {
        return Fix.watch(vm.model, keyOrFn, _.bind(handler, vm), {
            store: vm.store
        });
    }

    var target = null;
    var targetStack = [];

    function pushTarget(_target) {
        if (target) targetStack.push(target);
        Fix.Model.target = target = _target;
    }

    function popTarget() {
        Fix.Model.target = target = targetStack.pop();
    }

    var context = null;
    var contextStack = [];

    function pushContext(_context) {
        if (context) contextStack.push(context);
        Fix.Model.context = context = _context;
    }

    function popContext() {
        Fix.Model.context = context = contextStack.pop();
    }

    var oldWatch = Fix.watch;
    Fix.watch = function (model, expOrFn, cb, options) {
        if (BI.isPlainObject(cb)) {
            options = cb;
            cb = cb.handler;
        }
        if (typeof cb === "string") {
            cb = model[cb];
        }
        return oldWatch.call(this, model, expOrFn, function () {
            options && options.store && pushTarget(options.store);
            var res = cb.apply(this, arguments);
            options && options.store && popTarget();
            return res;
        }, options);
    };

    function findStore(widget) {
        if (target != null) {
            return target;
        }
        widget = widget || context;
        var p = widget;
        while (p) {
            if (p instanceof Fix.Model || p.store || p.__cacheStore) {
                break;
            }
            p = p._parent || (p.options && p.options.element);
        }
        if (p) {
            if (p instanceof Fix.Model) {
                return widget.__cacheStore = p;
            }
            widget.__cacheStore = p.store || p.__cacheStore;
            return p.__cacheStore || p.store;
        }
    }

    var _create = BI.createWidget;
    BI.createWidget = function (item, options, context) {
        var pushed = false;
        if (BI.isWidget(options)) {
            pushContext(options);
            pushed = true;
        } else if (context != null) {
            pushContext(context);
            pushed = true;
        }
        var result = _create.apply(this, arguments);
        pushed && popContext();
        return result;
    };

    _.each(["populate", "addItems", "prependItems"], function (name) {
        var old = BI.Loader.prototype[name];
        BI.Loader.prototype[name] = function () {
            pushContext(this);
            var result = old.apply(this, arguments);
            popContext();
            return result;
        };
    });

    function createStore() {
        var needPop = false;
        if (_global.Fix && this._store) {
            var store = findStore(this.options.context || this.options.element);
            if (store) {
                pushTarget(store);
                needPop = true;
            }
            this.store = this._store();
            this.store && (this.store._widget = this);
            needPop && popTarget();
            needPop = false;
            pushTarget(this.store);
            if (this.store instanceof Fix.Model) {
                this.model = this.store.model;
            } else {
                this.model = this.store;
            }
            needPop = true;
        }
        return needPop;
    }

    var _init = BI.Widget.prototype._init;
    BI.Widget.prototype._init = function () {
        var self = this;
        var needPop = createStore.call(this);
        _init.apply(this, arguments);
        needPop && popTarget();
    };

    var _render = BI.Widget.prototype._render;
    BI.Widget.prototype._render = function () {
        var needPop = false;
        if (_global.Fix && this._store) {
            needPop = true;
            pushTarget(this.store);
            initWatch(this, this.watch);
        }
        _render.apply(this, arguments);
        needPop && popTarget();
    };

    var unMount = BI.Widget.prototype.__d;
    BI.Widget.prototype.__d = function () {
        unMount.apply(this, arguments);
        this.store && BI.isFunction(this.store.destroy) && this.store.destroy();
        BI.each(this._watchers, function (i, unwatches) {
            unwatches = BI.isArray(unwatches) ? unwatches : [unwatches];
            BI.each(unwatches, function (j, unwatch) {
                unwatch();
            });
        });
        this._watchers && (this._watchers = []);
        if (this.store) {
            this.store._parent && (this.store._parent = null);
            this.store._widget && (this.store._widget = null);
            this.store = null;
        }
        delete this.__cacheStore;
    };

    _.each(["_mount"], function (name) {
        var old = BI.Widget.prototype[name];
        old && (BI.Widget.prototype[name] = function () {
            this.store && pushTarget(this.store);
            var res = old.apply(this, arguments);
            this.store && popTarget();
            return res;
        });
    });

    if (BI.isIE9Below && BI.isIE9Below()) {
        _.each(["each", "map", "reduce", "reduceRight", "find", "filter", "reject", "every", "all", "some", "any", "max", "min",
            "sortBy", "groupBy", "indexBy", "countBy", "partition",
            "keys", "allKeys", "values", "pairs", "invert",
            "mapObject", "findKey", "pick", "omit", "tap"], function (name) {
            var old = BI[name];
            BI[name] = function (obj, fn, context) {
                return typeof fn === "function" ? old(obj, function (key, value) {
                    if (!(key in Fix.$$skipArray)) {
                        return fn.apply(this, arguments);
                    }
                }, context) : old.apply(this, arguments);
            };
        });
        BI.isEmpty = function (ob) {
            if (BI.isPlainObject(ob) && ob.__ob__) {
                return BI.keys(ob).length === 0;
            }
            return _.isEmpty(ob);
        };
        BI.keys = function (ob) {
            var keys = _.keys(ob);
            var nKeys = [];
            for (var i = 0; i < keys.length; i++) {
                if (!(keys[i] in Fix.$$skipArray)) {
                    nKeys.push(keys[i]);
                }
            }
            return nKeys;
        };
        BI.values = function (ob) {
            var keys = BI.keys(obj);
            var length = keys.length;
            var values = [];
            for (var i = 0; i < length; i++) {
                values[i] = obj[keys[i]];
            }
            return values;
        };
        BI.extend = function () {
            var args = Array.prototype.slice.call(arguments);
            if (args.length < 1) {
                return {};
            }
            var object = args[0];
            var i = 1;
            while (i < args.length) {
                BI.each(args[i], function (key, v) {
                    object[key] = v;
                });
                i++;
            }
            return object;
        };
        BI.size = function (ob) {
            if (BI.isPlainObject(ob) && ob.__ob__) {
                return BI.keys(ob).length;
            }
            return _.size(ob);
        };
        BI.isEmptyObject = function (ob) {
            return BI.size(ob) === 0;
        };
        BI.deepClone = function (ob) {
            return Fix.toJSON(ob);
        };
    }
    BI.watch = Fix.watch;
}());<commit_msg>DEC-8536  fix : 修复 _mount执行中断导致context指向错误问题.<commit_after>;(function () {
    function initWatch (vm, watch) {
        vm._watchers || (vm._watchers = []);
        for (var key in watch) {
            var handler = watch[key];
            if (BI.isArray(handler)) {
                for (var i = 0; i < handler.length; i++) {
                    vm._watchers.push(createWatcher(vm, key, handler[i]));
                }
            } else {
                vm._watchers.push(createWatcher(vm, key, handler));
            }
        }
    }

    function createWatcher (vm, keyOrFn, handler) {
        return Fix.watch(vm.model, keyOrFn, _.bind(handler, vm), {
            store: vm.store
        });
    }

    var target = null;
    var targetStack = [];

    function pushTarget (_target) {
        if (target) targetStack.push(target);
        Fix.Model.target = target = _target;
    }

    function popTarget () {
        Fix.Model.target = target = targetStack.pop();
    }

    var context = null;
    var contextStack = [];

    function pushContext (_context) {
        if (context) contextStack.push(context);
        Fix.Model.context = context = _context;
    }

    function popContext () {
        Fix.Model.context = context = contextStack.pop();
    }

    var oldWatch = Fix.watch;
    Fix.watch = function (model, expOrFn, cb, options) {
        if (BI.isPlainObject(cb)) {
            options = cb;
            cb = cb.handler;
        }
        if (typeof cb === "string") {
            cb = model[cb];
        }
        return oldWatch.call(this, model, expOrFn, function () {
            options && options.store && pushTarget(options.store);
            var res = cb.apply(this, arguments);
            options && options.store && popTarget();
            return res;
        }, options);
    };

    function findStore (widget) {
        if (target != null) {
            return target;
        }
        widget = widget || context;
        var p = widget;
        while (p) {
            if (p instanceof Fix.Model || p.store || p.__cacheStore) {
                break;
            }
            p = p._parent || (p.options && p.options.element);
        }
        if (p) {
            if (p instanceof Fix.Model) {
                return widget.__cacheStore = p;
            }
            widget.__cacheStore = p.store || p.__cacheStore;
            return p.__cacheStore || p.store;
        }
    }

    var _create = BI.createWidget;
    BI.createWidget = function (item, options, context) {
        var pushed = false;
        if (BI.isWidget(options)) {
            pushContext(options);
            pushed = true;
        } else if (context != null) {
            pushContext(context);
            pushed = true;
        }
        var result = _create.apply(this, arguments);
        pushed && popContext();
        return result;
    };

    _.each(["populate", "addItems", "prependItems"], function (name) {
        var old = BI.Loader.prototype[name];
        BI.Loader.prototype[name] = function () {
            pushContext(this);
            var result = old.apply(this, arguments);
            popContext();
            return result;
        };
    });

    function createStore () {
        var needPop = false;
        if (_global.Fix && this._store) {
            var store = findStore(this.options.context || this.options.element);
            if (store) {
                pushTarget(store);
                needPop = true;
            }
            this.store = this._store();
            this.store && (this.store._widget = this);
            needPop && popTarget();
            needPop = false;
            pushTarget(this.store);
            if (this.store instanceof Fix.Model) {
                this.model = this.store.model;
            } else {
                this.model = this.store;
            }
            needPop = true;
        }
        return needPop;
    }

    var _init = BI.Widget.prototype._init;
    BI.Widget.prototype._init = function () {
        var self = this;
        var needPop = createStore.call(this);
        _init.apply(this, arguments);
        needPop && popTarget();
    };

    var _render = BI.Widget.prototype._render;
    BI.Widget.prototype._render = function () {
        var needPop = false;
        if (_global.Fix && this._store) {
            needPop = true;
            pushTarget(this.store);
            initWatch(this, this.watch);
        }
        _render.apply(this, arguments);
        needPop && popTarget();
    };

    var unMount = BI.Widget.prototype.__d;
    BI.Widget.prototype.__d = function () {
        unMount.apply(this, arguments);
        this.store && BI.isFunction(this.store.destroy) && this.store.destroy();
        BI.each(this._watchers, function (i, unwatches) {
            unwatches = BI.isArray(unwatches) ? unwatches : [unwatches];
            BI.each(unwatches, function (j, unwatch) {
                unwatch();
            });
        });
        this._watchers && (this._watchers = []);
        if (this.store) {
            this.store._parent && (this.store._parent = null);
            this.store._widget && (this.store._widget = null);
            this.store = null;
        }
        delete this.__cacheStore;
    };

    _.each(["_mount"], function (name) {
        var old = BI.Widget.prototype[name];
        old && (BI.Widget.prototype[name] = function () {
            this.store && pushTarget(this.store);
            try {
                var res = old.apply(this, arguments);
            } catch (e) {
                console.error(e);
            }
            this.store && popTarget();
            return res;
        });
    });

    if (BI.isIE9Below && BI.isIE9Below()) {
        _.each(["each", "map", "reduce", "reduceRight", "find", "filter", "reject", "every", "all", "some", "any", "max", "min",
            "sortBy", "groupBy", "indexBy", "countBy", "partition",
            "keys", "allKeys", "values", "pairs", "invert",
            "mapObject", "findKey", "pick", "omit", "tap"], function (name) {
            var old = BI[name];
            BI[name] = function (obj, fn, context) {
                return typeof fn === "function" ? old(obj, function (key, value) {
                    if (!(key in Fix.$$skipArray)) {
                        return fn.apply(this, arguments);
                    }
                }, context) : old.apply(this, arguments);
            };
        });
        BI.isEmpty = function (ob) {
            if (BI.isPlainObject(ob) && ob.__ob__) {
                return BI.keys(ob).length === 0;
            }
            return _.isEmpty(ob);
        };
        BI.keys = function (ob) {
            var keys = _.keys(ob);
            var nKeys = [];
            for (var i = 0; i < keys.length; i++) {
                if (!(keys[i] in Fix.$$skipArray)) {
                    nKeys.push(keys[i]);
                }
            }
            return nKeys;
        };
        BI.values = function (ob) {
            var keys = BI.keys(obj);
            var length = keys.length;
            var values = [];
            for (var i = 0; i < length; i++) {
                values[i] = obj[keys[i]];
            }
            return values;
        };
        BI.extend = function () {
            var args = Array.prototype.slice.call(arguments);
            if (args.length < 1) {
                return {};
            }
            var object = args[0];
            var i = 1;
            while (i < args.length) {
                BI.each(args[i], function (key, v) {
                    object[key] = v;
                });
                i++;
            }
            return object;
        };
        BI.size = function (ob) {
            if (BI.isPlainObject(ob) && ob.__ob__) {
                return BI.keys(ob).length;
            }
            return _.size(ob);
        };
        BI.isEmptyObject = function (ob) {
            return BI.size(ob) === 0;
        };
        BI.deepClone = function (ob) {
            return Fix.toJSON(ob);
        };
    }
    BI.watch = Fix.watch;
}());
<|endoftext|>


<commit_before>function Slide(node, config){
	if (typeof $ === 'undefined') {
		throw new Error('需要引入jQuery文件');
	}
	var defaultPara = {
		dir: 'horizontal',  //滚动方向（水平或竖直）
		speed: 500,  //滚动速度
		perGroup: 1,  //显示数量
		perSlideView: 1,  //每次滚动的数量
		autoPlay: 0,  //自动滚动的时间间隔，大于0时有效
		loop: true,  //是否循环滚动
		pagination: null,  //分页器
		outerPagination: false,  //是否是外部的分页器
		pageClickable: true,  //分页器是否可点击
		fullPage: false,  //是否全屏滚动
		showPageNum: false,  //是否显示分页器数字
		fadeInAndOut: false  //是否渐显与渐隐轮播
	};
	$.extend(defaultPara, config);
	this.block = $(node),
	this.dir = defaultPara.dir,
	this.speed = defaultPara.speed,
	this.perGroup = defaultPara.perGroup,
	this.perSlideView = defaultPara.perSlideView,
	this.autoPlay = defaultPara.autoPlay,
	this.loop = defaultPara.loop,
	this.pagination = $(defaultPara.pagination),
	this.outerPagination = defaultPara.outerPagination,
	this.pageClickable = defaultPara.pageClickable,
	this.fullPage = defaultPara.fullPage,
	this.showPageNum = defaultPara.showPageNum,
	this.fadeInAndOut = defaultPara.fadeInAndOut;
	//考虑到animate()方法而不得不暴露的变量
	this.list = this.block.find('ul');
	var _li = this.list.find('li');
	this.liWidth = _li.width(),
	this.liHeight = _li.height();
	//与轮播直接相关的内部变量
	var	_length = _li.length,
	_slideLength = Math.ceil((_length - this.perGroup) / this.perSlideView) + 1,
	_timer = null,
	_slideIndex = 0,
	_pageDot = null,
	_isSinglePage = this.perGroup === 1 && this.perSlideView === 1,  //是否是单页滚动
	_canShowPagination = this.pagination && _isSinglePage, //是否展示分页器
  _canFade = this.fadeInAndOut && _isSinglePage,  //是否允许渐隐渐显式轮播
  _that = this;
	//其他内部变量
	var _body = $("body");

	//初始化
	var _init = function(){
		//初始化轮播样式
		_setStyle();
		//添加分页器
		if(_canShowPagination){
			_createPagination();
		}
		//自动播放
		_setAutoPlay();
		//全屏模式下绑定鼠标滚轮事件
		if(_that.fullPage){
			$(document).on("mousewheel DOMMouseScroll", _bindMouseWheel);
		}
	};

	this.slidePrev = function(){
		clearInterval(_timer);
		if(_slideIndex > 0){
			_slideIndex --;
			!_canFade ?
			_slideAnimation(this.perSlideView) :
			_slideAnimation(_slideIndex);
		}
		else{
			if(this.loop){
				_slideTo(_slideLength - 1);
			}
		}
	};

	this.slideNext = function(notClear){
		if(!notClear){
			clearInterval(_timer);
		}
		if(_slideIndex < _slideLength - 1){
			_slideIndex ++;
			!_canFade ?
			_slideAnimation(-this.perSlideView) :
			_slideAnimation(_slideIndex);
			if(_slideIndex === _slideLength - 1 && !this.loop){
				clearInterval(_timer);
			}
		}
		else{
			if(this.loop){
				_slideTo(0, notClear);
			}
		}
	};

	var _slideTo = function(num, notClear){
		if(!notClear){
			clearInterval(_timer);
		}
		if(_canFade){
			_slideIndex = num;
			_slideAnimation(_slideIndex);
		}
		else{
			var _delta = num - _slideIndex;
			_slideIndex = num;
			_slideAnimation(-_delta * _that.perSlideView);
		}
	};

	//初始化样式
	var _setStyle = function(){
		if(_canFade){
			_that.block.width(_that.liWidth).height(_that.liHeight);
			_that.list.addClass('slide-fade');
			_li.eq(0).addClass('on');
			return;
		}
		if (_that.fullPage) {
			_li.width(_body.width());
			_li.height(_body.height());
		}
		if(_that.dir === 'horizontal'){
			_that.fullPage ?
			_that.liWidth = _li.width() :
			_that.block.width(_that.liWidth * _that.perGroup);
			_that.list.width(_that.liWidth * _length);
		}
		else{
			_that.fullPage ?
			_that.liHeight = _li.height() :
			_that.block.height(_that.liHeight * _that.perGroup);
			_that.list.height(_that.liHeight * _length);
		}
		_that.list.addClass('slide-' + _that.dir);
	};

	//初始化分页
	var _createPagination = function(){
		if(_that.outerPagination){
			_that.pagination.children().length === _length ?
			_pageDot = _that.pagination.children() :
			_pageDot = null;
		}
		else{
			var pageHtml = '';
			for(var i = 0; i < _length; i ++){
				j = _that.showPageNum ? i + 1 : '';
				pageHtml += '' + j + '';
			}
			_that.pagination.append(pageHtml);
			_pageDot = _that.pagination.children();
		}
		_pageDot.eq(0).addClass('on');
		//绑定分页器事件
		if(_that.pageClickable){
			_pageBind();
		}
	};

	var _setAutoPlay =function(){
		if(_that.autoPlay){
			_timer = setInterval(function(){
				_that.slideNext(true);
			}, _that.autoPlay);
		}
	};

	//分页器变换
	var _paginationChange = function(){
		_pageDot.eq(_slideIndex).addClass('on').siblings().removeClass('on');
	};

	//绑定分页器事件
	var _pageBind = function(){
		_pageDot.on('click', function(){
			_slideTo($(this).index());
		});
	};

	//绑定鼠标滚轮事件
	var _bindMouseWheel = function(e){
		e.preventDefault();
		var value = e.originalEvent.wheelDelta || -e.originalEvent.detail;
		value > 0 ?
		_that.slidePrev() :
		_that.slideNext();
	};

	//执行滚动
	var _slideAnimation = function(num){
		if(_canFade){
			_li.eq(num).fadeIn(300).siblings().fadeOut(300);
		}
		else{
			_that.dir === 'horizontal' ?
			_that.list.animate({left: '+=' + num * _that.liWidth + 'px'}, _that.speed) :
			_that.list.animate({top: '+=' + num * _that.liHeight + 'px'}, _that.speed);
		}
		if(_canShowPagination){
			_paginationChange();
		}
	};

	_init();
}<commit_msg>添加循环滚动的初始化结构样式<commit_after>function Slide(node, config){
	if (typeof $ === 'undefined') {
		throw new Error('需要引入jQuery文件');
	}
	var defaultPara = {
		dir: 'horizontal',  //滚动方向（水平或竖直）
		speed: 500,  //滚动速度
		perGroup: 1,  //显示数量
		perSlideView: 1,  //每次滚动的数量
		autoPlay: 0,  //自动滚动的时间间隔，大于0时有效
		loop: true,  //是否循环滚动
		pagination: null,  //分页器
		outerPagination: false,  //是否是外部的分页器
		pageClickable: true,  //分页器是否可点击
		fullPage: false,  //是否全屏滚动
		showPageNum: false,  //是否显示分页器数字
		fadeInAndOut: false  //是否渐显与渐隐轮播
	};
	$.extend(defaultPara, config);
	this.block = $(node),
	this.dir = defaultPara.dir,
	this.speed = defaultPara.speed,
	this.perGroup = defaultPara.perGroup,
	this.perSlideView = defaultPara.perSlideView,
	this.autoPlay = defaultPara.autoPlay,
	this.loop = defaultPara.loop,
	this.pagination = $(defaultPara.pagination),
	this.outerPagination = defaultPara.outerPagination,
	this.pageClickable = defaultPara.pageClickable,
	this.fullPage = defaultPara.fullPage,
	this.showPageNum = defaultPara.showPageNum,
	this.fadeInAndOut = defaultPara.fadeInAndOut;
	//考虑到animate()方法而不得不暴露的变量
	this.list = this.block.find('ul');
	var _li = this.list.find('li');
	this.liWidth = _li.width(),
	this.liHeight = _li.height();
	//与轮播直接相关的内部变量
	var	_length = _li.length,
	_slideLength = Math.ceil((_length - this.perGroup) / this.perSlideView) + 1,
	_timer = null,
	_slideIndex = 0,
	_pageDot = null,
	_isSinglePage = this.perGroup === 1 && this.perSlideView === 1,  //是否是单页滚动
	_canShowPagination = this.pagination && _isSinglePage, //是否展示分页器
  _canFade = this.fadeInAndOut && _isSinglePage,  //是否允许渐隐渐显式轮播
  _that = this;
	//其他内部变量
	var _body = $("body");

	//初始化
	var _init = function(){
		//初始化轮播样式
		_setStyle();
		//添加分页器
		if(_canShowPagination){
			_createPagination();
		}
    //单页状态下复制list头尾两个li元素
    if(_isSinglePage){
      _duplicateList();
    }
		//自动播放
		_setAutoPlay();
		//全屏模式下绑定鼠标滚轮事件
		if(_that.fullPage){
			$(document).on("mousewheel DOMMouseScroll", _bindMouseWheel);
		}
	};

	this.slidePrev = function(){
		clearInterval(_timer);
		if(_slideIndex > 0){
			_slideIndex --;
			!_canFade ?
			_slideAnimation(this.perSlideView) :
			_slideAnimation(_slideIndex);
		}
		else{
			if(this.loop){
				_slideTo(_slideLength - 1);
			}
		}
	};

	this.slideNext = function(notClear){
		if(!notClear){
			clearInterval(_timer);
		}
		if(_slideIndex < _slideLength - 1){
			_slideIndex ++;
			!_canFade ?
			_slideAnimation(-this.perSlideView) :
			_slideAnimation(_slideIndex);
			if(_slideIndex === _slideLength - 1 && !this.loop){
				clearInterval(_timer);
			}
		}
		else{
			if(this.loop){
				_slideTo(0, notClear);
			}
		}
	};

	var _slideTo = function(num, notClear){
		if(!notClear){
			clearInterval(_timer);
		}
		if(_canFade){
			_slideIndex = num;
			_slideAnimation(_slideIndex);
		}
		else{
			var _delta = num - _slideIndex;
			_slideIndex = num;
			_slideAnimation(-_delta * _that.perSlideView);
		}
	};

	//初始化样式
	var _setStyle = function(){
		if(_canFade){
			_that.block.width(_that.liWidth).height(_that.liHeight);
			_that.list.addClass('slide-fade');
			_li.eq(0).addClass('on');
			return;
		}
		if (_that.fullPage) {
			_li.width(_body.width());
			_li.height(_body.height());
		}
		if(_that.dir === 'horizontal'){
			_that.fullPage ?
			_that.liWidth = _li.width() :
			_that.block.width(_that.liWidth * _that.perGroup);
			_that.list.width(_that.liWidth * _length);
		}
		else{
			_that.fullPage ?
			_that.liHeight = _li.height() :
			_that.block.height(_that.liHeight * _that.perGroup);
			_that.list.height(_that.liHeight * _length);
		}
		_that.list.addClass('slide-' + _that.dir);
	};

	//初始化分页
	var _createPagination = function(){
		if(_that.outerPagination){
			_that.pagination.children().length === _length ?
			_pageDot = _that.pagination.children() :
			_pageDot = null;
		}
		else{
			var pageHtml = '';
			for(var i = 0; i < _length; i ++){
				j = _that.showPageNum ? i + 1 : '';
				pageHtml += '' + j + '';
			}
			_that.pagination.append(pageHtml);
			_pageDot = _that.pagination.children();
		}
		_pageDot.eq(0).addClass('on');
		//绑定分页器事件
		if(_that.pageClickable){
			_pageBind();
		}
	};

  var _duplicateList = function(){
    var firstList = _that.list.eq(0),
    lastList = _that.list.eq(-1);
    _that.list.prepend(lastList);
    _that.list.append(firstList);
    if(_that.fadeInAndOut){
      _that.dir === 'horizontal' ?
      _that.list.css('left', _that.liWidth + 'px') :
      _that.list.css('top', _that.liHeight + 'px') ;
    }
  };

	var _setAutoPlay =function(){
		if(_that.autoPlay){
			_timer = setInterval(function(){
				_that.slideNext(true);
			}, _that.autoPlay);
		}
	};

	//分页器变换
	var _paginationChange = function(){
		_pageDot.eq(_slideIndex).addClass('on').siblings().removeClass('on');
	};

	//绑定分页器事件
	var _pageBind = function(){
		_pageDot.on('click', function(){
			_slideTo($(this).index());
		});
	};

	//绑定鼠标滚轮事件
	var _bindMouseWheel = function(e){
		e.preventDefault();
		var value = e.originalEvent.wheelDelta || -e.originalEvent.detail;
		value > 0 ?
		_that.slidePrev() :
		_that.slideNext();
	};

	//执行滚动
	var _slideAnimation = function(num){
		if(_canFade){
			_li.eq(num).fadeIn(300).siblings().fadeOut(300);
		}
		else{
			_that.dir === 'horizontal' ?
			_that.list.animate({left: '+=' + num * _that.liWidth + 'px'}, _that.speed) :
			_that.list.animate({top: '+=' + num * _that.liHeight + 'px'}, _that.speed);
		}
		if(_canShowPagination){
			_paginationChange();
		}
	};

	_init();
}<|endoftext|>


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

MathJax.Hub.Register.StartupHook('HTML-CSS Jax Require', function () {
  MathJax.Hub.Config({
    'HTML-CSS': {
      styles: {
        '.MathJax .mfliph': {
          'display': 'inline-block !important',
          '-moz-transform': 'scaleX(-1)',
          '-webkit-transform': 'scaleX(-1)',
          '-o-transform': 'scaleX(-1)',
          'transform': 'scaleX(-1)',
          '-ms-filter': 'fliph',
          'filter': 'fliph'
        },
        '.MathJax .mar': {
          'font-style': 'normal !important'
        },
        '.MathJax .mar > span': {
          'font-style': 'normal !important'
        }
      }
    }
  });
});

MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready', function () {
  MathJax.Hub.Register.StartupHook('Arabic TeX Ready', function () {
    var MML = MathJax.ElementJax.mml;

    var makeElementFlippable = function (name) {
      var originalToHTML = MML[name].prototype.toHTML;

      MML[name].Augment({
        toHTML: function () {
          var element = originalToHTML.apply(this, arguments);

          if (this.arabicFlipH) {
            var flipElement = document.createElement('span');

            flipElement.className = 'mfliph';

            if ('ar' === this.arabicFontLang) {
              flipElement.className += ' mar'; // Keep the leading space
            }

            if (element.firstChild) {
              while (element.firstChild) {
                flipElement.appendChild(element.firstChild);
              }
            }

            element.appendChild(flipElement);
          }

          return element;
        }
      });
    };

    [
      'mfrac',
      'mi',
      'mn',
      'mo',
      'mrow',
      'ms',
      'msqrt',
      'msubsup',
      'mroot',
      'mtext'
    ].forEach(makeElementFlippable);

    MathJax.Hub.Register.StartupHook('HTML-CSS mtable Ready', function () {
      makeElementFlippable('mtable');

      MathJax.Hub.Startup.signal.Post('Arabic mtable Ready');
    });

    MathJax.Hub.Startup.signal.Post('Arabic Ready');
  });
});

MathJax.Extension.Arabic = {
  version: '1.0.0',
  config: MathJax.Hub.CombineConfig("Arabic", {
    dict: {
      // A macros to force English zero in both languages
      'Zero': ['zero', 'Text', ['0', '\u0635\u0641\u0631']],  // Better localized Zero
      'Radius': ['radius', 'Text', ['r', '\u0646\u0642']],  // Circle radius
      'Area': ['Area', 'Text', ['A', '\u0645']]  // Area of circles and other stuff
    },
    identifiersMap: {
      // Variable names
      'a': '\u0623',
      'b': '\u0628',  // TODO: Consider using Arabic letter dotless beh 0x66e instead
      'c': '\u062c\u0640',  // Suffixed with Unicode Arabic Tatweel 0x0640
      'x': '\u0633',
      'y': '\u0635',
      'z': '\u0639',
      'n': '\u0646',

      // Function names
      'f': '\u0642',  // TODO: Consider using dotless qaf (\u066f) instead
      'g': '\u062c\u0640',  // With Unicode Arabic Tatweel 0x0640
      'h': '\u0647\u0640',  // With Unicode Arabic Tatweel 0x0640

      // Mixed use
      'k': '\u0643',
      'r': '\u0631',
      't': '\u062a',
      'd': '\u062f',  // Function, variable and (dx)
      'e': '\u0647\u0640',  // With Unicode Arabic Tatweel 0x0640
      'm': '\u0645',
      'l': '\u0644',

      // Math functions
      'sin': '\u062c\u0627',
      'cos': '\u062c\u062a\u0627',
      'tan': '\u0638\u0627',
      'cot': '\u0638\u062a\u0627',
      'sec': '\u0642\u0627',
      'csc': '\u0642\u062a\u0627',
      'log': '\u0644\u0648'
    },
    numbersMap: {
      '0': '\u0660',
      '1': '\u0661',
      '2': '\u0662',
      '3': '\u0663',
      '4': '\u0664',
      '5': '\u0665',
      '6': '\u0666',
      '7': '\u0667',
      '8': '\u0668',
      '9': '\u0669'
    },
    operatorsMap: {
      // English to Arabic punctuations
      ',': '\u060c',
      ';': '\u061b',
      // Limits
      'lim': '\u0646\u0647\u0640\u0640\u0627'
    },
    isArabicPage: (document.documentElement.lang === 'ar')
  }),
  arabicLanguageRegExp: /([\u0600-\u06FF]+)/g,
  TeX: function (english, arabic) {
    // Creates a translated TeX macro.

    return function (name) {
      var TEX = MathJax.InputJax.TeX;

      var tex;
      if ('ar' === this.stack.env.lang) {
        tex = arabic;
      } else {
        tex = english;
      }

      this.Push(TEX.Parse(tex).mml());
    };
  },
  Text: function (english, arabicText) {
    // Creates a translated TeX macro, with an Arabic plain text.

    return MathJax.Extension.Arabic.TeX(english, '\\fliph{\\text{' + arabicText + '}}');
  },
  Symbols: function (english, arabicSymbols) {
    // Creates a translated TeX macro that converts Arabic symbols into text nodes,
    // and treats everything else as normal TeX.
    var arabic = arabicSymbols.replace(
      MathJax.Extension.Arabic.arabicLanguageRegExp,
      '\\fliph{\\text{$1}}'
    );

    return MathJax.Extension.Arabic.TeX(english, arabic);
  }
};

MathJax.Hub.Startup.signal.Post('Arabic TeX Startup');

MathJax.Hub.Register.StartupHook('TeX Jax Ready', function () {
  MathJax.Hub.Register.StartupHook('Arabic TeX Startup', function () {
    var TEX = MathJax.InputJax.TeX;
    var Arabic = MathJax.Extension.Arabic;
    var texParsePush = TEX.Parse.prototype.Push;
    var texParseMMLToken = TEX.Parse.prototype.mmlToken;
    var dict = MathJax.Hub.config.Arabic.dict;

    var englishNumbersRegExp = /[0-9]/g;

    var escapeRegExp = (function () {
      var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
      var reHasRegExpChar = new RegExp(reRegExpChar.source);

      return function (string) {
        return (string && reHasRegExpChar.test(string))
          ? string.replace(reRegExpChar, '\\$&')
          : string;
      };
    }());

    var getKeysRegExp = function (map) {
      var keys = Object.keys(map).sort(function (a, b) {
        return b.length - a.length;
      });

      return new RegExp(keys.map(escapeRegExp).join('|'), 'gi');
    };

    var identifiersMap = MathJax.Hub.config.Arabic.identifiersMap;
    var identifiersKeysRegExp = getKeysRegExp(identifiersMap);

    var operatorsMap = MathJax.Hub.config.Arabic.operatorsMap;
    var operatorsKeysRegExp = getKeysRegExp(operatorsMap);

    TEX.Definitions.Add({
      macros: {
        'ar': 'HandleArabic',
        'alwaysar': 'MarkAsArabic',
        'fliph': 'HandleFlipHorizontal',
        'transx': 'TranslateTeX',
        'transt': 'TranslateText',
        'transs': 'TranslateSymbols'
      }
    });

    TEX.Definitions.Add({
      macros: function () {
        var definitions = {};

        Object.keys(dict).forEach(function (key) {
          var texCommand = dict[key][0];
          definitions[texCommand] = key;
        });

        return definitions;
      }()
    });

    TEX.Parse.Augment(function () {
      var parsers = {};

      Object.keys(dict).forEach(function (key) {
        var helperName = dict[key][1];  // Text, TeX or Symbols
        var helperParams = dict[key][2];

        parsers[key] = Arabic[helperName].apply(null, helperParams);
      });

      return parsers;
    }());

    TEX.Parse.Augment({
      flipHorizontal: function (token) {
        token.arabicFlipH = !token.arabicFlipH;
          // Invert the value, because flipping twice means, it is not flipped
        return token;
      },
      arabicNumber: function (token) {
        var numbersMap = MathJax.Hub.config.Arabic.numbersMap;
        var text = token.data[0].data[0];
        var mapped = text.replace(englishNumbersRegExp, function (m) {
          return numbersMap[m];
        });

        if (mapped !== text) {
          token.data[0].data[0] = mapped;
          token.arabicFontLang = 'ar';
        }

        return this.flipHorizontal(token);
      },
      arabicIdentifier: function (token) {
        var text = token.data[0].data[0];

        if ('chars' === token.data[0].type) {
          // English Symbols like X and Y
          var mapped = text.replace(identifiersKeysRegExp, function (m) {
            return identifiersMap[m.toLowerCase()];
          });

          if (mapped !== text) {
            token.data[0].data[0] = mapped;
            token.arabicFontLang = 'ar';
          }
        }

        return this.flipHorizontal(token);
      },
      arabicOperator: function (token) {
        var text = token.data[0].data[0];
        var mapped = text.replace(operatorsKeysRegExp, function (m) {
          return operatorsMap[m];
        });

        if (mapped !== text) {
          token = this.flipHorizontal(token);
          token.arabicFontLang = 'ar';
          token.data[0].data[0] = mapped;
        }

        return token;
      },
      _getArgumentMML: function (name) {
        //  returns an argument that is a single MathML element
        //  (in an mrow if necessary)
        //
        //  This functions has been copied here from extensions/TeX/HTML.js, to avoid
        //  adding a dependency.
        //
        //  TODO: Consider importing (as a dependency) this from HTML.js instead!
        var arg = this.ParseArg(name);
        if (arg.inferred && arg.data.length === 1) {
          arg = arg.data[0];
        } else {
          delete arg.inferred;
        }

        return arg;
      },
      Push: function () {
        var beforeLang = this.stack.env.lang;
        var retVal = texParsePush.apply(this, arguments);

        // Huge giant hack to propagate `lang` from Arrays (and other environments?)
        // to their children fractions and others.
        if (beforeLang) {
          if (!this.stack.env.lang) {
            this.stack.env.lang = beforeLang;
          }
        }

        return retVal;
      },
      mmlToken: function (token) {
        // TODO: Check for possible incompatibility with boldsymbol extension
        var parsedToken = texParseMMLToken.call(this, token);

        if ('ar' === this.stack.env.lang) {
          this.markArabicToken(parsedToken);
        }

        return parsedToken;
      },
      markArabicToken: function (token) {
        if ('mn' === token.type) {
          return this.arabicNumber(token);
        } else if ('mi' === token.type) {
          return this.arabicIdentifier(token);
        } else if ('mo' === token.type) {
          return this.arabicOperator(token);
        }

        return token;
      },
      HandleArabic: function (name) {
        if (MathJax.Hub.config.Arabic.isArabicPage) {
          this.MarkAsArabic(name);
        }
      },
      TranslateTeX: function (name) {
        var english = this.GetArgument(name);
        var arabicText = this.GetArgument(name);
        var helper = Arabic.TeX(english, arabicText);
        return helper.call(this, name);
      },
      TranslateText: function (name) {
        var english = this.GetArgument(name);
        var arabicText = this.GetArgument(name);
        var helper = Arabic.Text(english, arabicText);
        return helper.call(this, name);
      },
      TranslateSymbols: function (name) {
        var english = this.GetArgument(name);
        var arabicText = this.GetArgument(name);
        var helper = Arabic.Symbols(english, arabicText);
        return helper.call(this, name);
      },
      MarkAsArabic: function (name) {
        var originalLang = this.stack.env.lang;

        this.stack.env.lang = 'ar';
        var arg = this._getArgumentMML(name);

        console.log('originalLang', originalLang);
        this.stack.env.lang = originalLang;  // Reset the language for other elements.

        this.Push(this.flipHorizontal(arg));
      },
      HandleFlipHorizontal: function (name) {
        var arg = this._getArgumentMML(name);
        this.Push(this.flipHorizontal(arg));
      }
    });

    MathJax.Hub.Startup.signal.Post('Arabic TeX Ready');
  });
});

// This file starting with the letter `z` to make sure it gets concatenated last!
MathJax.Ajax.loadComplete("[Contrib]/arabic/unpacked/arabic.js");
<commit_msg>Pump in the unpacked arabic.js<commit_after>/*!
 * The MIT License
 *
 * Copyright (c) 2015-2016 The Queen Rania Foundation for Education and Development
 *
 * http://www.qrf.org
 * http://www.edraak.org
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

MathJax.Hub.Register.StartupHook('HTML-CSS Jax Require', function () {
  MathJax.Hub.Config({
    'HTML-CSS': {
      styles: {
        '.MathJax .mfliph': {
          'display': 'inline-block !important',
          '-moz-transform': 'scaleX(-1)',
          '-webkit-transform': 'scaleX(-1)',
          '-o-transform': 'scaleX(-1)',
          'transform': 'scaleX(-1)',
          '-ms-filter': 'fliph',
          'filter': 'fliph'
        },
        '.MathJax .mar': {
          'font-style': 'normal !important'
        },
        '.MathJax .mar > span': {
          'font-style': 'normal !important'
        }
      }
    }
  });
});

MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready', function () {
  MathJax.Hub.Register.StartupHook('Arabic TeX Ready', function () {
    var MML = MathJax.ElementJax.mml;

    var makeElementFlippable = function (name) {
      var originalToHTML = MML[name].prototype.toHTML;

      MML[name].Augment({
        toHTML: function () {
          var element = originalToHTML.apply(this, arguments);

          if (this.arabicFlipH) {
            var flipElement = document.createElement('span');

            flipElement.className = 'mfliph';

            if ('ar' === this.arabicFontLang) {
              flipElement.className += ' mar'; // Keep the leading space
            }

            while (element.firstChild) {
              flipElement.appendChild(element.firstChild);
            }

            element.appendChild(flipElement);
          }

          return element;
        }
      });
    };

    [
      'mfrac',
      'mi',
      'mn',
      'mo',
      'mrow',
      'ms',
      'msqrt',
      'msubsup',
      'mroot',
      'mtext'
    ].forEach(makeElementFlippable);

    MathJax.Hub.Register.StartupHook('HTML-CSS mtable Ready', function () {
      makeElementFlippable('mtable');

      MathJax.Hub.Startup.signal.Post('Arabic mtable Ready');
    });

    MathJax.Hub.Startup.signal.Post('Arabic Ready');
  });
});

MathJax.Extension.Arabic = {
  version: '1.0.0',
  config: MathJax.Hub.CombineConfig("Arabic", {
    dict: {
      // A macros to force English zero in both languages
      'Zero': ['zero', 'Text', ['0', '\u0635\u0641\u0631']],  // Better localized Zero
      'Radius': ['radius', 'Text', ['r', '\u0646\u0642']],  // Circle radius
      'Area': ['Area', 'Text', ['A', '\u0645']]  // Area of circles and other stuff
    },
    identifiersMap: {
      // Variable names
      'a': '\u0623',
      'b': '\u0628',  // TODO: Consider using Arabic letter dotless beh 0x66e instead
      'c': '\u062c\u0640',  // Suffixed with Unicode Arabic Tatweel 0x0640
      'x': '\u0633',
      'y': '\u0635',
      'z': '\u0639',
      'n': '\u0646',

      // Function names
      'f': '\u0642',  // TODO: Consider using dotless qaf (\u066f) instead
      'g': '\u062c\u0640',  // With Unicode Arabic Tatweel 0x0640
      'h': '\u0647\u0640',  // With Unicode Arabic Tatweel 0x0640

      // Mixed use
      'k': '\u0643',
      'r': '\u0631',
      't': '\u062a',
      'd': '\u062f',  // Function, variable and (dx)
      'e': '\u0647\u0640',  // With Unicode Arabic Tatweel 0x0640
      'm': '\u0645',
      'l': '\u0644',

      // Math functions
      'sin': '\u062c\u0627',
      'cos': '\u062c\u062a\u0627',
      'tan': '\u0638\u0627',
      'cot': '\u0638\u062a\u0627',
      'sec': '\u0642\u0627',
      'csc': '\u0642\u062a\u0627',
      'log': '\u0644\u0648'
    },
    numbersMap: {
      '0': '\u0660',
      '1': '\u0661',
      '2': '\u0662',
      '3': '\u0663',
      '4': '\u0664',
      '5': '\u0665',
      '6': '\u0666',
      '7': '\u0667',
      '8': '\u0668',
      '9': '\u0669'
    },
    operatorsMap: {
      // English to Arabic punctuations
      ',': '\u060c',
      ';': '\u061b',
      // Limits
      'lim': '\u0646\u0647\u0640\u0640\u0627'
    },
    isArabicPage: (document.documentElement.lang === 'ar')
  }),
  arabicLanguageRegExp: /([\u0600-\u06FF]+)/g,
  TeX: function (english, arabic) {
    // Creates a translated TeX macro.

    return function (name) {
      var TEX = MathJax.InputJax.TeX;

      var tex;
      if ('ar' === this.stack.env.lang) {
        tex = arabic;
      } else {
        tex = english;
      }

      this.Push(TEX.Parse(tex).mml());
    };
  },
  Text: function (english, arabicText) {
    // Creates a translated TeX macro, with an Arabic plain text.

    return MathJax.Extension.Arabic.TeX(english, '\\fliph{\\text{' + arabicText + '}}');
  },
  Symbols: function (english, arabicSymbols) {
    // Creates a translated TeX macro that converts Arabic symbols into text nodes,
    // and treats everything else as normal TeX.
    var arabic = arabicSymbols.replace(
      MathJax.Extension.Arabic.arabicLanguageRegExp,
      '\\fliph{\\text{$1}}'
    );

    return MathJax.Extension.Arabic.TeX(english, arabic);
  }
};

MathJax.Hub.Startup.signal.Post('Arabic TeX Startup');

MathJax.Hub.Register.StartupHook('TeX Jax Ready', function () {
  var TEX = MathJax.InputJax.TeX;
  var Arabic = MathJax.Extension.Arabic;
  var texParsePush = TEX.Parse.prototype.Push;
  var texParseMMLToken = TEX.Parse.prototype.mmlToken;
  var dict = MathJax.Hub.config.Arabic.dict;

  var escapeRegExp = (function () {
    var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
    var reHasRegExpChar = new RegExp(reRegExpChar.source);

    return function (string) {
      return string.replace(reRegExpChar,'\\$&');
    };
  }());

  var getKeysRegExp = function (map) {
    var keys = Object.keys(map).sort(function (a, b) {
      return b.length - a.length;
    });

    return new RegExp(keys.map(escapeRegExp).join('|'), 'gi');
  };

  TEX.Definitions.Add({
    macros: {
      'ar': 'HandleArabic',
      'alwaysar': 'MarkAsArabic',
      'fliph': 'HandleFlipHorizontal',
      'transx': 'TranslateTeX',
      'transt': 'TranslateText',
      'transs': 'TranslateSymbols'
    }
  });

  TEX.Definitions.Add({
    macros: function () {
      var definitions = {};

      Object.keys(dict).forEach(function (key) {
        var texCommand = dict[key][0];
        definitions[texCommand] = key;
      });

      return definitions;
    }()
  });

  TEX.Parse.Augment(function () {
    var parsers = {};

    Object.keys(dict).forEach(function (key) {
      var helperName = dict[key][1];  // Text, TeX or Symbols
      var helperParams = dict[key][2];

      parsers[key] = Arabic[helperName].apply(null, helperParams);
    });

    return parsers;
  }());

  TEX.Parse.Augment({
    flipHorizontal: function (token) {
      token.arabicFlipH = !token.arabicFlipH;
        // Invert the value, because flipping twice means, it is not flipped
      return token;
    },
    arabicNumber: (function () {
      var englishNumbersRegExp = /[0-9]/g;
      var numbersMap = MathJax.Hub.config.Arabic.numbersMap;

      var replaceNumber = function (m) {
        return numbersMap[m];
      };

      return function (token) {
        var text = token.data[0].data[0];
        var mapped = text.replace(englishNumbersRegExp, replaceNumber);

        if (mapped !== text) {
          token.data[0].data[0] = mapped;
          token.arabicFontLang = 'ar';
        }

        return this.flipHorizontal(token);
      }
    }()),
    arabicIdentifier: (function () {
      var identifiersMap = MathJax.Hub.config.Arabic.identifiersMap;
      var identifiersKeysRegExp = getKeysRegExp(identifiersMap);

      var replaceIdentifier = function (m) {
        return identifiersMap[m.toLowerCase()];
      };

      return function (token) {
        var text = token.data[0].data[0];

        if ('chars' === token.data[0].type) {
          // English Symbols like X and Y
          var mapped = text.replace(identifiersKeysRegExp, replaceIdentifier);

          if (mapped !== text) {
            token.data[0].data[0] = mapped;
            token.arabicFontLang = 'ar';
          }
        }

        return this.flipHorizontal(token);
      }
    }()),
    arabicOperator: (function () {
      var operatorsMap = MathJax.Hub.config.Arabic.operatorsMap;
      var operatorsKeysRegExp = getKeysRegExp(operatorsMap);

      var replaceOperator = function (m) {
        return operatorsMap[m];
      };

      return function (token) {
        var text = token.data[0].data[0];
        var mapped = text.replace(operatorsKeysRegExp, replaceOperator);

        if (mapped !== text) {
          token = this.flipHorizontal(token);
          token.arabicFontLang = 'ar';
          token.data[0].data[0] = mapped;
        }

        return token;
      }
    }()),
    _getArgumentMML: function (name) {
      //  returns an argument that is a single MathML element
      //  (in an mrow if necessary)
      //
      //  This functions has been copied here from extensions/TeX/HTML.js, to avoid
      //  adding a dependency.
      //
      //  TODO: Consider importing (as a dependency) this from HTML.js instead!
      var arg = this.ParseArg(name);
      if (arg.inferred && arg.data.length === 1) {
        arg = arg.data[0];
      } else {
        delete arg.inferred;
      }

      return arg;
    },
    Push: function () {
      var beforeLang = this.stack.env.lang;
      var retVal = texParsePush.apply(this, arguments);

      // Huge giant hack to propagate `lang` from Arrays (and other environments?)
      // to their children fractions and others.
      if (beforeLang) {
        if (!this.stack.env.lang) {
          this.stack.env.lang = beforeLang;
        }
      }

      return retVal;
    },
    mmlToken: function (token) {
      // TODO: Check for possible incompatibility with boldsymbol extension
      var parsedToken = texParseMMLToken.call(this, token);

      if ('ar' === this.stack.env.lang) {
        this.markArabicToken(parsedToken);
      }

      return parsedToken;
    },
    markArabicToken: function (token) {
      if ('mn' === token.type) {
        return this.arabicNumber(token);
      } else if ('mi' === token.type) {
        return this.arabicIdentifier(token);
      } else if ('mo' === token.type) {
        return this.arabicOperator(token);
      }

      return token;
    },
    HandleArabic: function (name) {
      if (MathJax.Hub.config.Arabic.isArabicPage) {
        this.MarkAsArabic(name);
      }
    },
    TranslateTeX: function (name) {
      var english = this.GetArgument(name);
      var arabicText = this.GetArgument(name);
      var helper = Arabic.TeX(english, arabicText);
      return helper.call(this, name);
    },
    TranslateText: function (name) {
      var english = this.GetArgument(name);
      var arabicText = this.GetArgument(name);
      var helper = Arabic.Text(english, arabicText);
      return helper.call(this, name);
    },
    TranslateSymbols: function (name) {
      var english = this.GetArgument(name);
      var arabicText = this.GetArgument(name);
      var helper = Arabic.Symbols(english, arabicText);
      return helper.call(this, name);
    },
    MarkAsArabic: function (name) {
      var originalLang = this.stack.env.lang;

      this.stack.env.lang = 'ar';
      var arg = this._getArgumentMML(name);

      console.log('originalLang', originalLang);
      this.stack.env.lang = originalLang;  // Reset the language for other elements.

      this.Push(this.flipHorizontal(arg));
    },
    HandleFlipHorizontal: function (name) {
      var arg = this._getArgumentMML(name);
      this.Push(this.flipHorizontal(arg));
    }
  });

  MathJax.Hub.Startup.signal.Post('Arabic TeX Ready');
});

// This file starting with the letter `z` to make sure it gets concatenated last!
MathJax.Ajax.loadComplete("[Contrib]/arabic/unpacked/arabic.js");
<|endoftext|>


<commit_before>'use strict';

module.exports = TestCase;

var tests = require('../../cat-component-tests.json');

/*
 * This is a Catberry Cat-component file.
 * More details can be found here
 * https://github.com/catberry/catberry/blob/master/docs/index.md#cat-components
 */

/**
 * Creates new instance of "test-case" component.
 * @constructor
 */
function TestCase() {

}

/**
 * Gets data context for template engine.
 * This method is optional.
 * @returns {Promise<Object>|Object|null|undefined} Data context
 * for template engine.
 */
TestCase.prototype.render = function () {
	return this.$context.getStoreData()
		.then(function (data) {
			var componentName = data.componentName,
				cases = (tests[componentName] ?
					tests[componentName].cases : null) || [];
			return {
				cases: cases.map(function (testCase) {
					testCase.string = testCase.string ||
						JSON.stringify(testCase, null, '\t');
					testCase.visible =
						data.viewMode != 'gallery' || testCase.showInGallery;
					return testCase;
				}),
				componentName: componentName,
				isGalleryViewMode: data.viewMode === 'gallery'
			};
		});
};

/**
 * Returns event binding settings for the component.
 * This method is optional.
 * @returns {Promise<Object>|Object|null|undefined} Binding settings.
 */
TestCase.prototype.bind = function () {
	var window = this.$context.locator.resolve('window'),
		highlights = this.$context.element.querySelectorAll('js-highlight');
	for (var i = 0; i < highlights.length; i++) {
		window.hljs.highlightBlock(highlights[i]);
		console.log(highlights[i]);
	}
};<commit_msg>Update highlight<commit_after>'use strict';

module.exports = TestCase;

var tests = require('../../cat-component-tests.json');

/*
 * This is a Catberry Cat-component file.
 * More details can be found here
 * https://github.com/catberry/catberry/blob/master/docs/index.md#cat-components
 */

/**
 * Creates new instance of "test-case" component.
 * @constructor
 */
function TestCase() {

}

/**
 * Gets data context for template engine.
 * This method is optional.
 * @returns {Promise<Object>|Object|null|undefined} Data context
 * for template engine.
 */
TestCase.prototype.render = function () {
	return this.$context.getStoreData()
		.then(function (data) {
			var componentName = data.componentName,
				cases = (tests[componentName] ?
					tests[componentName].cases : null) || [];
			return {
				cases: cases.map(function (testCase) {
					testCase.string = testCase.string ||
						JSON.stringify(testCase, null, '\t');
					testCase.visible =
						data.viewMode != 'gallery' || testCase.showInGallery;
					return testCase;
				}),
				componentName: componentName,
				isGalleryViewMode: data.viewMode === 'gallery'
			};
		});
};

/**
 * Returns event binding settings for the component.
 * This method is optional.
 * @returns {Promise<Object>|Object|null|undefined} Binding settings.
 */
TestCase.prototype.bind = function () {
	var window = this.$context.locator.resolve('window'),
		highlights = this.$context.element.querySelectorAll('.js-highlight');
	for (var i = 0; i < highlights.length; i++) {
		window.hljs.highlightBlock(highlights[i]);
	}
};<|endoftext|>