Revit API: Get generating profiles of a solid form - revit-api

I selected some FamilyInstances and clicked "Create Form -> Solid Form".
How can I get the generating FamilyInstance(s), if I only have the Form?
var form = ele as Autodesk.Revit.DB.Form;
int nSub = form.ProfileCount; // <<<< 28 - I want a reference to each ElementId!
// form.GetGeneratingElementIds(); // only one
// form.GetMonitoredLinkElementIds(); // zero
// form.get_CurveLoopReferencesOnProfile(0,0); // ReferenceArray of 9 items
If it's impossible - can it be done the other way round? Like: I have a family_instance and try to find the "parent" Form.

Related

Using composed xpath to locate an element and click on it

I am trying to retrieve a list of elements using XPATH and from this list I want to retrieve a child element based on classname and click it.
var rowList = XPATH1 + className;
var titleList = className + innerHTMLofChildElement;
for(var i = 0; i < titleList.length; i++) {
if(titleList[i][0] === title) {
browser.click(titleList[i][0]); //I don't know what to do inside the click function
}
}
I had a similar implementation perhaps to what you are trying to do, however my implementation is perhaps more complex due to using CSS selectors rather than XPath. I'm certain this is not optimized, and can most likely be improved upon.
This uses the methods elementIdText() and elementIdClick() from WebdriverIO to work with the "Text Values" of the Web JSON Elements and then click the intended Element after matching what you're looking for.
http://webdriver.io/api/protocol/elementIdText.html
http://webdriver.io/api/protocol/elementIdClick.html
Step 1 - Find all your potential elements you want to work with:
// Elements Query to return Elements matching Selector (titles) as JSON Web Elements.
// Also `browser.elements('<selector>')`
titles = browser.$$('<XPath or CSS selector>')
Step 2 - Cycle through the Elements stripping out the InnerHTML or Text Values and pushing it into a separate Array:
// Create an Array of Titles
var titlesTextArray = [];
titles.forEach(function(elem) {
// Push all found element's Text values (titles) to the titlesTextArray
titlesTextArray.push(browser.elementIdText(elem.value.ELEMENT))
})
Step 3 - Cycle through the Array of Title Texts Values to find what you're looking for. Use elementIdClick() function to click your desired value:
//Loop through the titleTexts array looking for matching text to the desired title.
for (var i = 0; i < titleTextsArray.length; i++) {
if (titleTextsArray[i].value === title) {
// Found a match - Click the corresponding element that
// it belongs to that was found above in the Titles
browser.elementIdClick(titles[i].value.ELEMENT)
}
}
I wrapped all of this into a function in which i provided the intended Text (in your case a particular title) I wanted to search for. Hope this helps!
I don't know node.js, but in Java you should achieve your goal by:
titleList[i].findElementBy(By.className("classToFind"))
assuming titleList[i] is an element on list you want to get child elements from

Is it possible to use multiple NIBs mixed in a UICollectionView?

I have to create a view such as the iTunes Appstore with 3 different types of blocks: one for an image (ImageBlock), another for a list of object1 (Type1List) and a third for a list of object2 (Type2List).
I have functional MvxCollectionViewCells for all of the three, but I'd need to make an UICollectionView out of these three. I have an list of these lists (Items). A single list (Item) has a value called "type", which is an integer value 1, 2 or 3. I'd have to get this integer value for each Item and determine the NIB I want to use for this specific cell.
//Collection = UICollectionView
//ViewModel.Items = MvxObservableCollection<Item>
public override void ViewDidLoad()
{
base.ViewDidLoad();
var set = this.CreateBindingSet<View, ViewModel>();
// NIBs for types 1, 2 and 3 respectively
Collection.RegisterNibForCell(Type1List.Nib, Type1List.Key);
Collection.RegisterNibForCell(Type2List.Nib, Type2List.Key);
Collection.RegisterNibForCell(ImageBlock.Nib, ImageBlock.Key);
// This shows all items of type 1 correctly, and others using type 1 XIB with no contents
Source = new MvxCollectionViewSource(Collection, Type1List.Key);
// This gives a Null Reference Exception if used in place of the previous one
//Source = new MvxCollectionViewSource(Collection);
set.Bind(Source)
.To(vm => vm.Items);
// This takes the items and calculates the height for Collection in this View
// All types will differ in size
set.Bind(CollectionHeight)
.For(v => v.Constant)
.To(vm => vm.Items)
.WithConversion("IosCollectionHeight", Collection);
Collection.Source = Source;
// Set to 200 for now to see the cells
// TODO: set a working variable size
(Collection.CollectionViewLayout as UICollectionViewFlowLayout).ItemSize = new CoreGraphics.CGSize(UIScreen.MainScreen.Bounds.Width, 200);
//(Collection.CollectionViewLayout as UICollectionViewFlowLayout).EstimatedItemSize = new CoreGraphics.CGSize(UIScreen.MainScreen.Bounds.Width, 100);
set.Apply();
Collection.ReloadData();
}
So I have currently 2 problems:
I don't know how to use different NIBs by type for my UICollectionView
I don't know how to resize cells by type
All three cell NIBs are tested and working as intended, but this CollectionView is problematic.
-Pasketi

