I am trying to make a tree view be async. When the page is rendered, there is default tree items displayed. jsTree tries to reload the root anyway.
I want the page to render (with jsTree init'ed) with default items rendered from browser, not the ajax call. Then we the user tries to go deeper, thats when I want to do do the ajax calls.
Any help is appreciated. Thanks!
From Documentation: If both data and ajax are set the initial tree is rendered from the data string. When opening a closed node (that has no loaded children) an AJAX request is made.
An example,
$(function () {
$("#demo4").jstree({
"json_data" : {
"data" : [
{
"data" : "A node",
"state" : "closed"
},
{
"attr" : { "id" : "li.node.id" },
"data" : {
"title" : "Long format demo",
"attr" : { "href" : "#" }
}
}
],
"ajax" : { "url" : "/static/v.1.0rc/_docs/_json_data.json" }
},
"plugins" : [ "themes", "json_data" ]
});
});
Related
I'm building an application with react-admin and Spring REST as data API. I'm in the typical situation of having a Product object with relative comments.
In the element that shows the product I added ReferenceManyField in order to show the comments for that product. But here is the problem: according to the reference documentation, this component fetches the comments calling the comments list and finding comments that have the id of the father:
https://marmelab.com/react-admin/Fields.html#referencemanyfield
But since my Spring REST produces something similar for one specific product:
{
"id" : 1,
"description" : "Description of Product 1",
"price" : 50045.0,
"title" : "Title of product 1",
"additionaldata" : [ ],
"pimages" : [ ],
"_links" : {
"self" : {
"href" : "http://localhost:8080/products/1"
},
"product" : {
"href" : "http://localhost:8080/products/1"
},
"pcomments" : {
"href" : "http://localhost:8080/products/1/pcomments"
},
"vendor" : {
"href" : "http://localhost:8080/products/1/vendor"
}
}
}
The logic is inverse, we find the URI to call to find the list of comments for that particular product.
How can I make ReferenceManyField to call http://localhost:8080/products/1/pcomments to fetch comments for that product?
Try to do the following:
<ReferenceManyField source="your_source" target="_links['pcomments']['href']" reference="products"/>
You can wrap your search url in the filter prop of ReferenceManyField, then in your dataProvider get the filter from GET_MANY_REFERENCE(switch case). then you can do whatever you want
I have requirement where I have to create a cascading dropdown, means the value of the second dropdown will depends on the first one. The list are going to be hardcoded.
For e.g. The first dropdown of country and based on this value the second dropdown is of state corresponding to that country; I will have the list of state corresponding to each country.
Now I know how to apply constraint on the field using list but can that be extended to two level ??
I have also searched about datalist but I really don't want that as the list is going to be pan customer but datalist will make it customer specific and don't want customer to create the list themselves.
Any help will be highly appreciated.
Thanks
Alfresco does not have cascading dropdown lists out of the box.
Nevertheless, it will not be difficult to develop one.
Because your lists are hardcoded, there is a simple solution.
Generate the controls for the two dropdown lists. They can even be just an hidden field or an empty dropdown. If you are not familiar with the Alfresco form engine, it will be probably easier to use an hidden field like in the following example (snippet of the configuration in share-config-custom.xml):
<field id="dropdown1">
<control template="/org/alfresco/components/form/controls/hidden.ftl">
<control-param name="contextProperty">dropdown1</control-param>
</control>
</field>
<field id="dropdown2">
<control template="/org/alfresco/components/form/controls/hidden.ftl">
<control-param name="contextProperty">dropdown2</control-param>
</control>
</field>
In share-config-custom.xml, you can also add a new custom javascript and css:
<!-- Document Library client-side dependencies -->
<config evaluator="string-compare" condition="DocLibCustom">
<dependencies>
<js src="/js/cascading-dropdown.js" />
<css src="/css/cascading-dropdown.css" />
</dependencies>
</config>
The custom javascript and css can, using YUI, find the two controls and generate the necessary dropdown and event listeners. When the dropdown is updated, an event listener will update the cascading dropdown and will also update the hidden fields. The value of the hidden fields will be posted when the form is closed.
A better solution can be to use the custom javascript only to define a javascript library. You can then use this javascript library in a custom free marker template to use instead of "/org/alfresco/components/form/controls/hidden.ftl"
You can find hidden.ftl in:
/webapps/share/WEB-INF/classes/alfresco/site-webscripts/org/alfresco/components/form/controls/hidden.ftl
Do a copy of this ftl in the extension path and modify it to use your custom javascript.
If the lists are not hardcoded, simply use a webscript to generate the list and call it from the browser using ajax calls.
As you are with alfresco community edition 5.0.d, you can/should be using aikau for that sort of things, you can start learning and using aikau based on this tutorial for standalone aikau clients or this tutorial for new custom share pages.
Once you have your page setup (desc.xml, js and ftl), you should have something like this:
custom-page.get.desc.xml
<webscript>
<shortname>Test page 1</shortname>
<family>testing</family>
<url>/custom-uri</url>
</webscript>
custom-page.get.ftl
<#processJsonModel group="share"/>
and custom-page.get.js
model.jsonModel = {
services : [ "alfresco/services/NavigationService",
"alfresco/services/LogoutService",
// Add more services here !!!
],
widgets : [
// Add more widgets here
]
};
You need now to add two selects to your widgets array:
{
name : "alfresco/forms/Form",
config : {
scopeFormControls : false, // to avoid complex handling of
// pubSubScope
widgets : [ {
name : "alfresco/forms/controls/Select",
config : {
fieldId : "LEVEL_1",
label : "Level 1",
description : "Select an item from the list",
name : "level_1",
value : "1",
requirementConfig : {
initialValue : true
},
optionsConfig : {
fixed : [ {
label : "Item 1",
value : "1"
}, {
label : "Item 2",
value : "2"
}, {
label : "Item 3",
value : "3"
} ]
}
}
}, {
name : "alfresco/forms/controls/Select",
id : "LEVEL_2",
config : {
fieldId : "LEVEL_2",
label : "Level 2",
description : "Select an item from the list",
name : "level_2",
requirementConfig : {
initialValue : true
},
optionsConfig : {
fixed : [ {
label : "Item 1.1",
value : "1"
}, {
label : "Item 1.2",
value : "2"
}, {
label : "Item 1.3",
value : "3"
} ]
}
}
} ]
}
}
The next step would be to detect the change event in your first select then refresh the list of the second select with new items. In order to do so, you need either to define a new service or extend the select widget for your second select. I will go with option number 1:
CustomServiceForNestedSelects.js
define(
[ "dojo/_base/declare", "alfresco/core/Core", "dojo/_base/lang",
"alfresco/core/CoreXhr", "service/constants/Default" ],
function(declare, Core, lang, CoreXhr, AlfConstants) {
return declare(
[ Core, CoreXhr ],
{
pubSubScope : "",
levelOneFieldId : "LEVEL_1",
levelTwoFieldId : "LEVEL_2",
levelTwoItems : [ [ {
label : "Item 1.1",
value : "1"
}, {
label : "Item 1.2",
value : "2"
}, {
label : "Item 1.3",
value : "3"
} ], [ {
label : "Item 2.1",
value : "1"
}, {
label : "Item 2.2",
value : "2"
}, {
label : "Item 2.3",
value : "3"
} ], [ {
label : "Item 3.1",
value : "1"
}, {
label : "Item 3.2",
value : "2"
}, {
label : "Item 3.3",
value : "3"
} ] ],
constructor : function yreg_CustomServiceForNestedSelects__constructor(
args) {
lang.mixin(this, args);
this.alfSubscribe(this.pubSubScope
+ "_valueChangeOf_" + this.levelOneFieldId,
lang.hitch(this, this.levelOneChanged));
},
levelOneChanged : function yreg_CustomServiceForNestedSelects__levelOneChanged(
payload) {
var value = payload.value;
var levelTwo = dijit.byId(this.levelTwoFieldId);
if (levelTwo)
levelTwo
.setOptions(this.levelTwoItems[value - 1]);
},
});
});
And now, all that is left is to include your service in your page model
"<custom-package>/CustomServiceForNestedSelects"
Note:
You will need to register a custom package and place your service there, in order to learn how to do so, check this tutorial.
To test your page's content check http://127.0.0.1:8090/aikau-sample/page/na/ws/custom-uri in case you are trying this code in a stand alone aikau app, or http://127.0.0.1:8080/share/page/dp/ws/custom-uri, http://127.0.0.1:8080/share/page/hdp/ws/custom-uri for share custom pages
Aikau does actually provide cascading menus out-of-the-box, see the alfresco/menus/AlfCascadingMenu widget. There are examples of its use already present within Alfresco (for example the favourites list from under the sites menu in the main header in Share). If you already know the cascading contents then this can all be defined in your page WebScript. However, if you need to dynamically change the content of the cascaded menu then you should look at the implementation of alfresco/header/AlfSitesMenu or alfresco/documentlibrary/AlfCreateTemplateContentMenu (you can find the source in the Aikau GitHub project).
Some useful info: https://forums.alfresco.com/forum/developer-discussions/alfresco-share-development/cascading-dropdown-alfresco-share-03102011
Used that as a basis for my own cascading selects. Builds on the same concept as described by Marco Altieri
Is there a WordPress plugin that will enable deep linking to an embedded iframe? I'd like to be able, for example, to tweet a URL to a post that has extra information that will be passed down to the iframe.
An example would be an iframe that plays a video. The extra information in this case might be the time offset to start playing the video.
The extra info could be passed as query params, fragments, or some other way.
Probably not via a WordPress plugin, unless you are looking to develop a custom plugin.
It is best to avoid iframes whenever you can for these reasons.
That said, the solution is pretty simple using the window.postMessage method and works in most browsers, including IE8 and up.
Notes:
All messages should be sent as strings to avoid a nasty bug in IE8/9. If you want to pass an object, pass it in JSON format.
You can't JSON.serialize() the window.location object in IE8. If you are trying to pass that object, you have to copy the properties one by one.
IE only supports el.contentWindow.postMessage(), not el.postMessage().
Outer page
window.onload = function()
{
var child = document.getElementById('deep_link_frame');
var msg = {
"location" : {
"hash" : window.location.hash,
"host" : window.location.host,
"hostname" : window.location.hostname,
"href" : window.location.href,
"origin" : window.location.origin,
"pathname" : window.location.pathname,
"port" : window.location.port,
"protocol" : window.location.protocol,
"search" : window.location.search
}
};
child.contentWindow.postMessage(JSON.stringify(msg), '*');
};
Inner page
function bindEvent(el, eventName, eventHandler)
{
if (el.addEventListener)
{
el.addEventListener(eventName, eventHandler);
}
else
{
el.attachEvent('on' + eventName, eventHandler);
}
}
bindEvent(window, 'message', function(e)
{
if (e.origin === "http://your-domain.com")
{
var message = JSON.parse(e.data);
alert(message.location.href);
}
});
I have started to use ExtJs 4. I have grid with buttons in one column. I can't manage to get button click for button in selected cell by controller. I would like to get click and then details for row in order to open extra window with details.
Code:
Ext.define('AP.controller.List', {
extend : 'Ext.app.Controller',
stores : ['Users'],
models : ['User'],
views : [ 'List', 'Details' ],
init : function() {
console.log("users");
this.control({
'viewport > listPanel > userlist' : {
itemdblclick : this.userDbCClicked
},
'viewport > listPanel button AND WHAT MORE ?' : {
click : this.statusButtonClicked
}
});
},
userDbCClicked : function(grid, record) {
console.log("user db clicked");
},
statusButtonClicked : function(grid, record) {
// Here I would like to get row details after click on button in column
console.log("statusButtonClicked clicked ");
}
});
What should be put instead this code:
'viewport > listPanel button AND WHAT MORE?' : {
click : this.statusButtonClicked
}
Of course it dosen't work. How to get row by click on button in cell ?
Thanks in advance for help.
ExtJs is very powerfull framework but first steps are realy difficulted sometimes.
Bogus
put an action:'statusbutton' in your button config
then use 'viewport > listPanel > button[action=statusbutton]'
What Chris says is true. You can also you a name property on your button, it's just a way of querying your components. Explained here:
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.ComponentQuery
{
xtype: 'button',
name: 'statusbutton'
}
'viewport > listPanel > button[name=statusbutton]'
Here is a good starting guide for Ext.Apps:
http://docs.sencha.com/ext-js/4-1/#!/guide/mvc_pt1
and another one:
http://docs.sencha.com/ext-js/4-1/#!/guide/application_architecture
Can someone please throw some light on how to go about rendering an hyperlink in the cells of a particular column in ExtJS?
I have tried binding the column to a render function in my JS, from which I send back the html:
SELECT
However, with this, the problem is that, once I hit the controller through the link, the navigation is successful, but subsequent navigations to the data-grid show up only empty records.
The records get fetched from the DB successfully through the Spring MVC controller, I have checked.
Please note that this happens only once I use the row hyperlink in the extJS grid to navigate away from the grid. If I come to the grid, and navigate elsewhere and again come back to the grid, the data is displayed fine.
The problem only occurs in case of navigating away from the grid, using the hyperlink rendered in one/any of the cells.
Thanks for your help!
This is for ExtJS 4 and 5.
Use a renderer to make the contents look like a link:
renderer: function (value) {
return ''+value+'';
}
Then use the undocumented, dynamically generated View event cellclick to process the click:
viewConfig: {
listeners: {
cellclick: function (view, cell, cellIndex, record, row, rowIndex, e) {
var linkClicked = (e.target.tagName == 'A');
var clickedDataIndex =
view.panel.headerCt.getHeaderAtIndex(cellIndex).dataIndex;
if (linkClicked && clickedDataIndex == '...') {
alert(record.get('id'));
}
}
}
}
Try something like this:
Ext.define('Names', {
extend: 'Ext.data.Model',
fields: [
{ type: 'string', name: 'Id' },
{ type: 'string', name: 'Link' },
{ type: 'string', name: 'Name' }
]
});
var grid = Ext.create('Ext.grid.Panel', {
store: store,
columns: [
{
text: 'Id',
dataIndex: 'Id'
},
{
text: 'Name',
dataIndex: 'Name',
renderer: function (val, meta, record) {
return '' + val + '';
}
}
...
...
...
However my thanks to - ExtJS Data Grid Column renderer to have multiple values
Instead of using an anchor tag, I would probably use plain cell content styled to look like an anchor (using basic CSS) and handle the cellclick event of the GridPanel to handle the action. This avoids dealing with the anchor's default click behavior reloading the page (which is what I'm assuming is happening).
I created a renderer so it looked like you were clicking on it.
aRenderer: function (val, metaData, record, rowIndex, colIndex, store){
// Using CellClick to invoke
return "<a>View</a>";
},
But I used a cell event to manage the click.
cellclick: {
fn: function (o, idx, column, e) {
if (column == 1) // Doesn't prevent the user from moving the column
{
var store = o.getStore();
var record = store.getAt(idx);
// Do work
}
}
}
For these purposes I use CellActions or RowActions plugin depending on what I actually need and handle cell click through it.
If you want something that looks like an anchor, use <span> instead and do what #bmoeskau suggested.
You can use 'renderer' function to include any HTML you want into cell.
Thanks guys for your response.
AFter debugging the extJS-all.js script, I found the issue to be on the server side.
In my Spring MVC controller, I was setting the model to the session, which in the use-case I mentioned earlier, used to reset the "totalProperty" of Ext.data.XmlStore to 0, and hence subsequent hits to the grid, used to display empty records.
This is because, ext-JS grid, checks the "totalProperty" value, before it even iterates through the records from the dataStore. In my case, the dataStore had data, but the size was reset to null, and hence the issue showed up.
Thanks to all again for your inputs!