Dynamically changing the xpath expression of a binding element - xpath

I'm trying to reuse a subform by calling it with different datanodes, e.g. by clicking a trigger that changes the xpath expression and then loads the subform.
To do that, I created a binding element but I can't make it change dynamically. I know how to change the instance nodes values, so I make my bind element to point to a node, but it doesn't work. Something like this:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events">
<head>
<xf:model xmlns="">
<xf:instance>
<tmp>
<configuration uri="/tmp/props"/>
<props>
<prop id="demo id 1" value="demo value1"/>
<prop id="demo id 2" value="demo value2"/>
</props>
</tmp>
</xf:instance>
<xf:bind id="dynamicNodeset" nodeset="string(/tmp/configuration/#uri)"/>
</xf:model>
</head>
<body>
<xf:repeat bind="dynamicNodeset">
<xf:output ref="prop/#id"/>
<xf:input ref="prop/#value" class="xforms-value"/>
</xf:repeat>
</body>
</html>
I also tryed this with no success:
<xf:bind id="dynamicNodeset" nodeset="/tmp/configuration/#uri[string()]"/>
Any idea how can I achieve this?
And also via Js:
function changeBinding(modelId, bindId, newNodeset){
var model = document.getElementById(modelId).xfElement;
window.XsltForms_globals.openAction("XsltForms_change");
model.binds[0].nodeset = newNodeset;
model.setRebuilded(true);
model.addChange(bind);
window.XsltForms_globals.addChange(model);
window.XsltForms_globals.closeAction("XsltForms_change");
window.XsltForms_globals.refresh();
}
Thanks in advance.

There is no evaluate function in XPath 1.0 but, as a workaround, if the variable part of the expression is limited, you can always use just a predicate to select the corresponding element such as in /tmp/*[name() = substring-after(/tmp/configuration/#uri, '/tmp/)].

Related

Pass selected element from list group Thymeleaf

I am using Thymeleaf and Spring MVC for a project and I am displaying a list in Thymeleaf and I want to get the selected items and pass them when I press submit
This is my form with the list:
<form th:action="#{/trip-info}" th:object="${trip}" method="post">
....
<a class="list-group-item list-group-item-action" th:each="currentPerson : ${trip.employees}" th:text="${currentPerson.getFirstName() + ' ' + currentPerson.getLastName()}" onclick="addPerson(this)"></a>
</form>
I have the employees list displayed in my page, now I am not sure if I can pass to a controller the selected values or if I must use javascript and construct a body. Does anybody have any ideas ?
Thanks!
Transferring the selected form item is outside the role of 'Thymeleaf'.
'Thymeleaf' is a server side template engine that simply creates code in html.
The event (item select) changed by the client must be processed by JavaScript.
For a simple example,
Before submitting from the form, check the selected item in javascript and create a function that performs the submit.
If you need an example, show me your source code in more detail.
Additional comments -
There are two ways.
1. How does 'a tag' directly tell you about your event?
2. How to externally liseten events of 'a tag'
I wanted the '2' method, and you chose the '1' method.
Your source will be terminated with the href moved before executing the 'onclick' event.
Take a look at this example.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
some method<br/>
some method2<br/>
some method3<br/>
<script>
function someEvent(event){
console.log(event);
}
</script>
</body>
</html>
'href' works but is invalidated by void (0). Or moved to another window tab by target. And then onclick happens sequentially.
I can not speak English and the explanation is immature. I'm sorry.

How do I insert unique meta tags per page using docpad events

I'm trying to write a docpad plugin that will allow me to insert meta tags unique to each page, for example og:title or og:description. I've been able to accomplish this globally with the populateCollections event for global values, but have not been able to do this per page.
I'd like for this to work without the need for a template function so that the meta tag is inserted automatically based on the document's meta. One way might be to grab the contentRendered value in the writeBefore event and do string manipulation that way, but that seems hacky.
Any ideas?
This worked for what I needed. Basically, I'm getting the rendered content right before the file is written using the writeBefore event, and doing a very simple string replace which adds the meta tags and their unique values, which is pulled from the model in the collection.
writeBefore: (opts) ->
docPad = #docPad
templateData = docpad.getTemplateData()
siteUrl = templateData.site.url
for model in opts.collection.models
if model.get('outExtension') == 'html'
url = #getTag('og:url', siteUrl+model.get('url'))
title = #getTag('og:title', model.get('title'))
content = model.get('contentRendered')
if content
content = content.replace(/<\/title>/, '</title>'+url+title+description)
model.set('contentRendered', content)
# Helper
getTag: (ogName, data) ->
return "\n <meta property=\"#{ogName}\" content=\"#{data}\" />"
Great answer David, leaving this one if someone faced the same issue I did.
Check if meta tag is broken, if it is - don't render:
renderBefore: (opts) ->
for model in opts.collection.models
if model.get('date').toLocaleDateString()=='Invalid Date'
model.set('write', false)
docpad.log model.get('title')+' has broken date format!\n\n\n\n\n'
false
I am using partials in with collections. Adding what is needed in the document like this:
```
title: Meetings and Events
layout: page
description: "This is my custom description."
tags: ['resources']
pageOrder: 3
pageclass: rc-events
```
I needed a custom CSS class by page. Then you can call it in your default template like this.
<div id="main" class="container <%= #document.pageclass %>">
Should be the same for meta
<meta name="description" content="<%= #document.description) %>" />
or check your docpad.coffee file and put together helper function for prepared content based off of a default site value combined with a #document value. Then you can just call something like the default:
<meta name="description" content="<%= #getPreparedDescription() %>" />
Which is built by this helper function:
# Get the prepared site/document description
getPreparedDescription: ->
# if we have a document description, then we should use that, otherwise use the site's description
#document.description or #site.description

how to assign value for id attribute of image tag in visualforce page?

Am not able to assign the id value dynamically for an image...am referring this image javascript to display the up/down arrows accordingly...here is the code snippet...
<apex:variable var="count" value="{!1}"/>
<apex:image id="msn{!count}" url="{!URLFOR($Resource.style_resources, 'images/up-arrow.gif')}" alt="Open-close" />
but i get the compilation error as "literal value is expected for id"...
can't we dynamically assign the value for id attribute ??
From Apex image,
<apex:image id="theImage" value="/img/myimage.gif" width="220" height="55"/>
The example above renders the following HTML:
<img id="theImage" src="/img/myimage.gif" width="220" height="55"/>
So change
<apex:image id="msn{!count}" url="{!URLFOR($Resource.style_resources, 'images/up-arrow.gif')}" alt="Open-close" />
to
<img id="msn{!count}" src="{!URLFOR($Resource.style_resources, 'images/up-arrow.gif')}" alt="Open-close" />
You are correct you can't assign an element id dynamically. it has to be a string literal. I have however used the class attribute to create custom ids that can be later used in javascript. I do this with jQuery and it's powerful selectors to select elements based on tag type and class.
The example below is just a sample but with jQuery you can get pretty creative.
<apex:variable var="count" value="{!1}"/>
<apex:image id="msn"
url="{!URLFOR($Resource.style_resources, 'images/up-arrow.gif')}"
alt="Open-close"
styleClass="msn{!count}" />
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"/>
<script>
jQuery.noConflict();
function doSomethingWithImg() {
try {
var imgElement = jQuery('.msn1');
/*Do what you need to do with the element*/
} catch (e) { /*Ignore Error*/ }
}
</script>
Here is the link to jQuery selectors: jQuery Selector Documentation

