In Confluence v.5.3, I'm trying to write a User Macro that creates a table from my index page's children. Each child page has an Excerpt macro in it that I need to add to the index page's table. From my User Macro, the excerpts are being pulled out by calling Excerpt-Include within my macro. They are printing quite fine on the table.
My problem is I can't seem to use the excerpts within an if-else comparison. For whatever reason, it's not comparing them, or I'm writing it incorrectly. This is what I am attempting to do:
#set($macroFinal = "{excerpt-include:" + $page.getTitle() + "|nopanel=true}")
#set($myexcerpt = $action.getHelper().renderConfluenceMacro($macroFinal).replaceAll('"', '"') + " ")
#if($myexcerpt == "High")
#set($colors = "#F0F0F0")
#else
#set($colors = "#FFFFFF")
#end
Any idea how to get the comparison to work?
Well, egg on my face. Turns out I just needed to add a "toString" to the end of the whole thing.
#set($myexcerpt = $action.getHelper().renderConfluenceMacro($macroFinal).replaceAll('"', '"').toString())
So, lesson learned, when in doubt, toString.
Related
How can you display a specific item in an array with Pug? For example:
each answer in answers
li!= answer.Response
Will display each item in the array. But, say I wanted just the the third item or, better yet, pass a variable for a specific index to display. What is the syntax for this?
- const indexIwant = 2;
if answers && answers.length>indexIwant
li=answers[indexIwant]
You need to ensure answers is not null and has at least the number of items to include the indexed item you want.
Another thing: don't use != unless you know exactly what data you are handling.
The simplest way to access a specific index of an array in pug:
-const meals = ["breakfast", "lunch", "dinner"]
-const favoriteDishes = ["coffee & doughnut salad","cheese danish soup","red wine","banana split sandwich"]
-const sides = ["ranch dressing","chutney","ketchup","chocolate sauce"]
p I reckon I will fix myself a hefty helping of #{favoriteDishes[2]} for #{meals[0]} with a side of #{sides[2]}.
Considering that indentation and whitespace is everything in jade / pug, this works :))
I'm designing a Mastermind game, which basically compares 2 lists and marks the similarities. When a colour is found at the right place, a flag making the correct position is added and the item found on the reference list is marked off. The reference list is feeding off an array from another function. The problem is at the mark off, as any changes done to the reference list is changing also the original array, which i don't want it to happen
tempCode = mCode #mCode is the array combination randomly generated from another function
for i in range (len(uCode)): #user input array
for j in range (len(tempCode)): #temp array
if uCode[i] == tempCode[j]: # compare individual chars
if i == j: #compare position
flagMark = "*"
tempCode.insert(j+1, "x") #problem starts here
tempCode.remove(tempCode[j])
fCode.append(flagMark)
When the insert is reached both the tempCode and mCode change which it is not intended.
The code is written in a way should the user enter a combination of the same colours, thus checking the chras(the colours are just letters) and the position, and then mark them of with "x"
As it stands, when it gets to
tempCode.insert(j+1, "x")
the arrays will change to
mCode = ["B","R","x","G","Y"]
tempCode = ["B","R","x","G","Y"]
when I would just want
mCode = ["B","R","G","Y"]
tempCode = ["B","R","x","G","Y"]
See also this answer, which is a different presentation of the same problem.
Essentially, when you do tempCode = mCode, you're not making a copy of mCode, you're actually making another reference to it. Anything you do to tempCode thereafter affects the original as well, so at any given time the condition tempCode == mCode will be true (as they're the same object).
You probably want to make a copy of mCode, which could be done in either of the following ways:
tempCode = mCode.copy()
tempCode = mCode[:]
which produces a different list with the same elements, rather than the same list
Let's assume that I have Custom Table named Possible URL target parameters with code name xyz.PossibleTargets with 2 columns:
Explanation and Value.
How to feed drop-down field on page type with data to have Value (from table) as Value and Explanation as name in drop-down?
What I already tried and it is not working:
Generate value;name pairs divided by newline and place it as List of options:
z = ""; foreach (x in CMSContext.Current.GlobalObjects.CustomTables["xyz.PossibleTargets"].Items) {z += x.GetValue("Value"); z +=";"; z += x.GetValue("Explanation"); z += "\n" }; return z;
Validator do no allow me to do such trick.
Set option Macro expression and provide enumerable object:
CMSContext.Current.GlobalObjects.CustomTables["xyz.PossibleTargets"].Items
In Item transformation: {%Explanation%} and in Value column {%TargetValue%}.
This do not work also.
Dropdown configuration
How to do this correctly? Documentation and hints on the fields are not helpful.
Kentico v11.0.26
I think that you should do it without marking field as a macro. Just type there the macro. Take a look on screen
No need to use a macro, use straight SQL, using a macro only complicates what appears to be a simple dropdown list.
SELECT '', '-- select one --' AS Explanation
UNION
SELECT TargetValue, Explanation
FROM xyz_PossibleTargets -- make sure to use the correct table name
ORDER BY ExplanationText
This should populate exactly what you're looking for without the complication of a macro.
Having an issue with a bit of code designed to add an email alias to a list box. I have a check built in to ensure the item you attempt to add isn't already in the list, but the check is case sensitive when I don't want it to be. I'm not sure how to make it ignore the case... Here's my code:
Dim ItemToAdd as String = ""
ItemtoAdd = tbxItemtoAdd.Text + "#emaildomain.co.uk"
If Not lbxEmailAliases.Items.Contains(ItemtoAdd) Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If
At the moment if the list box contains johnsmith24#emaildomain.co.uk and you try to add Johnsmith24 (capital J), it will add this successfully, but I don't want it to do that. How do I get it to ignore case?
I've tried changing lbxEmailAliases.Items.Contains(ItemtoAdd) to lbxEmailAliases.Items.Contains(ItemtoAdd, StringComparison.CurrentCultureIgnoreCase) but it's not happy with this as there are too many arguments, it will only take one.
Any ideas please?
If this is a standard WinForm ListBox control, then there is no way to do it without looping through all of the items and checking each one individually. For instance:
Dim found As Boolean = False
For Each item As Object In ListBox1.Items
found = item.ToString().Equals(ItemToAdd, StringComparison.CurrentCultureIgnoreCase)
If found Then
Exit For
End If
Next
If found Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If
However, if you are comfortable with LINQ, you can do it more concisely like this:
If ListBox1.Items.OfType(Of String).Any(Function(item) item.Equals(ItemToAdd, StringComparison.CurrentCultureIgnoreCase)) Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If
Or, as Andy G pointed out, the LINQ Contains method is even easier since it accepts an IEqualityComparer and a stock one which supports case insensitive string comparisons is provided by the framework:
If ListBox1.Items.OfType(Of String).Contains(ItemToAdd, StringComparer.CurrentCultureIgnoreCase) Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If
It should be StringComparer, not StringComparison:
lbxEmailAliases.Items.Contains(ItemtoAdd, StringComparer.InvariantCultureIgnoreCase)
The method accepts an IEqualityComparer, the docs.
As pointed out by Steven Doggart, ListBox Items require the use of OfType(Of T):
lbxEmailAliases.Items.OfType(Of String).Contains(ItemtoAdd, StringComparer.InvariantCultureIgnoreCase)
An alternative could be the FindString-method:
If lbxEmailAliases.FindString(ItemtoAdd) = ListBox.NoMatches Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If
Note: This method searches for items that start with the specified string and returns the index of the first found item.
Means it will find jdoe#domain.com even if the existing e-mail-address is jdoe#domain.computer.com.
So maybe it's not the best solution for your specific case.
EDIT:
You can use FindStringExact instead. Like this you'll get the wanted case insensitive, non-partial comparison.
If lbxEmailAliases.FindStringExact(ItemtoAdd) = ListBox.NoMatches Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If
I am currently attempting to parse data that is sent from an outside source serially. An example is as such:
DATA|0|4|7x5|1|25|174-24|7x5|1|17|TERW|7x5|1|9|08MN|7x5|1|1|_
This data can come in many different lengths, but the first few pieces are all the same. Each "piece" originally comes in with CRLF after, so I've replaced them with string.gsub(input,"\r\n","|") so that is why my input looks the way it does.
The part I would like to parse is:
4|7x5|1|25|174-24|7x5|1|17|TERW|7x5|1|9|08MN|7x5|1|1|_
The "4" tells me that there will be four lines total to create this file. I'm using this as a means to set the amount of passes in the loop.
The 7x5 is the font height.
The 1 is the xpos.
The 25 is the ypos.
The variable data (172-24 in this case) is the text at these parameters.
As you can see, it should continue to loop this pattern throughout the input string received. Now the "4" can actually be any variable > 0; with each number equaling a set of four variables to capture.
Here is what I have so far. Please excuse the loop variable, start variable, and print commands. I'm using Linux to run this function to try to troubleshoot.
function loop_input(input)
var = tonumber(string.match(val, "DATA|0|(%d*).*"))
loop = string.match(val, "DATA|0|")
start = string.match(val, loop.."(%d*)|.*")
for obj = 1, var do
for i = 1, 4 do
if i == 1 then
i = "font" -- want the first group to be set to font
elseif i == 2 then
i = "xpos" -- want the second group to be set to xpos
elseif i == 3 then
i = "ypos" -- want the third group to be set to ypos
else
i = "txt" -- want the fourth group to be set to text
end
obj = font..xpos..ypos..txt
--print (i)
end
objects = objects..obj -- concatenate newly created obj variables with each pass
end
end
val = "DATA|0|4|7x5|1|25|174-24|7x5|1|17|TERW|7x5|1|9|08MN|7x5|1|1|_"
print(loop_input(val))
Ideally, I want to create a loop that, depending on the var variable, will plug in the captured variables between the pipe deliminators and then I can use them freely as I wish. When trying to troubleshoot with parenthesis around my four variables (like I have above), I receive the full list of four variables four times in a row. Now I'm having difficulty actually cycling through the input string and actually grabbing them out as the loop moves down the data string. I was thinking that using the pipes as a means to delineate variables from one another would help. Am I wrong? If it doesn't matter and I can keep the [/r/n]+ instead of each "|" then I am definitely all for that.
I've searched around and found some threads that I thought would help but I'm not sure if tables or splitting the inputs would be advisable. Like these threads:
Setting a variable in a for loop (with temporary variable) Lua
How do I make a dynamic variable name in Lua?
Most efficient way to parse a file in Lua
I'm fairly new to programming and trying to teach myself. So please excuse my beginner thread. I have both the "Lua Reference Manual" and "Programming in Lua" books in paperback which is how I've tried to mock my function(s) off of. But I'm having a problem making the connection.
I thank you all for any input or guidance you can offer!
Cheers.
Try this:
val = "DATA|0|4|7x5|1|25|174-24|7x5|1|17|TERW|7x5|1|9|08MN|7x5|1|1|_"
val = val .. "|"
data = val:match("DATA|0|%d+|(.*)$")
for fh,xpos,ypos,text in data:gmatch("(.-)|(.-)|(.-)|(.-)|") do
print(fh,xpos,ypos,text)
end