Esempio n. 1
1
        /// <summary>
        /// Extracts additional column display values from the search result
        /// The name attribute can now be a column separated list of attribute logical names
        /// </summary>
        /// <param name="columnAttributes"></param>
        /// <param name="fetchResult"></param>
        /// <param name="results"></param>
        /// <param name="i"></param>
        internal static void GetExtraColumns(string[] columnAttributes, EntityCollection fetchResult, AutoCompleteItem[] results, int i)
        {
            if (columnAttributes != null)
            {
                List<string> columnValues = new List<string>();
                bool first = true;
                // Get the additional column attributes to display
                foreach (string attribute in columnAttributes)
                {
                    if (first)
                    {
                        first = false;
                        continue;
                    }
                    string value = "";
                    Entity record = fetchResult.Entities[i];

                    if (record.FormattedValues.ContainsKey(attribute + "name"))
                    {
                        value = record.FormattedValues[attribute + "name"];
                    }
                    else
                    {
                        object attributeValue = record.GetAttributeValue(attribute);
                        if (attributeValue != null)
                        {
                            switch (attributeValue.GetType().Name)
                            {
                                case "EntityReference":
                                    value = ((EntityReference)attributeValue).Name;
                                    break;
                                default:
                                    value = attributeValue.ToString();
                                    break;
                            }
                        }
                    }
                    if (value != null && value.Length>0)
                    {
                        columnValues.Add(value);
                    }

                }
                results[i].ColumnValues = (string[])columnValues;
            }
        }
        public XrmLookupEditor(EditorArguments args)
            : base(args)
        {
            _args = args;
            _container = jQuery.FromHtml("<div ><table class='inline-edit-container' cellspacing='0' cellpadding='0'><tr><td><INPUT type=text class='sparkle-input-inline' /></td><td class='lookup-button-td'><input type=button class='sparkle-lookup-button' /></td></tr></table></div>");
            _container.AppendTo(_args.Container);

            jQueryObject inputField = _container.Find(".sparkle-input-inline");
            jQueryObject selectButton = _container.Find(".sparkle-lookup-button");
            _input = inputField;
            _input.Focus().Select();

            _autoComplete = inputField.Plugin<AutoCompleteObject>();

            AutoCompleteOptions options = new AutoCompleteOptions();

            options.MinLength = 100000;
            options.Delay = 0; // TODO- set to something that makes sense

            bool justSelected = false;
            options.Select = delegate(jQueryEvent e, AutoCompleteSelectEvent uiEvent)
            {
                if (_value == null) _value = new EntityReference(null,null,null);

                // Note we assume that the binding has added an array of string items
                AutoCompleteItem item = (AutoCompleteItem)uiEvent.Item;
                string value = item.Label;
                _input.Value(value);
                _value.Id = ((EntityReference)item.Value).Id;
                _value.Name = ((EntityReference)item.Value).Name;
                _value.LogicalName = ((EntityReference)item.Value).LogicalName;
                justSelected = true;
                Script.Literal("return false;");

            };
            //
            options.Focus = delegate(jQueryEvent e, AutoCompleteFocusEvent uiEvent)
            {
                // Prevent the value being updated in the text box we scroll through the results
                Script.Literal("return false;");
            };

            XrmLookupEditorOptions editorOptions = (XrmLookupEditorOptions)args.Column.Options;

            // wire up source to CRM search
            Action<AutoCompleteRequest, Action<AutoCompleteItem[]>> queryDelegate = delegate(AutoCompleteRequest request, Action<AutoCompleteItem[]> response)
            {

                 // Get the option set values
                editorOptions.queryCommand(request.Term, delegate(EntityCollection fetchResult)
                {
                   AutoCompleteItem[] results = new AutoCompleteItem[fetchResult.Entities.Count];

                    for (int i = 0; i < fetchResult.Entities.Count; i++)
                    {
                        results[i] = new AutoCompleteItem();
                        results[i].Label = (string)fetchResult.Entities[i].GetAttributeValue(editorOptions.nameAttribute);
                        EntityReference id = new EntityReference(null, null, null);
                        id.Name = results[i].Label;
                        id.LogicalName = fetchResult.Entities[i].LogicalName;
                        id.Id = (Guid)fetchResult.Entities[i].GetAttributeValue(editorOptions.idAttribute);
                        results[i].Value = id;

                        string typeCodeName = fetchResult.Entities[i].LogicalName;

                        // Get the type code from the name to find the icon
                        if (!string.IsNullOrEmpty(editorOptions.typeCodeAttribute))
                        {
                            typeCodeName = fetchResult.Entities[i].GetAttributeValue(editorOptions.typeCodeAttribute).ToString();
                        }

                        results[i].Image = MetadataCache.GetSmallIconUrl(typeCodeName);
                    }

                    response(results);

                    // Disable it now so typing doesn't trigger a search
                    AutoCompleteOptions disableOption = new AutoCompleteOptions();
                    disableOption.MinLength = 100000;
                    _autoComplete.AutoComplete(disableOption);
                });

            };

            options.Source = queryDelegate;
            inputField = _autoComplete.AutoComplete(options);
            ((RenderItemDelegate)Script.Literal("{0}.data('ui-autocomplete')", inputField))._renderItem = delegate(object ul, AutoCompleteItem item)
            {
                return (object)jQuery.Select("<li>").Append( "<a class='sparkle-menu-item'><span class='sparkle-menu-item-img'><img src='" + item.Image + "'/></span><span class='sparkle-menu-item-label'>" + item.Label + "</span></a>").AppendTo((jQueryObject)ul);
            };

            // Add the click binding to show the drop down
            selectButton.Click(delegate(jQueryEvent e)
            {
                AutoCompleteOptions enableOption = new AutoCompleteOptions();
                enableOption.MinLength = 0;
                _autoComplete.AutoComplete(enableOption);
                _autoComplete.AutoComplete(AutoCompleteMethod.Search, inputField.GetValue());

            });

            // Bind return to searching
            _input.Keydown(delegate(jQueryEvent e)
            {
                if (e.Which == 13 && !justSelected) // Return pressed - but we want to do a search not move to the next cell
                {
                    if (inputField.GetValue().Length > 0)
                        selectButton.Click();
                    else
                    {
                        // Set value to null
                        _value = null;
                        return;
                    }
                }
                else if (e.Which == 13)
                {
                    return;
                }
                switch (e.Which)
                {
                    case 13: // Return
                    case 38: // Up - don't navigate - but use the dropdown to select search results
                    case 40: // Down - don't navigate - but use the dropdown to select search results
                        e.PreventDefault();
                        e.StopPropagation();
                        break;

                }
                justSelected = false;
            });
        }
