Adobe DTM and arrays with varying numbers of elements - javascript

On our site, we have pages that can be assigned tags, and I'm having issues with figuring out how to handle this with Adobe DTM/Analytics. Each page can have between 1 and n tags being captured in an array. I can see them in the developer console just fine, ex:
> data.page.termIds
< [513, 1787, 115, 4330]
Each element corresponds to the tag ID.
I've been searching online but can't find any answers that really help me. This blog post is close, but it looks like they need to create a separate data element for each element in the array. I also found this question in the adobe forums, but it's similar to the blog post.
Does anyone know if this is even possible? Are we expected to create a block of data elements, with each one assigned to an array index?

Do not bother with the JS Object option unless you want to target a top level js object/variable. So for example foobar is okay but foo['bar'] or foo.bar is not. If you want to target anything "nested", skip JS Object and use Custom Script to check for it and return it, instead. This is because DTM doesn't do a good job of parsing or checking if the parent nodes exist before returning it. This is basically what was already said in the blog link you mentioned.
As for what the Data Element is returning and how to use it...the Data Element itself will have a return value of exactly what you return. So if you return an object, it will be an object. If you return an array, it will be an array. The trick (or caveat, or bug, depending on how you want to look at it) is how you reference or use the Data Element within the tools and rules.
The long story short of it is this: If you intend to use the %data_element_name% syntax (e.g. in any of the built in form fields in the rules, config settings, etc.) then you should only have your Data Element return a string type value (this is basically the issue the forum post link had, and I assume the issue you are running into).
If you want to be able to access it as some other type (e.g. the array, or js object in general), you need to use _satellite.getVar('data_element_name') syntax. The obvious drawback to this is it basically makes using DTM in a "non-coder" way useless in that you cannot use this in any of the built-in fields in rules. You can only use it in contexts where you can write javascript, e.g. Data > Custom type Conditions or in Javascript / 3rd Party Tag containers.
But one question for you is, what are you ultimately using the Data Element for? For example, if the end game here is you are looking to populate a prop or eVar or some other variable with a comma delimited string.. well just return your array as such in your Data Element and then you can use the %data_element_name% syntax.

Capturing the data is one thing and formatting is another.
My question is how do you need to see this data organized in reporting? Capturing the array itself doesn't do much unless you know what format you need it in. Are you hoping to capture these IDs and classify them? Do you want to see the array list by page?
Can you provide more detail on how you'll be reporting on these values?

Related

Read SharePoint List item using JavaScript

I am wondering if anyone could clarify my confusion on how to use JavaScript to read/filter SharePoint List items, please?
As a code example from MSDN:
https://msdn.microsoft.com/en-us/library/office/hh185007(v=office.14).aspx
In the CAML query XML, what is the FieldRef field in SharePoint List? Is it defined column names/list properties?
When ClientContext object load collListItem, it has a (Include) parameter which includes a bunch of field/property names, what are they? Are they defined column names/list properties as well?
Is there anyway I can know what field names are, so I can use/filter the List?
Thank you.
The FieldRef is the internal field name of the column. Sometimes it's the same as the display name but as the display name can be changed you can't be certain of this. When creating new columns, I find it best to create them WithoutSpacesLikeThis and then replace the spaces once created. This makes it much easier to see what's happening when you're referencing them in code or in a URL etc. The same with Sites,Lists, Libraries etc.
The quickest way to find the internal name is to open the column as if you were going to edit it and then look in the URL and you will find the internal name there.
For example, the internal name of ApprovalStatus is at the end of the below URL after Field=. If the field has been created with a space in the name the space will be replaced by %20. E.g. Approval%20Status.
_layouts/15/FldEdit.aspx?List=%7BE07BFB18-BBED-4A57-8988-6CAEB47FAA02%7D&Field=ApprovalStatus
Another way to see the field names would be to use the REST api. You can do this by adding _api/web/lits/getbytitle('NameOfList')/items to the end of the site collection URL. However, depending on the number of items you have in the list, it might return a lot of data.
https://tenant.sharepoint.com/sites/app/_api/web/lists/getbytitle('NameOfList)/items
When ClientContext object load collListItem, it has a (Include)
parameter which includes a bunch of field/property names, what are
they? Are they defined column names/list properties as well?
As far as this part of your question is concerned, can you provide some of the properties to give a better idea of what it is you're talking about, please?

