cloning/copying a dojo data store - dojox.grid

Hi can some one please tell me how to copy one data store to another in dojo. I tried it in following way but it doesn't work. Here I'm try to copy data from jsonStore to newGridStore.
jsonStore.fetch({query:{} , onComplete: onComplete});
var onComplete = function (items, request) {
newGridStore = null;
newGridStore = new dojo.data.ItemFileWriteStore({
data : {}
});
if (items && items.length > 0) {
var i;
for (i = 0; i < items.length; i++) {
var item = items[i];
var attributes = jsonStore.getAttributes(item);
if (attributes && attributes.length > 0) {
var j;
for (j = 0; j < attributes.length; j++) {
var newItem = {};
var values = jsonStore.getValues(item, attributes[j]);
if (values) {
if (values.length > 1) {
// Create a copy.
newItem[attributes[j]] = values.slice(0, values.length);
} else {
newItem[attributes[j]] = values[0];
}
}
}
newGridStore.newItem(newItem);
}
}
}
}

Based on the comments asked above. You are trying to copy values to a new Store for the single reason to be able to detect which values have changes and then save them individually, without having to send the entire store.
This approach is totally wrong.
Dojo has isDirty() and offers you the ability to revert() a store back to it's original values. It knows which values have changed and you don't need to do this.
Take a look at the bog standard IFWS here: http://docs.dojocampus.org/dojo/data/ItemFileWriteStore
Make sure you read everything from here: http://docs.dojocampus.org/dojo/data/ItemFileWriteStore#id8
What you want to do is create your own _saveCustom method which you will override your store with, and then when you save, you will be able to see which values have changed.
Click on the demo at the very bottom of the page. It shows you EXACTLY how do to it using _saveCustom

Related

Prevent nested lists in text-editor (froala)

I need to prevent/disable nested lists in text editor implemented in Angular. So far i wrote a hack that undos a nested list when created by the user. But if the user creates a normal list and presses the tab-key the list is shown as nested for a few milliseconds until my hack sets in back to a normal list. I need something like event.preventDefault() or stopPropagation() on tab-event keydown but unfortunately that event is not tracked for some reason. Also the froala settings with tabSpaces: falseis not showing any difference when it comes to nested list...in summary i want is: if the user creates a list and presses the tab-key that nothing happens, not even for a millisecond. Has anyone an idea about that?
Froala’s support told us, there’s no built-in way to suppress nested list creation. They result from TAB key getting hit with the caret on a list item. However we found a way to get around this using MutationObserver
Basically we move the now nested list item to his former sibling and remove the newly created list. Finally we take care of the caret position.
var observer = new MutationObserver(mutationObserverCallback);
observer.observe(editorNode, {
childList: true,
subtree: true
});
var mutationObserverCallback = function (mutationList) {
var setCaret = function (ele) {
if (ele.nextSibling) {
ele = ele.nextSibling;
}
var range = document.createRange();
var sel = window.getSelection();
range.setStart(ele, 0);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
};
var handleAddedListNode = function (listNode) {
if (! listNode.parentNode) {
return;
}
var parentListItem = listNode.parentNode.closest('li');
if (!parentListItem) {
return;
}
var idx = listNode.children.length - 1;
while (idx >= 0) {
var childNode = listNode.children[idx];
if (parentListItem.nextSibling) {
parentListItem.parentNode.insertBefore(childNode, parentListItem.nextSibling);
} else {
parentListItem.parentNode.appendChild(childNode);
}
--idx;
}
setCaret(parentListItem);
listNode.parentNode.removeChild(listNode);
};
mutationList.forEach(function (mutation) {
var addedNodes = mutation.addedNodes;
if (!addedNodes.length) {
return;
}
for (var i = 0; i < addedNodes.length; i++) {
var currentNode = addedNodes[i];
switch (currentNode.nodeName.toLowerCase()) {
case 'ol':
case 'ul':
handleAddedListNode(currentNode);
break;
// more optimizations
}
}
})
};

Sub Grid Total In Crm