Select UI Element by filtering properties in coded ui

I have a web application. And I am using coded ui to write automated tests to test the application.
I have a dropdown with a text box. Which on entering values in the textbox, the values in the dropdown gets filtered based on the text entered.
If I type inside textbox like 'Admin', I will get below options like this:
And I need to capture the two options displayed.
But using IE Developer tool (F12), I am not able to capture the filtered options, because the options that are displayed do not have any unique property (like this below). And the options that are NOT displayed have a class="hidden" property
Any way to capture the elements that are displayed by applying some kind of filter like 'Select ui elements whose class != hidden'
Thanks in advance!!
HI please try below code will it works for you or not.By traversing all those controls that have class ="hidden"
WpfWindow mainWindow = new WpfWindow();
mainWindow.SearchProperties.Add(HtmlControl.PropertyNames.ClassName, "hidden");
UITestControlCollection collection = mainWindow.FindMatchingControls();
foreach (UITestControl links in collection)
{
HtmlHyperlink mylink = (HtmlHyperlink)links;
Console.WriteLine(mylink.InnerText);
}
I'm not sure there is a way to do it by search properties, but there are other approaches.
One way would be to brute force difference the collections. Find all the list items, then find the hidden ones and do a difference.
HtmlControl listControl = /* find the UL somehow */
HtmlControl listItemsSearch = new HtmlControl(listControl);
listItemsSearch.SearchProperties.Add(HtmlControl.PropertyNames.TagName, "li");
HtmlControl hiddenListItemsSearch = new HtmlControl(listControl);
hiddenListItemsSearch.SearchProperties.Add(HtmlControl.PropertyNames.TagName, "li");
hiddenListItemsSearch.SearchProperties.Add(HtmlControl.PropertyNames.ClassName, "hidden");
var listItems = listItemsSearch.FindMatchingControls().Except(hiddenListItemsSearch.FindMatchingControls());
You will only be able to iterate this collection one time so if you need to iterate multiple times, create a function that returns this search.
var listItemsFunc = () => listItemsSearch.FindMatchingControls().Except(hiddenListItemsSearch.FindMatchingControls());
foreach(var listItem in listItemsFunc()){
// iterate 1
}
foreach(var listItem in listItemsFunc()){
// iterate 2
}
The other way I would consider doing it would be to filter based on the controls which have a clickable point and take up space on the screen (ie, not hidden).
listItemsSearch.FindMatchingControls().Where(x => {
try { x.GetClickablePoint(); return x.Width > 0 && x.Height > 0; } catch { return false; }
});

How can I get the properties from a property Group of a Custom Control as an Object?