Accessing the text value of custom column with NetSuite SuiteScript

I am working with NetSuite's server-side SuiteScript and need to access the display value of several custom Transaction Column Fields. The fields in question are each set up as type "List/Record" and are associated with existing Custom Lists.
Working in the NetSuite Script Debugger, I have inspected the values returned from nlapiLoadRecord('salesorder', orderInternalId). Looking at the Items in the resulting object (e.g. obj.sublists.item.line 1) I see that some of these List/Record custom fields provide both a number (the ID of the selected List entry) and a string (the displayed text value of the List entry), but other custom fields do not.
For example, I have two custom fields with IDs custcol1 and custcol2. These are both of type "List/Record". When the sales order is loaded, nlapiLoadRecord provides the fields "custcol1" (number) and "custcol1_display" (string) for custcol1, but only "custcol2" (number) for custcol2. I do not see any difference in the settings for these two custom fields, so it is unclear why one provides the string and the other does not.
I need to retrieve the string values for both fields. Is there a setting change I need to make so custcol2 will automatically return a "custcol2_display" value? Or is there another API call I can use to take the number value from "custcol2" and look up the associated string value in the underlying Custom List?
Try using record.getLineItemText('item', 'custcol2', linenum)
For debugging, I tend to use Firebug - it's a lot more effective than the NS debugger and quicker than logging statements for just testing things out.
I just noticed this is two years old, but I think you can put columnname.id to get the data value. It works for standard columns but not sure about custom ones.
One thing I have learned to use is the NetSuite debugger, I don't use it like a standard debugger but rather like the javascript console. Just paste in some code into the box and then debug it, it is great for seeing what the dang property values are and the data in them which seems to be a crapshoot in NetSuite.

Optimal way to pass system values to javascript