I have a primary Entity (Self-Insurance) and a secondary entity (Compensation). They have a 1:N relationship. So in my main form of Self Insurance I have a sub-grid with the name 'Worker_Compensation' where i am adding up some payroll values.
I have 2 questions. . .
1: The thing I want is that when I add some values in the sub-grid. I need to show a sum of all payrolls in the text below of my main form named as 'TOTAL'.
2: Where should i call this java script(On which event) Onload or Onsave of form ? or else where because I can seems to locate the events on Subgrid.
I am using a java script for this purpose.
enter code here
function setupGridRefresh() {
var targetgrid = document.getElementById("Worker_Compensation");
// If already loaded
if (targetgrid.readyState == 'complete') {
targetgrid.attachEvent("onrefresh", subGridOnload);
}
else {
targetgrid.onreadystatechange = function applyRefreshEvent() {
var targetgrid = document.getElementById("Worker_Compensation");
if (targetgrid.readyState == 'complete') {
targetgrid.attachEvent("onrefresh", subGridOnload);
}
}
}
subGridOnload();
}
function subGridOnload() {
//debugger;
var grid = Xrm.Page.ui.controls.get('Worker_Compensation')._control;
var sum = 0.00;
if (grid.get_innerControl() == null) {
setTimeout(subGridOnload, 1000);
return;
}
else if (grid.get_innerControl()._element.innerText.search("Loading") != -1) {
setTimeout(subGridOnload, 1000);
return;
}
var ids = grid.get_innerControl().get_allRecordIds();
var cellValue;
for (i = 0; i < ids.length; i++) {
if (grid.get_innerControl().getCellValue('new_estannualpayroll', ids[i]) != "") {
cellValue = grid.get_innerControl().getCellValue('new_estannualpayroll', ids[i]);
cellValue = cellValue.substring(2);
cellValue = parseFloat(cellValue);
sum = sum + cellValue;
}
}
var currentSum = Xrm.Page.getAttribute('new_payrolltotal').getValue();
if (sum > 0 || (currentSum != sum && currentSum != null)) {
Xrm.Page.getAttribute('new_payrolltotal').setValue(sum);
}
}
This piece of code is not working. after i add values in the grid my textbox remains empty!
Thanks in advance
If you are upgrading to Microsoft CRM 2015 soon or are already on Microsoft CRM 2015, you can do this without any JavaScript by simply creating a new calculated rollup field and placing that underneath the sub grid, or wherever you wish to place it on the form. Note that this field is calculated ever 12 hours, but if you wish to, it could be calculated on form load via JavaScript. You can see details about that at https://msdn.microsoft.com/en-us/library/dn817863.aspx -"Calculated and Rollup Attributes". The TechNet document, "Define rollup fields" at https://technet.microsoft.com/library/dn832162.aspx has some good examples, scenarios, and discussion about the limitations of the rollup fields.
You can do it with subgrid's onRefresh. This is also unsupportted way but it works. You must add this functions to your javascript
function AddEventToGridRefresh(gridName, functionToCall) {
// retrieve the subgrid
var grid = document.getElementById(gridName);
// if the subgrid still not available we try again after 1 second
if (grid == null) {
setTimeout(function () {AddEventToGridRefresh(gridName, functionToCall);}, 1000);
return;
}
// add the function to the onRefresh event
grid.control.add_onRefresh(functionToCall);
}
// function used in this example
function AdviseUser() {
alert("Sub-Grid refreshed");
}
For more information, here is the link

Watin: Iterating through text boxes in a telerik gridview

