Reddot cms IoRangeList inside IoRangePreExecute - asp-classic

Hi i don't have RedDot CMS and i want to know is it possible to use <!IoRangeList> inside <!IoRangePreExecute> also use ASP Classic to get sum of the elements inside for loop.
Or is the other way to do it
Here is my code
<!IoRangePreExecute>
<%
Dim a(5), b, c
%>
<% d = 0 %>
<!IoRangeList>
' user range list as loop to get value from reddot
a(<% d = d + 1 %>) = <%value%>
<!/IoRangeList>
<% For Each b in a
c = c + Cint(b)
Next
Response.Write(c)
%>
<!/IoRangePreExecute>
Im wondering is the correct way to do it

It would be easier to use the built in foreach loop tag, but yes you can do this that way(although the code in the rangelist isn't complete)

It is possible, but I would not recommend it. PreExecute is very inefficient, avoid if you can.
Prior to my recent departure from OpenText, I generally used iorangelist to output client-side code - perhaps as javascript data - and then used JS/JQuery to build a dynamic UI from this.
For your specific question, I would simply output the List loop as a client-side javascript:
<script>
var a = 0;
<%iorangelist%>
a += <%value%>; //I'd check for numeric here.
<%/iorangelist%>
console.log(a);
</script>

Related

Obtain data from dynamically incremented IDs in JQuery

I have a quick question about JQuery. I have dynamically generated paragraphs with id's that are incremented. I would like to take information from that page and bring it to my main page. Unfortunately I am unable to read the dynamically generated paragraph IDs to get the values. I am trying this:
var Name = ((data).find("#Name" + id).text());
The ASP.NET code goes like this:
Dim intI As Integer = 0
For Each Item As cItem in alProducts1
Dim pName As New System.Web.UI.HtmlControls.HtmlGenericControl("p")
pName.id = "Name" & intI.toString() pName.InnerText = Item.Name controls.Add(pName) intI += 1
Next
Those name values are the values I want...Name1, name2, name3 and I want to get them individually to put in their own textbox... I'm taking the values from the ASP.NET webpage and putting them into an AJAX page.
Your question is not clear about your exact requirement but you can get the IDs of elements with attr method of jQuery, here is an example:
alert($('selector').attr('id'));
You want to select all the elements with the incrementing ids, right?
// this will select all the elements
// which id starts with 'Name'
(data).find("[id^=Name]")
Thanks for the help everyone. I found the solution today however:
var Name = ($(data).find('#Name' + id.toString()).text());
I forgot the .toString() part and that seems to have made the difference.

How to use ASP.NET Resources in this way?

I am doing some labeling. I would like to add a resource key (s, sec) to one of my combo boxes with item[3sec, 5sec, 10sec, 30sec ...] and use it like:
Text="3<%$ Resources: myResource, s%>" to get comboBoxItem 3sec,
Text="5<%$ Resources: myResource, s%>" to get comboBoxItem 5sec ...
But I find that the server will treat this as plain text.
Do I need to define each item in a separate resource key pair?
Consider defining your resource file entry value as follows:
{0}sec
And then
String.Format(Resources.myResource.s, "3")
You can try creating your own custom expression builder. They are really powerful if you want to achieve what you have asked in your question.
Or, you can always do it using server-side code.
You could do it like this (with a DataBind() call somewhere):
Text='<%# "3" + Resources.myResource.s %>'
Edit: You can also do this from code behind. Something like this:
int[] times = new int[]{ 3, 5, 10, 30 };
foreach (int time in times)
{
string text = time.ToString() + Resources.myResource.s;
cbo.Items.Add(new ListItem(text, time.ToString()));
}
Edit 2: As per Muhammad's observation the first example doesn't work for this. I've used it for other controls, and I didn't see that for the current case it's not correct. Given this I would fill the control from code behind.

Filling multiple literals with the same value

I have multiple literals on a page. For example,
<asp:Literal id="Label1" runat="server" />
I have around 10 of these on one page and want to fill them all with the same value. Is there a good way to do that without referencing the id for each control?
Create a public property that holds the value you want to display and in the aspx use
<%= propertyName %>
everywhere you want to display the value.
If you're using resource files, you can set the meta:resourcekey attribute to the same value for all 10 of them.
The only way I've seen it done is make the id's a loopable name (e.g. Label1 - Label10) and loop through referencing the id. But we didn't try too hard for a different solution!
Are the Literals located in a single Container (for instance, a Panel) or are they littered about the page? If they are in a single container which does not contain too many other non-relevant controls, it would be as simple as looping through the Container's Controls collection.
Yes, I'm well aware that a Page is a Container as well, but it is almost always very inefficient to loop through all the controls in a Page. I wouldn't recommend it at all.
How are your labels named. If they have a common naming convention like Label1 - Label10 then you could do
for(int i = 1; i <= 10; i++)
{
Literal l = Page.FindControl(string.Format("Label{0}", i)) as Literal
if(l != null)
l.Text = "Whatever";
}
If they're not named similarly, you could just stick the label names in an array and loop through that instead of having 10 explicit .Text = statements. e.g.
string [] litNames = new string [] { "litFirst", "otherLit", "someOtherVar" }
foreach(string s in litNames)
{
Literal l = Page.FindControl(s) as Literal
if(l != null)
l.Text = "Whatever";
}

Why does my repeater keep crashing on Eval(NULL) values?

<asp:Repeater ID="rptLessons" runat="server">
<ItemTemplate>
<tr>
<td><%#Eval("fullname")%></td>
<td><%#isCompleted(Eval("totallessons"), Eval("completedlessons"), Eval("totalNumAvail"), Eval("totalNumCorrect"))%></td>
<td><%#FormatPercent(Eval("totalnumcorrect") / Eval("totalNumAvail"))%> <%-- (<%#Eval("totalnumcorrect")%> / <%#Eval("totalNumAvail")%>) --%></td>
<td><%#FormatPercent(Eval("completedlessons") / Eval("totallessons"))%> <%-- (<%#Eval("completedlessons")%> / <%#Eval("totallessons")%>) --%></td>
<td><%#Eval("lastaccessed")%></td>
</tr>
</ItemTemplate>
</asp:Repeater>
I can't figure it out but as soon as it hits some NULL data it refuses to move on to drawing the next elements.
You need to give a stack trace to be sure.
But I can see several issues:
DIV#0 errors inside FormatPercent
NULL errors.
Example Solution
(System.Convert.ToInt32 should convert DBNull/NULL to 0)
Or alter isCompleted to accept Object paramters and do your NULL / DBNull checking inside the function.
On slightly different approach that might be helpful would be to do your computations in your code behind rather than inline in the markup. Just easier to check for nulls etc. I almost always go down this path with anything other than a simple Eval() in my markup.
<td>
<%#GetCorrectPercent()%>
</td>
protected string GetCorrectPercent()
{
if(Eval("totalnumcorrect") == null || Eval("totalNumAvail") == null)
return "n/a";
return ((int)Eval("totalnumcorrect") / (int)Eval("totalNumAvail")).ToString();
}
Not sure all the formatting is correct here but this should get you going in a different direction. Eval() will work within the called methods so long as the caller is current performing a DataBind().
If I had to guess, I would say that your isCompleted function doesn't handle values of Nothing. This is a guess because the function hasn't been listed in your example.
I tend more towards the explicit. Forgive any minor mistakes in the code, I'm not able to test this.
If in your markup you swap out those evals for literals then in the code behind:
If you have a collection of MyClass.
In your page's init event
this.rptLessons.OnItemDataBound += rptLessons_DataBound...
In the load or where ever you choose
this.rptLessons.DataSource = CollectionOfMyClass;
this.rptLessons.DataBind();
Then in that itemDataBoundEvent
MyClass myClass = (MyClass)ri.DataItem;
Literal litFullname = FindControl(ri, "litFullName");
litFullName.Text = myClass.Fullname;
This way you can cater for nulls etc in a more controlled way than using eval.

How do you call a method from a variable in ASP Classic?

For example, how can I run me.test below?
myvar = 'test'
me.myvar
ASP looks for the method "myvar" and doesn't find it. In PHP I could simply say $me->$myvar but ASP's syntax doesn't distinguish between variables and methods. Suggestions?
Closely related to this, is there a method_exists function in ASP Classic?
Thanks in advance!
EDIT: I'm writing a validation class and would like to call a list of methods via a pipe delimited string.
So for example, to validate a name field, I'd call:
validate("required|min_length(3)|max_length(100)|alphanumeric")
I like the idea of having a single line that shows all the ways a given field is being validated. And each pipe delimited section of the string is the name of a method.
If you have suggestions for a better setup, I'm all ears!
You can achieve this in VBScript by using the GetRef function:-
Function Test(val)
Test = val & " has been tested"
End Function
Dim myvar : myvar = "Test"
Dim x : Set x = GetRef(myvar)
Response.Write x("Thing")
Will send "Thing has been tested" to the client.
So here is your validate requirement using GetRef:-
validate("Hello World", "min_length(3)|max_length(10)|alphanumeric")
Function required(val)
required = val <> Empty
End Function
Function min_length(val, params)
min_length = Len(val) >= CInt(params(0))
End Function
Function max_length(val, params)
max_length = Len(val) <= CInt(params(0))
End Function
Function alphanumeric(val)
Dim rgx : Set rgx = New RegExp
rgx.Pattern = "^[A-Za-z0-9]+$"
alphanumeric = rgx.Test(val)
End Function
Function validate(val, criterion)
Dim arrCriterion : arrCriterion = Split(criterion, "|")
Dim criteria
validate = True
For Each criteria in arrCriterion
Dim paramListPos : paramListPos = InStr(criteria, "(")
If paramListPos = 0 Then
validate = GetRef(criteria)(val)
Else
Dim paramList
paramList = Split(Mid(criteria, paramListPos + 1, Len(criteria) - paramListPos - 1), ",")
criteria = Left(criteria, paramListPos - 1)
validate = GetRef(criteria)(val, paramList)
End If
If Not validate Then Exit For
Next
End Function
Having provided this I have to say though that if you are familiar with PHP then JScript would be a better choice on the server. In Javascript you can call a method like this:-
function test(val) { return val + " has been tested"; )
var myvar = "test"
Response.Write(this[myvar]("Thing"))
If you are talking about VBScript, it doesn't have that kind of functionality. (at least not to my knowledge) I might attempt it like this :
Select myvar
case "test":
test
case "anotherSub":
anotherSub
else
defaultSub
end select
It's been a while since I wrote VBScript (thank god), so I'm not sure how good my syntax is.
EDIT-Another strategy
Personally, I would do the above, for security reasons. But if you absolutely do not like it, then you may want to try using different languages on your page. I have in the past used both Javascript AND VBScript on my Classic ASP pages (both server side), and was able to call functions declared in the other language from my current language. This came in especially handy when I wanted to do something with Regular Expressions, but was in VBScript.
You can try something like
<script language="vbscript" runat="server">
MyJavascriptEval myvar
</script>
<script language="javascript" runat="server">
function MyJavascriptEval( myExpression)
{
eval(myExpression);
}
/* OR
function MyJavascriptEval( myExpression)
{
var f = new Function(myExpression);
f();
}
*/
</script>
I didn't test this in a classic ASP page, but I think it's close enough that it will work with minor tweaks.
Use the "Execute" statement in ASP/VBScript.
Execute "Response.Write ""hello world"""
PHP's ability to dynamically call or create functions are hacks that lead to poor programming practices. You need to explain what you're trying to accomplish (not how) and learn the correct way to code.
Just because you can do something, doesn't make it right or a good idea.
ASP does not support late binding in this manner. What are you trying to do, in a larger sense? Explain that, and someone can show you how to accomplish it in asp.
Additionally, you might consider "objectifying" the validation functionality. Making classes is possible (though not widely used) in VB Script.
<%
Class User
' declare private class variable
Private m_userName
' declare the property
Public Property Get UserName
UserName = m_userName
End Property
Public Property Let UserName (strUserName)
m_userName = strUserName
End Property
' declare and define the method
Sub DisplayUserName
Response.Write UserName
End Sub
End Class
%>

Resources