diff --git a/Scrummer/Code/Controls/CTextbox.cs b/Scrummer/Code/Controls/CTextbox.cs
new file mode 100644
index 0000000..ed65c93
--- /dev/null
+++ b/Scrummer/Code/Controls/CTextbox.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+
+namespace Scrummer.Code.Controls
+{
+ public class CTextBox: TextBox
+ {
+ #region Declarations
+
+ private const string CssClassBase = "textbox";
+ private string _cssClassExtra = "";
+
+ private bool _allowEmpty = true;
+
+ private string _placeHolder = string.Empty;
+
+ #endregion
+
+ #region Properties
+
+ public string CssClassExtra
+ {
+ get { return _cssClassExtra; }
+ set { _cssClassExtra = value; }
+ }
+
+ public bool AllowEmpty
+ {
+ get { return _allowEmpty; }
+ set { _allowEmpty = value; }
+ }
+
+ public string PlaceHolder
+ {
+ get { return _placeHolder; }
+ set { _placeHolder = value; }
+ }
+
+ #endregion
+
+ #region Control life cycle
+
+ public CTextBox()
+ {
+ Init += CTextbox_Init;
+ PreRender += CTextbox_PreRender;
+ }
+
+ void CTextbox_Init(object sender, EventArgs e)
+ {
+ }
+
+ void CTextbox_PreRender(object sender, EventArgs e)
+ {
+ CssClass = CssClassBase;
+ if (string.IsNullOrEmpty(_cssClassExtra) == false)
+ {
+ CssClass = String.Format("{0} {1}", CssClassBase, _cssClassExtra);
+ }
+ if (Page.IsPostBack && _allowEmpty == false && IsEmpty())
+ {
+ CssClass += " textboxEmpty";
+ }
+ Attributes.Add("onchange", "ElementRemoveClass(this, 'textboxEmpty');");
+
+ if (string.IsNullOrEmpty(_placeHolder) == false)
+ {
+ Attributes.Add("placeholder", _placeHolder);
+ }
+
+ // FIX: The framework deletes textbox values on password mode
+ if (TextMode == TextBoxMode.Password)
+ {
+ Attributes["value"] = Text;
+ }
+ }
+
+ public override void RenderEndTag(HtmlTextWriter writer)
+ {
+ base.RenderEndTag(writer);
+ }
+
+ #endregion
+
+ #region Public methods
+
+ public bool IsEmpty()
+ {
+ return string.IsNullOrEmpty(Text);
+ }
+
+ #endregion
+
+ }
+}
\ No newline at end of file
diff --git a/Scrummer/Scripts/01. Base.js b/Scrummer/Scripts/01. Base.js
index 65b5a1e..ab40514 100644
--- a/Scrummer/Scripts/01. Base.js
+++ b/Scrummer/Scripts/01. Base.js
@@ -1,10 +1,58 @@
-
+
+////////////////////////
+// GetElement
+//
function GetElement(element) {
if (typeof element == "string") {
element = document.getElementById(element);
- }
+ }
return element;
-}
+}
+
+////////////////////////
+// ElementAddClass
+//
+function ElementAddClass(element, classname) {
+ element = GetElement(element);
+ if (!element) { return; }
+ var cn = element.className;
+ if (cn.indexOf(classname) != -1) {
+ return;
+ }
+ if (cn != '') {
+ classname = ' ' + classname;
+ }
+ element.className = cn + classname;
+}
+
+////////////////////////
+// ElementRemoveClass
+//
+function ElementRemoveClass(element, className) {
+ element = GetElement(element);
+ if (!element) { return; }
+ var regex = new RegExp('(?:^|\\s)' + className + '(?!\\S)');
+ if (regex.test(element.className)) {
+ element.className = element.className.replace(regex, '');
+ }
+}
+
+////////////////////////
+// ElementToggleClass
+//
+function ElementToggleClass(element, className) {
+ element = GetElement(element);
+ if (!element) { return; }
+ var regex = new RegExp('(?:^|\\s)' + className + '(?!\\S)');
+ if (regex.test(element.className)) {
+ element.className = element.className.replace(regex, '');
+ return true;
+ } else {
+ element.className = element.className + ' ' + className;
+ return false;
+ }
+}
+
function escapeHTML(s) {
return s.replace(/&/g, '&')
@@ -18,3 +66,5 @@ function fixedEncodeURIComponent(str) {
return '%' + c.charCodeAt(0).toString(16);
});
}
+
+
diff --git a/Scrummer/Scrummer.csproj b/Scrummer/Scrummer.csproj
index 85fac43..9481cc2 100644
--- a/Scrummer/Scrummer.csproj
+++ b/Scrummer/Scrummer.csproj
@@ -69,6 +69,7 @@
+
diff --git a/Scrummer/Styles/01. base.css b/Scrummer/Styles/01. base.css
index 1faca1c..f9d14a3 100644
--- a/Scrummer/Styles/01. base.css
+++ b/Scrummer/Styles/01. base.css
@@ -109,6 +109,15 @@ h3 {
border: solid 1px black;
box-shadow: 0px 0px 10px rgba(255,255,255,0.5), inset 0px -2px 5px rgba(255,255,255,1), inset 0px 2px 5px rgba(0,0,0,0.5);
}
+.textboxEmpty{
+ box-shadow: 0px 0px 10px rgba(255,0,0,0.5), inset 0px -2px 5px rgba(255,255,255,1), inset 0px 2px 5px rgba(0,0,0,0.5);
+ border: solid 1px rgb(255,0,0);
+}
+.textboxEmpty:focus{
+ box-shadow: 0px 0px 10px rgba(255,0,0,0.5), inset 0px -2px 5px rgba(255,255,255,1), inset 0px 2px 5px rgba(0,0,0,0.5);
+ border: solid 1px black;
+}
+
.button{
padding: 5px;