@fileOverview
widget.enchant.js
version: 0.2.0
@require enchant.js v0.6.0+
author: Ubiquitous Entertainment Inc.
@description
Library for making mobile webpage-style UIs in enchant.js.
Return objects that cannot be displayed as units in string or enchant.Surface in displayable form.
parameter: {*} content Data you wish to display.
returns: {*} enchant Entity object.
parseContent: function(content, font, color) {
var en;
if (typeof content === 'undefined') {
content = '';
}
if (typeof content === 'number') {
content = arguments.callee('' + content, font);
} else if (content instanceof enchant.Entity) {
} else if (content instanceof enchant.Surface) {
en = new enchant.Sprite(content.width, content.height);
en.image = content;
content = en;
} else if (typeof content == 'string') {
calced = getElementMetrics(content, font);
en = new enchant.Label(content);
en.width = calced.width;
en.height = calced.height;
if (font) {
en.font = font;
} else {
en.font = enchant.widget._env.font;
}
if (color) {
en.color = color;
}
content = en;
}
return content;
}
};
Events occurring during Scene beginning.
Issued when ended {gray enchant.Core#transitionPush} animation.
@type {String}
Events occurring during Scene end.
Issued when ended {gray enchant.Core#transitionPop} animation.
@type {String}
enchant.Event.TRANSITIONEXIT = 'transitionexit';
Event issued when positive button in enchant.widget.Confirm is pushed.
@type {String}
enchant.Event.ACCEPT = 'accept';
Event issued when negative button in enchant.widget.Confirm is pushed.
@type {String}
enchant.Event.CANCEL = 'cancel';
Event issued when form object content is changed.
@type {String}
enchant.Event.CHANGE = 'change';
Event issued when tap is detected.
Detected when touch ends without movement, and when double touch has ended.
@type {String}
enchant.Event.TAP = 'tap';
Event issued when double tap is detected.
Detected when two taps are detected within a set time and distance.
@type {String}
enchant.Event.DOUBLETAP = 'doubletap';
Event issued when hold is detected.
Detected when touch continues for a set time without movement.
@type {String}
enchant.Event.HOLD = 'hold';
Event issued when drag is detected.
Detected when touch position changes during hold.
@type {String}
enchant.Event.DRAG = 'drag';
Event issued when release is detected.
Detected when touch ends during hold.
@type {String}
enchant.Event.RELEASE = 'release';
Event issued when slip is detected.
Detected when touch position changes without holding.
@type {String}
enchant.Event.SLIP = 'slip';
Event issued when fling is detected.
Detected when touch ends and position moves faster than set speed.
@type {String}
enchant.Event.FLING = 'fling';
var NOTOUCH = 0;
var WAITDBL = 1;
var NOMOVE = 2;
var NOMOVEDBL = 3;
var MOVED = 4;
var HOLD = 5;
var getElementMetrics = function(string, font) {
var e = document.createElement('div');
var cvs = document.createElement('canvas');
var ctx = cvs.getContext('2d');
var arr, str, w;
var width = 0;
var height = 0;
if (!font) {
font = enchant.widget._env.font;
}
ctx.font = font;
e.style.font = font;
string = string || '';
string = string.replace(/<(br|BR) ?\/?>/g, '<br>');
arr = string.split('<br>');
for (var i = 0, l = arr.length; i < l; i++) {
str = arr[i];
w = ctx.measureText(str).width;
if (width < w) {
width = w;
}
}
e.innerHTML = string;
if (document.body) {
document.body.appendChild(e);
height = parseInt(getComputedStyle(e).height, 10);
e.style.position = 'absolute';
width = parseInt(getComputedStyle(e).width, 10);
document.body.removeChild(e);
} else {
height = 14 * arr.length;
}
return {
width: width + 1,
height: height + 1
};};
var calcLeastPosition = function(margin) {
margin |= 0;
return margin;
};
var calcMostPosition = function(child, parent, margin) {
margin |= 0;
return parent - margin - child;
};
var calcCenteredPosition = function(child, parent) {
return ~~(parent / 2) - ~~(child / 2);
};
var getScaleOffest = function(length, scale) {
var half = ~~(length / 2);
scale = scale || 1;
return half - ~~(half * scale);
};
var distribute = function(value, div) {
if (typeof div == 'array') {
var ratio = div;
var ret = new Array(ratio.length);
var retSum = 0;
var maxi = 0;
var max = 0;
var sum = 0;
var quo;
ratio.forEach(function(n) {
sum += n;
});
quo = value / sum;
for (var i = 0, l = ret.length; i < l; i++) {
ret[i] = Math.round(quo * ratio[i]);
if (ratio[i] < max) {
maxi = i;
max = ratio[i];
}
}
ret.forEach(function(n) {
retSum += n;
});
ret[maxi] += value - retSum;
} else if (typeof div == 'number') {
var ret = new Array(div);
var quo = ~~(value / div);
var rem = ~~(value % div);
for (var i = 0, l = div; i < l; i++) {
ret[i] = quo;
}
for (var i = 0, l = rem; i < l; i++) {
ret[i % div] += 1;
}
}
return ret;
};
var Adjust = {
fitToX: function(parent, margin) {
var l = parent.width;
var s = Math.min(
(l - margin * 2) / this.width,
(l - margin * 2) / this.height
);
if (this instanceof enchant.Sprite) {
this.scaleX = s;
this.scaleY = s;
} else {
this.width = ~~(this.width * s);
this.height = ~~(this.height * s);
}
},
fitToY: function(parent, margin) {
var l = parent.height;
var s = Math.min(
(l - margin * 2) / this.width,
(l - margin * 2) / this.height
);
if (this instanceof enchant.Sprite) {
this.scaleX = s;
this.scaleY = s;
} else {
this.width = ~~(this.width * s);
this.height = ~~(this.height * s);
}
},
fillX: function(parent, margin) {
var s = (parent.width - margin * 2) / this.width;
if (this instanceof enchant.Sprite) {
this.scaleX = s;
this.scaleY = s;
} else {
this.width = ~~(this.width * s);
this.height = ~~(this.height * s);
}
},
fillY: function(parent, margin) {
var s = (parent.height - margin * 2) / this.height;
if (this instanceof enchant.Sprite) {
this.scaleX = s;
this.scaleY = s;
} else {
this.width = ~~(this.width * s);
this.height = ~~(this.height * s);
}
}
};
var Effect = {
transitForwardIn: function(time) {
var core = enchant.Core.instance;
var child;
this.x = core.width;
var e = new enchant.Event(enchant.Event.RENDER);
for (var i = 0, l = this.childNodes.length; i < l; i++) {
child = this.childNodes[i];
child.dispatchEvent(e);
}
this.tl
.moveTo(0, 0, time, enchant.Easing.QUAD_EASEINOUT);
},
transitForwardOut: function(time) {
var core = enchant.Core.instance;
this.x = 0;
this.tl
.moveTo(-core.width, 0, time, enchant.Easing.QUAD_EASEINOUT);
},
transitBackIn: function(time) {
var core = enchant.Core.instance;
this.x = -core.width;
this.tl
.moveTo(0, 0, time, enchant.Easing.QUAD_EASEINOUT);
},
transitBackOut: function(time) {
var core = enchant.Core.instance;
this.x = 0;
this.tl
.moveTo(core.width, 0, time, enchant.Easing.QUAD_EASEINOUT);
},
popup: function() {
this.scaleX = 0.1;
this.scaleY = 0.1;
this.opacity = 0.1;
this.tl
.fadeTo(0.8, 3, enchant.Easing.QUAD_EASEOUT)
.and()
.scaleTo(1, 3, enchant.Easing.BOUNCE_EASEOUT);
},
popdown: function() {
this.tl
.fadeTo(0.1, 3, enchant.Easing.QUAD_EASEOUT)
.and()
.scaleTo(0.1, 3, enchant.Easing.BOUNCE_EASEOUT);
},
resizeTo: function(width, height, time, easing) {
return this.tl.tween({
width: width,
height: height,
time: time,
easing: easing
});
}
};
var Align = {
@scope enchant.Entity
Moves to left side of specified object.
parameter: {*} another Object that becomes standard.
parameter: {Number} margin Number of pixels shifted.
@requires widget.enchant.js
Moves to right side of specified object.
parameter: {*} another Object that becomes standard.
parameter: {Number} margin Number of pixels shifted.
@requires widget.enchant.js
Moves to upper side of specified object.
parameter: {*} another Object that becomes standard.
parameter: {Number} margin Number of pixels shifted.
@requires widget.enchant.js
Moves to lower side of specified object.
parameter: {*} another Object that becomes standard.
parameter: {Number} margin Number of pixels shifted.
@requires widget.enchant.js
Performs leftwards movement within specified object.
parameter: {*} another Object that becomes standard.
parameter: {Number} margin Number of pixels shifted.
@requires widget.enchant.js
Performs rightwards movement within specified object.
parameter: {*} another Object that becomes standard.
parameter: {Number} margin Number of pixels shifted.
@requires widget.enchant.js
Performs upwards movement within specified object.
parameter: {*} another Object that becomes standard.
parameter: {Number} margin Number of pixels shifted.
@requires widget.enchant.js
Performs downwards movement within specified object.
parameter: {*} another Object that becomes standard.
parameter: {Number} margin Number of pixels shifted.
@requires widget.enchant.js
Performs central movement along x axis within specified object.
parameter: {*} another Object that becomes standard.
parameter: {Number} margin Number of pixels shifted.
@requires widget.enchant.js
Performs central movement along y axis within specified object.
parameter: {*} another object that becomes standard.
parameter: {Number} margin Number of pictures shifted.
@requires widget.enchant.js
alignVerticalCenterIn: function(another) {
this.y = calcCenteredPosition(this.height, another.height);
return this;
}
};
for (var prop in Align) {
enchant.Entity.prototype[prop] = Align[prop];
}
var _transitionLock = false;
@scope enchant.Core
Perform pushScene with transition animation.
parameter: {enchant.Scene} inScene New scene transitioned to.
returns: {enchant.Scene} New scene
@requires widget.enchant.js
enchant.Core.prototype.transitionPush = function(inScene) {
if (_transitionLock) return null;
_transitionLock = true;
var time = 15;
var c = 0;
var outScene = this.currentScene;
Effect.transitForwardIn.call(inScene, time);
Effect.transitForwardOut.call(outScene, time);
this.addEventListener(enchant.Event.ENTER_FRAME, function(e) {
outScene.dispatchEvent(e);
if (c > time) {
_transitionLock = false;
this.removeEventListener(enchant.Event.ENTER_FRAME, arguments.callee);
inScene.dispatchEvent(new enchant.Event(enchant.Event.TRANSITIONENTER));
outScene.dispatchEvent(new enchant.Event(enchant.Event.TRANSITIONEXIT));
}
c++;
});
return this.pushScene(inScene);
};
Issue event after detecting several gestures.
Can detect tap, double tap, hold, drag, flick, and more.
parameter: {enchant.Entity} target Object for which you wish to detect input.
@constructs
@extends enchant.EventTarget
Surface corresponding to 9patch.
Does not respond to settings in content area.
parameter: {Number} width Surface width.
parameter: {Number} height Surface height.
@constructs
@extends enchant.Surface
Alert dialog.
Use from normal {gray enchant.widget.AlertScene}.
parameter: {*} content Content to display.
parameter: {String} ac Label for acceptance button.
see: enchant.widget.AlertScene
@constructs
@extends enchant.widget.EntityGroup
initialize: function(content, ac) {
var core = enchant.Core.instance;
var dialogwidth = enchant.widget._env.dialogWidth;
var dialogheight = enchant.widget._env.dialogHeight;
enchant.widget.EntityGroup.call(this, dialogwidth, dialogheight);
var margin = enchant.widget._env.dialogMargin;
content = enchant.widget.parseContent(content);
content.alignHorizontalCenterIn(this).alignTopIn(this, margin);
var accept = new enchant.widget.Button(ac);
accept.alignHorizontalCenterIn(this).alignBottomIn(this, margin);
var that = this;
accept.addEventListener(enchant.Event.TOUCH_END, function() {
that.dispatchEvent(new enchant.Event(enchant.Event.ACCEPT));
});
var np = new enchant.widget.Ninepatch(this.width, this.height);
np.src = core.assets['dialog.png'];
this.background = np;
this._content = content;
this._accept = accept;
this.addChild(content);
this.addChild(accept);
},
Function executed when agreement button is pushed.
@type {Function}
Confirm dialog.
Use from normal {gray enchant.widget.ConfirmScene}.
parameter: {*} content Content to display.
parameter: {String} ac Label for agreement button.
parameter: {String} ig Label for cancel button.
see: enchant.widget.ConfirmScene
@constructs
@extends enchant.widget.EntityGroup
initialize: function(content, ac, ig) {
var core = enchant.Core.instance;
var dialogwidth = enchant.widget._env.dialogWidth;
var dialogheight = enchant.widget._env.dialogHeight;
enchant.widget.EntityGroup.call(this, dialogwidth, dialogheight);
var margin = enchant.widget._env.dialogMargin;
var content = enchant.widget.parseContent(content);
content.alignHorizontalCenterIn(this).alignTopIn(this, margin);
var cancel = new enchant.widget.Button(ig);
cancel.alignLeftIn(this, margin).alignBottomIn(this, margin);
var accept = new enchant.widget.Button(ac);
accept.alignRightIn(this, margin).alignBottomIn(this, margin);
var that = this;
cancel.addEventListener(enchant.Event.TOUCH_END, function() {
that.dispatchEvent(new enchant.Event(enchant.Event.CANCEL));
});
accept.addEventListener(enchant.Event.TOUCH_END, function() {
that.dispatchEvent(new enchant.Event(enchant.Event.ACCEPT));
});
var np = new enchant.widget.Ninepatch(this.width, this.height);
np.src = core.assets['dialog.png'];
this.background = np;
this._content = content;
this._cancel = cancel;
this._accept = accept;
this.addChild(content);
this.addChild(cancel);
this.addChild(accept);
},
Function executed when cancel button is pushed.
@type {Function}
oncancel: function() {
},
Function executed when agreement button is pushed.
Prompt dialog.
Use from normal {gray enchant.widget.PromptScene}.
parameter: {*} content Content to display.
parameter: {String} ac Label for agreement label.
parameter: {String} ig Label for cancel button.
see: enchant.widget.PromptScene
@constructs
@extends enchant.widget.Confirm
Checkbox.
parameter: {String} value Level.
parameter: {String} text Label text.
parameter: {Boolean} checked Whether or not it is checked.
@constructs
@extends enchant.widget.Input
Confirm scene.
Interrupt other input, display selection screen.
parameter: {*} content Content to display.
parameter: {String} acceptName Label for agreement button.
parameter: {String} cancelName Label for cancel button.
@example
var confirm = new ConfirmScene('Okay?', 'OK', 'NO');
confirm.callback = function(bool) {
// true will return for accept, false will return for cancel.
};
// Processing for cancel and accept can be set separately.
confirm.oncancel = function() {
};
confirm.onaccept = function() {
};
@constructs
@extends enchant.widget.Modal
Confirm scene.
Interrupt other input and display input screen.
When you wish to allow input to multiple lines, use {gray enchant.widget.InputScene}.
parameter: {*} content Content to display.
parameter: {String} acceptName Label for agreement button.
parameter: {String} cancelName Label for cancel button.
parameter: {String} placeholder Placeholder.
@example
var confirm = new PromptScene('Input name', 'OK', 'cancel');
confirm.placeholder = 'Name';
confirm.callback = function(text) {
// Input array will be returned for accept, whereas null will be returned for cancel.
};
// Processing for cancel and accept can be set separately.
confirm.oncancel = function() {
};
confirm.onaccept = function(text) {
};
see: enchant.widget.InputScene
@constructs
@extends enchant.widget.Modal
Information.
Interrupts other input and displays input screen.
Unlike {gray enchant.widget.PromptScene}, you can input to multiple lines.
parameter: {*} content Content to display.
parameter: {String} acceptName Label for agreement button.
parameter: {String} cancelName Label for cancel button.
parameter: {String} placeholder Placeholder.
@example
var input = new InputScene('New Tweet', 'Tweet', 'Stop', '@twitter ');
input.callback = function(text) {
// Input array will be returned for accept, and null for cancel.
};
// Processing for cancel and accept can be set separately.
input.oncancel = function() {
};
input.onaccept = function(text) {
};
@constructs
@extends enchant.widget.Modal
List elements.
Icons and leftmost buttons can be set.
Use {gray enchant.widget.ListItemVertical} to set items lined up vertically.
parameter: {Number} width Element width.
parameter: {Number} height Element height.
parameter: {*} [content] ListItem content.
parameter: {enchant.Sprite|enchant.Surface} [icon] ListItem icon.
parameter: {enchant.Sprite|enchant.Surface} [icon] ListItem right side icon.
see: enchant.widget.ListItemVertical
@constructs
@extends enchant.widget.ListElement
Scroll content.
Correct level will become upwards scroll.
parameter: {Number} dy Scroll level.
scroll: function(dy) {
if (!this._content) {
return;
}
if (this.height >= this._content.height) {
this._content.y = 0;
return;
}
var max = 0
var min = this.height - this._content.height
var sy = this._content.y + dy;
if (sy > max) {
dy = max - this._content.y;
} else if (sy < min) {
dy = min - this._content.y;
}
this._content.y += dy;
}
});
Navigation bar.
Items are set for sent, right, and left.
parameter: {*} center Object you wish to display in center.
parameter: {*} left Item you wish to display to left.
parameter: {*} right Item you wish to display to right.
@constructs
@extends enchant.widget.EntityGroup
initialize: function(center, left, right) {
var core = enchant.Core.instance;
enchant.widget.EntityGroup.call(this, core.width, enchant.widget._env.itemHeight);
this._center;
this._rawCenter;
this._left;
this._rawLeft;
this._right;
this._rawRight;
this.center = center;
if (left) {
this.left = left;
}
if (right) {
this.right = right;
}
this.refresh();
var np = new enchant.widget.Ninepatch(this.width, this.height);
np.src = core.assets['navigationBar.png'];
this.background = np;
},
Renew change.
refresh: function() {
var center = this._center;
var left = this._left;
var right = this._right;
var margin = enchant.widget._env.listItemMargin;
if (center) {
center.alignHorizontalCenterIn(this).alignVerticalCenterIn(this);
}
if (left) {
left.alignLeftIn(this, margin).alignVerticalCenterIn(this);
}
if (right) {
right.alignRightIn(this, margin).alignVerticalCenterIn(this);
}
},
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.