I am currently developing a testing framework for a web data entry application that is using the Telerik ASP.Net framework and have run into a blocker. If I step through my code in debug mode the test will find the text box that I am looking for and enter some test data and then save that data to the database. The problem that I am running into is that when I let the test run on it's own the test fails saying that it couldn't fine the column that was declared. Here is my code:
/*Method to enter test data into cell*/
private TableCell EditFieldCell(string columnHeader)
{
var columnIndex = ColumnIndex(columnHeader);
if (columnIndex == -1)
throw new InvalidOperationException(String.Format("Column {0} not found.", columnHeader));
return NewRecordRow.TableCells[columnIndex];
}
/*Method to return column index of column searching for*/
public int ColumnIndex(string columnHeader)
{
var rgTable = GridTable;
var rgCount = 0;
var rgIndex = -1;
foreach (var rgRow in rgTable.TableRows)
{
foreach (var rgElement in rgRow.Elements)
{
if (rgElement.Text != null)
{
if (rgElement.Text.Equals(columnHeader))
{
rgIndex = rgCount;
break;
}
}
rgCount++;
}
return rgIndex;
}
My thinking is that something with my nested for loops is presenting the problem because the rgIndex value that is returned when I let the program run is -1 which tells me that the code in the for loops isn't being run.
TIA,
Bill Youngman
Code that gets the table Column index. You need to pass the Table(verify that the table exists while debug):
public int GetColumnIndex(Table table, string headerName)
{
ElementCollection headerElements = table.TableRows[0].Elements; //First row contains the header
int counter = 0;
foreach (var header in headerElements)
{
if (header.ClassName != null && header.ClassName.Contains(headerName)) //In this case i use class name of the header you can use the text
{
return counter;
}
counter++;
}
// If not found
return -1;
}

Dropdown field - first item should be blank

Using sharepoint build in lookup column and it set to required field. SharePoint automatically selects the first item in the dropdown box (kinda misleading for the end users).
Is there a way to display blank or Null for the first row of this drop down box?
(I am open to any solution. I prefer javascript type solution)
For Choice fields, the default value is configured in the column settings. If the "Default value" input box is populated, delete the value in order to use no default value.
Edit
For Lookup fields, the field seems to change dramatically if it is required. Fields that are NOT required have a "(None)" value by default. However, toggling the field to required will remove the "(None)" value and the first value is selected automatically.
One thing I found, is that if you use JavaScript to add the null value to the dropdown and then try to press OK you get an error page: "An unexpected error has occurred." As a workaround, I wrote some more code to do a quick validation that the field has a value before the form is submitted. If the field has no value, then it will prompt the user and cancel the submit. (Note: this code is only attached to the OK buttons so you may get errors while editing EditForm.aspx.. just choose a value for your lookup field and you'll be able to edit like normal)
Anyways, onto the code... I think the only line you'll need to change is var fieldTitle = 'Large Lookup Field'; to update it to the name of your field.
<script type="text/javascript">
function GetDropdownByTitle(title) {
var dropdowns = document.getElementsByTagName('select');
for (var i = 0; i < dropdowns.length; i++) {
if (dropdowns[i].title === title) {
return dropdowns[i];
}
}
return null;
}
function GetOKButtons() {
var inputs = document.getElementsByTagName('input');
var len = inputs.length;
var okButtons = [];
for (var i = 0; i < len; i++) {
if (inputs[i].type && inputs[i].type.toLowerCase() === 'button' &&
inputs[i].id && inputs[i].id.indexOf('diidIOSaveItem') >= 0) {
okButtons.push(inputs[i]);
}
}
return okButtons;
}
function AddValueToDropdown(oDropdown, text, value, optionnumber){
var options = oDropdown.options;
var option = document.createElement('OPTION');
option.appendChild(document.createTextNode(text));
option.setAttribute('value',value);
if (typeof(optionnumber) == 'number' && options[optionnumber]) {
oDropdown.insertBefore(option,options[optionnumber]);
}
else {
oDropdown.appendChild(option);
}
oDropdown.options.selectedIndex = 0;
}
function WrapClickEvent(element, newFunction) {
var clickFunc = element.onclick;
element.onclick = function(event){
if (newFunction()) {
clickFunc();
}
};
}
function MyCustomExecuteFunction() {
// find the dropdown
var fieldTitle = 'Large Lookup Field';
var dropdown = GetDropdownByTitle(fieldTitle);
if (null === dropdown) {
alert('Unable to get dropdown');
return;
}
AddValueToDropdown(dropdown, '', '', 0);
// add a custom validate function to the page
var funcValidate = function() {
if (0 === dropdown.selectedIndex) {
alert("Please choose a value for " + fieldTitle + ".");
// require a selection other than the first item (our blank value)
return false;
}
return true;
};
var okButtons = GetOKButtons();
for (var b = 0; b < okButtons.length; b++) {
WrapClickEvent(okButtons[b], funcValidate);
}
}
_spBodyOnLoadFunctionNames.push("MyCustomExecuteFunction");
</script>
In response Kit Menke, I've made a few changes to the code so it will persist previous value of the dropdown. I have added the following lines of code to AddValueToDropdown()....
function AddValueToDropdown(oDropdown, text, value, optionnumber){
var selectedIndex
if (oDropdown.options.selectedIndex)
selectedIndex = oDropdown.options.selectedIndex;
else
selectedIndex = -1;
// original code goes here
// changed last line of code (added "selectedIndex+1")
oDropdown.options.selectedIndex = selectedIndex+1;
}
To improve on top of Aaronster's answer: AddValueToDropdown can be done that way:
var injectedBlankValue = false;
function AddValueToDropdown(oDropdown, text, value, optionnumber) {
for (i = 0; i < oDropdown.options.length; i++) {
option = oDropdown.options[i];
if(option.getAttribute('selected')) // If one is already explicitely selected: we skip the whole process
return;
}
var options = oDropdown.options;
var option = document.createElement('OPTION');
option.appendChild(document.createTextNode(text));
option.setAttribute('value', value);
if (typeof (optionnumber) == 'number' && options[optionnumber]) {
oDropdown.insertBefore(option, options[optionnumber]);
}
else {
oDropdown.appendChild(option);
}
// changed last line of code (added 'selectedIndex+1')
oDropdown.options.selectedIndex = 0;
injectedBlankValue = true;
}
This is needed for document libraries where "add" and "set properties" are two distinct pages.
And funcValidate starts with:
var funcValidate = function () {
if (!injectedBlankValue)
return true;
All these changes is to make the whole thing work with document libraries.

help needed for making a calendar like MS Outlook?

i am doing work on an app like MS Outlook Calender where user can put events etc.
i am having problem with event object layout according to size etc. as user can drag and re size the event object in MS outlook calender and the size of event objects sets automatically.
i need the algorithm for doing so i have write my own but there are several problems help needed.
this screen shot will show the event object arrangement that is dynamic.
here is the ans
you can go for rectangle packing algorithm but keep in mind the events should be sorted w.r.t time and date and only horizontal packing will work for you
here is the rectangle packing algo
Since you're using Flex, this isn't a direct answer to your question, but it will hopefully set you down the right path.
Try taking a look at how FullCalendar's week and day views implement this. FullCalendar is a jQuery plugin that renders a calendar which does exactly what you're looking for.
You'll have to extract the rendering logic from FullCalendar and translate it to your project in Flex. I know JavaScript and ActionScript are very similar, but I've never used Flex — sorry I can't be more help in that area.
FullCalendar's repo is here. Specifically, it looks like AgendaView.js is the most interesting file for you to look at.
I think you are asking about a general object layout algorithm, right?
I am quite sure that this is a NP-complete problem: Arrange a set if intervals, each defined by a start and end as few columns as possible.
Being NP-complete means, that your best shot is probably trying out all possible arrangements:
find clusters in your objects -- the groups where you have something to do, where intervals do overlap.
for each cluster do
let n be the number of objects in the cluster
if n is too high (like 10 or 15), stop and just draw overlapping objects
generate all possible orderings of the objects in the cluster (for n objects, these are n! possible combinations, i.e. 6 objects, 120 possible orderings)
for each ordering lay out the objects in a trivial manner: loop through the elements and place them in an existing column if it fits there, start a new column if you need one.
keep the layout with the least columns
Here is how I did it:
Events are packet into columns variable by day (or some other rule)
Events in one column are further separated into columns, as long as there is a continuous intersection on the Y-axis.
Events are assigned their X-axis value (0 to 1) and their X-size (0 to 1)
Events are recursively expanded, until the last of each intersectioned group (by Y and X axis) hits the column barrier or another event, that has finished expanding.
Essentially it is a brute force, but works fairly quickly, since there are not many events that need further expanding beyond step 3.
var physics = [];
var step = 0.01;
var PackEvents = function(columns){
var n = columns.length;
for (var i = 0; i < n; i++) {
var col = columns[ i ];
for (var j = 0; j < col.length; j++)
{
var bubble = col[j];
bubble.w = 1/n;
bubble.x = i*bubble.w;
}
}
};
var collidesWith = function(a,b){
return b.y < a.y+a.h && b.y+b.h > a.y;
};
var intersects = function(a,b){
return b.x < a.x+a.w && b.x+b.w > a.x &&
b.y < a.y+a.h && b.y+b.h > a.y;
};
var getIntersections = function(box){
var i = [];
Ext.each(physics,function(b){
if(intersects(box,b) && b.x > box.x)
i.push(b);
});
return i;
};
var expand = function(box,off,exp){
var newBox = {
x:box.x,
y:box.y,
w:box.w,
h:box.h,
collision:box.collision,
rec:box.rec
};
newBox.x += off;
newBox.w += exp;
var i = getIntersections(newBox);
var collision = newBox.x + newBox.w > 1;
Ext.each(i,function(n){
collision = collision || expand(n,off+step,step) || n.collision;
});
if(!collision){
box.x = newBox.x;
box.w = newBox.w;
box.rec.x = box.x;
box.rec.w = box.w;
}else{
box.collision = true;
}
return collision;
};
Ext.each(columns,function(column){
var lastEventEnding = null;
var columns = [];
physics = [];
Ext.each(column,function(a){
if (lastEventEnding !== null && a.y >= lastEventEnding) {
PackEvents(columns);
columns = [];
lastEventEnding = null;
}
var placed = false;
for (var i = 0; i < columns.length; i++) {
var col = columns[ i ];
if (!collidesWith( col[col.length-1], a ) ) {
col.push(a);
placed = true;
break;
}
}
if (!placed) {
columns.push([a]);
}
if (lastEventEnding === null || a.y+a.h > lastEventEnding) {
lastEventEnding = a.y+a.h;
}
});
if (columns.length > 0) {
PackEvents(columns);
}
Ext.each(column,function(a){
a.box = {
x:a.x,
y:a.y,
w:a.w,
h:a.h,
collision:false,
rec:a
};
physics.push(a.box);
});
while(true){
var box = null;
for(i = 0; i < physics.length; i++){
if(!physics[i].collision){
box = physics[i];
break;
}
}
if(box === null)
break;
expand(box,0,step);
}
});
Result: http://imageshack.com/a/img913/9525/NbIqWK.jpg

Resources