/// <summary>
        /// Creates and attaches behaviors specified on the element declaratively.
        /// </summary>
        /// <param name="element">The element whose behaviors should be created and attached.</param>
        private void AttachBehaviors(Element element)
        {
            string[] behaviorNames = ((string)element.GetAttribute(Application.BehaviorsAttribute)).Split(",");
            int behaviorCount = behaviorNames.Length;

            for (int i = 0; i < behaviorCount; i++) {
                string name = behaviorNames[i].Trim();

                BehaviorRegistration registration = _registeredBehaviors[name];
                Debug.Assert(registration != null, "Unknown behavior '" + name + "'");

                if (registration != null) {
                    Dictionary<string, object> options = OptionsParser.GetOptions(element, name);

                    // Use the Application's IoC capabilities to create behaviors.
                    // This allows satisfying dependencies behaviors have to other services,
                    // and also allows behaviors to provide or register services into the container.

                    Behavior behavior = (Behavior)GetObject(registration.BehaviorType);
                    behavior.Initialize(element, options);

                    if (registration.ServiceType != null) {
                        // Special-case the common case where a behavior represents a single
                        // service type, and auto-register it.
                        // In the case where a behavior is registering multiple service types
                        // (not so common), it can do so manually in its Initialize method.

                        RegisterObject(registration.ServiceType, behavior);
                    }
                }
            }
        }
        public static Dictionary<string, object> GetOptions(Element element, string name)
        {
            // Options can be specified using a pseudo-JSON/css-esque syntax
            // as the value of a data-<name> attribute on the element.

            string optionsText = (string)element.GetAttribute("data-" + name);
            if (String.IsNullOrEmpty(optionsText) == false) {
                return Parse(optionsText);
            }
            else {
                // Create an empty object if no options were declaratively specified
                // so that behaviors always get an object instance in the call to
                // Initialize.

                return new Dictionary<string, object>();
            }
        }
        public static Dictionary<string, object> GetOptions(Element element, string name)
        {
            // Options can be specified using a pseudo-JSON/css-esque syntax
            // as the value of a data-<name> attribute on the element.

            string optionsText = (string)element.GetAttribute("data-" + name);
            if (String.IsNullOrEmpty(optionsText) == false) {
                if (optionsText.StartsWith("{")) {
                    // Vanilla JSON object
                    return Json.ParseData<Dictionary<string, object>>(optionsText);
                }

                // Treat it as our pseudo-JSON/CSS-esque syntax which requires a bit of rewriting
                // before it can be parsed as JSON.
                return Parse(optionsText);
            }
            else {
                // Create an empty object if no options were declaratively specified.
                return new Dictionary<string, object>();
            }
        }
Beispiel #4
0
        /// <summary>
        /// Construct a Module JS object to wrap the Html.Element representing the DOM element
        /// </summary>
        /// <param name="element"></param>
        public Module(Element element)
        {
            Instances.Add(new ModuleInstance(element, this));

            // store a reference to the JQuery and DOM elements
            this.Element = element;
            this.Obj = jQuery.FromElement(element);

            // This is currently unused code
            this.NeedsData = (string)element.GetAttribute("data-async") == "true";
            if (this.NeedsData)
            {
                this.LoadingElement = Document.CreateElement("div");
                this.LoadingElement.ClassName = "loading";
                this.LoadingElement.InnerHTML = "Loading...";

                jQuery.FromElement(this.LoadingElement).InsertAfter(this.Obj.Find(".data"));

                this.Obj.Find(".data").Hide(0);
                this.LoadData();
            }
        }
        private void SetupBindings(Element element, object model)
        {
            Debug.Assert(element != null);

            string bindings = (string)element.GetAttribute(Application.BindingsAttribute);
            bindings.ReplaceRegex(Application.BindingsRegex, delegate(string match /*, string binderType, string expressionType, string expressionValue */) {
                string binderType = (string)Arguments.GetArgument(1);
                string expressionType = (string)Arguments.GetArgument(2);
                string expressionValue = (string)Arguments.GetArgument(3);

                ExpressionFactory expressionFactory = _registeredExpressions[expressionType];
                Debug.Assert(expressionFactory != null, "Unknown expression of type '" + expressionType + "' found.");

                if (expressionFactory != null) {
                    Expression expression = expressionFactory(model, expressionType, expressionValue);
                    Binder binder = null;

                    // TODO: Add support for binding attributes - @xxx

                    if (binderType.StartsWith("on.")) {
                        Debug.Assert(expression.CanChange == false, "Events cannot be bound to dynamic expressions.");
                        Debug.Assert(expression.GetValue() is Action);

                        binder = new EventBinder(element, binderType.Substr(3), (ElementEventListener)expression.GetValue());
                    }
                    else if (binderType.StartsWith("style.")) {
                        object style = element.Style;
                        binder = new PropertyBinder(style, binderType.Substr(6), expression);
                    }
                    else {
                        BinderFactory binderFactory = _registeredBinders[binderType];
                        if (binderFactory == null) {
                            binder = new PropertyBinder(element, binderType, expression);
                        }
                        else {
                            binder = binderFactory(element, binderType, expression);
                        }
                    }

                    if (binder != null) {
                        binder.Update();
                        if (expression.CanChange == false) {
                            // Since the expression value cannot change, there isn't a whole lot of need
                            // to keep the binder alive and manage it.
                            binder = null;
                        }
                    }

                    if (binder != null) {
                        // The binder is managed using a behavior that is attached to the element.
                        // This allows stashing the model for later retrieval, as well as a way to
                        // dispose bindings (the behavior disposes all binders it is managing).

                        BinderManager binderManager = (BinderManager)Behavior.GetBehavior(element, typeof(BinderManager));
                        if (binderManager == null) {
                            binderManager = new BinderManager();
                            binderManager.Initialize(element, null);
                            binderManager.Model = model;
                        }

                        binderManager.AddBinder(binder);
                    }
                }

                return String.Empty;
            });
        }