I'm working on a Custom Control that displays markers on Google Maps. I have a couple of properties like "maptype" , "zoom", etc. It is easy to access them in Javascript: I can use #{javascript:compositeData.zoom} to get the value of the zoom property.
Now this is my problem: I use a group of properties for each marker.
The name of the group is "marker" and a marker has 6 properties: "title", "layer", "infotext", "icon", "address" and "animation".
If I try to access the group with
var markers = #{javascript:compositeData.marker};
I'm getting an error in firebug:
missing : after property id var markers = [{layer=2,
address=Oldenzaal, animation=DROP, icon=/ogo_notes.png...
an arrow is pointing to the first = between layer and 2
(I am not allowed to put in an image in stackoverflow)
If I use
var markers = #{javascript:'"' + compositeData.marker + '"'};
markers is an Object, but each Object contains a string with all the propperties of the marker.
I know I can do some coding to make an object of each string, but this is not easy if not all propperties are required. If a propperty is not required than it will not show up in the string.
I guess that there must be a more easy way to get each marker as an object so I can get the value of the icon with code like:
var icon = marker.icon
How can I do this?
You can use compositeData.marker.icon to get the property icon inside the group marker. If you have checked "Allow multiple instances" for the group then to get the properties you will have to go:
compositeData.marker[0].icon
compositeData.marker[1].icon
and so on...
Update 26-Apr-2012 (Naveen)
To use it with client side javascript you can try to put the value in a hidden input field like this:
<xp:inputHidden id="hdnIcon">
<xp:this.defaultValue><![CDATA[#{javascript:var value = new Array();
for (var i=0 ; i<compositeData.marker.length ; i++) {
value.push(compositeData.marker[i].icon);
}
return #Implode(value, ",");}]]></xp:this.defaultValue>
</xp:inputHidden>
The value of this hidden input field can be read through client-side javascript like this:
var value = document.getElementById("#{id:hdnIcon}").value.split(",");
for (var i=0 ; i<value.length ; i++) {
<YOUR CODE>
}
Another way to do this can be to convert compositeData.marker and its contents to a JSON string and then run the client-side javascript on it.

How can I set the default value in a SharePoint list field, based on the value in another field?

I have a custom list in SharePoint (specifically, MOSS 2007.) One field is a yes/no checkbox titled "Any defects?" Another field is "Closed by" and names the person who has closed the ticket.
If there are no defects then I want the ticket to be auto-closed. If there are, then the "Closed by" field ought to be filled in later on.
I figured I could set a calculated default value for "Closed by" like this:
=IF([Any defects?],"",[Me])
but SharePoint complains I have referenced a field. I suppose this makes sense; the default values fire when the new list item is first opened for entry and there are no values in any fields yet.
I understand it is possible to make a calculated field based on a column value but in that case the field cannot be edited later.
Does anyone have any advice how to achieve what I am trying to do?
Is it possible to have a "OnSubmit" type event that allows me to execute some code at the point the list item is saved?
Thank you.
Include a content editor web part in the page (newform.aspx / editform.aspx) and use jQuery (or just plain javascript) to handle the setting of default values.
Edit: some example code:
In the lists newform.aspx, include a reference to jquery. If you look at the html code, you can see that each input tag gets an id based on the field's GUID, and a title that's set to the fields display name.
now, using jquery we can get at these fields using the jQuery selector like this:
By title:
$("input[title='DISPLAYNAMEOFFIELD']");
by id (if you know the field's internal guid, the dashes will ahve to be replaced by underscores:
// example field id, notice the guid and the underscores in the guid ctl00_m_g_054db6a0_0028_412d_bdc1_f2522ac3922e_ctl00_ctl04_ctl15_ctl00_ctl00_ctl04_ctl00_ctl00_TextField
$("input[id*='GUID']"); //this will get all input elements of which the id contains the specified GUID, i.e. 1 element
We wrap this in the ready() function of jQuery, so all calls will only be made when the document has fully loaded:
$(document).ready(function(){
// enter code here, will be executed immediately after page has been loaded
});
By combining these 2 we could now set your dropdown's onchange event to the following
$(document).ready(function(){
$("input[title='DISPLAYNAMEOFFIELD']").change(function()
{
//do something to other field here
});
});
The Use jQuery to Set A Text Field’s Value on a SharePoint Form article on EndUserSharePoint.com shows you how to set a default value for a field using JavaScript/jQuery.
They also have a whole series of articles on 'taming calculated columns' that will show you many more powerful options you have for calculated fields with the use of jQuery.
One thing to be aware of when inserting JavaScript into a SharePoint page and modifying the DOM is support. There is a small chance that a future service pack will break the functionality you add, and it is quite likely that the next version of SharePoint will break it. Keeping this mind however, I believe it's a good solution at this time.
I've got a walk through with sample code that may help
Setting a default duration for new calendar events
It sets the End Time/Date fields to Start Time + 1.5 hours when you create a new event.
Its complicated a little by the steps need to do the time/date work, but you'll see examples of how to find the elements on the form and also one way to get your script onto the newform.aspx without using SPD.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">
</script>
<script type="text/javascript">
// Set the hours to add - can be over 24
var hoursToAdd = 1;
// Mins must be 0 or div by 5, e.g. 0, 5, 10, 15 ...
var minutesToAdd = 30;
// JavaScript assumes dates in US format (MM/DD/YYYY)
// Set to true to use dates in format DD/MM/YYYY
var bUseDDMMYYYYformat = false;
$(function() {
// Find the start and end time/minutes dropdowns by first finding the
// labels then using the for attribute to find the id's
// NOTE - You will have to change this if your form uses non-standard
// labels and/or non-english language packs
var cboStartHours = $("#" + $("label:contains('Start Time Hours')").attr("for"));
var cboEndHours = $("#" + $("label:contains('End Time Hours')").attr("for"));
var cboEndMinutes = $("#" + $("label:contains('End Time Minutes')").attr("for"));
// Set Hour
var endHour = cboStartHours.attr("selectedIndex") + hoursToAdd;
cboEndHours.attr("selectedIndex",endHour % 24);
// If we have gone over the end of a day then change date
if ((endHour / 24)>=1)
{
var txtEndDate = $("input[title='End Time']");
var dtEndDate = dtParseDate(txtEndDate.val());
if (!isNaN(dtEndDate))
{
dtEndDate.setDate( dtEndDate.getDate() + (endHour / 24));
txtEndDate.val(formatDate(dtEndDate));
}
}
// Setting minutes is easy!
cboEndMinutes.val(minutesToAdd);
});
// Some utility functions for parsing and formatting - could use a library
// such as www.datejs.com instead of this
function dtParseDate(sDate)
{
if (bUseDDMMYYYYformat)
{
var A = sDate.split(/[\\\/]/);
A = [A[1],A[0],A[2]];
return new Date(A.join('/'));
}
else
return new Date(sDate);
}
function formatDate(dtDate)
{
if (bUseDDMMYYYYformat)
return dtDate.getDate() + "/" + dtDate.getMonth()+1 + "/" + dtDate.getFullYear();
else
return dtDate.getMonth()+1 + "/" + dtDate.getDate() + "/" + dtDate.getFullYear();
}
</script>

Resources