Beispiel #1
0
        public void Truthiness()
        {
            Assert.IsFalse(JavaScriptHelpers.IsTruthy(null), "Null is not truthy.");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy(this), "Non-null object is truthy.");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy(true), "Boolean value of true is truthy.");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy(false), "Boolean value of false is not truthy.");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((sbyte)42), "Non-zero sbyte value is truthy");
            Assert.IsTrue(JavaScriptHelpers.IsTruthy((sbyte)-42), "Non-zero sbyte value is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((sbyte)0), "Zero sbyte value is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((byte)42), "Non-zero byte value is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((byte)0), "Zero byte value is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((char)0), "Char value is truthy.");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((short)42), "Non-zero short value is truthy");
            Assert.IsTrue(JavaScriptHelpers.IsTruthy((short)-42), "Non-zero short value is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((short)0), "Zero short value is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((ushort)42), "Non-zero ushort value is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((ushort)0), "Zero ushort value is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((int)42), "Non-zero int value is truthy");
            Assert.IsTrue(JavaScriptHelpers.IsTruthy((int)-42), "Non-zero int value is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((int)0), "Zero int value is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((uint)42), "Non-zero uint value is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((uint)0), "Zero uint value is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((long)42), "Non-zero long value is truthy");
            Assert.IsTrue(JavaScriptHelpers.IsTruthy((long)-42), "Non-zero long value is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((long)0), "Zero long value is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((ulong)42), "Non-zero ulong value is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((ulong)0), "Zero ulong value is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((float)42), "Non-zero float value is truthy");
            Assert.IsTrue(JavaScriptHelpers.IsTruthy((float)-42), "Non-zero float value is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((float)0), "Zero float value is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((double)42), "Non-zero double value is truthy");
            Assert.IsTrue(JavaScriptHelpers.IsTruthy((double)-42), "Non-zero double value is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((double)0), "Zero double value is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((decimal)42), "Non-zero decimal value is truthy");
            Assert.IsTrue(JavaScriptHelpers.IsTruthy((decimal) - 42), "Non-zero decimal value is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((decimal)0), "Zero decimal value is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy("42"), "Non-zero length string is truthy");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy(""), "Zero length string is not truthy");

            Assert.IsTrue(JavaScriptHelpers.IsTruthy((bool?)true), "Nullable values' truthiness is based on the actual value if they do not have a value assigned.");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((bool?)false), "Nullable values' truthiness is based on the actual value if they do not have a value assigned.");
            Assert.IsFalse(JavaScriptHelpers.IsTruthy((char?)null), "Nullable values are not truthy if they do not have a value assigned.");
        }
 public void Abort(System.IO.TextWriter writer, bool isHtmlBool)
 {
     // Bound attribute
     if (binding != null)
     {
         RenderAttribute(writer, attribute.Name, attribute.Binding.Expression);
     }
     // Simple attribute
     else if (!isHtmlBool)
     {
         RenderAttribute(writer, attribute.Name, attribute.Value);
     }
     else if (JavaScriptHelpers.IsTruthy(attribute.Value))
     {
         RenderAttribute(writer, attribute.Name, attribute.Name);
     }
 }
Beispiel #3
0
        protected bool TryRenderIf(AjaxPage page, IEnumerable <string> templateNames, System.IO.TextWriter writer, out AttributeBinding ifBinding, out bool canRender)
        {
            if (If == null)
            {
                ifBinding = null;
                canRender = true;
                return(true);
            }

            ifBinding = If.Evaluate(page);

            if (!ifBinding.IsValid)
            {
                canRender = false;
                return(false);
            }

            canRender = JavaScriptHelpers.IsTruthy(ifBinding.Value);
            return(true);
        }
