Choose a valid template solution that can render custom functions - ruby-on-rails

I'm wondering how to let my customer 'personalize' their view executing some of my custom functions using an mustache/handlebar format, but I'm not able to understand how to do it effectively. I have it in my mind the flow, but in code, I don't know where to start.
Example given:
I want my users to be able to invoke a function/method called read_json(url,key)
So in my mind, the flow should be to have a template like mustache or liquid and have: Today the weather is {{read_json(https://weathersystem,temperature)}} degrees and have it rendered to: Today the weather is 56 degrees.
Or maybe having a set of functions that the user will declare as variable weather somewhere in my rails database, specific to the user like: weather=read_json("https:/weathersystem", temperature) and then the user would be able to do something like: Today the weather is {{weather}} degrees
Since the text or function the user might want to add or {{ function }} to be rendered every time it's invoked by the users since the text they have this could be rendered in a normal view or into an API response.
I'm kinda struggling figuring it out what or how can be done.
Cheers!

I think it should be done on client side
so if you use jQuery, you can do this
your view file: x.html
<div>Today the weather is <span class="read-json" data-type="weathersystem" data-subtype="temperature"></span> degrees</div>
javascript file
$('.read-json').each(function(el) {
var $el = $(el)
var type = $el.data('type')
var subType = $el.data('subType')
// url = ... set URL based on `type` and `subType` variable above
$el.load(url)
}

Related

Add Offset selector to Grails Pagination

I have this grails application and I've added a number field and a button which on click passes on the query parameters, specifically the offset value so the user can navigate to a specific page faster, since the pagination has some 2000+ pages on a max=10 basis, you can imagine navigating that. Anyway, so my problem is that I'm handing the offset with jquery and all fine but when I press enter on the number field that triggers the form which is build in combination with the controller and practically filters back to page 1. So I wonder if someone knows how would I add an extra field that will pass in an offset value as well when form with filters is submitted. Sorry no code to post but this application is a monster and I suck at Grails or Spring boot in general. Any support is appreciated.
Do you mean 2000 pages or rows.
Also i think if you share some few codes from your
Controller method
GSP (Thus the .gps file)
Javascript implementation
it will give a lot of people an insight on how to help us all solve the questions
I'll post the answer for those who might look for this.
Grails pagination uses TwitterBootstrapTagLib class, you'll find the pagination logic there. It looks for an 'offset' variable in the session params and if it doesn't find one it creates one.
Now the solution is a bit trickier than setting an 'offset' variable because when you do so you will disable the paging arrows, why? too long to explain, but trust me, you will.
To avoid having to control all the other parts of the pagination which is done perfectly well from this class you can create a new session variable, e.g. _offset, in the controller that calls the data that needs pagination.
def controllerActionX() {
...
if(params.containsKey('offset') && !params.containsKey('_offset')){
params['_offset'] = params.offset
}
...
}
You need to check first because in a second iteration you don't want to reassign offset to _offset because then you'll be stuck in one page. Also notice that offset already exists in the session, assigned by the bootstrap class.
Then you create your fields in the view:
<input type="submit" class="goto-page" id="goto-page" value="Go To Page"/>
<g:field type="number" class="topage-number" name="_offset" min="1" value="${params._offset?:1}"/>
This is self-explanatory, however, the value from the _offset field is a value entered by a human so we still need to calculate the offset based on the max records per page, i.e. in order to get page 2 on a 10 records-per-page basis, our offset has to be between 11-19, 19 preferably because it makes calculation easier.
And last step in the service layer we calculate everything like this:
def get(HttpSession session, Map params, Xclass xUser, String status) {
....
String offset = '0'
if(params.containsKey('_offset')){
if(params['_offset'] != params.offset){
params.offset = ((params._offset as int) * (max as int)) - 1
}else{
params['_offset'] = (params.offset as int) / (max as int) + 1
}
}
if (params.containsKey('offset')) offset = params.offset
...
def result = executeQuery(resultsQuery,mapping, [max: max, offset: offset])
result
That's it. Remember to cast your variables as integers when you calculate; you don't have to convert them to String after that since that is handled by the session.
By the way this is a poorly written application because the service layer should never handle any endpoint transactions, that is only a controller's job if we're following proper SOLID and MVC principles, but I found this application like this so I had to work with it.

Adobe DTM Pass Unix Timestamp to eVar

I'd like to pass the Unix timestamp to a hit level eVar in DTM. I would assume I could pass some Javascript like this:
function() {
var now = new Date();
return now.getTime();
}
However, I am not sure where to pass it in DTM. Would this be passed in the "Customize Page Code" editor in the Tool Settings or somewhere else?
You can create a Data Element of type Custom Code. Name it something like current_timestamp or whatever. The code should not be wrapped in the function declaration syntax (DTM already wraps it in a function callback internally). So just put the following in the code box:
var now = new Date();
return now.getTime();
Then in your Adobe Analytics Tool Config (for global variables), or within a Page Load, Event Based, or Direct Call Rule, within the Adobe Analytics Config section. choose which eVar you want to set, and for the value, put %current_timestamp% (or whatever you named it, using % at start/end of it. You should see it show up in a dropdown as you start typing % in the value field).
Alternatively, if you want to assign the eVar in a custom code box in one of those locations, you can use the following javascript syntax e.g (assume eVar1 in example).
s.eVar1 = _satellite.getVar('current_timestamp');
Note that with this syntax, you do not wrap the data element name with %
One last note. This is client-side code, so the timestamp will be based on the user's browser's timezone settings. So for example, a visitor from the US and another visitor from China both visiting a page physically at the same time (server request at the same time), will show two different timestamps because they are in two different timezones.
This makes for some misleading data in reports, so make sure you break it down by other geo based dimensions, or do some extra math in your Data Element to convert the timestamp to a single timezone (e.g. convert it to EST). In practice, most people will pick whatever timezone their office is located in, or else what their server's timezone is set to.

Dynamic Tag Management - Storing

We're in the process of moving to DTM implementation. We have several variables that are being defined on page. I understand I can make these variables available in DTM through data elements. Can I simply set up a data elem
So set data elements
%prop1% = s.prop1
%prop2% = s.prop2
etc
And then under global rules set
s.prop1 = %s.prop1%
s.prop2 = %s.prop2%
etc
for every single evar, sprop, event, product so they populate whenever they are set on a particular page. Good idea or terrible idea? It seems like a pretty bulky approach which raises some alarm bells. Another option would be to write something that pushes everything to the datalayer, but that seems like essentially the same approach with a redundant step when they can be grabbed directly.
Basically I want DTM to access any and all variables that are currently being set with on-page code, and my understanding is that in order to do that they must be stored in a data element first. Does anyone have any insight into this?
I use this spec for setting up data layers: Data Layer Standard
We create data elements for each key that we use from the standard data layer. For example, page name is stored here
digitalData.page.pageInfo.pageName
We create a data element and standardize the names to this format "page.pageInfo.pageName"
Within each variable field, you access it with the %page.pageInfo.pageName% notation. Also, within javascript of rule tags, you can use this:
_satellite.getVar('page.pageInfo.pageName')
It's a bit unwieldy at times but it allows you to separate the development of the data layer and tag manager tags completely.
One thing to note, make sure your data layer is complete and loaded before you call the satellite library.
If you are moving from a legacy s_code implementation to DTM, it is a good best practice to remove all existing "on page" code (including the reference to the s_code file) and create a "data layer" that contains the data from the eVars and props on the page. Then DTM can reference the object on the page and you can create data elements that map to variables.
Here's an example of a data layer:
<script type="text/javascript">
DDO = {} // Data Layer Object Created
DDO.specVersion = "1.0";
DDO.pageData = {
"pageName":"My Page Name",
"pageSiteSection":"Home",
"pageType":"Section Front",
"pageHier":"DTM Test|Home|Section Front"
},
DDO.siteData = {
"siteCountry":"us",
"siteRegion":"unknown",
"siteLanguage":"en",
"siteFormat":"Desktop"
}
</script>
The next step would be to create data elements that directly reference the values in the object. For example, if I wanted to create a data element that mapped to the page name element in my data layer I would do the following in DTM:
Create a new data element called "pageName"
Select the type as "JS Object"
In the path field I will reference the path to the page name in my data layer example above - DDO.pageData.pageName
Save the data element
Now this data element can be referenced in any variable field within any rule by simply typing a '%'. DTM will find any existing data elements and you can select them.
I also wrote about a simple script you can add to your implementation to help with your data layer validation.Validate your DTM Data Layer with this simple script
Hope this helps.

Big Commerce Custom Fields

I'm planning on allowing a client to provide a couple codes for each product that I'll need to reference with Javascript on the product pages.
Basically my plan was to use the Big Commerce's 'custom fields' to do so, but I'm having trouble spitting out the custom fields onto the product pages. I've been looking all over for some type of GLOBAL variable that allows me to reference custom fields, but I'm coming up dry. I would think there would be some type of GLOBAL array with all the custom fields in it, or a way to reference them by name directly.
Am I blind, or is there just no way to do this directly in the BC template file?
Thanks.
In Bigcommerce the custom fields can generally be found within the ProductOtherDetails.html Panel which contains a Snippet named ProductCustomFieldItem.html. This snippet has the markup for each custom field that the system outputs.
Inside of the ProductCustomFieldItem.html Snippet are the two codes you are looking for: %%GLOBAL_CustomFieldName%% and %%GLOBAL_CustomFieldValue%%.
I ran into this as well - given that it's quite a long time later, I'm supposing there's no better answer - a decent amount of searching turned up nothing useful as it seems all you can do is output the full set of custom fields as a set of divs.
So, I output them into a div which was hidden:
<div id="fpd-custom-fields" style="display:none;">
%%SNIPPET_ProductCustomFields%%
</div>
and then set up a javascript function to get the value based on the name:
function getCustomFieldValue(label)
{
var value = '';
$('#fpd-custom-fields div.Label').each(function()
{
if($(this).text().toLowerCase() == (label.toLowerCase() + ':'))
{
value = $('div.Value', $(this).parent()).text().trim();
}
});
return value;
}
Doesn't feel quite right as it's not a very clean solution, but was the best I could come up with unfortunately!

JQGrid and .NET MVC - Load Search Results

Ok, I am new at jQuery, but the JQGrid has peaked my interest. While implementing the grid, I have come across two problems that I am not sure how to solve. Both involve loading the grid with results.
How do you load the grid when you have parameters in your route. For instance, http://domain.com/search/results/2010/KY...I am wanting all results matching 2010 in Kentucky. In the javascript section of the grid initialization, I need to supply a URL (such as /search/gridResults/). How does one pass the other route values or at least use them to load the grid.
Same question, but more along the lines of when the page is loaded with posted form values from a search form.
Perhaps the URL is mostly to do with AJAX-y functions. It would be nice to sort and page with AJAX but to load the grid with AJAX is not neccessary.
Sorry for the long post, but I am sure others have faced this problem even though Google tells me otherwise :) PS - I have looked at Phil Haacks (sp?) and Craig something's blogs about using JQGrid, but neither touch upon loading pre-determined search results.
You can specify that directly with the 'url' key. e.g.: /search/gridResults/2010/KY
I actually use a custom javascript method in the postData jqgrid key for this (which you could use to solve your question 1 depending on the situation). This seemed kind of lame to me that I had to write this method, but I found something on the internet and had to keep hacking on it to make it flexible enough for my uses.
Code for custom method below. It reads params from the url directly. For POST params, you would need to do something else obviously, but to get them to jqgrid, it's the same idea:
// Read a page's GET URL variables and return them as an associative array.
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(
window.location.href.indexOf('?') + 1
).split('&');
for(var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
if (hash.length == 2) {
vars.push(hash[0]);
vars[hash[0]] = decodeURIComponent(hash[1].replace("+", "%20"));
}
}
return vars;
}
Hopefully that helps... If you come up with something better, I'd love to hear it. :)

Resources