-
-
Save stlsmiths/1753580 to your computer and use it in GitHub Desktop.
stlsmith's edits
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[% page.load_scripts_at_top = 1 %] | |
<!-- IF you add this, you will run the 3.5.0pr2 code directly from yuilibrary, and can remove all your Gallery crap ... | |
<script type="text/javascript" src="http://yui.yahooapis.com/3.5.0pr2/build/yui/yui-min.js"></script> | |
--> | |
<script type="text/javascript"> | |
/* Delete the gallery stuff | |
YUI.add('datatabledatasource-350-preview-patch', function (Y) { | |
// Or just put this in your code directly | |
Y.Plugin.DataTableDataSource.prototype.onDataReturnInitializeTable = function (e) { | |
this.get('host').set('data', (e.response && e.response.results) || []); | |
}; | |
}, '0.1', { requires: ['datatable-datasource'] }); | |
YUI({gallery: 'gallery-2012.02.01-21-35'}) | |
.use( 'gallery-datatable-350-preview', 'datatable', 'datatype', 'model', 'view', 'panel', 'dd-plugin', 'button', | |
'datasource-io', 'datatable-datasource', 'datatable-jsonschema', function (Y) { | |
*/ | |
// new YUI.use statement, leaving out gallery stuff | |
YUI().use( 'datatable', 'datatype', 'model', 'view', 'panel', 'dd-plugin', 'button', | |
'datasource-io', 'datatable-datasource', 'datatable-jsonschema', function (Y) { | |
// ------------------------- | |
// Define a few DataTable helper methods | |
// NOTE: These only work with the 3.5.0PR release of DataTable | |
// ------------------------- | |
/** | |
Method to take an existing TD or TR Node element as input "target" and scan | |
the dataset (ModelList) for the underlying data record (a Model). | |
@method getRecord | |
@param target {Node} Either a TR or TD Node | |
@returns {Model} Data record or false (or -1 if not found) | |
**/ | |
//FIXME: if target is numeric or string, not working yet ... Node only works | |
Y.DataTable.prototype.getRecord = function( target ) { | |
var rs = this.get('data') | |
tag = target.get('tagName').toLowerCase(); | |
var row = ( tag === 'td' ) ? target.ancestor() : ( tag === 'tr' ) ? target : null; | |
if ( !row ) return false; | |
if ( Y.Lang.isNumber(row) ) // assume row is rowindex | |
return rs.item(row) || false; | |
else if ( row instanceof Y.Node || Y.Lang.isString(row) ) { | |
var crow = ( Y.Lang.isString(row) ) ? row : row.get('id'); // matches based on DOM id | |
var rec = -1; | |
rs.some( function(item) { | |
if ( item.get('entryid') === crow ) { | |
rec = item; | |
return true; | |
} | |
}); | |
return rec; | |
} | |
return false; | |
} | |
/** | |
Helper method to return the column's key property associated with the current TD. | |
Uses DataTable's current method of identifying a class on TD as "yui3-datatable-col-XXX" | |
where XXX is the column 'key' (or 'name') | |
@method getDTColumnKey | |
@param tdTarget {Node} The TD cell to return column key to | |
@returns ckey {String} column key name | |
**/ | |
Y.DataTable.prototype.getCellColumnKey = function( tdTarget ) { | |
var DT_COL_CLASS = this.getClassName('col'); | |
var regex = new RegExp( DT_COL_CLASS+'-(.*)'), // currently creates /yui3-datatable-col-(.*) to grab column key | |
tdclass = tdTarget.get('className').split(" "), | |
ckey = -1; | |
// | |
// Scan through the TD class(es), checking for a match | |
// | |
Y.Array.some( tdclass, function(item){ | |
var mitem = item.match( regex ); | |
if ( mitem && mitem[1] ) { | |
ckey = mitem[1].replace(/^\s+|\s+$/g,""); // trim all spaces | |
return true; | |
} | |
}); | |
return ckey || false; | |
} | |
/* https://gist.github.com/1707631 | |
Y.DataTable.prototype.getCellColumnKey = function (node) { | |
var classRE = new RegExp('\b' + this.getClassName('col') + '-(\W+)'), | |
name, column; | |
node = node.ancestor('.' + this.getClassName('cell'), true); | |
if (node) { | |
name = (node.get('className').match(classRE) || [])[1]; | |
column = name && this.getColumn(name); | |
} | |
return column && column.key; | |
}; | |
*/ | |
/** | |
Method to scan the "columns" Array for the target and return the requested column. | |
The requested "target" can be either of ; | |
a column index, | |
or a TD Node, | |
or a column "key", column "name" or "_yuid" (in that order). | |
@method getColumn | |
@param target {Number | Node | String} Either the column index, the TD node or a column ID | |
@returns {Object} Column | |
**/ | |
Y.DataTable.prototype.getColumn = function( target ) { | |
var cs = this.get('columns'), | |
ckey = null; | |
if (Y.Lang.isNumber(target) ) | |
return cs[target]; //return cs.keys[col]; | |
else if ( Y.Lang.isString(target) || target instanceof Y.Node ) { // check for 'key' or then 'name', finally '_yuid' | |
ckey = ( target instanceof Y.Node ) ? ckey = this.getCellColumnKey( target ) : ckey; | |
col = ( ckey ) ? ckey : target; | |
// Check if a column "key" | |
var cm = -1; | |
Y.Array.some( cs, function(citem) { | |
if ( citem['key'] === col ) { | |
cm = citem; | |
return true; | |
} | |
}); | |
if ( cm !== -1) return cm; // found one, bail !! | |
// If not found, Check if a column "name" | |
Y.Array.some( cs, function(citem) { | |
if ( citem.name === col ) { | |
cm = citem; | |
return true; | |
} | |
}); | |
if ( cm!==-1 ) return cm; | |
// If not found, Check if a column "_yui" something | |
Y.Array.some( cs, function(citem) { | |
if ( citem._yuid === col ) { | |
cm = citem; | |
return true; | |
} | |
}); | |
return cm; | |
} else | |
return false; | |
} | |
//================================================================================================== | |
// Execution Begins | |
//================================================================================================== | |
var cols, myDT; | |
// | |
// --- Define DataTable custom formatters for this example | |
// | |
var fmtPublished = function(o) { | |
var published = o.value; | |
return o.value == 1 ? | |
"yes" : | |
"no"; | |
} | |
var fmtBlank = function(o) { | |
var fclass = o.column.className || null; | |
if (fclass) | |
o.className += ' '+fclass; | |
o.value = ' '; | |
} | |
var fmtChkBox = function(o){ | |
var cell = '<input type="checkbox" class="myCheckboxFmtr" />'; | |
o.value = cell; | |
o.className += ' align-center'; | |
} | |
cols = [ | |
{ name:'selectBox', label:'Select <input type="checkbox" id="selAll" title="Click to toggle ALL records"/>', | |
formatter: fmtChkBox, allowHTML:true }, // must use allowHTML:true if we insert HTML with the formatter ... | |
{ key:"entryid", label:'Entry ID', sortable:true }, | |
{ key:"title", label:"Title", sortable:true }, | |
{ key:"created_at", label:'Created On', sortable:true }, | |
{ key:"published", label:'Published', formatter: fmtPublished, sortable:true }, | |
{ key:"reply_count", label:'Replies', sortable:true }, | |
{ name:'edit', label:'- Edit -', formatter: fmtBlank, className:'align-center cell-edit' }, | |
{ name:'delete', label:'- Delete -', formatter: fmtBlank, className:'align-center cell-delete' } | |
]; | |
// | |
// Create the DataTable and render it | |
// | |
var ds = new Y.DataSource.GET({ | |
source:'[% c.uri_for_action('/user/manage_entries', [ c.user.name ]) %]', | |
ioConfig: { | |
headers: { | |
'Accept': 'application/json' | |
} | |
} | |
}); | |
ds.plug(Y.Plugin.DataSourceJSONSchema, { | |
schema: { | |
resultListLocator: "data_table", | |
resultFields: [ | |
{ key: "entryid" }, | |
{ key: "title" }, | |
{ key: "created_at" }, | |
{ key: "published" }, | |
{ key: "reply_count" }, | |
] | |
} | |
}); | |
/* | |
ds.sendRequest({ | |
callback: { | |
success: function (e) { | |
Y.log(e); | |
} | |
} | |
}); | |
*/ | |
myDT = new Y.DataTable({ | |
columns: cols, | |
}); | |
myDT.plug(Y.PluginDataTableDataSource, { | |
datasource: ds, | |
initialRequest: "" | |
}); | |
myDT.render('#dtable'); | |
myDT.datasource.load({request:''}); | |
// ------------------------- | |
// Create a Panel to serve as the Row Editor box | |
// ... this uses a template defined in <script> templates below, nice way to | |
// hide content until we want to display it. (see the beginning of http://yuilibrary.com/yui/docs/app/app-todo.html for an example) | |
// ------------------------- | |
// var insertFlag = false; | |
var editorPanel = new Y.Panel({ | |
srcNode : '#idPanel', | |
width : 320, | |
xy : [ 750, 170 ], | |
visible : false, | |
render : true, | |
zIndex : 10, | |
plugins : [Y.Plugin.Drag], | |
buttons: [ | |
{ | |
value : 'Save', | |
section: Y.WidgetStdMod.FOOTER, | |
action : function (e) { | |
if (e) e.preventDefault(); | |
saveFormData(); | |
this.hide(); | |
} | |
}, | |
{ | |
value : 'Cancel', | |
section: Y.WidgetStdMod.FOOTER, | |
action : function (e) { | |
e.preventDefault(); | |
this.hide(); | |
} | |
} | |
], | |
on : { | |
'render' : function() { | |
Y.one("#main").show(); // render the "main" page elements, | |
} | |
} | |
}); | |
//----------------- | |
// Function to save the FORM data, based on current values. | |
// Define a mapping object to help us figure out how to apply INPUT[name=xxx] to what | |
// column of each record. | |
// Uses the setting of FORM hidden value "frmInsertFlag" to determine if this is a new | |
// record or if we are saving an existing record. | |
// If existing, the record "clientId" is saved in FORM hidden value "frmRecord" | |
//----------------- | |
var saveFormData = function() { | |
var theForm = document.forms[0], | |
rec_id = theForm.frmRecord.value, // if INSERT, this is disregarded ... | |
newData = {}, | |
raw_value = 0, | |
data_value = 0; | |
// | |
// Define a mapping between the INPUT 'name' settings and the record "key" names ... | |
// also, define a parser on a few numeric items | |
// | |
var record_map = [ | |
{ field:'entryid', ckey:'entryid', parser: parseInt }, | |
{ field:'title', ckey:'title'}, | |
{ field:'published', ckey:'created_at'}, | |
{ field:'reply_count', ckey:'reply_count', parser: parseInt } | |
]; | |
// | |
// Run through the "record_map" FORM variables, inserting data values into "newData" | |
// that will serve as the data object for DataTable | |
// | |
Y.Array.each( record_map, function(item){ | |
raw_value = theForm[item.field].value; | |
data_value = ( item.parser && Y.Lang.isFunction(item.parser) ) ? item.parser.call(this,raw_value) : raw_value ; | |
newData[ item.ckey ] = data_value; | |
}); | |
// | |
// Now insert the "newData" object into DataTable's data, | |
// check frmInsertFlag for whether it is "new" or "updated" data | |
// | |
if ( parseInt( theForm.frmInsertFlag.value ) === 0 ) | |
myDT.modifyRow( rec_id, newData ); | |
else | |
myDT.addRow( newData ); | |
} | |
// trap an ENTER key on the form, save the data ... | |
editorPanel.get('srcNode').on('key', function() { | |
saveFormData(); | |
editorPanel.hide(); | |
}, 'enter'); | |
// | |
// Define DEFAULT data for a "New" inserted row | |
// | |
var default_data = { | |
title : 'New Entry', | |
body : "", | |
valRecord : 0, | |
valInsert : 1 | |
}; | |
// position of "Insert Row" dialog | |
var default_dialog_xy = [ 220, 130 ]; | |
//----------------- | |
// Displays the Panel (i.e. Dialog) for either EDIT of existing data or INSERT of new data. | |
// The passed in "record" and "xy" provide which record to edit and the XY position of the Panel when displayed. | |
// For a NEW record, these will be null. | |
// | |
// If "insert_obj" is defined, then it assumes we are INSERTing a new record, and uses the default_data above. | |
//----------------- | |
var showDT_Dialog = function( record, xy, insert_obj ) { | |
var thePanel, DialogTMPL, body_html, header_html; | |
// | |
// Grab the dialog internal content from the <script> template | |
// | |
DialogTMPL = Y.one("#dialog-template").getContent(); | |
thePanel = editorPanel; | |
if ( !insert_obj ) { // we are EDITING and existing row ... | |
// | |
// Define the substitution objects to fill in the INPUT default values | |
// | |
var form_data = { | |
valID : record.get('entryid'), | |
valReplies : record.get('reply_count'), | |
valTitle : record.get('title'), | |
valCreatedAt : record.get('created_at'), | |
valPublished : record.get('published'), | |
valRecord : record.get('entryid'), | |
valInsert : 0 | |
} | |
xy[0] += 50; // offset the dialog a tinch, from the Edit TD ... | |
header_html = 'Editing Row No. ' + (myDT.get('data').indexOf(record)+1); | |
body_html = Y.Lang.sub( DialogTMPL, form_data ); | |
} else { // we are INSERTING a new row ... | |
insertFlag = true; // used | |
xy = default_dialog_xy; | |
header_html = 'Inserting NEW Row'; | |
body_html = Y.Lang.sub( DialogTMPL, insert_obj ); | |
} | |
// | |
// Fill the Panel content, position it and display it | |
// | |
thePanel.set( 'xy', xy ); | |
thePanel.set( 'headerContent', header_html ); | |
thePanel.set( 'bodyContent', body_html ); | |
thePanel.show(); | |
} | |
// Button click handler for the "Insert New Row" button | |
new Y.Button({srcNode:"#btnInsert"}).on("click",function() { | |
editorPanel.hide(); | |
showDT_Dialog( 0, 0, default_data ); | |
}); | |
// ------------------------- | |
// Define a click handler on table cells ... | |
// Note: use Event Delegation here (instead of just .on() ) because we may be | |
// deleting rows which may cause problems with just .on | |
// ------------------------- | |
myDT.delegate("click", function(e) { | |
var cell = e.currentTarget, // the clicked TD | |
row = cell.ancestor(), // the parent of TD, which is TR | |
rec = this.getRecord( cell ), // Call the helper method above to return the "data" record (a Model) | |
ckey = this.getCellColumnKey( cell ), // | |
col = this.getColumn( cell ); // | |
var d_ckey = col.key || col.name || 'not set'; // if column key returned is a yui_id, don't display it | |
// ... that means we are in the "Select", "Edit" or "Delete" columns | |
// | |
// Update status box | |
// | |
var StatusTMPL = Y.one("#status-template").getContent(); // this retrieves HTML containing {xxx} tags for substitution | |
Y.one("#idStatus").setContent( Y.Lang.sub( StatusTMPL, { // ... do the substitution into the template using Y.Lang.sub | |
rec_id : rec.get('entryid'), | |
rec_index: this.get('data').indexOf(rec), | |
col_key : d_ckey, | |
col_index: Y.Array.indexOf( this.get('columns'), col ), //this.get('columns').indexOf(col), | |
raw_data : rec.get(ckey) || 'No Data' | |
} ) ); | |
// | |
// If a column 'action' is available, process it | |
// | |
switch( col.name || null ) { | |
case 'edit': | |
showDT_Dialog( rec, cell.getXY() ); | |
break; | |
case 'delete': | |
if ( confirm("Are you sure you want to delete this record ?") === true ) { | |
// DELETE CALL GOES HERE | |
myDT.removeRow( rec.get('entryid') ); | |
Y.one("#idStatus").setContent("<br/><b>Row was Deleted!</b>"); | |
} | |
break; | |
} | |
}, "tbody tr td", myDT); | |
// the selector, internal scope | |
// ------------------------- | |
// Click handler on "Select" TH checkbox, toggle the settings of all rows | |
// ------------------------- | |
Y.one("#selAll").on("click", function(e){ | |
var selAll = this.get('checked'); // the checked status of the TH checkbox | |
// | |
// Get a NodeList of each of INPUT with class="myCheckboxFmtr" in the TBODY | |
// | |
var chks = myDT.get('srcNode').all("tbody input.myCheckboxFmtr"); | |
chks.each( function(item){ | |
item.set('checked', selAll); // set the individual "checked" to the TH setting | |
}); | |
}); | |
// ------------------------- | |
// Handle the "Process Selected Rows" BUTTON press, | |
// ------------------------- | |
new Y.Button({srcNode:"#btnProcess"}).on("click",function(){ | |
// | |
// Get a NodeList of all nodes on the DT which have the checkboxes I defined, | |
// with class="myCheckBoxFmtr" AND that are currently "checked" | |
// | |
var chks = this.get("srcNode").all("tbody tr td input.myCheckboxFmtr"); // get all checks | |
// in a perfect world ... i.e. one without IE 8-, we could just do ... | |
// var chkd = this.get("srcNode").all("tbody tr td input.myCheckboxFmtr:checked"); | |
// | |
// Loop over the NodeList (using it's .each method) and append the employee name to the message. | |
// Note: 'chkd' contains nodes of the INPUT checkboxes, step back twice to get the parent TR node | |
// | |
var msg = "The following Employees will be processed;\n\n"; // define the beginning of our message string | |
chks.each( function(item){ | |
if ( !item.get('checked') ) return; | |
var rec = this.getRecord( item.ancestor().ancestor() ); // item is INPUT, first parent is TD, second is TR | |
msg += rec.get('em_id') + ' : ' + rec.get('ename') + "\n"; | |
}, this); | |
alert(msg); | |
}, myDT); | |
}); | |
</script> | |
<script type="text/x-template" id="status-template"> <!-- used in Y.delegate ... tbody tr td --> | |
<table id="dt_info" width="250"> | |
<tr><th width="50%">Record clientId :</th><td>{rec_id}</td></tr> | |
<tr><th>Record Index :</th><td>{rec_index}</td></tr> | |
<tr><th>Col Key :</th><td>{col_key}</td></tr> | |
<tr><th>Col Index :</th><td>{col_index}</td></tr> | |
<tr><th>Raw Data :</th><td>{raw_data}</td></tr> | |
</table> | |
</script> | |
<script type="text/x-template" id="dialog-template"> <!-- used in Function showDT_Dialog --> | |
<form name="roweditor"> | |
<fieldset id="myfieldset"> | |
<table> | |
<tr><th>Title :</th><td><input type="text" name="title" value="{title}" /></td></tr> | |
<tr><th>Published :</th><td><input type="select" name="published" value="{published}" /></td></tr> | |
<tr><th>Body : </th><td><textarea name="body" rows=10 cols=45>{body}</textarea></td></tr> | |
</table> | |
</fieldset> | |
<input type="hidden" name="frmRecord" value="{valRecord}" /> | |
<input type="hidden" name="frmInsertFlag" value="{valInsert}" /> | |
</form> | |
</script> | |
<div id="main"> | |
<h2>Manage Entries</h2> | |
<table> | |
<tr valign="top"> | |
<td> | |
<div id="dtable"></div> | |
<br/><button id="btnProcess">Process SELECTED Rows</button> <button id="btnInsert">Insert New Row</button> | |
</td> | |
<td width="300" align="center"> | |
TD Click Status:<br/> | |
<div id="idStatus"></div> | |
</td> | |
</tr> | |
</table> | |
<br/> | |
<div id="idPanel"> | |
<div class="yui3-widget-hd"></div> | |
<div class="yui3-widget-bd"></div> | |
</div> | |
<div id="idCalendarBox" style="z-index:12;"></div> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"data_table" : [ | |
{ | |
"parent" : null, | |
"entryid" : 1, | |
"path" : "1", | |
"author" : { | |
"email" : "[email protected]", | |
"password" : "$2a$08$ZY0mDB7wEHdPZWEtB9YPK.SH332XctfUj77eSnLfQLSXxsr/Encxu", | |
"created_at" : null, | |
"userid" : 1, | |
"entries" : [ | |
{ | |
"title" : "huhuhuhuhuhuh", | |
"entryid" : 1 | |
} | |
], | |
"updated_at" : null, | |
"name" : "dhoss" | |
}, | |
"children" : [], | |
"published" : 1, | |
"created_at" : "January 31, 2012 at 21:50:10 UTC", | |
"updated_at" : null, | |
"title" : "huhuhuhuhuhuh", | |
"display_title" : "huhuhuhuhuhuh", | |
"reply_count" : 0 | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment