Include specific attribute or child-element text in breadcrumb rendering - oxygenxml

Within the author it displays a breadcrumb, and I know you can modify its display to either some other static text or localisation, but I'm wondering if it's possible to dynamically show an attribute, or execute some other context-specific xpath dynamically.
As a test I can change the breadcrumb using the localisation editor variable ${i18n()}.
cc_config.xml
<elementRenderings platform="webapp">
<render element="num" as="${i18n(test)}" annotation="${i18n(test)}"/>
translation-cc.xml
<key value="test">
<comment></comment>
<val lang="en_US">Year</val>
"Year" is actually a num element.
However, trying any other variable, even 'more static' ones like ${cf} or ${tp} simply render the variable text literally, instead of evaluating it.
cc_config.xml
<elementRenderings platform="webapp">
<render element="paragraph" as="${xpath_eval(./#eId)}" annotation="${xpath_eval(./#eId)}"/>
<render element="p" as="${tp}" annotation="${tp}"/>
(paragraphs do have an eId attribute)
As you can see, I tried using annotation; but these tooltips also simply display the variable literally.
I also fiddled and tried a bunch of xpath stuff, like #eId/.#eId//#eId, but I think there's some restriction in using the Content Completion Configuration File with respect to editor variables.
So is the thinking right but I am doing something wrong, or is it not the right way but there is some other way to affect the breadcrumb? Maybe with the schema?

The element display names in cc_config.xml file do not support most of the editor variables. Most of them, like ${cf} (current file) and ${tp} (total number of pages) don't make sense to be used when rendering the name of an element.
The xpath_eval would make sense - the display name of an element may depend on its attributes (e.g. the #id attribute), it's index in the document (e.g. 'Section 3'), etc. We have a feature request registered for this case and I added your vote to it.
As a partial workaround you can use a JS API to compute the display name of the element based on the element original name and its attributes:
goog.events.listen(workspace, sync.api.Workspace.EventType.BEFORE_EDITOR_LOADED, function(e) {
e.options.elementNameEnhancer = function(elemName, attrs) {
var displayString = elemName;
var attr = attrs['id'];
if (attr) {
displayString += ' (#' + attr.attributeValue + ')';
}
return displayString;
};
});

Related

Asp-route-id: passed integer becomes 0

I have the following problem.
I have a product for which I run some tests.
In my cshtml page, I show the test runs for some product item, like this:
<td><a asp-action="TestDetail" asp-route-id="#Model.ResultViewModels[i].TestRunId">Content</a></td>
TestRunId is an integer. For example, TestRunId could be 9. This works: the URL looks correct.
In my cshtml page, the user can click on this, to see more details.
However, when I log the asp-route-id in my controller, this TestRunId seems to be 'lost'. In my example below, the second logging shows testrunId: 0. I expect this to be also 9.
public IActionResult TestPlanRunDetail(int TestRunId)
{
logger.LogInformation("TestPlanRunDetail function called.");
logger.LogInformation("TestRunId: " + TestRunId);
// Omitted for brevity
return View(detail);
}
The parameter name in asp-route-xxx must be same as the parameter name in the backend (int xxx)
So, change one of your param names to match the other
asp-route-{value} is an Anchor Tag Helper.
The Anchor Tag Helper enhances the standard HTML anchor (<a ... ></a>) tag by adding new attributes. By convention, the attribute names are prefixed with asp-. The rendered anchor element's href attribute value is determined by the values of the asp- attributes.
The Reason:
Any value occupying the {value} placeholder is interpreted as a potential route parameter
Therefore, if you use asp-controller="controller" asp-action="action" asp-route-id="#Model.ResultViewModels[i].TestRunId".
The generated HTML href will be href="/controller/action?id=0">Content</a>
where 0 is the actual #Model.ResultViewModels[i].TestRunId.
Notice that the parameter name in href is id instead of TestRunId?
Your TestPlanRunDetail(int TestRunId) take TestRunId, but not id, and that is why you get TestRunId=0.
The Easier Solution:
Change asp-route-id to asp-route-TestRunId (or asp-route-testrunid as it is not case sensitive).
Alternate Solution:
Define a default route template in Startup.Configure:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{action=Index}/{id?}");
});
In the model:
<a asp-action="TestDetail"
asp-route-id="#Model.ResultViewModels[i].TestRunId">
Content
</a>
Then, the generated href will be href="/TestDetail/12".

