Exemple #1
0
        /// <summary>
        /// Render the data view to the output for the current page.
        /// </summary>
        /// <param name="page"></param>
        /// <param name="templateNames"></param>
        /// <param name="writer"></param>
        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 data source was not specified
            if (Data == null)
            {
                Abort(page, templateNames, writer);
                return;
            }

            // Get the data associated with the data view
            var dataBinding = Data.Evaluate(page);

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

            // Render the inline template for top level dataviews
            string templateId = null;
            string controlId = null;
            bool renderControlId = false;
            if (page.Context.IsGlobal)
            {
                templateId = page.NextControlId;
                controlId = Attributes.Where(a => a.Name == "id").Select(a => a.Value).FirstOrDefault();
                if (controlId == null)
                {
                    renderControlId = true;
                    controlId = page.NextControlId;
                }
                writer.Write("<");
                writer.Write(Tag);
                writer.Write(" class='sys-template' id='");
                writer.Write(templateId);
                writer.Write("'>");
                writer.Write(Template);
                writer.Write("</");
                writer.Write(Tag);
                writer.Write(">");
            }

            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];

            RenderStartTag(page, writer, ifBinding, dataBinding, contentTemplateBinding,
                // Include the nested template index as a special attribute
                new AttributeBinding(new Attribute() { Name = "data-sys-tmplidx", Value = NestedTemplateIndex.ToString() }, null),
                // If this is a top-level dataview then we will need to ensure an id so that linking can occur
                renderControlId ? new AttributeBinding(new Attribute() { Name = "id", Value = controlId }, null) : null);

            // Convert the data into a list
            IEnumerable list;
            if (dataBinding.Value == null)
                list = new object[0];
            else if (dataBinding.Value is IEnumerable && !(dataBinding.Value is string))
                list = (IEnumerable) dataBinding.Value;
            else
                list = new[] {dataBinding.Value};

            // Process the template for each list item
            var index = 0;
            foreach (var item in list)
            {
                // Begin a new template context
                using (var context = page.BeginContext(item, index++, null))
                {
                    RenderContextBeginMarker(context, Tag, writer);

                    foreach (var block in Blocks)
                        block.Render(page, templateNames.Concat(ownTemplateNames).ToArray(), writer);

                    RenderContextEndMarker(context, Tag, writer);
                }
            }

            RenderEndTag(writer);

            // Render script linking logic
            if (page.Context.IsGlobal)
                writer.Write("<script type=\"text/javascript\">$exoweb({{ domReady: function() {{ Sys.Application.linkElement(document.getElementById(\"{0}\"), document.getElementById(\"{1}\")); }} }});</script>", controlId, templateId);
        }
Exemple #2
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);
            }
        }
Exemple #3
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 data source was not specified
            if (Data == null)
            {
                Abort(page, templateNames, writer);
                return;
            }

            // Get the data associated with the content control
            var dataBinding = Data.Evaluate(page);
            var templateBinding = Template != null ? Template.Evaluate(page) : null;
            var dataTypeBinding = DataType != null ? DataType.Evaluate(page) : null;

            // Output the original template if the data binding expression could not be evaluated
            if ((!dataBinding.IsValid && (dataTypeBinding == null || !dataTypeBinding.IsValid)) || (templateBinding != null && !templateBinding.IsValid))
            {
                Abort(page, templateNames, writer);
                return;
            }

            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];

            // Just render an empty content element if the data is null
            if (dataBinding.IsValid && dataBinding.Value == null)
            {
                RenderStartTag(page, writer, ifBinding, dataBinding, contentTemplateBinding);
                RenderEndTag(writer);
                return;
            }

            // Get the binding data
            object data;
            bool isAdapter;
            ModelType referenceType;
            Type valueType;
            bool isList;

            // Valid binding
            if (dataBinding.IsValid)
            {
                data = dataBinding.Value;
                isAdapter = data is Adapter;
                object realData = isAdapter ? ((Adapter)data).RawValue : data;
                ModelProperty property = dataBinding.Property;
                referenceType = realData is ModelInstance ? ((ModelInstance)realData).Type :
                                property is ModelReferenceProperty ? ((ModelReferenceProperty)property).PropertyType : null;
                valueType = realData != null && !(realData is ModelInstance || realData is IEnumerable<ModelInstance>) ? realData.GetType() :
                            property is ModelValueProperty ? ((ModelValueProperty)property).PropertyType : null;
                isList = (property != null && property.IsList) || (realData is IEnumerable && !(realData is string));
            }

            // Datatype hint only
            else
            {
                var dataType = (string)dataTypeBinding.Value;
                isAdapter = Data is Binding.AdapterExtension || dataType == "ExoWeb.View.Adapter";
                isList = dataType.EndsWith("[]");
                if (isList)
                    dataType = dataType.Substring(0, dataType.Length - 2);
                valueType =	dataType == "String" ? typeof(string) :	dataType == "Number" ? typeof(decimal) : dataType == "Date" ? typeof(DateTime) : dataType == "Boolean" ? typeof(bool) : null;
                referenceType = valueType == null ? ModelContext.Current.GetModelType(dataType) : null;
                data = null;
            }

            // Evaluate content:template binding to get this content control's declare template(s)
            var templates = templateBinding != null && templateBinding.DisplayValue != null ? templateBinding.DisplayValue.Split(' ') : new string[0];

            // Join in the ContentTemplateNames value (sys:content-template) and the context's template names
            templates = templateNames.Concat(templates).Concat(ownTemplateNames).Distinct().ToArray();

            // Find the correct template
            var template = FindTemplate(page, isAdapter, referenceType, valueType, isList, templates);

            // Output the original template if a matching template could not be found
            if (template == null)
            {
                writer.Write("<!-- A template could not be found matching the specified criteria (TagName={0}, Adapter={1}, Type={2}{3}, IsList={4}, Names='{5}') -->", Tag, isAdapter, referenceType, valueType, isList, string.Join(", ", templates));
                Abort(page, templateNames, writer);
                return;
            }

            // Render the template inside a new template context
            using (var context = page.BeginContext(data, null))
            {
                // Render the original content start tag
                RenderStartTag(page, writer, attributes => template.Class.Length > 0 ? MergeClassName(attributes, template) : attributes, ifBinding, dataBinding, contentTemplateBinding, templateBinding, new AttributeBinding(new Attribute() { Name = "data-sys-tcindex", Value = context.Id }, null));

                // Render the content template
                template.Render(page, templates.Where(t => !template.Name.Contains(t)).Concat(template.ContentTemplateNames).ToArray(), writer);

                // Render the original content end tag
                RenderEndTag(writer);
            }
        }