Esempio n. 3
0
        public XrmLookupEditor(EditorArguments args) : base(args)
        {
            _args      = args;
            _container = jQuery.FromHtml("<div ><table class='inline-edit-container' cellspacing='0' cellpadding='0'><tr><td><INPUT type=text class='sparkle-input-inline' /></td><td class='lookup-button-td'><input type=button class='sparkle-lookup-button' /></td></tr></table></div>");
            _container.AppendTo(_args.Container);

            jQueryObject inputField   = _container.Find(".sparkle-input-inline");
            jQueryObject selectButton = _container.Find(".sparkle-lookup-button");

            _input = inputField;
            _input.Focus().Select();

            _autoComplete = inputField.Plugin <AutoCompleteObject>();

            AutoCompleteOptions options = new AutoCompleteOptions();

            options.MinLength = 100000;
            options.Delay     = 0; // TODO- set to something that makes sense

            bool justSelected = false;

            options.Select = delegate(jQueryEvent e, AutoCompleteSelectEvent uiEvent)
            {
                if (_value == null)
                {
                    _value = new EntityReference(null, null, null);
                }

                // Note we assume that the binding has added an array of string items
                AutoCompleteItem item  = (AutoCompleteItem)uiEvent.Item;
                string           value = item.Label;
                _input.Value(value);
                _value.Id          = ((EntityReference)item.Value).Id;
                _value.Name        = ((EntityReference)item.Value).Name;
                _value.LogicalName = ((EntityReference)item.Value).LogicalName;
                justSelected       = true;
                Script.Literal("return false;");
            };
            //
            options.Focus = delegate(jQueryEvent e, AutoCompleteFocusEvent uiEvent)
            {
                // Prevent the value being updated in the text box we scroll through the results
                Script.Literal("return false;");
            };

            XrmLookupEditorOptions editorOptions = (XrmLookupEditorOptions)args.Column.Options;

            // wire up source to CRM search
            Action <AutoCompleteRequest, Action <AutoCompleteItem[]> > queryDelegate = delegate(AutoCompleteRequest request, Action <AutoCompleteItem[]> response)
            {
                // Get the option set values
                editorOptions.queryCommand(request.Term, delegate(EntityCollection fetchResult)
                {
                    AutoCompleteItem[] results = new AutoCompleteItem[fetchResult.Entities.Count];

                    for (int i = 0; i < fetchResult.Entities.Count; i++)
                    {
                        results[i]         = new AutoCompleteItem();
                        results[i].Label   = (string)fetchResult.Entities[i].GetAttributeValue(editorOptions.nameAttribute);
                        EntityReference id = new EntityReference(null, null, null);
                        id.Name            = results[i].Label;
                        id.LogicalName     = fetchResult.Entities[i].LogicalName;
                        id.Id            = (Guid)fetchResult.Entities[i].GetAttributeValue(editorOptions.idAttribute);
                        results[i].Value = id;

                        string typeCodeName = fetchResult.Entities[i].LogicalName;

                        // Get the type code from the name to find the icon
                        if (!string.IsNullOrEmpty(editorOptions.typeCodeAttribute))
                        {
                            typeCodeName = fetchResult.Entities[i].GetAttributeValue(editorOptions.typeCodeAttribute).ToString();
                        }

                        results[i].Image = MetadataCache.GetSmallIconUrl(typeCodeName);
                    }

                    response(results);

                    // Disable it now so typing doesn't trigger a search
                    AutoCompleteOptions disableOption = new AutoCompleteOptions();
                    disableOption.MinLength           = 100000;
                    _autoComplete.AutoComplete(disableOption);
                });
            };

            options.Source = queryDelegate;
            inputField     = _autoComplete.AutoComplete(options);
            ((RenderItemDelegate)Script.Literal("{0}.data('ui-autocomplete')", inputField))._renderItem = delegate(object ul, AutoCompleteItem item)
            {
                return((object)jQuery.Select("<li>").Append("<a class='sparkle-menu-item'><span class='sparkle-menu-item-img'><img src='" + item.Image + "'/></span><span class='sparkle-menu-item-label'>" + item.Label + "</span></a>").AppendTo((jQueryObject)ul));
            };

            // Add the click binding to show the drop down
            selectButton.Click(delegate(jQueryEvent e)
            {
                AutoCompleteOptions enableOption = new AutoCompleteOptions();
                enableOption.MinLength           = 0;
                _autoComplete.AutoComplete(enableOption);
                _autoComplete.AutoComplete(AutoCompleteMethod.Search, inputField.GetValue());
            });

            // Bind return to searching
            _input.Keydown(delegate(jQueryEvent e)
            {
                if (e.Which == 13 && !justSelected) // Return pressed - but we want to do a search not move to the next cell
                {
                    if (inputField.GetValue().Length > 0)
                    {
                        selectButton.Click();
                    }
                    else
                    {
                        // Set value to null
                        _value = null;
                        return;
                    }
                }
                else if (e.Which == 13)
                {
                    return;
                }
                switch (e.Which)
                {
                case 13:     // Return
                case 38:     // Up - don't navigate - but use the dropdown to select search results
                case 40:     // Down - don't navigate - but use the dropdown to select search results
                    e.PreventDefault();
                    e.StopPropagation();
                    break;
                }
                justSelected = false;
            });
        }
