Checkboxes are not appearing - javascript

The check-box code below is not working for creating check-boxes against each and every folder of tree structure. It is simple java-script and HTML concept of check boxes which I made use of. I want check-boxes to be created for the tree structure against each and every folder(in left hand side ) of the tree hierarchy.
As the moment I am getting the output as a text associated with each and every folder of the tree hierarchy. So is it something I am doing wrong here? If so, kindly suggest me how can I rectify this error.
var tree = new Tree({
model: model,
checkBoxes: true,
persist: false,
branchIcons: true,
branchReadOnly: false,
checkBoxes: true,
nodeIcons: true,
getLabel: function(item) {
if (!item.root)
return '<input type="checkbox" name="'+ item.name +'" id="'+ item.name +'" value="1" /> '+ item.name;
}
}, "tree");

Related

Kendo Grid: how to get the selected item from a Combobox cell template when using with Angular

I have a Kendo grid which I am using within Angular, and have a field with a combo box, that has the editor set to the following function...
function comboCellTemplate(container, options) {
var input = $('<input name="' + options.field + '" />')
input.appendTo(container)
var combobox = input.kendoComboBox({
autoBind: true,
filter: "contains",
placeholder: "select...",
suggest: true,
dataTextField: "description",
dataValueField: "code",
dataSource: data,
});
And data is a list of simple json objects...
[
{code: 'code1', description: 'desc1'}
{code: 'code2', description: 'desc2'}
[
Each field in the grid data is bound to the same objects (ie with a code and description field)
I a previous post, to get sorting and filtering working I need to bind a field to the display field...
{
field: "Category.description",
title: "Category",
editor: comboCellTemplate,
template: "#=Category.description#"
},
When I do this, the combo box seems to set the field of the grid to the code.
How can I get this to set the grid data to the whole data object (ie the {code, description})
I have tried adding a on - change handler to do this
input.on('change', function () {
var val = input.val();
//var dataItem = input.dataItem();
options.model.set(options.field, val + 'xx');
});
but can't see how to get the "selected Item" from the combo
I don't seem to be able to find this in the help (in particular when using Angular)
Any help here would be greatly appreciated.
regards, Peter
I think you can simply add a change handler to the editor and set it from there:
function comboCellTemplate(container, options) {
var input = $('<input name="' + options.field + '" />')
input.appendTo(container)
var combobox = input.kendoComboBox({
autoBind: true,
filter: "contains",
placeholder: "select...",
suggest: true,
dataTextField: "description",
dataValueField: "code",
dataSource: data,
change: function () {
options.model.set(options.field, this.dataItem());
}
});
}
Ok, I think I have got to the bottom of this (after lots of diving through the doco)
I could get everything to work after I discovered that you can give a column a "magical" compare function.
So using this, my field can go back to binding to the whole json object ..
and add the sortable as follows...
{
field: "Category",
title: "Category",
editor: comboCellTemplate,
template: "#=Category.description#",
sortable:{
compare: function (a, b){
return a.Category.description.localeCompare(b.Category.description);
}
},
Now everything works exactly as I expect, and I don't need to do anything extra in the combobox. I hope this ("simple when you know how") tip can save someone else all the time it took me to find it.

delete row(s) from ng-grid table from button

I have a table with ng-grid, and the problem is that i'm not sure how to collect the selected row(s) id or variable to pass into my delete function.
here is a quick mockup of what i'm trying to do
http://plnkr.co/edit/zy653RrqHmBiRJ7xDHlV?p=preview
the following code is from my html, a clickable delete button that takes in 2 parameters, the array of checkbox ids and the index at the corresponding table. This delete method was obtained from this tutorial : http://alexpotrykus.com/blog/2013/12/07/angularjs-with-rails-4-part-1/
<div class="btn-group">
<button class="my-btn btn-default button-row-provider-medical-services" ng-click="deleteProviderMedicalService([], $index)">Delete</button>
</button>
</div>
<div class="gridStyle ngGridTable" ng-grid="gridOptions">
</div>
The following code grabs the json data from a url, queries it and returns it. It also contains the delete function that gets called from the controller in the html page.
app.factory('ProviderMedicalService', ['$resource', function($resource) {
function ProviderMedicalService() {
this.service = $resource('/api/provider_medical_services/:providerMedicalServiceId', {providerMedicalServiceId: '#id'});
};
ProviderMedicalService.prototype.all = function() {
return this.service.query();
};
ProviderMedicalService.prototype.delete = function(providerId) {
this.service.remove({providerMedicalServiceId: providerId});
};
return new ProviderMedicalService;
}]);
The following is my controller(not everything, just the most important bits). $scope.provider_medical_services gets the json data and puts it into the ng-grid gridOptions.
After reading the ng-grid docs, i must somehow pass the checkbox ids from the selectedItems array and pass it into html doc to the delete function. Or, i'm just doing this completely wrong, as i hacked this together. Solutions and suggestions are greatly appreciated
(function() {
app.controller('ModalDemoCtrl', ['$scope', 'ProviderMedicalService', '$resource', '$modal', function($scope, ProviderMedicalService, $resource, $modal) {
var checkBoxCellTemplate = '<div class="ngSelectionCell"><input tabindex="-1" class="ngSelectionCheckbox" type="checkbox" ng-checked="row.selected" /></div>';
$scope.provider_medical_services = ProviderMedicalService.all();
$scope.deleteProviderMedicalService = function(ids,idx) {
$scope.provider_medical_services.splice(idx, 1);
return ProviderMedicalService.delete(ids);
};
$scope.gridOptions = {
columnDefs: [
{
cellTemplate: checkBoxCellTemplate,
showSelectionCheckbox: true
},{
field: 'name',
displayName: 'CPT Code/Description'
},{
field: 'cash_price',
displayName: 'Cash Price'
},{
field: 'average_price',
displayName: 'Average Price'
},
],
data: 'provider_medical_services',
selectedItems: []
};
i think the easiest option is pass an (array index) as data-id to your dom, which u can pick it from there.
{{$index}} is a variable you can use in ng-repeat
======= ignore what i said above, since i normaly writes my own custom stuff ======
I just had a look at ng-grid, i took their example. i've added a delete all selected function, as well as someone elses delete current row function ( these is pure angular way ) to see the code, hover over the top right corner < edit in jsbin >
http://jsbin.com/huyodove/1/
Honestsly i don't like it this way, you would be better off use something like lodash to manage your arrays and do your own custom grid. Using foreach to find the row index isn't good performance.
In their doc, it says you can change the row template, and which you should, so you can add the {{index}} to that row, and filter your data through that index rather which is a little bit better. anyway beware of deleting cells after you have filter your table.
I don't quite get much your question, but you can access to selectedItems of ng-grid as following: $scope.gridOptions.$gridScope.selectedItems (see ng-grid API for more information, but technically this array holds the list of selected items in multiple mode - or only one item in single mode)
For your case, the deleteAll() function could be someething like this:
$scope.deleteAll = function() {
$scope.myData = [];
}
The delete() function which delete selected items can be:
$scope.delete = function() {
$.each($scope.gridOptions.$gridScope.selectedItems, function(index, selectedItem) {
//remove the selected item from 'myData' - it is 2-ways binding to any modification to myData will be reflected in ng-grid table
//you could check by either name or unique id of item
});
}

how to create a menu within an ng-grid

we are really having problems finding a way on how to create a menu within an ng-grid.
Something similar to the ECB block within share point.
So, there would be a button that when clicked would show options for that particular row.
We may be looking in the wrong places, but we can't find any help or examples on the internet..
As I told you few days ago you should use row and celltemplates to achieve something like this.
Here is the changed code to better match the current state of your question:
$scope.gridOptions = {
data: 'myData',
rowTemplate: '<div ng-style="{\'cursor\': row.cursor, \'z-index\': col.zIndex() }" ' +
'ng-repeat="col in renderedColumns" ng-class="col.colIndex()" ' +
'class="ngCell {{col.cellClass}}" ng-cell></div>' +
'<div ng-show="showmenu" class="hmenu">' +
'<ul>' +
'<li><button ng-click="viewme(row.entity.name)">View</button></li>' +
'<li><button ng-click="editme(row.entity.name)">Edit</button></li>' +
'</ul>' +
'</div>',
columnDefs: [{
field: 'name',
displayName: 'Name'
}, {
field: 'age',
displayName: 'Age',
cellTemplate: '<div class="ngCellText">{{row.getProperty(col.field)}}' +
'<span ng-click="$parent.showmenu=!$parent.showmenu"><button>click me</button></span>' +
'</div>'
}]
};
True, this is no beauty, but it shows you how to go on. Do your styling in style.css and the row template. This is the best I can do with my weekend laptop.
Here is the Plunker
You could potentially set each CellTemplate to have its own ng-if/ng-show block that's hidden/shown based on a variable on your row.entity object. Then, when your function fires for the selection of the row, you can set that variable ($scope.whatever) to hide/show what's necessary. On my phone at the moment, but I'll try to make a plnkr/jsfiddle later.

ExtJS 4.2.1 - Updating XTemplate after store load

I have a bit of a weird situation...
I have a DataView that's backed by a store. However, in the XTemplate, I'm trying to show the quantity of a certain type of JSON record. Each record has a property value pair that denotes its type. For example:
data: [
{ type: 'W' },
{ type: 'A' },
{ type: 'W' },
{ type: 'W' }
]
So there are 3 JSON objects of 'W' and 1 JSON object of type 'A'. The number of 'W' should be displayed in the HTML element with the class 'total-pending'; 'A', in the HTML element with the class 'total-approved.'
My XTemplate:
tpl: Ext.create('Ext.XTemplate',
'<div style="text-align:center">Leave Requests</div>',
'<table cellpadding="0" class="table-wrap">',
'<tr>',
'<td class="x-leave-request approved"><span class="total-approved">0</span>Approved</td>',
'<td class="x-leave-request pending"><span class="total-pending">0</span>Pending</td>'denied">0</span>Denied</td>',
'</tr>',
'</table>'
)
I've read a bit about templates and stores, but I can't seem to figure out how to update those numbers. I tried to add a function callback to store.on('load', function{}) to change the HTML element via Ext.get(Ext.query('span.total-pending')[0]).update(3) but it had no effect.. Any ideas?
I am not sure will help your request but try and share result with us.
Try to make a function to count total values of W and A then call appropiate function inside the XTemplate via this.function()
tpl: Ext.create('Ext.XTemplate',
'<div style="text-align:center">Leave Requests</div>',
'<table cellpadding="0" class="table-wrap">',
'<tr>',
'<td class="x-leave-request approved"><span class="total-approved">{totalw:this.getTotalw()}</span>Approved</td>',
'<td class="x-leave-request pending"><span class="total-pending">{totala:this.getTotala()}</span>Pending</td>'denied">0</span>Denied</td>',
'</tr>',
'</table>'
)
I solved it using the hint that Oguz gave. What I ended up doing was creating an Ext.util.Hashmap instance, whose pairs were status type and total (e.g. <'W', 10>). Then I called:
<tpl for=".">
{[this.updateStatusTotal(values.type)]}
</tpl>
...
updateStatusTotal : function(type) {
var me = this,
map = me.map,
total = map.get(type);
map.put(type, ++total);
}
then later in the code where the <td> elements are, I call:
{[this.getStatusTotal('W')]}
Done :)

How to make use of something like Factory in jquery/javascript

I want to use some good coding standards for the current project. The overall outcome is achievable now (in my project), but i want help regarding following a better approach.
I'll try my best to explain what I am doing.
I have a xml Response for System and Product information (The xml is too big to accomodate here 1MB approx)
I have two panes left Pane (an accordion listing what is to be clicked) right Pane (JQUERY UI TABS inside which is JPANEL accomodating JQGRID inside it)
When the left Pane any item is clicked 3 params are sent, id of the anchor tag, Service Name & an alias (which decides what tab content should be) to function infa9Services(id,sname,alias){...}
<a id="infa9Services"\>DataIntegrationService</a> //this is the Service Name
alias is coming from a map, which maps service Name to a alias DIS (in one case)
The Right Pane contains a <div id="detailTable"></div> which gets populated from infa9Services function.
Content of infa9Services function
var tabs = [ "Service", "Property", "Additional Info" ];
//Above array creates the Jquery Tab heading
var lis="";
var divs="";
var panels=[];
var tpanels="";
var adtrs="";
var service=[];
var property=[];
var aDoctor=[];
var homeFileList=[];
var ssaprlist=[];
var refData=[];
fetching data from xml response xml
$(xml).find('product').each(function(){
$(this).children('DomainMeta').each(function(){
$(this).children('Service').each(function(){
if(sname==$(this).attr('name')) //There are more than one service in the xml, so checking which Service name was clicked, in this case DataIntegrationService
{
$(this).children('OptionGroup').each(function(){
if($(this).attr('name').toLowerCase().indexOf("service") >= 0)
{
$(this).children('Option').each(function(){
var srow={};
srow.name=$(this).attr('name');
srow.value=$(this).attr('value');
service.push(srow);
});
}
else
{
$(this).children('Option').each(function(){
var prow={};
prow.name=$(this).attr('name');
prow.value=$(this).attr('value');
property.push(prow);
});
}
});
}
});
});
Now here I am checking using if else what alias is it, based on which i'll fetch data
if(alias==="PCIS")
{
$(this).children('addressDoctor').each(function(){
$(this).children('addressDoctor_info').each(function(){
//adding xml values to aDoctor array
});
});
$(this).children('homefilelist').each(function(){
$(this).children('homefilelist_info').each(function(){
//adding xml values to homeFileList array
});
});
}
else if(alias==="PCRS")
{
$(this).children('homefilelist').each(function(){
$(this).children('homefilelist_info').each(function(){
//adding xml values to homeFileList array
});
});
}
else if(alias==="DIS")
{
$(this).children('addressDoctorEngVerDIS').each(function(){
adtrs='<tr width="100%">'+
'<th class="thPanel" align="left" valign="top" width="40%">'+$(this).children('addressDoctorEngVer_info').attr('name')+'</th>'+
'<td align="left" width="60%">'+$(this).children('addressDoctorEngVer_info').attr('value')+'</td>'+
'</tr>';
});
}
else if(alias==="CMS")
{
$(this).children('referenceDataLocation').each(function(){
$(this).children('referenceDataLocation_info').each(function(){
//adding xml values to refData array
});
});
$(this).children('ssaprDirList').each(function(){
$(this).children('ssaprDirList_info').each(function(){
//adding xml values to ssaprlist array
});
});
}
});
dynamically adding li 's (for UI tabs)
$.each(tabs, function(i, item) {
lis+='<li>'+item+'</li>';
});
dynamically adding div's with class="class" (for JPanel) is there a better way here?
panels[0]='<div title="General Information" class="class">'+
'<div class="jqUIDiv">'+
'<table id="tblService" width="100%"></table>'+
'<div id="ServiceGridpager"></div>'+
'</div>'+
'</div>';
panels[1]='<div title="General Information" class="class">'+
'<div class="jqUIDiv">'+
'<table id="tblProperty" width="100%"></table>'+
'<div id="PropertyGridpager"></div>'+
'</div>'+
'</div>';
Here again I am making use of if else what alias is it, based on which i'll populate data from the vars which were fetched before
if(alias==="PCIS")
{
panels[2]='<div title="Address Doctor" class="class" >'+
'<table class="jpanelTable">'+
'<tbody>'+adtrs+'</tbody>'+
'</table>'+
'</div>';
panels[2]+='<div title="Address Doctor Configuration" class="class">'+
'<div class="jqUIDiv">'+
'<table id="tblAdditional" width="100%"></table>'+
'<div id="AdditionalGridpager"></div>'+
'</div>'+
'</div>';
panels[2]+='<div title="Home File List" class="class">'+
'<div class="jqUIDiv">'+
'<table id="tblHomeFileList" width="100%"></table>'+
'<div id="HomeFileListGridpager"></div>'+
'</div>'+
'</div>';
}
else if(alias==="PCRS")
{
panels[2]='<div title="Home File List" class="class">'+
'<div class="jqUIDiv">'+
'<table id="tblHomeFileList" width="100%"></table>'+
'<div id="HomeFileListGridpager"></div>'+
'</div>'+
'</div>';
}
else if(alias==="DIS")
{
panels[2]='<div title="Address Doctor" class="class" >'+
'<table class="jpanelTable">'+
'<tbody>'+adtrs+'</tbody>'+
'</table>'+
'</div>';
}
else if(alias==="CMS")
{
panels[2]='<div title="Reference Data Location" class="class">'+
'<div class="jqUIDiv">'+
'<table id="tblRefData" width="100%"></table>'+
'<div id="RefDataGridpager"></div>'+
'</div>'+
'</div>';
panels[2]+='<div title="SSAPR" class="class">'+
'<div class="jqUIDiv">'+
'<table id="tblSSAPR" width="100%"></table>'+
'<div id="SSAPRGridpager"></div>'+
'</div>'+
'</div>';
}
else
{
panels[2]='<div title="Additional Information" class="class" >'+
'<table class="jpanelTable">'+
'<tbody>'+
'<tr width="100%">'+
'<td align="left" style="word-break:break-all;">'+NA+'</td>'+
'</tr>'+
'</tbody>'+
'</table>'+
'</div>';
}
Note: panel[0],panel1,panel[2] are contents of the 3 tabs
dynamically adding div 's (content for Jquery UI Tab)
$.each(panels, function(i, item) {
divs+='<div id="tabs-'+i+'">'+item+'</div>';
});
adding the whole thing to detailTable (Right Pane)
$('#detailTable').empty();
$('#detailTable').html('<div class="titleBlue">Configuration>'+productname+'>'+sname+' ('+alias+')</div>');
$("<div id='loadingDiv'><table id='detailTable' width='100%'><tbody><tr><td align='center'>Please wait</td></tr><tr><td align='center'><img src='/csm/view/include/images/loading.gif' alt='Loading'/></td></tr></tbody></table></div>").appendTo('#detailTable');
$('<div id="tabs">'+'<ul>'+lis+'</ul>'+divs+'</div>').appendTo('#detailTable').delay(10).queue(function(){
$('.class').jPanel({
'effect' : 'fade',
'speed' : 'medium',
'easing' : 'swing'
});
});
More.. JQGrids to populate tblService, tblSSAPR, tblRefData etc tables (not included here)
How can I make use of something like Factory or something more Generic in such a case? If suppose there are a lot of alias to be checked it will be very cumbersome to do it the way I am doing it currently. Any help would be appreciated. Thanks
Screen shot
Update
My XML content
<?xml-stylesheet type="text/xsl" href="csmclientinfa9.xsl"?>
<csmclient product="infa9" date="12/16/11 12:10 PM" version="1.0">
<system>
</system>
<product>
<DomainMeta>
<Service type="PCIntegrationService" name="TestPCInteg" version="" licenseName="lic_PCIS"> //THIS IS PCIS SERVICE
<ServiceProcess>
<Node name="N_1a63931"></Node>
<PreStartCommand> null</PreStartCommand>
<PostStartCommand> null</PostStartCommand>
<JvmOptions> </JvmOptions>
<OptionGroup name="IntegrationServiceProcessOptions">
<Option name="Codepage_Id" value="4" ></Option>
<Option name="$PMSourceFileDir" value="$PMRootDir/SrcFiles" ></Option>
</OptionGroup>
</ServiceProcess>
<OptionGroup name="IntegrationServiceOptions">
<Option name="ServiceResilienceTimeout" value="180" ></Option>
</OptionGroup>
</Service>
<Service type="DataIntegrationService" name="TestDIS" version="" licenseName="lic_DIS"> //THIS IS DIS SERVICE
<ServiceProcess>
<Node name="N_1163931"></Node>
<PreStartCommand> null</PreStartCommand>
<PostStartCommand> null</PostStartCommand>
<JvmOptions> -Dfile.encoding=UTF-8 -server -Xms256M -Xmx512M -XX:GCTimeRatio=19 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:NewRatio=2</JvmOptions>
<OptionGroup name="SQLServiceOptions">
<Option name="MaxConcurrentConnections" value="100" ></Option>
<Option name="MaxPlanCacheSize" value="100" ></Option>
</OptionGroup>
<OptionGroup name="WebServiceOptions">
<Option name="MaxPlanCacheSize" value="100" ></Option>
</OptionGroup>
</ServiceProcess>
<OptionGroup name="SQLServiceOptions">
<Option name="ConnectionCleanupPeriod" value="30000" ></Option>
<Option name="DTMKeepAliveTime" value="0" ></Option>
</OptionGroup>
<OptionGroup name="CoreServiceOptions">
<Option name="SafeModeLevel" value="0" ></Option>
</OptionGroup>
</Service>
</DomainMeta>
<homefilelist>
<homefilelist_info permission='-rwxr-xr-x' hardlink='1' owner='idp' group='support' fsize='61597' date='22 Mar 2011' filename='libpmwspsvrcmn.so' />
<homefilelist_info permission='-rwxr-xr-x' hardlink='1' owner='idp' group='support' fsize='21778' date='22 Mar 2011' filename='libpmorablk.so' />
</homefilelist>
<addressDoctor filename='AD100.cfg'>
<addressDoctor_info name='MemoryUsage' value='1048' />
<addressDoctor_info name='PreloadingMethod' value='MAP' />
</addressDoctor>
<addressDoctorEngVerPCIS>
<addressDoctorEngVer_info name='EngineVersion' value='5.2.5' />
</addressDoctorEngVerPCIS>
<addressDoctorEngVerDIS>
<addressDoctorEngVer_info name='EngineVersion' value='5.2.6' />
</addressDoctorEngVerDIS>
<referenceDataLocation location='/home/idp/av/default'>
<referenceDataLocation_info permission='-rw-r--r--' hardlink='1' owner='idp' group='support' fsize='196' month='Aug' date='2' time='11:06' filename='copyright.txt'/>
</referenceDataLocation>
<ssaprDirList>
<ssaprDirList_info permission='-rw-r--r--' hardlink='1' owner='idp' group='support' fsize='2737558' month='Oct' date='14' time='2010' filename='turkey.ysp' />
</ssaprDirList>
</product>
</csmclient>
More Updates
var aDoctor=[];
var adtrs="";
var homeFileList=[];
if(alias==="PCIS")
{
$(this).children('addressDoctorEngVerPCIS').each(function(){
adtrs='<tr width="100%">'+
'<th class="thPanel" align="left" valign="top" width="40%">'+$(this).children('addressDoctorEngVer_info').attr('name')+'</th>'+
'<td align="left" width="60%">'+$(this).children('addressDoctorEngVer_info').attr('value')+'</td>'+
'</tr>';
});
$(this).children('addressDoctor').each(function(){
$(this).children('addressDoctor_info').each(function(){
var adevrow={};
adevrow.name=$(this).attr('name');
adevrow.value=$(this).attr('value');
aDoctor.push(adevrow);
});
});
$(this).children('homefilelist').each(function(){
$(this).children('homefilelist_info').each(function(){
var row={};
isPresent=true;
row.permission=$(this).attr('permission');
row.hardlink=$(this).attr('hardlink');
row.owner=$(this).attr('owner');
row.group=$(this).attr('group');
row.fsize=$(this).attr('fsize');
row.date=$(this).attr('date');
row.filename=$(this).attr('filename');
homeFileList.push(row);
});
});
}
/*moving on for HTML construction, panels[..]
panels[0] is for 1st jquery ui tab
panels[1] is for 2nd jquery ui tab
panels[2] is for 3rd jquery ui tab*/
/*I am also using jqGrid, so I am giving one example for PCIS, how I am using aDoctor array */
if(alias==="PCIS")
{
//Additional Information
if(aDoctor.length>0)
{
jQuery("#tblAdditional").jqGrid({
datatype: "local",
data: aDoctor,
colNames:['Name','Value'],
colModel:[
{name:'name',index:'name', align:"left"},
{name:'value',index:'value', align:"left"}
],
pager : '#AdditionalGridpager',
rowNum:10,
rowList:[10,50,100],
scrollOffset:0,
height: 'auto',
autowidth:true,
viewrecords: true,
gridview: true
});
jQuery("#tblAdditional").setGridParam({rowNum:10}).trigger("reloadGrid");
jQuery("#tblAdditional").jqGrid('filterToolbar',{stringResult: true, searchOnEnter: false, defaultSearch: 'cn'});
}
else //i am displaying none in the table
}
//So now my panel is complete for PCIS, if you refer my question, all code is available :) I know it's really big, but this is my 1st project and I want it to be better than this :) Thanks
The Factory design pattern must have a switch (if/else block or associative array) under the hood anyhow. You won't ever shorten code by using it. The only benefit you'll get here is that you might hide away or separate some of that long code. Returning a function from another function, or returning an array where one of the properties is a function (set in the factory) is about as close as you can get to this pattern in JavaScript. The code sample below show something very much like a factory that is just as good in the JavaScript case, and might be slightly less confusing.
I'm not sure what you mean by Generic. If you're referring to "generics", ala Java or C#, then it won't help you in this scenario. Generics in those languages help you get around static typing and avoid duplicating classes. You're not using classes at all here.
If you're simply trying to avoid repeating yourself, you should look for a functional refactor here. See what repeats, and what doesn't. Figure out how you can loop or map to the stuff that doesn't repeat, and write the code that does repeat only once.
For example, I'd use an associative array to map strings to functions for your big if/else block, and I'd extract that child-looping code into a more generialized function:
function forAll(parentName, childName, action) {
$(this).children(parentName).each(function(){
$(this).children(childName).each(function(){
action();
});
});
}
var aliasToHandlerMap =
{
"PCIS": function() {
forAll('addressDoctor', 'addressDoctor_info', function() {
//adding xml values to aDoctor array
});
forAll('homefilelist', 'homefilelist_info', function() {
//adding xml values to homeFileList array
});
},
"PCRS": function() {
forAll('homefilelist', 'homefilelist_info', function() {
//adding xml values to homeFileList array
});
},
"DIS": function() {
$(this).children('addressDoctorEngVerDIS').each(function(){
adtrs=
'<tr width="100%">'+
'<th class="thPanel" align="left" valign="top" width="40%">'+
$(this).children('addressDoctorEngVer_info').attr('name')+'</th>'+
'<td align="left" width="60%">'+
$(this).children('addressDoctorEngVer_info').attr('value')+'</td>'+
'</tr>';
});
},
"CMS": function() {
forAll('referenceDataLocation', 'referenceDataLocation_info', function() {
//adding xml values to refData array
});
forAll('ssaprDirList', 'ssaprDirList_info', function() {
//adding xml values to ssaprlist array
});
}
};
// Execute the appropriate handler for the particular alias
var handler = aliasToHandlerMap[alias];
handler();
In this case I'd also recommend you name each of those handlers, and build the map using named functions. I just wanted to show you visually how much code compression you get from this.
You should be able to do similar things for your long strings of HTML that you're building. If they follow a general pattern, make a function for them, and extract the parts that change into parameters that you pass in.
And you generally shouldn't be building styles into your elements (e.g. align="left" valign="top" width="40%"). You should use style sheets that apply to those specific items, applying only CSS classes when necessary, so that you to specify that in only one place. That should shorten a lot of the element creation code, and might let you use jQuery DOM creation to avoid messy string concatenation code.
All refactoring of long code boils down to an application of the same principle - find out what repeats, and what doesn't repeat. Extract the part that repeat, and build an iterable or indexable structure out of the part that doesn't repeat.
To start learning how to do generalized refactoring in languages using a Functional Programming style, I suggest you watch the SICP lecture videos. They use LISP, but teach you it while you're watching the videos, and the principles apply to every language out there. That language lends itself extremely well to this type of refactoring, which is why he uses it.
You could also look into CoffeeScript, which allows you to take java code and shrink it into a more compact syntax :) It compiles back into pretty-printed JavaScript, so you don't have to worry about server impact, installing code on client boxes, etc.
Also, check out a few of these links for more reading on general code refactoring:
http://en.wikipedia.org/wiki/Code_refactoring
http://martinfowler.com/refactoring/ (he wrote a book)
I think you are asking for a better way to make your code without having to hard code the html? If that is the case you could use jQuery.template() http://api.jquery.com/jQuery.template/. It's in beta but it should help you by not having to hardcode your html into the javascript.
For my projects we do our templating in PHP and just have jquery do ajax calls if the data or templates need to change.
If this is not what you are looking for can you be more descriptive with your question?
If you are looking at refactoring further you can use the same jPanel to buld tabs using just a simple div markup like you did for accordion just replace your jPanel js file with the latest 1.4 version that will save some markup junk for you and also you have too much of html as strings try using a javascript template engine here

Categories

Resources