How to use locale entity in js-code - firefox-addon

is it possible to get the value of an entity
<!ENTITY gatwayError "Gateway error">
using javascript? For now I reference them in my xul file using
&gatewayError;
UPDATE: In my ff-sidebar.xul within the <page> I have
<stringbundleset id="stringbundleset">
<stringbundle id="strings"
src="chrome://myaddon/locale/de/sidebar.properties"/>
</stringbundleset>
In my ff-sidebar.js I do on click:
var strbundle = document.getElementById("strings");
var localizedString = strbundle.getString("test");
This gives me following error
Should it not be
var strbundle = document.getElementById("stringbundleset");
This gives me no error but no result too.

Basically what Neil posted there is what you need to do (minus first paragraph rant :P )
Here's an example (basically digest from Neil's links):
Your XUL file:
<stringbundleset id="strbundles">
<stringbundle id="strings" src="chrome://yourextension/locale/something.properties"/>
</stringbundleset>
Your something.properties (there you define your localized strings key=value). Of course you can have as many files as you want/need:
something=Some text for localization
something2=Some more text
Your js file:
var strbundle = document.getElementById("strings");
var localizedString = strbundle.getString("something");
Hope this helps.

This works for small numbers of entities. For instance, menuitems sometimes have two entities with slightly different text depending on what the menuitem will be used for, and the correct entity is then copied to the label. The worst abuse of this was for the Delete menuitem in Thunderbird and SeaMonkey's mail windows, which had labels for unsubscribing from newsgroups, deleting folders, cancelling news posts, deleting single or multiple messages, or undeleting single or multiple messages from folders using the IMAP mark as delete model. Phew!
If you have lots of locale data then the best thing is to put it in its own .properties file and read it using a <stringbundle>. If your script doesn't have access to a <stringbundle> element it is also possible to manually retrieve an nsIStringBundle from the nsIStringBundleService.

Related

Acumatica Customization: Add PO Nbr column to SO Line

