/// <summary> /// Add elements to the set of matched elements. /// </summary> /// /// <param name="elements"> /// The elements to add. /// </param> /// /// <returns> /// A new CQ object. /// </returns> /// /// <url> /// http://api.jquery.com/add/ /// </url> public CQ Add(IEnumerable <IDomObject> elements) { CQ res = NewInstance(this); res.AddSelection(elements); return(res); }
private CQ FindImpl(Selector selector) { CQ csq = New(); csq.AddSelection(selector.Select(Document, this)); csq.Selector = selector; return(csq); }
private CQ FindImpl(Selector selector) { CQ csq = NewCqInDomain(); var selection = selector.ToContextSelector().Select(Document, this); csq.AddSelection(selection); csq.Selector = selector; return(csq); }
/// <summary> /// Selects then zero-based nth cells (th and td) from all rows in any matched tables. This will /// most likely no do what you expect if the table has colspan cells. /// </summary> /// /// <param name="column"> /// The zero-based index of the column to target. /// </param> /// /// <returns> /// A new CQ object containing all the th and td cells in the specified column. /// </returns> public CQ GetTableColumn(int column) { CQ result = New(); foreach (var el in FilterElements(this, "table")) { result.AddSelection(el.Cq().Find(String.Format("tr>th:eq({0}), tr>td:eq({0})", column))); } return(result); }
/// <summary> /// Create a new CQ object from a single element. Unlike the constructor method <see cref="CsQuery.CQ"/> /// this new objet is not bound to any context from the element. /// </summary> /// /// <param name="element"> /// The element to wrap /// </param> /// /// <returns> /// A new CQ object /// </returns> public static CQ Create(IDomObject element) { CQ csq = new CQ(); if (element is IDomDocument) { csq.Document = (IDomDocument)element; csq.AddSelection(csq.Document.ChildNodes); } else { csq.CreateNewFragment(Objects.Enumerate(element)); } return csq; }
/// <summary> /// Given a table header or cell, returns all members of the column in the table. This will most /// likely not work as you would expect if there are colspan cells. /// </summary> /// /// <returns> /// A new CQ object containing all the th and td cells in the specified column. /// </returns> public CQ GetTableColumn() { var els = this.Filter("th,td"); CQ result = New(); foreach (var el in els) { var elCq = el.Cq(); int colIndex = elCq.Index(); result.AddSelection(elCq.Closest("table").GetTableColumn(colIndex)); } return(result); }
/// <summary> /// Create a new CQ object from a single element. Unlike the constructor method <see cref="CsQuery.CQ"/> /// this new objet is not bound to any context from the element. /// </summary> /// /// <param name="element"> /// The element to wrap /// </param> /// /// <returns> /// A new CQ object /// </returns> public static CQ Create(IDomObject element) { CQ csq = new CQ(); if (element is IDomDocument) { csq.Document = (IDomDocument)element; csq.AddSelection(csq.Document.ChildNodes); } else { csq.CreateNewFragment(Objects.Enumerate(element)); } return(csq); }
/// <summary> /// Get the first ancestor element of any element in the seleciton set that is also one of the /// elements in the sequence passed by parameter, beginning at the current element and /// progressing up through the DOM tree. /// </summary> /// /// <param name="elements"> /// The elements to target. /// </param> /// /// <returns> /// A new CQ object. /// </returns> /// /// <url> /// http://api.jquery.com/closest/#closest1 /// </url> public CQ Closest(IEnumerable <IDomObject> elements) { // Use a hashset to operate faster - since we already have one for the selection set anyway HashSet <IDomObject> elementSet = new HashSet <IDomObject>(elements); CQ csq = NewCqInDomain(); foreach (var el in SelectionSet) { var search = el; while (search != null) { if (elementSet.Contains(search)) { csq.AddSelection(search); search = null; continue; } search = search.ParentNode; } } return(csq); }
/// <summary> /// Configures a new instance for a sequence of elements and an existing context. /// </summary> /// /// <param name="elements"> /// A sequence of elements. /// </param> /// <param name="context"> /// The context. /// </param> private void ConfigureNewInstance(CQ dom,IEnumerable<IDomObject> elements, CQ context) { dom.CsQueryParent = context; dom.AddSelection(elements); }
/// <summary> /// Insert every element in the selection at or after the index of each target (adding offset to /// the index). If there is more than one target, the a clone is made of the selection for the /// 2nd and later targets. /// </summary> /// /// <exception cref="InvalidOperationException"> /// Thrown if attempting to add elements to a disconnected (parentless) sequence /// </exception> /// /// <param name="target"> /// The target element /// </param> /// <param name="offset"> /// The offset from the target at which to begin inserting /// </param> /// <param name="insertedElements"> /// [out] The inserted elements. /// </param> /// /// <returns> /// The current CQ object /// </returns> protected CQ InsertAtOffset(IEnumerable<IDomObject> target, int offset, out CQ insertedElements) { CQ cq = target as CQ; SelectionSet<IDomObject> sel = null; if (cq!=null) { sel = cq.SelectionSet; } bool isTargetCsQuery = cq != null; bool isFirst = true; // Copy the target list: it could change otherwise List<IDomObject> targets = new List<IDomObject>(target); insertedElements = new CQ(); bool isEmptyTarget = sel.Count == 0; // bind the source to the target's document if it was itself a CsQuery object, and update its selection set to reflect the // current document. if (isTargetCsQuery) { Document = cq.Document; } if (isTargetCsQuery && isEmptyTarget) { // If appending items to an empty selection, just add them to the selection set sel.AddRange(SelectionSet); insertedElements.AddSelection(SelectionSet); // selection set will be messed up if document was changed; rebuild it SelectionSet.Clear(); SelectionSet.AddRange(insertedElements); } else { foreach (var el in targets) { if (el.IsDisconnected) { // Disconnected items are added to the selection set (if that's the target) if (!isTargetCsQuery) { throw new InvalidOperationException("You can't add elements to a disconnected element list, it must be in a selection set"); } int index = sel.IndexOf(el); sel.OutputOrder = SelectionSetOrder.OrderAdded; foreach (var item in SelectionSet) { sel.Insert(index + offset, item); } insertedElements.AddSelection(SelectionSet); // selection set will be messed up if document was changed; rebuild it SelectionSet.Clear(); SelectionSet.AddRange(insertedElements); } else { if (isFirst) { insertedElements.AddSelection(SelectionSet); InsertAtOffset(el, offset); isFirst = false; // selection set will be messed up if document was changed; rebuild it SelectionSet.Clear(); SelectionSet.AddRange(insertedElements); } else { var clone = Clone(); clone.InsertAtOffset(el, offset); insertedElements.AddSelection(clone); } } } } return this; }
/// <summary> /// Insert every element in the selection at or after the index of each target (adding offset to /// the index). If there is more than one target, the a clone is made of the selection for the /// 2nd and later targets. /// </summary> /// /// <exception cref="InvalidOperationException"> /// Thrown if attempting to add elements to a disconnected (parentless) sequence /// </exception> /// /// <param name="target"> /// The target element /// </param> /// <param name="offset"> /// The offset from the target at which to begin inserting /// </param> /// <param name="insertedElements"> /// [out] The inserted elements. /// </param> /// /// <returns> /// The current CQ object /// </returns> protected CQ InsertAtOffset(IEnumerable <IDomObject> target, int offset, out CQ insertedElements) { CQ cq = target as CQ; SelectionSet <IDomObject> targetSelectionSet = null; if (cq != null) { targetSelectionSet = cq.SelectionSet; } bool isTargetCsQuery = cq != null; bool isFirst = true; // Copy the target list: it could change otherwise List <IDomObject> targets = new List <IDomObject>(target); insertedElements = NewInstance(); bool isEmptyTarget = targetSelectionSet.Count == 0; // bind the source to the target's document if it was itself a CsQuery object, and update its selection set to reflect the // current document. if (isTargetCsQuery) { Document = cq.Document; } if (isTargetCsQuery && isEmptyTarget) { // If appending items to an empty selection, just add them to the selection set targetSelectionSet.AddRange(SelectionSet); insertedElements.AddSelection(SelectionSet); // selection set will be messed up if document was changed; rebuild it //SelectionSet.Clear(); //SelectionSet.AddRange(insertedElements); } else { foreach (var el in targets) { if (el.IsDisconnected) { // Disconnected items are added to the selection set (if that's the target) if (!isTargetCsQuery) { throw new InvalidOperationException("You can't add elements to a disconnected element list, it must be in a selection set"); } int index = targetSelectionSet.IndexOf(el); targetSelectionSet.OutputOrder = SelectionSetOrder.OrderAdded; foreach (var item in SelectionSet) { targetSelectionSet.Insert(index + offset, item); } insertedElements.AddSelection(SelectionSet); // selection set will be messed up if document was changed; rebuild it //SelectionSet.Clear(); //SelectionSet.AddRange(insertedElements); } else { if (isFirst) { insertedElements.AddSelection(SelectionSet); InsertAtOffset(el, offset); isFirst = false; // selection set will be messed up if document was changed; rebuild it //SelectionSet.Clear(); //SelectionSet.AddRange(insertedElements); } else { var clone = Clone(); clone.InsertAtOffset(el, offset); insertedElements.AddSelection(clone); } } } } return(this); }
/// <summary> /// Insert every element in the selection at or after the index of each target (adding offset to /// the index). If there is more than one target, the a clone is made of the selection for the /// 2nd and later targets. /// </summary> /// /// <remarks> /// This is a helper for Before and After. There is special handling when the target is not part /// of a DOM. Instead of altering the DOM, this method will alter the selection set, and return a /// CQ object that contains the new sequence. Normally, it would return the same CQ object (but /// alter the DOM). /// </remarks> /// /// <param name="target"> /// The target element. /// </param> /// <param name="offset"> /// The offset from the target at which to begin inserting. /// </param> /// <param name="insertedElements"> /// [out] The inserted elements. /// </param> /// /// <returns> /// The current CQ object. /// </returns> protected CQ InsertAtOffset(CQ target, int offset, out CQ insertedElements) { // Copy the target list: it could change otherwise List <IDomObject> targets = new List <IDomObject>(target); bool isTargetDisconnected = (target.CsQueryParent != null && target.Document != target.CsQueryParent.Document) || targets.Any(item => item.ParentNode == null); bool isFirst = true; insertedElements = NewCqUnbound(); // bind the source to the target's document if it was itself a CsQuery object, and update its selection set to reflect the // current document. Document = target.Document; if (isTargetDisconnected) { // When the target is disconnected, just append elements to the selection set, not to the DOM CQ result = NewCqInDomain(); result.CsQueryParent = this.CsQueryParent; if (offset == 0) { result.AddSelection(Selection); } result.AddSelection(target); if (offset == 1) { result.AddSelection(Selection); } result.SelectionSet.OutputOrder = SelectionSetOrder.OrderAdded; insertedElements.AddSelection(Selection); return(result); } else { foreach (var el in targets) { bool isElDisconnected = el.ParentNode == null; if (isFirst) { insertedElements.AddSelection(SelectionSet); InsertAtOffset(el, offset); isFirst = false; } else { var clone = this.Clone(); clone.InsertAtOffset(el, offset); insertedElements.AddSelection(clone); } } } return(target); }
/// <summary> /// Insert every element in the selection at or after the index of each target (adding offset to /// the index). If there is more than one target, the a clone is made of the selection for the /// 2nd and later targets. /// </summary> /// /// <remarks> /// This is a helper for Before and After. There is special handling when the target is not part /// of a DOM. Instead of altering the DOM, this method will alter the selection set, and return a /// CQ object that contains the new sequence. Normally, it would return the same CQ object (but /// alter the DOM). /// </remarks> /// /// <param name="target"> /// The target element. /// </param> /// <param name="offset"> /// The offset from the target at which to begin inserting. /// </param> /// <param name="insertedElements"> /// [out] The inserted elements. /// </param> /// /// <returns> /// The current CQ object. /// </returns> protected CQ InsertAtOffset(CQ target, int offset, out CQ insertedElements) { // Copy the target list: it could change otherwise List<IDomObject> targets = new List<IDomObject>(target); bool isTargetDisconnected = (target.CsQueryParent != null && target.Document != target.CsQueryParent.Document) || targets.Any(item => item.ParentNode == null); bool isFirst = true; insertedElements = NewCqUnbound(); // bind the source to the target's document if it was itself a CsQuery object, and update its selection set to reflect the // current document. Document = target.Document; if (isTargetDisconnected) { // When the target is disconnected, just append elements to the selection set, not to the DOM CQ result = NewCqInDomain(); result.CsQueryParent = this.CsQueryParent; if (offset == 0) { result.AddSelection(Selection); } result.AddSelection(target); if (offset == 1) { result.AddSelection(Selection); } result.SelectionSet.OutputOrder = SelectionSetOrder.OrderAdded; insertedElements.AddSelection(Selection); return result; } else { foreach (var el in targets) { bool isElDisconnected = el.ParentNode == null; if (isFirst) { insertedElements.AddSelection(SelectionSet); InsertAtOffset(el, offset); isFirst = false; } else { var clone = this.Clone(); clone.InsertAtOffset(el, offset); insertedElements.AddSelection(clone); } } } return target; }
/// <summary> /// Add elements to the set of matched elements. /// </summary> /// /// <param name="elements"> /// The elements to add. /// </param> /// /// <returns> /// A new CQ object. /// </returns> /// /// <url> /// http://api.jquery.com/add/ /// </url> public CQ Add(IEnumerable<IDomObject> elements) { CQ res = new CQ(this); res.AddSelection(elements); return res; }
/// <summary> /// Configures a new instance for a sequence of elements and an existing context. /// </summary> /// /// <param name="elements"> /// A sequence of elements. /// </param> /// <param name="context"> /// The context. /// </param> private void ConfigureNewInstance(CQ dom, IEnumerable <IDomObject> elements, CQ context) { dom.CsQueryParent = context; dom.AddSelection(elements); }