Beispiel #4
0
        internal override void Render(AjaxPage page, string[] templateNames, System.IO.TextWriter writer)
        {
            bool             canRender;
            AttributeBinding ifBinding;

            if (!TryRenderIf(page, templateNames, writer, out ifBinding, out canRender))
            {
                Abort(page, templateNames, writer);
                return;
            }

            if (!canRender)
            {
                return;
            }

            // Output the original template if toggle on was not specified
            if (On == null)
            {
                Abort(page, templateNames, writer);
                return;
            }

            // Get the data associated with the data view
            var onBinding = On.Evaluate(page);

            // Output the original template if no data for on was found
            if (!onBinding.IsValid)
            {
                Abort(page, templateNames, writer);
                return;
            }

            var onValue = onBinding.Value;

            var classValue   = "";
            var classBinding = (AttributeBinding)null;

            if (ClassName != null)
            {
                classBinding = ClassName.Evaluate(page);

                // Output the original template if no data for class was found
                if (!classBinding.IsValid)
                {
                    Abort(page, templateNames, writer);
                    return;
                }

                classValue = (string)classBinding.Value;
            }

            ToggleAction?actionValue;

            var actionBinding = (AttributeBinding)null;

            // Get the value of the toggle action (i.e.: show, hide, etc.)
            if (Action != null)
            {
                actionBinding = Action.Evaluate(page);

                // Output the original template if no data for action was found
                if (!actionBinding.IsValid)
                {
                    Abort(page, templateNames, writer);
                    return;
                }

                actionValue = (ToggleAction)Enum.Parse(typeof(ToggleAction), (string)actionBinding.Value, true);
            }
            else if (!string.IsNullOrEmpty(classValue))
            {
                actionValue = ToggleAction.AddClass;
            }
            else
            {
                actionValue = ToggleAction.Show;
            }

            var groupNameBinding = (AttributeBinding)null;

            if (GroupName != null)
            {
                groupNameBinding = GroupName.Evaluate(page);

                // Output the original template if no data for group name was found
                if (!groupNameBinding.IsValid)
                {
                    Abort(page, templateNames, writer);
                    return;
                }
            }

            var strictModeValue   = false;
            var strictModeBinding = (AttributeBinding)null;

            if (StrictMode != null)
            {
                strictModeBinding = StrictMode.Evaluate(page);

                // Output the original template if no data for strict mode was found
                if (!strictModeBinding.IsValid)
                {
                    Abort(page, templateNames, writer);
                    return;
                }

                if (strictModeBinding.Value is bool)
                {
                    strictModeValue = (bool)strictModeBinding.Value;
                }
                else
                {
                    strictModeValue = bool.Parse((string)strictModeBinding.Value);
                }
            }

            bool?equals;

            var whenBinding = (AttributeBinding)null;

            // Evaluate whether the on and when conditions are equal or
            // satisified, which determines whether the toggle is on or off
            if (When == null)
            {
                if (strictModeValue)
                {
                    // In strict mode the on value must be a boolean true
                    if (!(onValue is bool))
                    {
                        throw new ApplicationException(string.Format("With strict mode enabled, toggle:on should be a value of type Boolean, actual type \"{0}\".", onValue == null ? "null" : onValue.GetType().Name));
                    }

                    equals = (bool)onValue;
                }
                else if (onValue is System.Collections.IEnumerable)
                {
                    equals = false;

                    // Satisfied if there are any items
                    foreach (object o in (System.Collections.IEnumerable)onValue)
                    {
                        equals = true;
                        break;
                    }
                }
                else
                {
                    // Otherwise, check to see that the on value is "truthy"
                    equals = JavaScriptHelpers.IsTruthy(onValue);
                }
            }
            else
            {
                whenBinding = When.Evaluate(page);

                var whenValue = whenBinding.Value;

                if (whenValue == null)
                {
                    equals = (onValue == null);
                }
                else if (whenValue is FunctionInstance)
                {
                    object result;

                    try
                    {
                        result = Page.ScriptMarshaller.Unwrap(((FunctionInstance)whenValue).Call(null, Page.ScriptMarshaller.Wrap(onValue)));
                    }
                    catch
                    {
                        Abort(page, templateNames, writer);
                        return;
                    }

                    if (strictModeValue)
                    {
                        if (!(result is bool))
                        {
                            throw new ApplicationException(string.Format("With strict mode enabled, toggle:when function should return a value of type Boolean, found type \"{0}\".", result == null ? "null" : result.GetType().Name));
                        }
                        equals = (bool)result;
                    }
                    else
                    {
                        equals = JavaScriptHelpers.IsTruthy(result);
                    }
                }
                else
                {
                    equals = whenValue.Equals(onValue);
                }
            }

            // If no class value is defined then abort
            if ((actionValue == ToggleAction.AddClass || actionValue == ToggleAction.RemoveClass) && string.IsNullOrEmpty(classValue))
            {
                Abort(page, templateNames, writer);
                return;
            }

            bool render = actionValue == ToggleAction.Render || actionValue == ToggleAction.Dispose;

            AttributeBinding contentTemplateBinding;

            if (!TryContentTemplate(page, templateNames, writer, out contentTemplateBinding))
            {
                Abort(page, templateNames, writer);
                return;
            }

            var ownTemplateNames = contentTemplateBinding != null ?
                                   ((string)contentTemplateBinding.Value).Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) :
                                   new string[0];

            using (var context = render ? page.BeginContext(page.Context.DataItem, null) : null)
            {
                RenderStartTag(page, writer, attrs => MergeAttribute(MergeAttribute(MergeAttribute(attrs,
                                                                                                   "class", value =>
                {
                    if (actionValue == ToggleAction.AddClass || actionValue == ToggleAction.RemoveClass)
                    {
                        if ((actionValue == ToggleAction.AddClass && equals.Value) || (actionValue == ToggleAction.RemoveClass && !equals.Value))
                        {
                            value = AttributeHelper.EnsureClassName(value, classValue);
                        }
                        else
                        {
                            value = AttributeHelper.RemoveClassName(value, classValue);
                        }
                    }

                    // Add/remove the "toggle-on" and "toggle-off" classes based on state
                    value = AttributeHelper.EnsureClassName(value, equals.Value ? "toggle-on" : "toggle-off");
                    value = AttributeHelper.RemoveClassName(value, equals.Value ? "toggle-off" : "toggle-on");

                    return(value);
                }).ToArray(),
                                                                                    "style", value =>
                {
                    if (actionValue == ToggleAction.Show || actionValue == ToggleAction.Hide ||
                        actionValue == ToggleAction.Render || actionValue == ToggleAction.Dispose)
                    {
                        if (((actionValue == ToggleAction.Show || actionValue == ToggleAction.Render) && equals.Value) ||
                            ((actionValue == ToggleAction.Hide || actionValue == ToggleAction.Dispose) && !equals.Value))
                        {
                            if (AttributeHelper.GetCssStyle(value, "display") == "none")
                            {
                                value = AttributeHelper.RemoveCssStyle(value, "display");
                            }
                        }
                        else
                        {
                            value = AttributeHelper.EnsureCssStyle(value, "display", "none");
                        }
                    }

                    return(value);
                }).ToArray(),
                                                                     "disabled", value =>
                {
                    if (actionValue == ToggleAction.Enable || actionValue == ToggleAction.Disable)
                    {
                        if ((actionValue == ToggleAction.Enable && equals.Value) || (actionValue == ToggleAction.Disable && !equals.Value))
                        {
                            value = null;
                        }
                        else
                        {
                            value = "disabled";
                        }
                    }

                    return(value);
                }), ifBinding, onBinding, classBinding, actionBinding, groupNameBinding, strictModeBinding, whenBinding, contentTemplateBinding,
                               // If this is render/dispose, include the nested template index as a special attribute
                               render ? new AttributeBinding(new Attribute()
                {
                    Name = "data-sys-tmplidx", Value = NestedTemplateIndex.ToString()
                }, null) : null,
                               render ? new AttributeBinding(new Attribute()
                {
                    Name = "data-sys-tcindex", Value = context.Id
                }, null) : null);

                // Only render the inner blocks if the template would be rendered client-side
                if (!render || (actionValue == ToggleAction.Render && equals.Value) || (actionValue == ToggleAction.Dispose && !equals.Value))
                {
                    foreach (var block in Blocks)
                    {
                        block.Render(page, templateNames.Concat(ownTemplateNames).ToArray(), writer);
                    }
                }

                RenderEndTag(writer);
            }
        }