What is the most effective way to pass object and category ids or other system variables which shouldn't be presented to the user, from server to the browser?
Let's say I have a list of items where I can do something with each of them by javascript, for example show tooltip html or add to favorites by ajax, or display on a map. Where is it best to save that tooltip html, or database id, or geoposition?
Some options I can think of are:
some dictionary within <script></script> tag for each item,
microformats,
inline xml,
rel attributes,
css class names with specific information, e.g. class="lat-12345 uid-45678",
one <script></script> with a dictionary of html ids mapping dictionaries with system values in the template,
javascript generated from the database and included via <script src="..."></script> with a dictionary of html ids mapping dictionaries with system values in the template,
ajax requests for all cases when I need more information than just id,
event handlers with parameters within html tags, e.g. onmouseover="tooltip(this, 123, 'Hello world!')".
P.S. I prefer unobtrusive solutions and also the loading/execution time is important.
Perhaps I am missing something... why not just JSON?
How you "send" it (either in the initial page load as "javascript" or via AJAX or whatnot) is really just a trivial detail determined mostly by when the data is available. (JSON is a subset of legal JavaScript syntax.)
Then it's just a matter of the correct transformation. Of course, by pushing this to JSON/JS, you may render some non-JS clients non-interoperable, if that's a consideration for you. If such is indeed the case, why not just perform the transformation server-side using well, any number of the techniques you put at top?
You can also use arbitrary attributes in HTML (the HTML5 spec may include "data-*" which is formally legalized) -- while not technically "correct", all major web-browsers will accept unknown attributes which can be accessed through the DOM API.
I'd prefer a single AJAX call to fetch whatever data you know you need at the outset, so you can have a simple JSON object available in your script. You can, of course, supplement that with additional calls should you find you need more information.
If that's impractical, then "hardcoding" a JavaScript object in a <script>...</script> tag is the next best option. Of course, "hardcoding" is from the browser's perspective. The actual content would surely be written by server-side script from your database.
One method you can use is custom attributes. I think you refer to this as micro-formats, but I am not entirely sure if they are the same thing so I have written a description below.
Having hit the same question before, I basically use something like the following:
<div data-pid="1234">
<a href="#" class="add-to-favourites">
<img src="addToFavourites.png" />
</a>
</div>
$("a.add-to-favourites").click(function() {
$.load("/Favourites/Add.php?prodID="+$(this).parent().attr("data-pid"));
});
This should do exactly what you want to do. The reason I have put the pid in the div, not the a tag, is that you can then place all the other product information within the div with other actions the user can take, for example displaying a tooltip on mouseover using data-description, or displaying on a map using data-geo-x and data-geo-y. Of course you can name these anything you want.
Support / Acceptance
This is becoming a perfectly accepted way to do what you want to do. HTML 5 supports this for precisely the kind of thing you are trying to achieve.
So it is supported by HTML 5, but what about HTML 4?
It may make HTML 4 invalid, but the world is moving on to bigger and better things. Older browsers (IE6 and before, FF1 / 2, Opera 7 / 8 / 9) are becoming less common so it shouldnt be a problem. It wont actually break older browsers - the functionality will still work.
Important validity note
Make sure you prepend the data- onto the attribute name. This will make the attribute perfectly valid in HTML 5.
A few extra hints
In jQuery 1.5, I have heard from an answer to my question that you can simply specify attr("pid") to return the value of data-pid. If this is the case then I would be careful when naming the second part of the attribute name after the name of an actual attribute (for example, instead of data-id, use data-pid - especially if the id attribute is specified. I am not sure what effect it would have if you didn't do this, but its better to avoid the problem in the first place than have issues with the site at a later date due to this.
Hope this is what you were looking for.
ASP.NET offers a very convenient way to do this. You can simply write a JavaScript object. I am sure other templating engines offer similar ways to do this.
var person = {
Name : <%= _person.Name %>,
Age : <%= _person.Age %>
};
I would implement a Javascript singleton AppCacheManager that initializes in the document.ready event. A bit JS oop and you have a fully fledged OOP datastore.
Whenever information is needed, you load it through Ajax / RESTful Webservice and cache it in the AppCache Manager. So you have 2 caches: 1. Browser Cache, possible due to RESTful webservice URL caching, and 2: the JS Cache Manager.
You access all requests to the AppCacheManager which transparently fetches the new data or returns the cached data, so that the client doesnt need to know anything of the caching.
in short:
write a JS CacheManager
don't fetch the whole data at once but in small parts when needed and cache them
define a convenient interface for the cachemanager
Example usage:
linktext
Unobtrusiveness is a very difficult thing in JS and i'd be eager to know something about that, too.
hope that helped.

Any clever ways to serialize an HTML element? - Javascript

I'm trying to store a reference of an HTML tag for later reuse.
e.g. If I click on a div and save a pointer to that div within Javascript, will there be a way I could serialize such pointer? So I could de-serialize it and use the pointer in another instance of the web application?
Only methods I can think of are the following:
Use id or name attributes
Create a CSS selector for that element
Any other ideas guys? =)
You could try generating an XPath string for the element - the more complex the string, the more accurate and portable an identifier it will be.
For example, a simple element-only XPath query string would not be very unique, and likely to re-occur:
'//html/body/div/div/p/strong'
Factoring in all attributes might be overkill
'//html/body[#onclick="somereallylongjavascript" and class="nosidebar"]/div[#id="wrapper" and #class="posts"]/div[#class="entry" and #id="firstentry"]/p[#class="first"]/strong'
But you could probably find a nice middle-ground by limiting to certain attributes, maybe just to IDs:
'//html/body/div[#id="wrapper"]/div[#id="firstentry"]/p/strong'
You can retrieve XPath natively in all browsers. There's the W3C method:
var myElement=document.evaluate(
XPathstring,
document,
function(ns){return{'html':'http://www.w3.org/1999/xhtml','':null}[ns];},
9,
null
).singleNodeValue;
(the ns function is purely if you need application/xhtml+xml support)
The IE method is more simplistic but less flexible:
var myElement=document.selectSingleNode(XPathString);
Creating the XPath string is a different issue of course - there are various options, none native unfortunately. XPather is a moz add-on that provides an interface that does this - its source is MPL-ed and relatively simple but is probably more than you need. There are various shorter scripts available that provide simpler solutions.
Edit: Justin Johnson has provided a link to an SO answer containing a VERY short XPath-generating function. It's a bit simplistic, it uses odd id notation (id(blah) instead of [#id="blah"]) and doesn't toLowerCase() its tagNames which could impair portability, but other than that it looks perfect for your needs.
What exactly are you trying to save? And where exactly are you re-using it?
A DOM element would be very specific to that particular browser rendering on that page -- Just hitting refresh will give you an whole new DOM element. So, what about it do you need to save & recreate?
How about the innerHTML of the element?
Only logical way is to use id.
It is ussually not hard to assign id to all important elements based on database values.
Based on the way you worded your question, I don't think that would be possible. What exactly do you mean by "another instance of the web application"? Since JavaScript will be running on the client side, you won't be able to share data between clients. However, you might want to do something like store/read from a database. Can you describe more of the functionality you are trying to achieve?
XPath seems to be the most appropriate; however, only if the page structure is (relatively) static up to that node. Here are some references and code:
Method for getting the xpath of an arbitrary node and example use
getPathTo($("a")[4]):
yields
"id("hlinks-custom")/A[2]"
MDC XPath documentation
It looks like JSON.stringify( yourDivReference ) and JSON.parse( serializedObjectString ) might do what you're looking for.
UPDATE: Actually, the JSON methods don't like the circular references in the DOM. See this question for more details: How to serialize DOM node to JSON even if there are circular references?
I do, however, agree with Sergey that using the ID seems like a better way to go.
Another idea - to generate own custom id's for all elements based on some rules:
element id starts from parent id. -> customid = "body/item"
If normal id is available use it. if not, use element type. Than add order in current subtree.
so, you will get something like "body-0/item-0" for example above or "body-0/div-4" if id is not known.
When you will try to use your "custom id" and page will be changed, you will have a chance to find closest element, comparing all elements custom id to stored "custom id".
I've tried something like this:
{tag:"div", style:"float:left;", "class":"fancy", inner:[
{tag:"a", href:"http://google.com", inner:"A link to google!" },
{tag:"a", href:"http://yahoo.com", inner:"A link to yahoo!" }
]}
Seems to work okay, although it's easy to get lost with all the curly brackets.
edit - maybe I completely misunderstood what you want... if you want to serialize a handle to that element, like what would be returned by getElementById, you might as well just use the id.

