/// <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>(); } }
/// <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; }); }