meta tag in ASP.NET MVC 3

How can I put meta tag to work only for one page. If I want to put it .aspx file, where is right place.
Thanks.
Since you haven't said yet, I'm assuming you're using the Razor engine (the "default" for new MVC3 projects). In that case, you just need to insert a new section into your layout view, and only render that section if you need to insert a meta tag.
For example, working from the stock New ASP.NET MVC 3 Project template, you would edit your Views\Shared\_Layout.cshtml file, and before the closing </head> tag, do something like this:
#this.RenderSection("MetaContent", false)
</head>
Then, in any of your views that you needed to, add this:
#section MetaContent
{
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />
}
If you're still using the ASPX layout engine for some reason, you can accomplish the same thing using the <asp:ContentPlaceHolder> tags in your master page and <asp:Content> tags in your views.
EDIT:
Since you're using the ASP.NET Forms layout engine still, here's the same basic idea as above in aspx syntax:
In your master page, you add the tag:
<asp:ContentPlaceHolder ID="MetaContent" runat="server" />
</head>
And in your .aspx views, you add a new content section (you should already have at least two -- a title and a body):
<asp:Content ID="Meta" ContentPlaceHolderID="MetaContent" runat="server">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />
</asp:Content>
I was going to suggest exactly what Michael said (+1). Another option would be to put a boolean in the ViewBag, something like:
ViewBag.ForceIE8Mode = true;
For pages that you want to force into IE8 Mode.
and then in your view, wrap the meta tag in a conditional. either
#if(ViewBag.ForceIE8Mode == true) {
<meta... />
}
or
<% if(ViewBag.ForceIE8Mode == true) { %>
<meta... />
<% } %>

Windows Phone 7 WebBrowser content height

I want to set the height of WebBrowser control dynamically, depending on the content height.
My scenario is: On that specific view I have different elements - an Image, MediaElement etc. and between those rich text that is presented in that WebBrowser control. To achieve unified scrolling I have wrapped all content in a scrollview and disabled scrolling on the webbrowser control.
Currently I have a JavaScript method that gets called when body has done loading and sends the height information to C# codebehind but the calculated height is incorrect.
My hack today is to basically multiply the returned value with about 1.75.
In the page head I have the following meta tags:
<meta charset='Windows-1257'>
<meta name='viewport' content='width=device-width' />
<meta name='viewport' content='user-scalable=no' />
<meta name='viewport' content='initial-scale = 1.0' />
<meta name='HandheldFriendly' content='true' />"
<meta name='target-densitydpi=device-dpi' />
This is my body tag.
<body onLoad="SendDataToPhoneApp()" style="margin:0px;padding:0px;">
My JavaScript functions:
<script>
function getDocHeight() {
return document.getElementById('pageWrapper').offsetHeight;
}
function SendDataToPhoneApp() {
window.external.Notify('' + getDocHeight());
}
</script>
pageWrapper is a direct child of body.
Try using document.body.clientHeight in your Javascript. Also you might have better luck with your scenario if you construct everything inside the WebBrowser. You can put images in the HTML of course and you could put a still-frame placeholder image for your MediaElement, calling back into C# and poping up a real MediaElement when needed.

Resources