Esempio n. 4
0
        public XrmLookupEditor(EditorArguments args) : base(args)
        {
            XrmLookupEditor self = this;

            _args      = args;
            _container = jQuery.FromHtml("<div><table class='inline-edit-container' cellspacing='0' cellpadding='0'><tr><td><INPUT type=text class='sparkle-input-inline' /></td><td class='lookup-button-td'><input type=button class='sparkle-lookup-button' /></td></tr></table></div>");
            _container.AppendTo(_args.Container);

            jQueryObject inputField   = _container.Find(".sparkle-input-inline");
            jQueryObject selectButton = _container.Find(".sparkle-lookup-button");

            _input = inputField;
            _input.Focus().Select();

            _autoComplete = inputField.Plugin <AutoCompleteObject>();

            AutoCompleteOptions options = new AutoCompleteOptions();

            options.Position  = new Dictionary <string, object>("collision", "fit");
            options.MinLength = 100000;
            options.Delay     = 0; // TODO- set to something that makes sense
            XrmLookupEditorOptions editorOptions = (XrmLookupEditorOptions)args.Column.Options;

            bool justSelected = false;

            options.Select = delegate(jQueryEvent e, AutoCompleteSelectEvent uiEvent)
            {
                if (_value == null)
                {
                    _value = new EntityReference(null, null, null);
                }

                // Note we assume that the binding has added an array of string items
                AutoCompleteItem item    = (AutoCompleteItem)uiEvent.Item;
                EntityReference  itemRef = (EntityReference)item.Value;
                if (itemRef.LogicalName == "footerlink")
                {
                    XrmLookupEditorButton button = editorOptions.footerButton;
                    button.OnClick(item);
                }
                else
                {
                    string value = item.Label;
                    _input.Value(value);
                    _value.Id          = itemRef.Id;
                    _value.Name        = itemRef.Name;
                    _value.LogicalName = ((EntityReference)item.Value).LogicalName;
                    justSelected       = true;
                }
                Script.Literal("return false;");
            };

            options.Focus = delegate(jQueryEvent e, AutoCompleteFocusEvent uiEvent)
            {
                // Prevent the value being updated in the text box as we scroll through the results
                Script.Literal("return false;");
            };

            options.Open = delegate(jQueryEvent e, jQueryObject o)
            {
                self._searchOpen = true;
                if (editorOptions.showFooter && totalRecordsReturned > 0)
                {
                    WidgetObject menu = (WidgetObject)Script.Literal("{0}.autocomplete({1})", _input, "widget");
                    AddFooter(menu, totalRecordsReturned);
                }
            };

            options.Close = delegate(jQueryEvent e, jQueryObject o)
            {
                self._searchOpen = false;
                WidgetObject menu   = (WidgetObject)Script.Literal("{0}.autocomplete({1})", _input, "widget");
                jQueryObject footer = menu.Next();
                if (footer.Length > 0 || footer.HasClass("sparkle-menu-footer"))
                {
                    footer.Hide();
                }
            };

            // If there multiple names, add them to the columnAttributes
            string[] columns = editorOptions.nameAttribute.Split(",");

            if (columns.Length > 1)
            {
                editorOptions.columns       = columns;
                editorOptions.nameAttribute = columns[0];
            }

            // wire up source to CRM search
            Action <AutoCompleteRequest, Action <AutoCompleteItem[]> > queryDelegate = delegate(AutoCompleteRequest request, Action <AutoCompleteItem[]> response)
            {
                // Get the option set values
                editorOptions.queryCommand(request.Term, delegate(EntityCollection fetchResult)
                {
                    if (fetchResult.TotalRecordCount > fetchResult.Entities.Count)
                    {
                        totalRecordsReturned = fetchResult.TotalRecordCount;
                    }
                    else
                    {
                        totalRecordsReturned = fetchResult.Entities.Count;
                    }

                    int recordsFound             = fetchResult.Entities.Count;
                    bool noRecordsFound          = recordsFound == 0;
                    XrmLookupEditorButton button = editorOptions.footerButton;
                    bool footerButton            = (button != null);

                    AutoCompleteItem[] results = new AutoCompleteItem[recordsFound + (footerButton ? 1 : 0) + (noRecordsFound ? 1 :0)];

                    for (int i = 0; i < recordsFound; i++)
                    {
                        results[i]         = new AutoCompleteItem();
                        results[i].Label   = (string)fetchResult.Entities[i].GetAttributeValue(editorOptions.nameAttribute);
                        EntityReference id = new EntityReference(null, null, null);
                        id.Name            = results[i].Label;
                        id.LogicalName     = fetchResult.Entities[i].LogicalName;
                        id.Id            = (Guid)fetchResult.Entities[i].GetAttributeValue(editorOptions.idAttribute);
                        results[i].Value = id;
                        XrmLookupBinding.GetExtraColumns(editorOptions.columns, fetchResult, results, i);
                        string typeCodeName = fetchResult.Entities[i].LogicalName;

                        // Get the type code from the name to find the icon
                        if (!string.IsNullOrEmpty(editorOptions.typeCodeAttribute))
                        {
                            typeCodeName = fetchResult.Entities[i].GetAttributeValue(editorOptions.typeCodeAttribute).ToString();
                        }

                        if (editorOptions.showImage)
                        {
                            results[i].Image = MetadataCache.GetSmallIconUrl(typeCodeName);
                        }
                    }

                    int itemsCount = recordsFound;
                    if (noRecordsFound)
                    {
                        AutoCompleteItem noRecordsItem = new AutoCompleteItem();
                        noRecordsItem.Label            = SparkleResourceStrings.NoRecordsFound;
                        results[itemsCount]            = noRecordsItem;
                        itemsCount++;
                    }

                    if (footerButton)
                    {
                        // Add the add new
                        AutoCompleteItem addNewLink = new AutoCompleteItem();
                        addNewLink.Label            = button.Label;
                        addNewLink.Image            = button.Image;
                        addNewLink.ColumnValues     = null;
                        addNewLink.Value            = new Entity("footerlink");
                        results[itemsCount]         = addNewLink;
                    }
                    response(results);

                    // Disable it now so typing doesn't trigger a search
                    AutoCompleteOptions disableOption = new AutoCompleteOptions();
                    disableOption.MinLength           = 100000;
                    _autoComplete.AutoComplete(disableOption);
                });
            };

            options.Source = queryDelegate;
            inputField     = _autoComplete.AutoComplete(options);
            RenderItemDelegate autoCompleteDelegates = ((RenderItemDelegate)Script.Literal("{0}.data('ui-autocomplete')", inputField));

            autoCompleteDelegates._renderItem = delegate(object ul, AutoCompleteItem item)
            {
                if (item.Value == item.Label)
                {
                    return((object)jQuery.Select("<li class='ui-state-disabled'>" + item.Label + "</li>").AppendTo((jQueryObject)ul));
                }

                string itemHtml = "<a class='sparkle-menu-item'>";
                // Allow for no image by passing false to 'ShowImage' on the XrmLookupEditorOptions options
                if (item.Image != null)
                {
                    itemHtml += "<span class='sparkle-menu-item-img'><img src='" + item.Image + "'/></span>";
                }
                itemHtml += "<span class='sparkle-menu-item-label'>" + item.Label + "</span><br/>";
                if (item.ColumnValues != null && item.ColumnValues.Length > 0)
                {
                    foreach (string value in item.ColumnValues)
                    {
                        itemHtml += "<span class='sparkle-menu-item-moreinfo'>" + value + "</span>";
                    }
                }
                itemHtml += "</a>";
                return((object)jQuery.Select("<li>").Append(itemHtml).AppendTo((jQueryObject)ul));
            };

            // Add the click binding to show the drop down
            selectButton.Click(delegate(jQueryEvent e)
            {
                AutoCompleteOptions enableOption = new AutoCompleteOptions();
                enableOption.MinLength           = 0;
                _autoComplete.AutoComplete(enableOption);
                _autoComplete.AutoComplete(AutoCompleteMethod.Search, inputField.GetValue());
            });

            // Bind return to searching
            _input.Keydown(delegate(jQueryEvent e)
            {
                if (e.Which == 13 && !justSelected) // Return pressed - but we want to do a search not move to the next cell
                {
                    if (inputField.GetValue().Length > 0)
                    {
                        selectButton.Click();
                    }
                    else
                    {
                        // Set value to null
                        _value = null;
                        return;
                    }
                }
                else if (e.Which == 13)
                {
                    return;
                }
                if (self._searchOpen)
                {
                    switch (e.Which)
                    {
                    case 9:
                    case 13:     // Return
                    case 38:     // Up - don't navigate - but use the dropdown to select search results
                    case 40:     // Down - don't navigate - but use the dropdown to select search results
                        e.PreventDefault();
                        e.StopPropagation();
                        break;
                    }
                }
                else
                {
                    switch (e.Which)
                    {
                    case 13:     // Return
                        e.PreventDefault();
                        e.StopPropagation();
                        break;
                    }
                }
                justSelected = false;
            });
        }