Beispiel #5
0
        protected void RenderStartTag(AjaxPage page, System.IO.TextWriter writer, Func <IEnumerable <AttributeBinding>, IEnumerable <AttributeBinding> > attributeTransform, bool abort, params AttributeBinding[] bindings)
        {
            // Immediately abort if no tag name
            if (Tag == null)
            {
                return;
            }

            // Open Tag
            writer.Write("<" + Tag);

            // Attributes
            string innerContent = null;
            var    attributes   = (Attributes ?? new List <Attribute>())
                                  .Select(attribute => attribute.Binding == null ? new AttributeBinding(attribute, null) : attribute.Binding.Evaluate(page));

            // Adding binding attributes if necessary
            if (bindings != null && bindings.Length > 0)
            {
                attributes = attributes.Concat(bindings.Where(b => b != null));
            }

            // Transform the attributes if necessary
            if (attributeTransform != null)
            {
                attributes = attributeTransform(attributes);
            }

            string classNames = null;
            bool   foundId    = false;
            bool   isTextArea = Tag.Equals("textarea", StringComparison.InvariantCultureIgnoreCase);

            var attrs = attributes.ToArray();

            // Write the attributes to the output stream
            foreach (var attribute in attrs)
            {
                // Ensure that multiple id attributes are not specified
                if (!page.Context.IsGlobal && (attribute.Name == "id" || attribute.Name == "sys:id"))
                {
                    if (foundId)
                    {
                        throw new ApplicationException("Found multiple id attributes: " + Markup);
                    }
                    foundId = true;
                }

                // Determine if the attribute represents bound element content
                if (attribute.IsBound)
                {
                    if (attribute.Name == "sys:innerhtml" || (isTextArea && attribute.Name == "sys:value"))
                    {
                        innerContent = (attribute.DisplayValue ?? "");
                    }
                    else if (attribute.Name == "sys:innertext")
                    {
                        innerContent = HttpUtility.HtmlEncode(attribute.DisplayValue ?? "");
                    }
                }

                bool isHtmlBoolean;
                var  attributeName = attribute.Name.StartsWith("sys:") ? attribute.Name.Substring(4) : attribute.Name;
                if (Tag.Equals("input", StringComparison.InvariantCultureIgnoreCase))
                {
                    var attr = attrs.SingleOrDefault(a => a.Name.Equals("type", StringComparison.InvariantCultureIgnoreCase) && a.IsValid && a.Value != null);
                    if (attr == null)
                    {
                        isHtmlBoolean = HtmlHelpers.IsBooleanAttribute(attributeName, Tag, null, true);
                    }
                    else
                    {
                        isHtmlBoolean = HtmlHelpers.IsBooleanAttribute(attributeName, Tag, attr.Value.ToString());
                    }
                }
                else
                {
                    isHtmlBoolean = HtmlHelpers.IsBooleanAttribute(attributeName, Tag);
                }

                if (abort)
                {
                    attribute.Abort(writer, isHtmlBoolean);
                }
                else
                {
                    if (attribute.Name == "class")
                    {
                        if (classNames == null)
                        {
                            classNames = (string)attribute.Value;
                        }
                        else
                        {
                            classNames += " " + (string)attribute.Value;
                        }
                    }
                    else
                    {
                        if (attribute.Name.StartsWith("sys:class-"))
                        {
                            // If binding evaluates as truthy, then render the store the class name
                            if (JavaScriptHelpers.IsTruthy(attribute.Value))
                            {
                                string sysClassValue = attribute.Name.Substring(10);
                                if (classNames == null)
                                {
                                    classNames = sysClassValue;
                                }
                                else
                                {
                                    classNames += (classNames.Length > 0 ? " " : "") + sysClassValue;
                                }
                            }
                        }
                        attribute.Render(page, writer, isHtmlBoolean, !page.Context.IsGlobal, isTextArea);
                    }
                }
            }

            // Write direct class and sys:class- attribute values together. Note: by checking
            // for null we may be avoiding writing a class attribute altogether whereas the
            // client framework would have produced an empty class attribute.
            if (classNames != null)
            {
                writer.Write(" class=\"");
                HttpUtility.HtmlAttributeEncode(classNames, writer);
                writer.Write("\"");
            }

            // Close Tag
            if (IsEmpty)
            {
                if (!string.IsNullOrEmpty(innerContent))
                {
                    writer.Write(">" + innerContent + "</" + Tag + ">");
                }
                else if (HtmlHelpers.IsSelfClosing(Tag))
                {
                    writer.Write(" />");
                }
                else
                {
                    writer.Write("></" + Tag + ">");
                }
            }
            else if (!string.IsNullOrEmpty(innerContent))
            {
                writer.Write(">" + innerContent);
            }
            else
            {
                writer.Write(">");
            }
        }
        public void Render(AjaxPage page, System.IO.TextWriter writer, bool isHtmlBool, bool generateIds, bool isTextArea)
        {
            // Bound attribute
            if (binding != null)
            {
                // Valid binding
                if (binding.IsValid)
                {
                    // Render the binding value for sys attributes
                    if (attribute.Name.StartsWith("sys:"))
                    {
                        var attributeName = attribute.Name.Substring(4);

                        // Render two-way binding expressions
                        if (attribute.Binding.IsTwoWay)
                        {
                            RenderAttribute(writer, "data-sys-" + attributeName, attribute.Binding.Expression);
                        }

                        if (binding.Value != null)
                        {
                            if (attributeName != "if" && attributeName != "innerhtml" && attributeName != "innertext" && !(isTextArea && attributeName == "value") && !attribute.Name.StartsWith("sys:class-"))
                            {
                                if (isHtmlBool)
                                {
                                    if (JavaScriptHelpers.IsTruthy(binding.Value))
                                    {
                                        RenderAttribute(writer, attributeName, attributeName);
                                    }
                                }
                                else
                                {
                                    RenderAttribute(writer, attributeName, binding.Value.ToString());
                                }
                            }
                        }
                    }
                    else
                    {
                        RenderAttribute(writer, "data-" + attribute.Name.Replace(':', '-'), attribute.Binding.Expression);
                    }
                }

                // Invalid binding
                else
                {
                    RenderAttribute(writer, attribute.Name, attribute.Binding.Expression);
                }
            }
            else if (generateIds && (attribute.Name == "id" || attribute.Name == "sys:id"))
            {
                RenderAttribute(writer, "id", page.Context.GetInstanceId(attribute.Value));
            }
            // Simple attribute
            else if (attribute.Name.Contains(":") && attribute.Name != "sys:id")
            {
                RenderAttribute(writer, "data-" + attribute.Name.Replace(':', '-'), attribute.Value);
            }
            else if (isHtmlBool)
            {
                if (JavaScriptHelpers.IsTruthy(attribute.Value))
                {
                    RenderAttribute(writer, attribute.Name, attribute.Name);
                }
            }
            else
            {
                RenderAttribute(writer, attribute.Name, attribute.Value);
            }
        }