Vis js timeline range element custom draw

I have found vis.js extremely useful but now need to add custom 'symbols' (up indicator, down indicator, etc) to the edges (start / end) of a range element used in a timeline.
I can add separate elements to precede / succeed other elements but this involves quite a bit more effort and stacking is affected etc.
Or... I can place html text / symbols inside a table with css forcing it to the start / end of the element but this does not seem to display correctly always.
What would be the suggested approach to resolve this?
You should provide a template function in the options that will render your range item.
The content returned by your template function may be any valid HTML, so it's up to you to use a div, table, ... whatever to add and position your extra symbols.
Docs:
https://visjs.org/docs/timeline/#Templates
Timeline supports templates to format item contents. Any template engine (such as handlebars or mustache) can be used, and one can also manually build HTML. In the options, one can provide a template handler. This handler is a function accepting an item's data as the first argument, the item element as the second argument and the edited data as the third argument, and outputs formatted HTML.
Example:
var options = {
template: function (item, element, data) {
return '<h1>' + item.header + data.moving?' '+ data.start:'' + '</h1><p>' + item.description + '</p>';
},
onMoving: function (item, callback) {
item.moving = true;
}
};

Buddypress Conditional Profile Fields

Is there any way I can create custom/conditional registration/profile fields in buddypress.
I tried Googling a lot about this, but I am not getting proper solution.
The condition what I am thinking of is :
I want to create 2/3 dropdowns, suppose if 1st one contains vehicles type(car, bike,),
then the second dropdown's option should change according to what user is choosing in dropdown 1.
any help would be appreciated.
Thanks a ton in advance. :-)
Currently there is no working plugin or hack for that. I saw such thing on some sites - but this is done via JavaScript and heavily modifying of a registration page source code.
It will be little tricky unless you touch register/resgistration.php source.
you can do like this if you little familiar with jquery.
Theres a hidden field ( id "signup_profile_field_ids" ) in buddypress registration form which tells server what fields in registration form, it will look like
<input type="hidden" name="signup_profile_field_ids" id="signup_profile_field_ids" value="5,11,1,10,32">
value of that field contains field ids of the registration form.
Now, you need to select a parent field to show conditional fields. you need to know parent and conditional field ids
now use this jquery code
<script type="text/javascript">
$(function(){
var childs = new Array("Child id 1","Child id 1"); // your child fields ids
var options = new Array("Car","Bike"); // your parent field options, notice option and child number is same, which means, one child for one option
var parent = "Parent Field id"; // place you parent field id
var currentFields = new Array();
currentFields = $("#signup_profile_field_ids").val().split(','); // take all current fields ids in an array
$.each(childs, function(index,value){
$('#field_'+value).parent().hide(); // hide all child fields first
currentFields.splice(currentFields.indexOf(value),1);
});
$("#signup_profile_field_ids").val( currentFields.join() );
$('#field_'+parent).after('<div id="conditional-fields-conteiner></div>"');
$('#field_'+parent).change(function(){
var option = $(this).val();
var appendField = childs[options.indexOf(option)];
var html = $("#field_"+appendField).parent().html();
$('#conditional-fields-conteiner').html(html);
$.each(childs, function(index,value){
currentFields.splice(currentFields.indexOf(value),1);
});
currentField[] = appendField;
$("#signup_profile_field_ids").val( currentFields.join() );
});
});
</script>
This may seems complex, but this is the easiest approach. if you are planning it in membership site, dont use it. user can manupulate conditional fields simply by editing html.
Theres also a plugin for this, going to release soon. I am developing it
http://rimonhabib.com/coming-up-next-buddypress-nested-conditional-fields/

Subscribing to changes in a Collection but not in a template