Esempio n. 5
0
        public override void Init(System.Html.Element element, Func<object> valueAccessor, Func<System.Collections.Dictionary> allBindingsAccessor, object viewModel, object context)
        {
            XrmLookupEditorButton footerButton = (XrmLookupEditorButton)allBindingsAccessor()["footerButton"];
            bool showFooter = (bool)allBindingsAccessor()["showFooter"];
            jQueryObject container = jQuery.FromElement(element);
            jQueryObject inputField = container.Find(".sparkle-input-lookup-part");
            jQueryObject selectButton = container.Find(".sparkle-input-lookup-button-part");
            EntityReference _value = new EntityReference(null, null, null);
            AutoCompleteOptions options = new AutoCompleteOptions();
            options.MinLength = 100000; // Don't enable type down - use search button (or return)
            options.Delay = 0;
            options.Position = new Dictionary<string, object>("collision", "fit");
            bool justSelected = false;
            int totalRecordsReturned = 0;
            Action<AutoCompleteItem,bool> setValue = delegate(AutoCompleteItem item,bool setFocus)
            {
                if (_value == null) _value = new EntityReference(null, null, null);
                string value = item.Label;
                inputField.Value(value);
                _value.Id = ((Guid)item.Value);
                _value.Name = item.Label;
                _value.LogicalName = (string)item.Data;
                justSelected = true;
                TrySetObservable(valueAccessor, inputField, _value, setFocus);
            };

            // Set the value when selected
            options.Select = delegate(jQueryEvent e, AutoCompleteSelectEvent uiEvent)
            {
                // Note we assume that the binding has added an array of string items
                AutoCompleteItem item = (AutoCompleteItem)uiEvent.Item;
                string data = ((string)item.Data);
                if (data == "footerlink" || data==null)
                {
                    footerButton.OnClick(item);
                    e.PreventDefault();
                    e.StopImmediatePropagation();
                    Script.Literal("return false;");
                }
                else
                {
                    setValue(item, true);
                    Script.Literal("return false;");
                }
            };

            options.Open = delegate(jQueryEvent e, jQueryObject o)
            {

                if (showFooter && totalRecordsReturned>0)
                {
                    WidgetObject menu = (WidgetObject)Script.Literal("{0}.autocomplete({1})", inputField, "widget");
                    XrmLookupEditor.AddFooter(menu, totalRecordsReturned);
                }
            };

            options.Close = delegate(jQueryEvent e, jQueryObject o)
            {

                WidgetObject menu = (WidgetObject)Script.Literal("{0}.autocomplete({1})", inputField, "widget");
                jQueryObject footer = menu.Next();
                if (footer.Length > 0 || footer.HasClass("sparkle-menu-footer"))
                {
                    footer.Hide();
                }
            };
            // Get the query command
            Action<string, Action<EntityCollection>> queryCommand = (Action<string, Action<EntityCollection>>)((object)allBindingsAccessor()["queryCommand"]);
            string nameAttribute = ((string)allBindingsAccessor()["nameAttribute"]);
            string idAttribute = ((string)allBindingsAccessor()["idAttribute"]);
            string typeCodeAttribute = ((string)allBindingsAccessor()["typeCodeAttribute"]);
            string[] columnAttributes = null;
            // If there multiple names, add them to the columnAttributes
            string[] columns = nameAttribute.Split(",");

            if (columns.Length > 1)
            {
                columnAttributes = columns;
                nameAttribute = columnAttributes[0];
            }

            // wire up source to CRM search
            Action<AutoCompleteRequest, Action<AutoCompleteItem[]>> queryDelegate = delegate(AutoCompleteRequest request, Action<AutoCompleteItem[]> response)
            {
                Action<EntityCollection> queryCallBack = delegate(EntityCollection fetchResult)
                    {
                        int recordsFound = fetchResult.Entities.Count;
                        bool noRecordsFound = recordsFound == 0;
                        AutoCompleteItem[] results = new AutoCompleteItem[recordsFound + (footerButton!=null ? 1 : 0) + (noRecordsFound ? 1 : 0)];

                        for (int i = 0; i < recordsFound; i++)
                        {
                            results[i] = new AutoCompleteItem();
                            results[i].Label = (string)fetchResult.Entities[i].GetAttributeValue(nameAttribute);
                            results[i].Value = fetchResult.Entities[i].GetAttributeValue(idAttribute);
                            results[i].Data = fetchResult.Entities[i].LogicalName;
                            GetExtraColumns(columnAttributes, fetchResult, results, i);

                            string typeCodeName = fetchResult.Entities[i].LogicalName;
                            // Get the type code from the name to find the icon
                            if (!string.IsNullOrEmpty(typeCodeAttribute))
                            {
                                typeCodeName = fetchResult.Entities[i].GetAttributeValue(typeCodeAttribute).ToString();
                            }

                            results[i].Image = MetadataCache.GetSmallIconUrl(typeCodeName);
                        }

                        if (fetchResult.TotalRecordCount > fetchResult.Entities.Count)
                        {
                            totalRecordsReturned = fetchResult.TotalRecordCount;
                        }
                        else
                        {
                            totalRecordsReturned = fetchResult.Entities.Count;
                        }
                        int itemsCount = recordsFound;
                        if (noRecordsFound)
                        {
                            AutoCompleteItem noRecordsItem = new AutoCompleteItem();
                            noRecordsItem.Label = SparkleResourceStrings.NoRecordsFound;
                            results[itemsCount] = noRecordsItem;
                            itemsCount++;
                        }
                        if (footerButton != null)
                        {
                            // Add the add new
                            AutoCompleteItem addNewLink = new AutoCompleteItem();
                            addNewLink.Label = footerButton.Label;
                            addNewLink.Image = footerButton.Image;
                            addNewLink.ColumnValues = null;
                            addNewLink.Data = "footerlink";
                            results[itemsCount] = addNewLink;
                        }
                        response(results);

                        // Disable it now so typing doesn't trigger a search
                        AutoCompleteOptions disableOption = new AutoCompleteOptions();
                        disableOption.MinLength = 100000;
                        inputField.Plugin<AutoCompleteObject>().AutoComplete(disableOption);
                    };

                // Call the function with the correct 'this' context
                Script.Literal("{0}.call({1}.$parent,{2},{3})",queryCommand, context, request.Term, queryCallBack);
            };

            options.Source = queryDelegate;
            options.Focus = delegate(jQueryEvent e, AutoCompleteFocusEvent uiEvent)
            {
                // Prevent the value being updated in the text box we scroll through the results
                Script.Literal("return false;");
            };
            inputField = inputField.Plugin<AutoCompleteObject>().AutoComplete(options);

            // Set render template
            ((RenderItemDelegate)Script.Literal("{0}.data('ui-autocomplete')", inputField))._renderItem = delegate(object ul, AutoCompleteItem item)
            {
                if (item.Data==null)
                {
                    return (object)jQuery.Select("<li class='ui-state-disabled'>" + item.Label + "</li>").AppendTo((jQueryObject)ul);
                }

                string html = "<a class='sparkle-menu-item'><span class='sparkle-menu-item-img'>";
                if (item.Image!=null)
                {
                    html += @"<img src='" + item.Image + "'/>";
                }
                html += @"</span><span class='sparkle-menu-item-label'>" + item.Label + "</span><br>";

                if (item.ColumnValues != null && item.ColumnValues.Length > 0)
                {
                    foreach (string value in item.ColumnValues)
                    {
                        html += "<span class='sparkle-menu-item-moreinfo'>" + value + "</span>";
                    }
                }
                html += "</a>";
                return (object)jQuery.Select("<li>").Append(html).AppendTo((jQueryObject)ul);

            };

            // Add the click binding to show the drop down
            selectButton.Click(delegate(jQueryEvent e)
            {
                AutoCompleteOptions enableOption = new AutoCompleteOptions();
                enableOption.MinLength = 0;
                inputField.Focus();
                inputField.Plugin<AutoCompleteObject>().AutoComplete(enableOption);
                inputField.Plugin<AutoCompleteObject>().AutoComplete(AutoCompleteMethod.Search);
            });

            // handle the field changing
            inputField.Change(delegate(jQueryEvent e)
            {
                string inputValue = inputField.GetValue();
                if (inputValue != _value.Name)
                {
                    // The name is different from the name of the lookup reference
                    // search to see if we can auto resolve it
                    TrySetObservable(valueAccessor, inputField, null,false);
                    AutoCompleteRequest lookup = new AutoCompleteRequest();
                    lookup.Term = inputValue;
                    Action<AutoCompleteItem[]> lookupResults = delegate(AutoCompleteItem[] results)
                    {
                        int selectableItems =0;
                        // If there is only one, then auto-set
                        if (results != null)
                        {
                            foreach (AutoCompleteItem item in results)
                            {
                                if (isItemSelectable(item))
                                {
                                    selectableItems++;
                                }
                                if (selectableItems > 2)
                                    break;
                            }
                        }

                        if (selectableItems == 1)
                        {
                            // There is only a single value so set it now
                            setValue(results[0], false);
                        }
                        else
                        {
                            inputField.Value(String.Empty);
                        }
                    };

                    queryDelegate(lookup, lookupResults);
                }
            });

            Action disposeCallBack = delegate()
            {
                if ((bool)Script.Literal("$({0}).data('ui-autocomplete')!=undefined", inputField))
                {
                    Script.Literal("$({0}).autocomplete(\"destroy\")", inputField);
                }
            };

            //handle disposal (if KO removes by the template binding)
            Script.Literal("ko.utils.domNodeDisposal.addDisposeCallback({0}, {1})", element, (object)disposeCallBack);
            Knockout.BindingHandlers["validationCore"].Init(element, valueAccessor, allBindingsAccessor, null, null);

            // Bind return to searching
            inputField.Keydown(delegate(jQueryEvent e)
            {
                if (e.Which == 13 && !justSelected) // Return pressed - but we want to do a search not move to the next cell
                {
                    selectButton.Click();
                }
                else if (e.Which == 13)
                {
                    return;
                }
                switch (e.Which)
                {
                    case 13: // Return
                    case 38: // Up - don't navigate - but use the dropdown to select search results
                    case 40: // Down - don't navigate - but use the dropdown to select search results
                        e.PreventDefault();
                        e.StopPropagation();
                        break;
                }
                justSelected = false;
            });

            //Script.Literal("return { controlsDescendantBindings: true };");
        }