I am trying to create a customization to add the PO Nbr associated in the PO Link graph to a column in the SO Line. I know the link is made in the SOLineSplit table, but I am struggling with how to actually show that field in the SO Line. I have made a custom Usr field for PO Nbr, but not sure what I should be entering in the attributes (or DAC extension, whatever is the best way) in order to show the PO Nbr data from the SOLineSplit table.
I remember struggling with this early on, so it's an excellent question. The challenge is that you mention getting to the PO from the SO LINE, but an SO Line can be split across multiple PO's. That's why you end up having to dig into the SOLineSplit for the link. Let's take a look at the link from SOLineSplit to PO...
There are a couple of possibilities when you look into the SOOrderEntry graph. The following code snippets show relationships. Your SOLineSplit may have a direct reference to the PO/POLine as shown here:
PXSelectBase<POLine> selectlinkedDropShips = new PXSelectJoin<POLine,
InnerJoin<SOLineSplit, On<SOLineSplit.pOType, Equal<POLine.orderType>,
And<SOLineSplit.pONbr, Equal<POLine.orderNbr>,
And<SOLineSplit.pOLineNbr, Equal<POLine.lineNbr>>>>>,
Where<SOLineSplit.orderType, Equal<Current<SOOrder.orderType>>,
And<SOLineSplit.orderNbr, Equal<Current<SOOrder.orderNbr>>,
And<POLine.orderType, Equal<POOrderType.dropShip>>>>>(this);
If that simple path doesn't get you there, the more detailed path of an SO to a PO lies in the INItemPlan reflecting the demand of the SOLineSplit (via the PlanID) and then tied to POLine via POLine.PlanID = INItemPlan.SupplyPlanID as shown in the following snippet.
foreach (PXResult<POLine, POOrder, INItemPlan, SOLineSplit> res in PXSelectJoin<POLine,
InnerJoin<POOrder, On<POLine.FK.Order>,
InnerJoin<INItemPlan, On<INItemPlan.supplyPlanID, Equal<POLine.planID>>,
InnerJoin<SOLineSplit, On<SOLineSplit.planID, Equal<INItemPlan.planID>,
And<SOLineSplit.pOType, Equal<POLine.orderType>,
And<SOLineSplit.pONbr, Equal<POLine.orderNbr>,
And<SOLineSplit.pOLineNbr, Equal<POLine.lineNbr>>>>>>>>,
Where<POLine.orderType, Equal<Required<POLine.orderType>>,
And<POLine.orderNbr, Equal<Required<POLine.orderNbr>>,
And2<Where<POLine.cancelled, Equal<boolTrue>,
Or<POLine.completed, Equal<boolTrue>>>,
And2<Where<POOrder.orderType, NotEqual<POOrderType.dropShip>,
Or<POOrder.isLegacyDropShip, Equal<True>>>,
And<SOLineSplit.receivedQty, Less<SOLineSplit.qty>,
And<SOLineSplit.pOCancelled, NotEqual<boolTrue>,
And<SOLineSplit.completed, NotEqual<boolTrue>>>>>>>>>
.Select(graph, poOrder.OrderType, poOrder.OrderNbr))
{...
As you can imagine, you would have to set some rules around restricting an SO Line to a single PO, but that honestly would be more trouble than it's worth as the standard functionality is valuable in being more robust. I would suggest either putting your link in the Allocations list (or Line Details in more recent versions of Acumatica ERP) or produce a smart panel popup to show all the PO links per splits of the current SO Line.

Parse HTML to retrieve specific tags value with Google Apps Script

I'm trying to parse a HTML to retrieve the value of tag, on my Google Apps Script code. contains line breaks in attributes, and appears more than once but I only want the first value. (In this case, only 'foo' is required.)
<b class="
"
>
foo
</b><b class="
"
>
var
</b>
On Google Apps Script, functions such as 'getElementByTagName' is not available. So I first though of using regexp but it's not the wise option here.
Does anyone have an idea on how I can move forward? Any comment/guess would be highly appreciated!
How about using XmlService for your situation as a workaround? At XmlService, even if there are several line breaks in the tags, the value can be retrieved. I think that there are several workarounds for your situation. So please think of this as one of them.
The flow of sample script is as follows.
Flow :
Add the header of xml and a root element tag to the html.
Parse the creates xml value using XmlService.
Retrieve the first value of tags using XmlService.
Sample script :
var html = '<b class="\n"\n>\nfoo\n</b><b class="\n"\n>\nvar\n</b>\n'; // Your sample value
var xml = '<?xml version="1.0"?><sampleContents>' + html + '</sampleContents>';
var res = XmlService.parse(xml).getRootElement().getChildren()[0].getText().trim();
Logger.log(res) // foo
Note :
In this sample script, your sample html was used. So if you use more complicated one, can you provide it? I would like to modify the script.
Reference :
XML Service
If this was not what you want, please tell me. I would like to modify it.
Edit 1 :
Unfortunately, for the value retrieved from the URL, above script cannot be used. So I used "Parser" which is a GAS library for your situation. The sample script is as follows.
Sample script :
var url = "https://www.booking.com/searchresults.ja.html?ss=kyoto&checkin_year=2018&checkin_month=10&checkin_monthday=1&checkout_year=2018&checkout_month=10&checkout_monthday=2&no_rooms=1&group_adults=1&group_children=0";
var html = UrlFetchApp.fetch(url).getContentText();
var res = Parser.data(html).from("<b class=\"\n\"\n>").to("</b>").build().trim();
Logger.log(res) // US$11
Note :
Before you run this script, please install "Parser". About the install of library, you can see it at here.
The project key of the library is M1lugvAXKKtUxn_vdAG9JZleS6DrsjUUV
References :
Parser
Managing libraries
google app script Exceeded memory limit
google script scrape parser with 2 classes with the same name
Edit 2 :
For your 2nd URL in your comment, it seems that the URL is different from your 1st one. And also your new URL has no tag of <b class=\"\n\"\n>. By this, the value you want cannot be retrieved. But from the 1st URL in your comment, I presumed about the value what you want. Please confirm the following script?
var url = "https://www.booking.com/searchresults.ja.html?ss=kyotogranvia&checkin_year=2018&checkin_month=10&checkin_monthday=1&checkout_year=2018&checkout_month=10&checkout_monthday=2&no_rooms=1&group_adults=1&group_children=0";
var html = UrlFetchApp.fetch(url).getContentText();
var res = Parser.data(html).from("<span class=\"lp-postcard-avg-price-value\">").to("</span>").build().trim();
Logger.log(res) // US$289

Umbraco console app to change the name and link of a document without publishing all children

I've written a console app using the Umbraco (7.1.4) contentService API to move some nodes and rename them in a site redesign. It all works fine except when I rename the document the 'Link to Document' doesn't change. The code is adapted from https://github.com/sitereactor/umbraco-console-example.
private static void MoveNode(IContentService contentService, int nodeId, int newParentId, string newname)
{
//Get the Root Content
var nodeContent = contentService.GetByIds(nodeId.AsEnumerableOfOne()).First();
nodeContent.Name = newname;
contentService.Move(nodeContent, newParentId);
var status = contentService.SaveAndPublishWithStatus(nodeContent);
Console.WriteLine(status);
}
Status is True and the page name is changed when I look at it in back office but the 'Link to Document' doesn't change. Now if I use
var status = contentService.PublishWithChildrenWithStatus(nodeContent);
Then it works but takes a lot longer (minutes), but if I change the name in back office then it only takes seconds but the links are updated correctly. Is there another way to rename a document without Publishing all the children?
(I've left out a bit of code in the above - sometimes it moves sometimes it just renames, but in either case I have to publish with the children to get it to work.)
It seems this happens because the XML cache file has not been updated.
Have a look here for a few ways of doing it
http://our.umbraco.org/wiki/reference/api-cheatsheet/publishing-and-republishing
Or the quickest is just delete APP_Data\umbraco.config - the XML cache file, probably not recommended for Prod but gets things working quickly in dev.

umbraco - how to get all of nodes by Document Type

How can I get all nodes by specific Document Type?
For example, I want to get in code behind all of nodes with Document Type: s3Article. How can I do this?
New informations:
IEnumerable<Node> nodes = uQuery.GetNodesByType("s3Article").Where(x => x.NiceUrl.Contains("en"));
lvArticles.DataSource = nodes;
lvArticles.DataBind();
This is my code. I had to use Where(x => x.NiceUrl.Contains("en")), because I have 2 language version- without Where I receive nodes from all catalogues with doctype s3Article, but I want to get only from one language version.
Problem is here:
<a href='<%# umbraco.library.NiceUrl(Tools.NumericTools.tryParseInt( Eval("id"))) %>'><%# Eval("title")%></a>
<%# Tools.TextTools.makeIMGHTML("../.."+ Eval("img").ToString(),"180") %>
<%# umbraco.library.StripHtml(Limit(Eval("Article"), 1000))%>
<%# Eval("author")%>
System.Web.HttpException: DataBinding:
'umbraco.presentation.nodeFactory.Node' does not contain a property named 'title'.
The same problem happens with the title, img, article, author. Only ID works nice. How to resolve it?
You can use the uQuery GetNodesByType(string or int) method:
IEnumerable<Node> nodes = uQuery.GetNodesByType("s3Article");
Alternatively, you can use an extension method to get all descendant nodes and then query them by type as in the following answer:
Umbraco 4.6+ - How to get all nodes by doctype in C#?
You could use this to databind to a control within a usercontrol like so:
lvArticles.DataSource = nodes.Select(n => new {
ID: n.Id,
Title: n.GetProperty("title").Value,
Author: n.GetProperty("author").Value,
Article: n.GetProperty("article").Value,
Image: n.GetProperty("img").Value,
});
lvArticles.DataBind();
Only you would need to strip the html, convert the image id to a url, etc. within the select statement as well...
As Shannon Deminick mentions, uQuery is somewhat obsolete. ExamineManager will be the fastest execution time. https://our.umbraco.org/forum/developers/api-questions/45777-uQuery-vs-Examine-vs-IPublishedContent-for-Querying
I also found it to be the easiest and most readable approach to use ExamineManager's search builder. Very flexible, and has the added benefit of being very readable due to the Fluent Builder pattern the U Team used.
This will search ALL nodes, so if you need within a specific branch, you can use .ParentId(1234) etc.
var query = ExamineManager.Instance.CreateSearchCriteria()
.NodeTypeAlias("yourDocumentType")
.Compile();
IEnumerable<IPublishedContent> myNodes = Umbraco.TypedSearch(query);
I prefer typed nodes, but you can also just use "Search()" instead of "TypedSearch()" if you prefer dynamic nodes.
Another example including a specific property value "myPropValue" == "ABC",
var query = ExamineManager.Instance.CreateSearchCriteria()
.NodeTypeAlias("yourDocumentType")
.Or() //Other predicate .And, .Not etc.
.Field("myPropValue", "ABC")
.Compile();
Ref - https://our.umbraco.org/documentation/reference/querying/umbracohelper/

Best way of storing an "array of records" at design-time

I have a set of data that I need to store at design-time to construct the contents of a group of components at run-time.
Something like this:
type
TVulnerabilityData = record
Vulnerability: TVulnerability;
Name: string;
Description: string;
ErrorMessage: string;
end;
What's the best way of storing this data at design-time for later retrieval at run-time? I'll have about 20 records for which I know all the contents of each "record" but I'm stuck on what's the best way of storing the data.
The only semi-elegant idea I've come up with is "construct" each record on the unit's initialization like this:
var
VulnerabilityData: array[Low(TVulnerability)..High(TVulnerability)] of TVulnerabilityData;
....
initialization
VulnerabilityData[0].Vulnerability := vVulnerability1;
VulnerabilityData[0].Name := 'Name of Vulnerability1';
VulnerabilityData[0].Description := 'Description of Vulnerability1';
VulnerabilityData[0].ErrorMessage := 'Error Message of Vulnerability1';
VulnerabilityData[1]......
.....
VulnerabilityData[20]......
Is there a better and/or more elegant solution than this?
Thanks for reading and for any insights you might provide.
You can also declare your array as consts and initialize it...
const
VulnerabilityData: array[Low(TVulnerability)..High(TVulnerability)] of TVulnerabilityData =
(
(Vulnerability : vVulnerability1; Name : Name1; Description : Description1; ErrorMessage : ErrorMessage1),
(Vulnerability : vVulnerability2; Name : Name2; Description : Description2; ErrorMessage : ErrorMessage2),
[...]
(Vulnerability : vVulnerabilityX; Name : NameX; Description : DescriptionX; ErrorMessage : ErrorMessageX)
)
);
I don't have an IDE on this computer to double check the syntax... might be a comma or two missing. But this is how you should do it I think.
not an answer but may be a clue: design-time controls can have images and other binary data associated with it, why not write your data to a resource file and read from there? iterating of course, to make it simpler, extensible and more elegant
The typical way would be a file, either properties style (a=b\n on each line) cdf, xml, yaml (preferred if you have a parser for it) or a database.
If you must specify it in code as in your example, you should start by putting it in something you can parse into a simple format then iterate over it. For instance, in Java I'd instantiate an array:
String[] vals=new String[]{
"Name of Vulnerability1", "Description of Vulnerability1", "Error Message of Vulnerability1",
"Name of Vulnerability2", ...
}
This puts all your data into one place and the loop that reads it can easily be changed to read it from a file.
I use this pattern all the time to create menus and for other string-intensive initialization.
Don't forget that you can throw some logic in there too! For instance, with menus I will sometimes create them using data like this:
"^File", "Open", "Close", "^Edit", "Copy", "Paste"
As I'm reading this in I scan for the ^ which tells the code to make this entry a top level item. I also use "+Item" to create a sub-group and "-Item" to go back up to the previous group.
Since you are completely specifying the format you can add power later. For instance, if you coded menus using the above system, you might decide at first that you could use the first letter of each item as an accelerator key. Later you find out that File/Close conflicts with another "C" item, you can just change the protocol to allow "Close*e" to specify that E should be the accelerator. You could even include ctrl-x with a different character. (If you do shorthand data entry tricks like this, document it with comments!)
Don't be afraid to write little tools like this, in the long run they will help you immensely, and I can turn out a parser like this and copy/paste the values into my code faster than you can mold a text file to fit your example.

Resources