I'm very new to meteor, so apologies if I'm missing something very basic here.
I thought it would be fun to create a very simple textpad style app to check out meteor. I took the todo app and changed the data structures to be 'folders' and 'docs' rather than 'lists' and 'todos', so I have a list of folders and when you click on the folder you get a list of the documents in that folder.
I've then added some code to show the 'content' attribute of a single 'doc' when one of the docs in the list is clicked.
I'm using ace to add some pretty print to the content of the doc (https://github.com/ajaxorg/ace). I've set ace up to work with a hidden textarea containing the plaintext version of my document, and the editor object takes this text and pretty prints it.
The problem with ace is that I don't want the template containing the ace editor to be replaced every time the contents of the doc changes (as it takes half a second to reinitialise, which is a crappy experience after every character is typed!). Instead, I want to update the textarea template and then use the ace API to tell the editor to update it's input based on what is in the textarea.
Now, this is probably the wrong way to approach the problem, but I've ended up using two templates. The first contains a textarea containing doc.contents, which is reactive to the underlying model:
<template name="doc_content">
<textarea name="editor">{{content}}</textarea>
</template>
The second one contains the 'editor' div which ace uses to display the pretty printed text.
<template name="doc_init">
<div id="editor"></div>
</template>
The idea is that the first template will update every time the user types (on all clients), and the second template is only ever re-loaded for each new doc we load.
Template.doc_content.content = function() {
var doc_id = Session.get('viewing_itemname');
if (!doc_id) {
return {};
}
var doc = Docs.findOne({_id:doc_id});
if (doc && doc.content) {
// #1 Later
var editor = Session.get('editor');
if (editor) {
editor.getSession().setValue(doc.content);
}
return doc.content;
} else {
return '';
}
};
When you enter text into the editor div I make a call to Docs.update(doc_id, {$set: {content: text}});, which updates the value in the textarea on each client. All good so far.
editor.getSession().on('change', function(){
var text = editor.getSession().getValue();
Docs.update(doc_id, {$set: {content: text}});
});
What I want to do, for all clients other than the client which made the change, is to subscribe to the change for that doc and call editor.getSession().setContent() with the text which has just been changed, taking the text from the textarea and using it to fill the editor.
I've tried to do this by making that call from the template containing the textarea (as this changes whenever the doc is updated - see #1 above). However, this puts the clients into an infinite loop because changing the value in the editor causes another call to Docs.update.
Obviously this doesn't happen when you render a template, so I'm assuming there's some magic in meteor which can prevent this happening, but I'm not sure how.
Any thoughts?
TIA!
There's a lot to absorb in your question, but if I understand correctly, you might simply be after Deps.autorun:
Deps.autorun(function () {
var doc_id = Session.get('viewing_itemname');
if (!doc_id) {
return {};
}
var doc = Docs.findOne({_id:doc_id});
// do stuff with doc
});
Deps.autorun is really useful in that it will get re-run if any of its
dependencies change. These dependencies are limited to those that are "reactive"
such as Collections and Sessions, or anything that implements the reactive API.
In your case, both Session.get and findOne are reactive so if their values
change at all, Deps.autorun will run the function again.

CKEditor.net table class

In a asp.net C# webapp I'm using the CKEditor 3.6.2 and I'm facing the following problem:
In my stylesheet I have a CSS class to use in tables and I'm trying to bring this class already filled in the "Table properties", "Advanced" tab and the "Stylesheet Classes" field.
I want to bring this field filled with the string "blue_table", which is the name of my CSS class. I'm working with the source of the "table" plugin. I have figured out how to change the value of fields like width and height, but the one I want is the "Stylesheet Classes" field.
Do any of you know to to set a default value for this field?
You don't have to edit the ckeditor.js file to customise the editor. You can add the following either to config.js and use it site wide or on any page where you're using CKEditor (inside a script tag as below, after the editor fields you're using).
<script type="text/javascript">
CKEDITOR.on( 'dialogDefinition', function( ev ) {
// Take the dialog name and its definition from the event data.
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
// Check if the definition is from the dialog we're
// interested on (the Table dialog).
if ( dialogName == 'table' ) {
// Set the tab
var advTab = dialogDefinition.getContents( 'advanced');
// Grab the field
var stylesField = advTab.get('advCSSClasses');
// Set the default value
stylesField['default'] = 'blue_table';
}
});
</script>
This is modified from the CKEditor documentation. The hardest part is working out the IDs and names for all the fields used in the dialogs.
Finally I found the answer. This property is in the dialogadvtab, in the property "advCSSClasses". The thing is that this plugin is inside the core js, I mean the ckeditor.js.
I had to do this :
children :
[
{
id : 'advCSSClasses',
att : 'class',
type : 'text',
label : lang.cssClasses,
'default' : 'blue_table',
setup : setupAdvParams,
commit : commitAdvParams
}
]
The "problem" now is that I had to do it in the ckeditor.js, which is not a good practice. The problem is solved, but not int the best way.

Resources