Esempio n. 6
0
 private static bool isItemSelectable(AutoCompleteItem item)
 {
     string data = (string)item.Data;
     return data != null && data != "footerlink";
 }
Esempio n. 7
0
        public override void Init(System.Html.Element element, Func<object> valueAccessor, Func<System.Collections.Dictionary> allBindingsAccessor, object viewModel, object context)
        {
            jQueryObject container = jQuery.FromElement(element);
            jQueryObject inputField = container.Find(".sparkle-input-lookup-part");
            jQueryObject selectButton = container.Find(".sparkle-input-lookup-button-part");
            EntityReference _value = new EntityReference(null, null, null);
            AutoCompleteOptions options = new AutoCompleteOptions();
            options.MinLength = 100000; // Don't enable type down - use search button (or return)
            options.Delay = 0;
            options.Position = new Dictionary<string, object>("collision", "fit");

            bool justSelected = false;

            // Set the value when selected
            options.Select = delegate(jQueryEvent e, AutoCompleteSelectEvent uiEvent)
            {

                // Note we assume that the binding has added an array of string items
                AutoCompleteItem item = (AutoCompleteItem)uiEvent.Item;
                if (_value == null) _value = new EntityReference(null, null, null);
                string value = item.Label;
                inputField.Value(value);
                _value.Id = ((Guid)item.Value);
                _value.Name = item.Label;
                _value.LogicalName = (string)item.Data;
                justSelected = true;
                TrySetObservable(valueAccessor, inputField, _value);
                Script.Literal("return false;");

            };

            // Get the query command
            Action<string, Action<EntityCollection>> queryCommand = (Action<string, Action<EntityCollection>>)((object)allBindingsAccessor()["queryCommand"]);
            string nameAttribute = ((string)allBindingsAccessor()["nameAttribute"]);
            string idAttribute = ((string)allBindingsAccessor()["idAttribute"]);
            string typeCodeAttribute = ((string)allBindingsAccessor()["typeCodeAttribute"]);
            string[] columnAttributes = null;
            // If there multiple names, add them to the columnAttributes
            string[] columns = nameAttribute.Split(",");

            if (columns.Length > 1)
            {
                columnAttributes = columns;
                nameAttribute = columnAttributes[0];
            }

            // wire up source to CRM search
            Action<AutoCompleteRequest, Action<AutoCompleteItem[]>> queryDelegate = delegate(AutoCompleteRequest request, Action<AutoCompleteItem[]> response)
            {
                Action<EntityCollection> queryCallBack = delegate(EntityCollection fetchResult)
                    {
                        AutoCompleteItem[] results = new AutoCompleteItem[fetchResult.Entities.Count];

                        for (int i = 0; i < fetchResult.Entities.Count; i++)
                        {
                            results[i] = new AutoCompleteItem();
                            results[i].Label = (string)fetchResult.Entities[i].GetAttributeValue(nameAttribute);
                            results[i].Value = fetchResult.Entities[i].GetAttributeValue(idAttribute);
                            results[i].Data = fetchResult.Entities[i].LogicalName;
                            GetExtraColumns(columnAttributes, fetchResult, results, i);

                            string typeCodeName = fetchResult.Entities[i].LogicalName;
                            // Get the type code from the name to find the icon
                            if (!string.IsNullOrEmpty(typeCodeAttribute))
                            {
                                typeCodeName = fetchResult.Entities[i].GetAttributeValue(typeCodeAttribute).ToString();
                            }

                            results[i].Image = MetadataCache.GetSmallIconUrl(typeCodeName);
                        }

                        response(results);

                        // Disable it now so typing doesn't trigger a search
                        AutoCompleteOptions disableOption = new AutoCompleteOptions();
                        disableOption.MinLength = 100000;
                        inputField.Plugin<AutoCompleteObject>().AutoComplete(disableOption);
                    };

                // Call the function with the correct 'this' context
                Script.Literal("{0}.call({1}.$parent,{2},{3})",queryCommand, context, request.Term, queryCallBack);

            };

            options.Source = queryDelegate;
            options.Focus = delegate(jQueryEvent e, AutoCompleteFocusEvent uiEvent)
            {
                // Prevent the value being updated in the text box we scroll through the results
                Script.Literal("return false;");
            };
            inputField = inputField.Plugin<AutoCompleteObject>().AutoComplete(options);

            // Set render template
            ((RenderItemDelegate)Script.Literal("{0}.data('ui-autocomplete')", inputField))._renderItem = delegate(object ul, AutoCompleteItem item)
            {
                string html = "<a class='sparkle-menu-item'><span class='sparkle-menu-item-img'><img src='" + item.Image + "'/></span><span class='sparkle-menu-item-label'>" + item.Label + "</span><br>";
                if (item.ColumnValues != null && item.ColumnValues.Length > 0)
                {
                    foreach (string value in item.ColumnValues)
                    {
                        html += "<span class='sparkle-menu-item-moreinfo'>" + value + "</span>";
                    }
                }
                html += "</a>";
                return (object)jQuery.Select("<li>").Append(html).AppendTo((jQueryObject)ul);

            };

            // Add the click binding to show the drop down
            selectButton.Click(delegate(jQueryEvent e)
            {
                AutoCompleteOptions enableOption = new AutoCompleteOptions();
                enableOption.MinLength = 0;
                inputField.Focus();
                inputField.Plugin<AutoCompleteObject>().AutoComplete(enableOption);

                inputField.Plugin<AutoCompleteObject>().AutoComplete(AutoCompleteMethod.Search);
            });

            // handle the field changing
            inputField.Change(delegate(jQueryEvent e)
            {
                if (inputField.GetValue() != _value.Name)
                    TrySetObservable(valueAccessor, inputField, null);
            });

            Action disposeCallBack = delegate()
            {
                if ((bool)Script.Literal("$({0}).data('ui-autocomplete')!=undefined", inputField))
                {
                    //inputField.Plugin<AutoCompleteObject>().AutoComplete(AutoCompleteMethod.Destroy);
                    Script.Literal("$({0}).autocomplete(\"destroy\")", inputField);
                }
            };

            //handle disposal (if KO removes by the template binding)
            Script.Literal("ko.utils.domNodeDisposal.addDisposeCallback({0}, {1})", element, (object)disposeCallBack);
            Knockout.BindingHandlers["validationCore"].Init(element, valueAccessor, allBindingsAccessor, null, null);

            // Bind return to searching
            inputField.Keydown(delegate(jQueryEvent e)
            {

                if (e.Which == 13 && !justSelected) // Return pressed - but we want to do a search not move to the next cell
                {
                    selectButton.Click();
                }
                else if (e.Which == 13)
                {
                    return;
                }
                switch (e.Which)
                {
                    case 13: // Return
                    case 38: // Up - don't navigate - but use the dropdown to select search results
                    case 40: // Down - don't navigate - but use the dropdown to select search results
                        e.PreventDefault();
                        e.StopPropagation();
                        break;

                }
                justSelected = false;
            });

            //Script.Literal("return { controlsDescendantBindings: true };");
        }
