AW.Templates.Textarea - let's get started
Okay, so I really need a skinned textarea.... and I love all the events, etc. that comes with input boxes so.....
That means this will involve many people and plenty of time... since after-all we want it to be good enough that Alex can easily include it into the next release (hopefully soon.... next bug release?).
So, I started by taking the imagetext Template and UI and began to take out the native HTML for the input box, and replace it with the native textarea element... easier said than done but we'll see how we can do it.
First off, remember that input boxes maintain a value. Textarea's maintain an innerHTML-type value.... BUT you'll notive the startEditGecko has a line in it for e.value..... because e.innerHTML isn't updated from the AW.HTML.TEXTAREA until you finish editing the textarea or explicitly set it....
BUGS:
1) I had to explicitly fire the startEdit event in the controller.... how is this supposed to be fired?
2) Should we not use the AW.HTML.TEXTAREA and use a straight textarea dom object? The input boxes are created as node2 in the bottom of the Gecko start... but not in ie... don't know why.
3) ANY SUGGESTIONS WILL HELP!
4) ANY SUGGESTIONS WILL HELP!
5) I DON'T understand all about the models, controllers, panels, etc. etc.... but I'm learning.
AW.Templates.Textarea = AW.System.Template.subclass();
AW.Templates.Textarea.create = function(){
var obj = this.prototype;
function _text(){return this.getControlProperty("text")}
function _tooltip(){return this.getControlProperty("tooltip")}
var span = AW.HTML.SPAN;
var ruler = new span;
ruler.setClass("item", "ruler");
var text = new AW.HTML.TEXTAREA;
text.setClass("item", "text");
text.setContent("text", _text);
var box = new span;
box.setClass("item", "box");
box.setContent("sign", "");
box.setContent("marker", "");
box.setContent("ruler", ruler);
box.setContent("text", text);
obj.setTag("span");
obj.setClass("item", "template");
obj.setClass("templates", "textarea");
obj.setAttribute("title", _tooltip);
obj.setContent("box", box);
if (AW.gecko){
obj.setAttribute("tabIndex", "-1");
}
var startEditIE = function(startText){
var self = this;
var item = self.getAttribute("aw");
var originalText = self.getControlProperty("text");
var text = originalText;
var valid;
var e = self.getContent("box/text").element();
var x = self.element();
alert('startIE');
if (!e || !x) {
return;
}
var textarea = (e.tagName == "textarea") || (e.tagName == "textarea");
function raiseEvent(name){
var text1 = self.getControlProperty("text");
var fullname = AW.camelCase("on", item, name);
var result = self.raiseEvent(fullname, text, self.$0, self.$1, self.$2);
var text2 = self.getControlProperty("text");
if (text2 != text1) {
updateText(text2);
}
return result;
}
if (raiseEvent("editStarting")){
e = null;
x = null;
return;
}
function nobubble(event){
event.cancelBubble = true;
}
function updateText(text){
e.innerHTML = text;
}
function onpropertychange(event){
var text1 = self.getControlProperty("text");
var text2 = e.innerHTML.replace(/ /g, " ");
if (text2 != text1){
self.setControlProperty("text", text2);
}
var text3 = self.getControlProperty("text");
if (text3 != text2 ) {
updateText(text3);
}
}
function onkeydown(event){
if (event.keyCode == 27){ // 'escape' key
e.innerHTML = originalText;
event.returnValue = false;
if (!self.$owner){
return;
}
onbeforedeactivate(event);
if (valid) {
ondeactivate(event);
}
return;
}
if (event.keyCode == 13){ // 'enter' key
text = self.getControlProperty("text");
if (!self.$owner){
if (raiseEvent("validating")){
return;
}
raiseEvent("validated");
return;
}
event.returnValue = false;
event.cancelBubble = true;
onbeforedeactivate(event);
if (valid) {
ondeactivate(event);
}
return;
}
var r;
// if (textarea) {
// r = e.createTextRange();
// }
// else {
r = document.body.createTextRange();
r.moveToElementText(e);
// }
var s = document.selection.createRange();
if ((event.keyCode == 36 || event.keyCode == 37) && // home, left arrow
r.compareEndPoints("StartToStart", s)){
event.cancelBubble = true;
r = null;
s = null;
return;
}
if ((event.keyCode == 35 || event.keyCode == 39) && // end, right arrow
r.compareEndPoints("EndToEnd", s)){
event.cancelBubble = true;
r = null;
s = null;
return;
}
}
function onbeforedeactivate(event){
valid = false;
text = self.getControlProperty("text");
if (text != e.innerHTML.replace(/ /g, " ")){
text = e.innerHTML.replace(/ /g, " ");
self.setControlProperty("text", text);
}
var text2 = self.getControlProperty("text");
if (text2 != text){
updateText(text2);
text = text2;
}
if (self.element().contains(event.toElement)){
event.returnValue = false;
return;
}
if (raiseEvent("editEnding")){
event.cancelBubble = true;
event.returnValue = false;
return;
}
if (originalText == text){
valid = true;
return;
}
if (raiseEvent("validating")){
event.cancelBubble = true;
event.returnValue = false;
return;
}
raiseEvent("validated");
valid = true;
}
function ondeactivate(event){
text = self.getControlProperty("text");
e.removeExpression("aw-value");
e.detachEvent("onselectstart", nobubble);
e.detachEvent("oncontextmenu", nobubble);
x.detachEvent("onmousedown", nobubble);
x.detachEvent("onmouseup", nobubble);
x.detachEvent("onclick", nobubble);
x.detachEvent("ondoubleclick", nobubble);
e.detachEvent("onpropertychange", onpropertychange);
e.detachEvent("onkeydown", onkeydown);
e.detachEvent("onbeforedeactivate", onbeforedeactivate);
e.detachEvent("ondeactivate", ondeactivate);
// if (!textarea){
// e.contentEditable = false;
// }
e.parentNode.scrollLeft = 0;
x.className = x.className.replace(" aw-edit-" + item, "");
if (self.$owner) {
self.$owner.$edit = false;
}
raiseEvent("editEnded");
e = null;
x = null;
}
x.className = x.className.replace(/ aw-mousedown-\w+/g, "") + " aw-edit-" + item;
// if (!textarea){
// e.contentEditable = true;
// }
e.attachEvent("onselectstart", nobubble);
e.attachEvent("oncontextmenu", nobubble);
// if (textarea){
// e.select();
// }
// else {
e.focus();
// }
e.setExpression("aw-value", input ? "this.value" : "this.innerHTML");
x.attachEvent("onmousedown", nobubble);
x.attachEvent("onmouseup", nobubble);
x.attachEvent("onclick", nobubble);
x.attachEvent("ondoubleclick", nobubble);
e.attachEvent("onpropertychange", onpropertychange);
e.attachEvent("onkeydown", onkeydown);
e.attachEvent("onbeforedeactivate", onbeforedeactivate);
e.attachEvent("ondeactivate", ondeactivate);
if (self.$owner) {
self.$owner.$edit = true;
}
raiseEvent("editStarted");
if (typeof(startText) == "string"){
e.innerHTML = startText;
}
};
var startEditGecko = function(startText){
var self = this;
var item = self.getAttribute("aw");
var originalText = self.getControlProperty("text");
var text = originalText;
// alert(text);
var e = self.getContent("box/text").element();
var x = self.element();
if (!e || !x) {
return;
}
var updateText = function(text){
// alert(text+' (U)');
e.innerHTML = text;
};
function raiseEvent(name){
var text1 = self.getControlProperty("text");
var fullname = AW.camelCase("on", item, name);
var result = self.raiseEvent(fullname, text, self.$0, self.$1, self.$2);
var text2 = self.getControlProperty("text");
if (text2 != text1) {
updateText(text2);
}
return result;
}
if (raiseEvent("editStarting")){
e = null;
x = null;
// alert('return due to editStarting');
return;
}
updateText = function(text){
// alert(text+' (2)');
e.innerHTML = text;
};
function nobubble(event){
event.stopPropagation();
}
function oninput(event){
var text1 = self.getControlProperty("text");
var text2 = e.value;
// alert(text1+' (3) '+text2);
if (text2 != text1){
self.setControlProperty("text", text2);
}
var text3 = self.getControlProperty("text");
// alert(text2+' (4) '+text3);
if (text3 != text2 ) {
updateText(text3);
}
text = text3;
}
function onkeydown(event){
if (event.keyCode == 27){ // 'escape' key
alert(originalText+' (ESC)');
e.innerHTML = originalText;
event.preventDefault();
if (!self.$owner){
return;
}
try {
self.$owner.getContent("focus").element().focus();
return;
}
catch(err){
// ignore focus errors
}
onfocus(event);
return;
}
if (event.keyCode == 13){ // 'enter' key
text = self.getControlProperty("text");
alert(text+' (ENT)');
if (!self.$owner){
insideFocus = true;
if (raiseEvent("validating")){
insideFocus = false;
return;
}
raiseEvent("validated");
insideFocus = false;
return;
}
event.preventDefault();
event.stopPropagation();
try {
self.$owner.getContent("focus").element().focus();
return;
}
catch(err){
// ignore focus errors
}
onfocus(event);
return;
}
if ((event.keyCode == 36 || event.keyCode == 37) && // home, left arrow
e.selectionStart > 0){
event.stopPropagation();
return;
}
if ((event.keyCode == 35 || event.keyCode == 39) && // end, right arrow
e.selectionStart < e.value.length){
event.stopPropagation();
return;
}
}
function cancelEvent(event){
if (event.target != document){
event.preventDefault();
event.stopPropagation();
}
}
var insideFocus;
function focusBack(event){
event.preventDefault();
event.stopPropagation();
e.focus();
window.removeEventListener("blur", cancelEvent, true);
insideFocus = false;
}
var inDocFocus;
function docFocus(event){
if (inDocFocus){
return;
}
inDocFocus = true;
var e = document.createEvent("HTMLEvents");
e.initEvent("focus", false, false);
e.deferred = true;
window.setTimeout(function(){
if (inDocFocus){
onfocus(e);
}
e = null;
});
}
function onfocus(event){
if (event.type=="focus" && event.target == document && !event.deferred){
return docFocus(event);
}
inDocFocus = false;
if (insideFocus || (event.type=="focus" && event.target == e)){
return;
}
insideFocus = true;
window.addEventListener("blur", cancelEvent, true);
function isInside(parent, child){
try {
var range = document.createRange();
range.selectNode(parent);
return child && (range.compareNode(child) == 3);
}
catch(err){
return false;
}
}
if (event.type == "focus" &&
(isInside(x, event.target) || isInside(self.$popup, event.target))){
return focusBack(event);
}
oninput(event);
if (raiseEvent("editEnding")){
return focusBack(event);
}
if (text != originalText){
if (raiseEvent("validating")){
return focusBack(event);
}
raiseEvent("validated");
}
window.removeEventListener("blur", cancelEvent, true);
insideFocus = false;
e.removeEventListener("contextmenu", nobubble, false);
x.removeEventListener("mousedown", nobubble, false);
x.removeEventListener("mouseup", nobubble, false);
x.removeEventListener("click", nobubble, false);
x.removeEventListener("doubleclick", nobubble, false);
e.removeEventListener("input", oninput, false);
e.removeEventListener("keydown", onkeydown, false);
window.removeEventListener("focus", onfocus, true);
// if (!textarea){
// node2.innerHTML = self.getControlProperty("text");
// e.parentNode.replaceChild(node2, e);
// }
x.className = x.className.replace(" aw-edit-" + item, "");
AW.lockFocus = false;
if (self.$owner) {
self.$owner.$edit = false;
}
raiseEvent("editEnded");
e = null;
x = null;
// node1 = null;
// node2 = null;
if (event.type=="focus" && event.deferred){
document.dispatchEvent(event);
}
}
x.className = x.className.replace(/ aw-mousedown-\w+/g, "") + " aw-edit-" + item;
// if (textarea){
// e.select();
// }
// else {
// var node1 = document.createElement("textarea");
// node1.setAttribute("id", e.id);
// node1.setAttribute("type", "text");
// node1.setAttribute("class", e.className);
// node1.setAttribute("autocomplete", "off");
// node1.setAttribute("innerHTML", text);
// var node2 = e.parentNode.replaceChild(node1, e);
// e = node1;
// e.focus();
// }
e.focus();
e.addEventListener("contextmenu", nobubble, false);
x.addEventListener("mousedown", nobubble, false);
x.addEventListener("mouseup", nobubble, false);
x.addEventListener("click", nobubble, false);
x.addEventListener("doubleclick", nobubble, false);
e.addEventListener("input", oninput, false);
e.addEventListener("keydown", onkeydown, false);
window.addEventListener("focus", onfocus, true);
AW.lockFocus = true;
if (self.$owner) {
self.$owner.$edit = true;
}
raiseEvent("editStarted");
if (typeof(startText) == "string"){
e.innerHTML = startText;
oninput.call(self);
}
};
if (AW.ie) {
obj.startEdit = startEditIE;
}
if (!AW.ie) {
obj.startEdit = startEditGecko;
}
};
AW.UI.Textarea = AW.System.Control.subclass();
AW.UI.Textarea.create = function(){
AW.Templates.Textarea.create.call(this);
var obj = this.prototype;
obj.setClass("templates", "");
obj.setClass("ui", "input");
obj.setClass("item", "control");
obj.setClass("text", "expand");
obj.setAttribute("tabIndex", "-1");
function _tabIndex(){
return this.getTabProperty("index");
}
obj.getContent("box/text").setAttribute("tabIndex", _tabIndex);
var _refresh = function(){this.refresh()};
var itemController = {
onControlActivated: "startEdit",
onControlTextChanged: _refresh,
onControlImageChanged: _refresh,
onControlValueChanged: _refresh,
onControlLinkChanged: _refresh,
onControlTooltipChanged:_refresh,
onControlStateChanged: _refresh };
obj.setController("item", itemController);
obj.setEvent("onactivate", function(event){
var e = this.getContent("box/text").element();
if (e && event.srcElement != e ){
this.setTimeout(function(){
e.setActive();
});
}
});
};
var TA = new AW.UI.Textarea;
TA.setSize(200,50); //SUCCESS
TA.setPosition(400,100); //SUCCESS
TA.setControlTooltip("this is a test"); //SUCCESS
TA.setControlText("Starting\nValue"); //SUCCESS
// TA.onControlValueChanging=function(){stat.setControlText('onControlValueChanging');}; //FAILED
// TA.onControlValueChanged=function(){stat.setControlText('onControlValueChanged');}; //FAILED
// TA.onControlActivating=function(){stat.setControlText('onControlActivating');}; //SUCCESS
// TA.onControlActivated=function(){stat.setControlText('onControlActivated');}; //SUCCESS
// TA.onControlDeactivating=function(){stat.setControlText('onControlDeactivating');}; //SUCCESS
// TA.onControlDeactivated=function(){stat.setControlText('onControlDeactivated');}; //SUCCESS
// TA.onKeyPress=function(){stat.setControlText('onKeyPress');}; //SUCCESS
// TA.onControlMouseOver=function(){stat.setControlText('onControlMouseOver');}; //SUCCESS
// TA.onControlMouseOut=function(){stat.setControlText('onControlMouseOut');}; //SUCCESS
// TA.onControlMouseDown=function(){stat.setControlText('onControlMouseDown');}; //SUCCESS
// TA.onControlMouseUp=function(){stat.setControlText('onControlMouseUp');}; //SUCCESS
// TA.onControlClicked=function(){stat.setControlText('onControlClicked');}; //SUCCESS
// TA.onControlDoubleClicked=function(){stat.setControlText('onControlDoubleClicked');}; //SUCCESS
// TA.onControlEditStarting = function(text){stat.setControlText('onControlEditStarting '+text);}; //SUCCESS
// TA.onControlEditStarted = function(text){stat.setControlText('onControlEditStarted '+text);}; //SUCCESS
// TA.onControlValidating = function(text){stat.setControlText('onControlValidating '+text);}; //SUCCESS
// TA.onControlValidated = function(text){stat.setControlText('onControlValidated '+text);}; //SUCCESS
// TA.onControlEditEnding = function(text){stat.setControlText('onControlEditEnding '+text);}; //SUCCESS
// TA.onControlEditEnded = function(text){stat.setControlText('onControlEditEnded '+text);}; //SUCCESS
document.write(TA);
var but = new AW.UI.Button;
but.setPosition(800,10);
but.setControlText('Push Test');
but.onClick=function(){TA.setControlText('Testing\nTesting\nTesting');};
document.write(but);
var get = new AW.UI.Button;
get.setPosition(800,50);
get.setControlText('Get Test');
get.onClick=function(){alert(TA.getControlText());};
document.write(get);
var ref = new AW.UI.Input;
ref.setPosition(400,50);
ref.setControlText('For Reference');
document.write(ref);
var stat = new AW.UI.Label;
stat.setPosition(0,300);
stat.setControlText('Status Here');
document.write(stat);
John Mason
December 22,