should I ALSO keep my data in a Javascript data structure? or just in the DOM?

I am very new to Javascript and Jquery, so my apologies for this beginner's question.
In a simple ajax web app, I am creating an HTML page which is mainly a big table. Each row in this table describes an event (party, show, etc). My page not only displays this information but is meant to let the user do a bunch of things with it, in particular to dynamically search and filter the table according to a variety of criteria.
First an abstract beginner's question: in this broad kind of situation (by which I mean that you want your javascript code to run a bunch of operations on the information you retrieve from the webserver) would you use the DOM as a data structure? The ease with which one can search and manipulate it (using Jquery) makes that a possibility. (E.g., "find me table rows describing an event with date column = 2010-01-01 and event type column = 'private party'.) Or would you keep the same information in a traditional Javascript data structure, search/filter/operate on that using plain javascript code and then update the DOM accordingly to display the results to the user?
(As a newbie, I imagine the first, DOM-only approach to be slower while the latter to be take up a good deal of memory. Right? Wrong?)
Assuming the second strategy is reasonable (is it?), then a practical question: can I simply store in my Javascript objects a pointer to the corresponding Jquery object? Eg, can I do
var events = new Array();
// ....
var event3094 = new Event('party','2010-01-01' /*, ... */);
event3094.domElement = $("#correctIdOfTheEventRowInMyTable");
events.push(event3094)
Does this store just a reference (pointer?) to the Jquery object in each Event object or is it creating a new copy of the Jquery object?
I am just wondering "how the pros" do it. : )
Thank you for any advice and insight.
cheers
lara
There are so many ways to do this, but DOM manipulation will almost always be slower than JS manipulation.
To answer your question, anytime you use $(selector) a new jQuery object is created and a match to find the element is performed.
I would recommend two approaches:
FIRST OPTION
Load data in a normal HTML table
Read through the rows, and store just the data (each cell's contents) in an array similar to your code example.
Store a reference to the tr in that object.
Then you can process filter, etc, and only apply changes and searches to the DOM as needed.
SECOND OPTION
Load the page without the table
Load the data as JSON from the server, and generate a table from the data
Store reference to the tr element
Basically, you don't want to perform a $(selector) a 1000 times. The concept is something like this:
var $rows = $("table tr");
// ...
event.domElement = $rows[0]; // Stores reference to existing DOM node, not a new jQuery object.
Then when you need to use jQuery methods on the object, you could use $(yourEvent.domElement) to wrap it in a jQuery wrapper.
Depending on the number of rows you might expect to be shown for most of your users (let's assume it's no more than a few hundred), I myself would probably aim to just keep everything in the DOM table that you're already building. (If you are expecting to be dealing with thousands of rows on one page, you might want to explore a different solution rather than sending it all to the browser.)
There are a few things that you did not mention in your original post. First, how are you creating this table? I imagine using a server-side solution. How easy is that to modify? How much extra work would it be to go through and generate all of your data a second time in a different format, as XML or JSON? Does this add a bunch of complexity on the server-side, only so that you can add more complexity client-side to match? Certain platforms may make this trivial, but is something to consider.
Now, in regards to your alternatives to the DOM:
I agreed and mentioned in a comment above that I don't think JSON would be very optimal "out of the box" for what you want to do. A javascript array is no better. XML is nice in that you can use jquery to easily traverse/filter, but then you still have to deal with your DOM. Sure, you can store references to your DOM elements, but that just seems like a bunch of work up front and then some more work later when matching them up. And without necessarily guaranteeing any major performance boost.
So, to answer your question directly as it is phrased, should you ALSO keep your data in a JavaScript data structure, or just in the DOM: You did mention this was a "simple" ajax web app. My recommendation is to try and keep this simple, then! Your example of how you can so easily use jquery to find rows and cells based on search criteria should be enough to convince you to give this a try!
Best of luck!-Mike
I think you'l find that the DOM method is close to the same speed if I follow your logic right. The second method will require you to manipulate the data, and then apply the changes to the DOM, where the first method allows both operations at the same time.
If youve got alot of data i would for go making objects and just supply it as XML. that way you get most of the same features as operating on the HTML DOM but you dont have a crazy markup structure like a table to navigate through.
I think it's largely a personal preference, but I like to store the objects in JavaScript and then render them to HTML as needed. From my understanding
event3094.domElement = $("#correctIdOfTheEventRowInMyTable");
will store a reference to the jQuery wrapper of your row element (not a copy).
One benefit of storing is JS is that if you have lost of objects (eg 10,000 ) and only render a small fraction of them, the browser will perform a lot better if you're not creating 10,000 * (number of DOM elements per object) elements.
Edit: Oh, and if you can, you might want to send the data from the server to the client as JSON. It's very compact (compared to XML) and in the new browsers it can be parsed quickly and safely using JSON.parse(). For older browsers, just use this library http://www.json.org/js.html . The library will only create a global JSON namespace if the browser doesn't supply it.
One thing to consider is how you need to access your data. If all the data for an element's event is contained in the element (an event operating solely on a table cell for example), then storing in the DOM makes sense.
However, if the calculation of one element depends on data form other elements (a summation of all table cells in a particular column, for example), you may find it difficult to gather up all the data if it's scattered about in DOM elements compared to a single data structure.

Categories