Esempio n. 8
0
        public XrmLookupEditor(EditorArguments args)
            : base(args)
        {
            XrmLookupEditor self = this;

            _args = args;
            _container = jQuery.FromHtml("<div><table class='inline-edit-container' cellspacing='0' cellpadding='0'><tr><td><INPUT type=text class='sparkle-input-inline' /></td><td class='lookup-button-td'><input type=button class='sparkle-lookup-button' /></td></tr></table></div>");
            _container.AppendTo(_args.Container);

            jQueryObject inputField = _container.Find(".sparkle-input-inline");
            jQueryObject selectButton = _container.Find(".sparkle-lookup-button");
            _input = inputField;
            _input.Focus().Select();

            _autoComplete = inputField.Plugin<AutoCompleteObject>();

            AutoCompleteOptions options = new AutoCompleteOptions();
            options.Position = new Dictionary<string, object>("collision", "fit");
            options.MinLength = 100000;
            options.Delay = 0; // TODO- set to something that makes sense
            XrmLookupEditorOptions editorOptions = (XrmLookupEditorOptions)args.Column.Options;

            bool justSelected = false;
            options.Select = delegate(jQueryEvent e, AutoCompleteSelectEvent uiEvent)
            {
                if (_value == null) _value = new EntityReference(null,null,null);

                // Note we assume that the binding has added an array of string items
                AutoCompleteItem item = (AutoCompleteItem)uiEvent.Item;
                EntityReference itemRef = (EntityReference)item.Value;
                if (itemRef.LogicalName == "footerlink")
                {
                    XrmLookupEditorButton button = editorOptions.footerButton;
                    button.OnClick(item);
                }
                else
                {
                    string value = item.Label;
                    _input.Value(value);
                    _value.Id = itemRef.Id;
                    _value.Name = itemRef.Name;
                    _value.LogicalName = ((EntityReference)item.Value).LogicalName;
                    justSelected = true;
                }
                Script.Literal("return false;");

            };

            options.Focus = delegate(jQueryEvent e, AutoCompleteFocusEvent uiEvent)
            {
                // Prevent the value being updated in the text box as we scroll through the results
                Script.Literal("return false;");
            };

            options.Open = delegate(jQueryEvent e, jQueryObject o)
            {
                self._searchOpen = true;
                if (editorOptions.showFooter && totalRecordsReturned>0)
                {
                    WidgetObject menu = (WidgetObject)Script.Literal("{0}.autocomplete({1})", _input, "widget");
                    AddFooter(menu,totalRecordsReturned);
                }
            };

            options.Close = delegate(jQueryEvent e, jQueryObject o)
            {
                self._searchOpen = false;
                WidgetObject menu = (WidgetObject)Script.Literal("{0}.autocomplete({1})", _input, "widget");
                jQueryObject footer = menu.Next();
                if (footer.Length > 0 || footer.HasClass("sparkle-menu-footer"))
                {
                    footer.Hide();
                }
            };

            // If there multiple names, add them to the columnAttributes
            string[] columns = editorOptions.nameAttribute.Split(",");

            if (columns.Length > 1)
            {
                editorOptions.columns = columns;
                editorOptions.nameAttribute = columns[0];
            }

            // wire up source to CRM search
            Action<AutoCompleteRequest, Action<AutoCompleteItem[]>> queryDelegate = delegate(AutoCompleteRequest request, Action<AutoCompleteItem[]> response)
            {
                 // Get the option set values
                editorOptions.queryCommand(request.Term, delegate(EntityCollection fetchResult)
                {
                    if (fetchResult.TotalRecordCount > fetchResult.Entities.Count)
                    {
                        totalRecordsReturned = fetchResult.TotalRecordCount;
                    }
                    else
                    {
                        totalRecordsReturned = fetchResult.Entities.Count;
                    }

                    int recordsFound = fetchResult.Entities.Count;
                    bool noRecordsFound = recordsFound == 0;
                    XrmLookupEditorButton button = editorOptions.footerButton;
                    bool footerButton = (button != null);

                    AutoCompleteItem[] results = new AutoCompleteItem[recordsFound + (footerButton ? 1 : 0) + (noRecordsFound ? 1 :0) ];

                    for (int i = 0; i < recordsFound; i++)
                    {
                        results[i] = new AutoCompleteItem();
                        results[i].Label = (string)fetchResult.Entities[i].GetAttributeValue(editorOptions.nameAttribute);
                        EntityReference id = new EntityReference(null, null, null);
                        id.Name = results[i].Label;
                        id.LogicalName = fetchResult.Entities[i].LogicalName;
                        id.Id = (Guid)fetchResult.Entities[i].GetAttributeValue(editorOptions.idAttribute);
                        results[i].Value = id;
                        XrmLookupBinding.GetExtraColumns(editorOptions.columns, fetchResult, results, i);
                        string typeCodeName = fetchResult.Entities[i].LogicalName;

                        // Get the type code from the name to find the icon
                        if (!string.IsNullOrEmpty(editorOptions.typeCodeAttribute))
                        {
                            typeCodeName = fetchResult.Entities[i].GetAttributeValue(editorOptions.typeCodeAttribute).ToString();
                        }

                        if (editorOptions.showImage)
                        {
                            results[i].Image = MetadataCache.GetSmallIconUrl(typeCodeName);
                        }
                    }

                    int itemsCount = recordsFound;
                    if (noRecordsFound)
                    {
                        AutoCompleteItem noRecordsItem = new AutoCompleteItem();
                        noRecordsItem.Label = SparkleResourceStrings.NoRecordsFound;
                        results[itemsCount] = noRecordsItem;
                        itemsCount++;
                    }

                    if (footerButton)
                    {
                        // Add the add new
                        AutoCompleteItem addNewLink = new AutoCompleteItem();
                        addNewLink.Label = button.Label;
                        addNewLink.Image = button.Image;
                        addNewLink.ColumnValues = null;
                        addNewLink.Value = new Entity("footerlink");
                        results[itemsCount] = addNewLink;
                    }
                    response(results);

                    // Disable it now so typing doesn't trigger a search
                    AutoCompleteOptions disableOption = new AutoCompleteOptions();
                    disableOption.MinLength = 100000;
                    _autoComplete.AutoComplete(disableOption);
                });

            };

            options.Source = queryDelegate;
            inputField = _autoComplete.AutoComplete(options);
            RenderItemDelegate autoCompleteDelegates = ((RenderItemDelegate)Script.Literal("{0}.data('ui-autocomplete')", inputField));
            autoCompleteDelegates._renderItem = delegate(object ul, AutoCompleteItem item)
            {
                if(item.Value==item.Label)
                {
                    return (object)jQuery.Select("<li class='ui-state-disabled'>"+item.Label+"</li>").AppendTo((jQueryObject)ul);
                }

                string itemHtml = "<a class='sparkle-menu-item'>";
                // Allow for no image by passing false to 'ShowImage' on the XrmLookupEditorOptions options
                if (item.Image != null)
                {
                    itemHtml += "<span class='sparkle-menu-item-img'><img src='" + item.Image + "'/></span>";
                }
                itemHtml += "<span class='sparkle-menu-item-label'>" + item.Label + "</span><br/>";
                if (item.ColumnValues != null && item.ColumnValues.Length > 0)
                {
                    foreach (string value in item.ColumnValues)
                    {
                        itemHtml += "<span class='sparkle-menu-item-moreinfo'>" + value + "</span>";
                    }
                }
                itemHtml += "</a>";
                return (object)jQuery.Select("<li>").Append(itemHtml).AppendTo((jQueryObject)ul);
            };

            // Add the click binding to show the drop down
            selectButton.Click(delegate(jQueryEvent e)
            {
                AutoCompleteOptions enableOption = new AutoCompleteOptions();
                enableOption.MinLength = 0;
                _autoComplete.AutoComplete(enableOption);
                _autoComplete.AutoComplete(AutoCompleteMethod.Search, inputField.GetValue());

            });

            // Bind return to searching
            _input.Keydown(delegate(jQueryEvent e)
            {
                if (e.Which == 13 && !justSelected) // Return pressed - but we want to do a search not move to the next cell
                {
                    if (inputField.GetValue().Length > 0)
                        selectButton.Click();
                    else
                    {
                        // Set value to null
                        _value = null;
                        return;
                    }
                }
                else if (e.Which == 13)
                {
                    return;
                }
                if (self._searchOpen)
                {
                    switch (e.Which)
                    {
                        case 9:
                        case 13: // Return
                        case 38: // Up - don't navigate - but use the dropdown to select search results
                        case 40: // Down - don't navigate - but use the dropdown to select search results
                            e.PreventDefault();
                            e.StopPropagation();
                            break;
                    }
                }
                else
                {
                    switch (e.Which)
                    {
                        case 13: // Return
                            e.PreventDefault();
                            e.StopPropagation();
                            break;

                    }
                }
                justSelected = false;
            });
        }
Esempio n. 9
0
        /// <summary>
        /// Extracts additional column display values from the search result
        /// The name attribute can now be a column separated list of attribute logical names
        /// </summary>
        /// <param name="columnAttributes"></param>
        /// <param name="fetchResult"></param>
        /// <param name="results"></param>
        /// <param name="i"></param>
        internal static void GetExtraColumns(string[] columnAttributes, EntityCollection fetchResult, AutoCompleteItem[] results, int i)
        {
            if (columnAttributes != null)
            {
                List<string> columnValues = new List<string>();
                bool first = true;
                // Get the additional column attributes to display
                foreach (string attribute in columnAttributes)
                {
                    if (first)
                    {
                        first = false;
                        continue;
                    }
                    string value = "";
                    Entity record = fetchResult.Entities[i];

                    if (record.FormattedValues.ContainsKey(attribute + "name"))
                    {
                        value = record.FormattedValues[attribute + "name"];
                    }
                    else
                    {
                        value = record.GetAttributeValue(attribute).ToString();
                    }
                    columnValues.Add(value);

                }
                results[i].ColumnValues = (string[])columnValues;
            }
        }