/* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness http://overset.com ---> .asd { white-space: pre; width: 100px; } /* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness ---> .asd { white-space: pre; width: 100px; } /* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness ---> .asd { white-space: pre; width: 100px; } /* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness ---> .asd { white-space: pre; width: 100px; } /* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness ---> .asd { white-space: pre; width: 100px; } /* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness ---> .asd { white-space: pre; width: 100px; } /* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness ---> .asd { white-space: pre; width: 100px; } /* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness ---> .asd { white-space: pre; width: 100px; } /* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness ---> .asd { white-space: pre; width: 100px; } /* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness ---> .asd { white-space: pre; width: 100px; } /* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness ---> .asd { white-space: pre; width: 100px; } /* test jimpalmer@gmail.com * this * insane func */ function addEntry (arg1,arg2,testing) { var insane = '', too_dles = 0.0; $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); $('#hframe')[0.0f].contentWindow.document.open().close(); $('#hframe').sss()[0].location.hash = '#' + 'asdasd'; // testing this awesome $CODE } /* asd ***/ function test () { return yarr; } <!--- and the CFMX madness ---> .asd { white-space: pre; width: 100px; }
<html> <head> "Initial Catalog=<DBNAME>;Data Source=<DBNAME>;User ID=<DBUSER>;password=<DBPASS>;" <script language="JavaScript" type="text/javascript" src="jquery.js"></script> <script> function addEntry () { $('#hframe')[0].contentWindow.document.open().close(); $('#hframe').contents()[0].location.hash = '#' + (new Date()).getTime(); } </script> </head> <body> <input type="button" onClick="addEntry();" value="add history entry"><br> <iframe id="hframe" src="cache.html" /> </body> </html>
// csc.exe /t:library /out:sqlExample.dll /r:LitJson.dll com.overset.sqlExample.cs namespace com.overset { using System; using System.Data; using System.Data.SqlClient; using LitJson; public class sqlExample { /* provide your sqlclient connection string here */ public string __connStr = "Initial Catalog=<DBNAME>;Data Source=<DBNAME>;User ID=<DBUSER>;password=<DBPASS>;" public sqlExample () { /* ctor */ } /// <summary> /// Function to save a row depending on the arguments supplied in a single JSON string /// </summary> /// <params name="fieldsObject">(string) '{\'field1\':\'value1\', ...}'</params> /// <returns>(bool) success</returns> public bool saveRow (string fieldsObject) { } }
/* * jTPS - table sorting, pagination, and animated page scrolling * version 0.4 * Author: Jim Palmer * Released under MIT license. */ (function($) { // apply table controls + setup initial jTPS namespace within jQuery $.fn.jTPS = function ( opt ) { $(this).data('tableSettings', $.extend({ perPages: [5, 6, 10, 20, 50, 'ALL'], // the "show per page" selection perPageText: 'Show per page:', // text that appears before perPages links perPageDelim: '<span style="color:#ccc;">|</span>', // text or dom node that deliminates each perPage link perPageSeperator: '..', // text or dom node that deliminates split in select page links scrollDelay: 30, // delay (in ms) between steps in anim. - IE has trouble showing animation with < 30ms delay scrollStep: 1, // how many tr's are scrolled per step in the animated vertical pagination scrolling fixedLayout: true // autoset the width/height on each cell and set table-layout to fixed after auto layout }, opt)); // generic pass-through object + other initial variables var pT = $(this), page = page || 1, perPages = $(this).data('tableSettings').perPages, perPage = perPage || perPages[0], rowCount = $('tbody tr', this).length; // append jTPS class "stamp" $(this).addClass('jTPS'); // setup the fixed table-layout so that the animation doesn't bounce around - faux grid for table if ( $(this).data('tableSettings').fixedLayout ) { // "fix" the table layout and individual cell width & height settings if ( $(this).css('table-layout') != 'fixed' ) { // find max tbody td cell height var maxCellHeight = 0; // set width style on the TH headers (rely on jQuery with computed styles support) $('thead th', this).each(function () { $(this).css('width', $(this).width()); }); // ensure browser-formated widths for each column in the thead and tbody var tbodyCh = $('tbody', this)[0].childNodes, tmpp = 0; // loop through tbody children and find the Nth <TR> for ( var tbi=0, tbcl=tbodyCh.length; tbi < tbcl; tbi++ ) if ( tbodyCh[ tbi ].nodeName == 'TR' ) maxCellHeight = Math.max( maxCellHeight, tbodyCh[ tbi ].offsetHeight ); // now set the height attribute and/or style to the first TD cell (not the row) for ( var tbi=0, tbcl=tbodyCh.length; tbi < tbcl; tbi++ ) if ( tbodyCh[ tbi ].nodeName == 'TR' ) for ( var tdi=0, trCh=tbodyCh[ tbi ].childNodes, tdcl=trCh.length; tdi < tdcl; tdi++ ) if ( trCh[ tdi ].nodeName == 'TD' ) { trCh[ tdi ].style.height = maxCellHeight + 'px'; tdi = tdcl; } // now set the table layout to fixed $(this).css('table-layout','fixed'); } } // remove all stub rows $('.stubCell', this).remove(); // add the stub rows var stubCount=0, cols = $('tbody tr:first td', this).length, stubs = ( perPage - ( $('tbody tr', this).length % perPage ) ), stubHeight = $('tbody tr:first td:first', this).css('height'); for ( ; stubCount < stubs && stubs != perPage; stubCount++ ) $('tbody tr:last', this).after( '<tr class="stubCell"><td colspan="' + cols + '" style="height: ' + stubHeight + ';"> </td></tr>' ); // paginate the result if ( rowCount > perPage ) $('tbody tr:gt(' + (perPage - 1) + ')', this).addClass('hideTR'); // bind sort functionality to theader onClick $('thead th[sort]', this).each( function (tdInd) { $(this).addClass('sortableHeader').unbind('click').bind('click', function () { var desc = $(pT).find('thead th:eq(' + tdInd + ')').hasClass('sortAsc') ? true : false; // sort the rows sort( pT, tdInd, desc ); // show first perPages rows var page = parseInt( $(pT).find('.hilightPageSelector:first').html() ) || 1; $(pT).find('tbody tr').removeClass('hideTR').filter(':gt(' + ( ( perPage - 1 ) * page ) + ')').addClass('hideTR'); $(pT).find('tbody tr:lt(' + ( ( perPage - 1 ) * ( page - 1 ) ) + ')').addClass('hideTR'); // scroll to first page $(pT).find('.pageSelector:first').click(); // hilight the sorted column header $(pT).find('thead .sortDesc, thead .sortAsc').removeClass('sortDesc').removeClass('sortAsc'); $(pT).find('thead th:eq(' + tdInd + ')').addClass( desc ? 'sortDesc' : 'sortAsc' ); // hilight the sorted column $(pT).find('tbody').find('td.sortedColumn').removeClass('sortedColumn'); $(pT).find('tbody tr:not(.stubCell)').each( function () { $(this).find('td:eq(' + tdInd + ')').addClass('sortedColumn'); } ); clearSelection(); } ); } ); // add perPage selection link + delim dom node $('tfoot .selectPerPage', this).empty(); var pageSel = perPages.length; while ( pageSel-- ) $('tfoot .selectPerPage', this).prepend( ( (pageSel > 0) ? $(this).data('tableSettings').perPageDelim : '' ) + '<span class="perPageSelector">' + perPages[pageSel] + '</span>' ); // now draw the page selectors drawPageSelectors( this, page || 1 ); // prepend the instructions and attach select hover and click events $('tfoot .selectPerPage', this).prepend( $(this).data('tableSettings').perPageText ).find('.perPageSelector').each( function () { if ( ( parseInt($(this).html()) || rowCount ) == perPage ) $(this).addClass('perPageSelected'); $(this).bind('mouseover mouseout', function (e) { e.type == 'mouseover' ? $(this).addClass('perPageHilight') : $(this).removeClass('perPageHilight'); } ); $(this).bind('click', function () { // set the new number of pages perPage = parseInt( $(this).html() ) || rowCount; if ( perPage > rowCount ) perPage = rowCount; // remove all stub rows $('.stubCell', this).remove(); // redraw stub rows var stubCount=0, cols = $(pT).find('tbody tr:first td').length, stubs = ( perPage - ( $(pT).find('tbody tr').length % perPage ) ), stubHeight = $(pT).find('tbody tr:first td:first').css('height'); for ( ; stubCount < stubs && stubs != perPage; stubCount++ ) $(pT).find('tbody tr:last').after( '<tr class="stubCell"><td colspan="' + cols + '" style="height: ' + stubHeight + ';"> </td></tr>' ); // set new visible rows $(pT).find('tbody tr').removeClass('hideTR').filter(':gt(' + ( ( perPage - 1 ) * page ) + ')').addClass('hideTR'); $(pT).find('tbody tr:lt(' + ( ( perPage - 1 ) * ( page - 1 ) ) + ')').addClass('hideTR'); // back to the first page $(pT).find('.pageSelector:first').click(); $(this).siblings('.perPageSelected').removeClass('perPageSelected'); $(this).addClass('perPageSelected'); // redraw the pagination drawPageSelectors( pT, 1 ); // update status bar var cPos = $('tbody tr:not(.hideTR):first', pT).prevAll().length, ePos = $('tbody tr:not(.hideTR):not(.stubCell)', pT).length; $('tfoot .status', pT).html( 'Showing ' + ( cPos + 1 ) + ' - ' + ( cPos + ePos ) + ' of ' + rowCount + '' ); clearSelection(); } ); } ); // show the correct paging status var cPos = $('tbody tr:not(.hideTR):first', this).prevAll().length, ePos = $('tbody tr:not(.hideTR)', this).length; $('tfoot .status', this).html( 'showing ' + ( cPos + 1 ) + ' - ' + ( cPos + ePos ) + ' of ' + rowCount ); // clear selected text function function clearSelection () { if ( document.selection && typeof(document.selection.empty) != 'undefined' ) document.selection.empty(); else if ( typeof(window.getSelection) === 'function' && typeof(window.getSelection().removeAllRanges) === 'function' ) window.getSelection().removeAllRanges(); } // render the pagination functionality function drawPageSelectors ( target, page ) { // add pagination links $('tfoot .pagination', target).empty(); var pages = (perPage >= rowCount) ? 0 : Math.ceil( rowCount / perPage ), totalPages = pages; while ( pages-- ) $('tfoot .pagination', target).prepend( '<div class="pageSelector">' + ( pages + 1 ) + '</div>' ); var pageCount = $('tfoot .pageSelector', target).length; $('tfoot .pageSelector.hidePageSelector', target).removeClass('hidePageSelector'); $('tfoot .pageSelector.hilightPageSelector', target).removeClass('hilightPageSelector'); $('tfoot .pageSelectorSeperator', target).remove(); $('tfoot .pageSelector:lt(' + ( ( page > ( pageCount - 4 ) ) ? ( pageCount - 5 ) : ( page - 2 ) ) + '):not(:first)', target).addClass('hidePageSelector') .eq(0).after( '<div class="pageSelectorSeperator">' + $(target).data('tableSettings').perPageSeperator + '</div>' ); $('tfoot .pageSelector:gt(' + ( ( page < 4 ) ? 4 : page ) + '):not(:last)', target).addClass('hidePageSelector') .eq(0).after( '<div class="pageSelectorSeperator">' + $(target).data('tableSettings').perPageSeperator + '</div>' ); $('tfoot .pageSelector:eq(' + ( page - 1 ) + ')', target).addClass('hilightPageSelector'); // remove the pager title if no pages necessary if ( perPage >= rowCount ) $('tfoot .paginationTitle', target).css('display','none'); else $('tfoot .paginationTitle', target).css('display',''); // bind the pagination onclick $('tfoot .pagination .pageSelector', target).each( function () { $(this).bind('click', function () { // if double clicked - stop animation and jump to selected page - this appears to be a tripple click in IE7 if ( $(this).hasClass('hilightPageSelector') ) { if ( $(this).parent().queue().length > 0 ) { // really stop all animations and create new queue $(this).parent().stop().queue( "fx", [] ).stop(); // set the user directly on the correct page without animation var beginPos = ( ( parseInt( $(this).html() ) - 1 ) * perPage ), endPos = beginPos + perPage; $('tbody tr', pT).removeClass('hideTR').addClass('hideTR'); $('tbody tr:gt(' + (beginPos - 2) + '):lt(' + ( perPage ) + ')', pT).andSelf().removeClass('hideTR'); // update status bar var cPos = $('tbody tr:not(.hideTR):first', pT).prevAll().length, ePos = $('tbody tr:not(.hideTR):not(.stubCell)', pT).length; $('tfoot .status', pT).html( 'Showing ' + ( cPos + 1 ) + ' - ' + ( cPos + ePos ) + ' of ' + rowCount + '' ); } clearSelection(); return false; } // hilight the specific page button $(this).parent().find('.hilightPageSelector').removeClass('hilightPageSelector'); $(this).addClass('hilightPageSelector'); // really stop all animations $(this).parent().stop().queue( "fx", [] ).stop().dequeue(); // setup the pagination variables var beginPos = $('tbody tr:not(.hideTR):first', pT).prevAll().length, endPos = ( ( parseInt( $(this).html() ) - 1 ) * perPage ); if ( endPos > rowCount ) endPos = (rowCount - 1); // set the steps to be exponential for all the page scroll difference - i.e. faster for more pages to scroll var sStep = $(pT).data('tableSettings').scrollStep * Math.ceil( Math.abs( ( endPos - beginPos ) / perPage ) ); if ( sStep > perPage ) sStep = perPage; var steps = Math.ceil( Math.abs( beginPos - endPos ) / sStep ); // start scrolling while ( steps-- ) { $(this).parent().animate({'opacity':1}, $(pT).data('tableSettings').scrollDelay, function () { // reset the scrollStep for the remaining items if ( $(this).queue("fx").length == 0 ) sStep = ( Math.abs( beginPos - endPos ) % sStep ) || sStep; /* scoll up */ if ( beginPos > endPos ) { $('tbody tr:not(.hideTR):first', pT).prevAll(':lt(' + sStep + ')').removeClass('hideTR'); if ( $('tbody tr:not(.hideTR)', pT).length > perPage ) $('tbody tr:not(.hideTR):last', pT).prevAll(':lt(' + ( sStep - 1 ) + ')').andSelf().addClass('hideTR'); // if scrolling up from less rows than perPage - compensate if < perPage var currRows = $('tbody tr:not(.hideTR)', pT).length; if ( currRows < perPage ) $('tbody tr:not(.hideTR):last', pT).nextAll(':lt(' + ( perPage - currRows ) + ')').removeClass('hideTR'); /* scroll down */ } else { var endPoint = $('tbody tr:not(.hideTR):last', pT); $('tbody tr:not(.hideTR):lt(' + sStep + ')', pT).addClass('hideTR'); $(endPoint).nextAll(':lt(' + sStep + ')').removeClass('hideTR'); } // update status bar var cPos = $('tbody tr:not(.hideTR):first', pT).prevAll().length, ePos = $('tbody tr:not(.hideTR):not(.stubCell)', pT).length; $('tfoot .status', pT).html( 'Showing ' + ( cPos + 1 ) + ' - ' + ( cPos + ePos ) + ' of ' + rowCount + '' ); } ); } // redraw the pagination drawPageSelectors( pT, parseInt( $(this).html() ) ); } ); } ); }; /* sort function */ function sort ( target, tdIndex, desc ) { var sorted = $('thead th:eq(' + tdIndex + ')', target).hasClass('sortAsc') || $('thead th:eq(' + tdIndex + ')', target).hasClass('sortDesc') || false, nullChar = String.fromCharCode(0), re = /([-]{0,1}[0-9.]{1,})/g, rows = $('tbody tr:not(.stubCell)', target).get(), procRow = []; $(rows).each( function(key, val) { // setup temp-scope variables for comparison evauluation var x = ( $('td:eq(' + tdIndex + ')', val).html() || '' ).toString().toLowerCase() || '', xN = x.replace(re, nullChar + '$1' + nullChar).split(nullChar), tD = (new Date(x)).getTime(), xNl = xN.length; if ( tD ) procRow.push( tD + ',' + (procRow.length) ); else { var dS = []; for (var i=0; i < xNl; i++) dS.push( (new Date( xN[ i ] )).getTime() || parseFloat( xN[ i ] ) || xN[ i ] ); procRow.push( dS.join(',') + ',' + (procRow.length) ); } } ); if ( !sorted ) { // use the quick sort algorithm quickSort( procRow, 0, (rows.length - 1) ); // properly position order of sort if ( !desc ) procRow.reverse(); } // now re-order the parent tbody based off the quick sorted tbody map $('tbody:first', target).before('<tbody></tbody>'); var nr = procRow.length, tf = $('tbody:first', target)[0]; // move the row from old tbody to new tbody in order of new tbody with replaceWith to retain original tbody row positioning if ( sorted ) while ( nr-- ) tf.appendChild( rows[ nr ] ); else while ( nr-- ) tf.appendChild( rows[ parseInt( procRow[ nr ].split(',').pop() ) ] ); // remove the old table $('tbody:last', target).remove(); // redraw stub rows var stubCount=0, cols = $('tbody tr:first td', target).length, stubs = ( perPage - ( $('tbody tr', target).length % perPage ) ), stubHeight = $('tbody tr:first td:first', target).css('height'); for ( ; stubCount < stubs && stubs != perPage; stubCount++ ) $('tbody tr:last', target).after( '<tr class="stubCell"><td colspan="' + cols + '" style="height: ' + stubHeight + ';"> </td></tr>' ); } /* Quick Sort algorithm - instantiation of Michael Lamont's Quick Sort pseudocode from http://linux.wku.edu/~lamonml/algor/sort/quick.html */ function quickSort ( numbers, left, right ) { var l_hold = left, r_hold = right, pivot = numbers[left]; // natural sort comparison "operator overload" var chCompare = function ( a, b ) { var ca = a.split(',').slice( 0, ( a.length - 1 ) ), cb = b.split(',').slice( 0, ( a.length - 1 ) ); for ( var cLoc=0, nMin = Math.min( ca.length, cb.length ), nMax = Math.max( ca.length, cb.length ); cLoc < nMax; cLoc++ ) { if ( ( parseFloat( ca[ cLoc ] ) || ca[ cLoc ] ) < ( parseFloat( cb[ cLoc ] ) || cb[ cLoc ] ) ) return -1; if ( ( parseFloat( ca[ cLoc ] ) || ca[ cLoc ] ) > ( parseFloat( cb[ cLoc ] ) || cb[ cLoc ] ) ) return 1; if ( cLoc > nMin && cLoc <= nMax ) return 0; } return 0; } while (left < right) { while ( ( chCompare( numbers[right], pivot ) >= 0 ) && ( left < right ) ) right--; if (left != right) { numbers[left] = numbers[right]; left++; } while ( ( chCompare( numbers[left], pivot ) <= 0 ) && ( left < right ) ) left++; if (left != right) { numbers[right] = numbers[left]; right--; } } numbers[left] = pivot; pivot = left; left = l_hold; right = r_hold; if (left < pivot) quickSort( numbers, left, ( pivot - 1 ) ); if (right > pivot) quickSort( numbers, ( pivot + 1 ), right ); }; // chainable return this; }; })(jQuery);
<script> $(document).ready(function () { $('pre.code').each( function () { var aa=new Date(); for (var k = 'function,var,class,using,namespace,public,private,protected,private,return,while,if,for,switch', d = 'string,bool,date,int,float,hashtable,array', r = [ {c:'c',r:/(?:\/\*(.|[\n\r])*?\*\/)|(?:\/\/[^\n\r]+)|(?:<![-]{2,3}([\s\S](?!>))+[-]{2,3}>)/}, // comments {c:'s',r:/(?:\'[^\']*\')|(?:"[^"]*")/}, // strings {c:'n',r:/(?:\d+\.?\d*[%]?)/}, // numbers {c:'k',r:(new RegExp('(?:' + k.split(',').join(')|(?:') + ')'))}, // keywords {c:'d',r:(new RegExp('(?:' + d.split(',').join(')|(?:') + ')'))}, // datatypes {c:'w',r:/(?:[A-Za-z_-]\w*)/}, // word (variables) {c:'f',r:/(?:[\[\]\(\)\{\}\/]+)/} // flow operators ],is = $(this).text(),os = '',re = '',rec = 0,rel = r.length; rec < rel; rec++ ) { re += (re ? '|' : '') + r[rec].r.source; } for (var t = new RegExp(re,'gmi'),pi = 0,a = true,c = 0,of = 0,sl = is.length; c < sl && (a = t.exec(is)); c++) { for (rec = 0; rec < rel; rec++) { if (r[rec].r.test(a[0])) { //console.log(a[0]+' -- '+pi+' vs '+(t.lastIndex - a[0].length)); os += is.substring(pi,(t.lastIndex - a[0].length)).replace(/</g,'<').replace(/>/g,'>') +'<p class="'+ r[rec].c +'">'+ a[0].replace(/</g,'<').replace(/>/g,'>') +'</p>'; pi = t.lastIndex; break; } } } $(this).replaceWith('<pre class="code">'+ os + is.substring(pi,is.length) +'</pre>\n'+ ((new Date()).getTime() - aa.getTime()) +'ms'); } ); }); </script>
/** * Lx : ECMAScript Lexical Analyzer with a lex like API. * * License: LGPLv3 * * @author Chris Corbyn * @version 0.0.0 */ /** * References the currently running LxAnalyzer. * * @see {@link LxAnalyzer} */ var Lx; /** * Default callback routine for LxDefaultRule. * * Pre-defined only for optimization. * * If overridden, the action invoked by the default rule will be the new * action. */ var LxDefaultAction = function LxDefaultAction() { Lx.Echo(); return Lx.Text.charCodeAt(0); }; /** * The default matching rule used internally by Lx. * * Pre-defined only for optimization. * * If overridden any unmatched tokens will be checked by the new rule. */ var LxDefaultRule = { /** Required property "pattern" specifying what to match */ pattern : /^[\x00-\xFF]/, /** Required property "action" specifying the routine to invoke */ action : LxDefaultAction }; /** * An action which does nothing. * * Pre-defined for optimization. * * If overridden, rules applied will have the new action by default. */ var LxEmptyAction = function LxEmptyAction() { }; /** * The entire lexical analyzer class. * * This class contains all functionality for scanning. When running it is * also accessible via the global instance Lx. * * - Configuration methods are camelCase, starting with a lowercase letter. * - Scanning routine methods are CamelCase starting with an uppercase letter. * - Scanning properties are CamelCase starting with an uppercase letter. * * @constructor */ var LxAnalyzer = function LxAnalyzer() { /** The input stream (String) */ this.In = ''; /** The output stream (String) */ this.Out = ''; /** The current start condition (state ID) */ this.START = 0; /** The initial start condition (state ID) */ this.INITIAL = 0; /** The EOF token ID */ this.EOF = 0; /** The matched text during a scan */ this.Text = ''; /** The matched Text length during a scan */ this.Leng = 0; /** The current line number (only if Lx.countLines() is specified) */ this.LineNo = 1; /** The value of the matched token */ this.Lval = {}; /** @private */ var _TID = 256; /** @private */ var _SID = 0; /** @private */ var _rules = { 0 : [] }; /** @private */ var _wantsMore = false; /** @private */ var _stateStack = []; /** @private */ var _minInputSize = 32; /** @private */ var self = this; /** For consistency between actions using Lx and token specification */ Lx = self; // -- Public methods /** * FSA optimization setting for minimum input fragment size. * * The scanner will first test if a rule matches inside the first s chars * of the input source. * * Tokens are permitted to be longer (for example long strings), but the * first s chars in the token then must fit the pattern. * * Default value 32 should work fine, raising it will increase the chance of * matching very long tokens at the expense of speed. * * If you try to match an entire string with a rule of say, * /"[^"]*"/ then matching will fail for long strings (and rightly so). A * more optimized (and flexible) way to match such strings is to use state * switching. * * Lx.rule('"', Lx.INITIAL).performs(function() { * // Opening " * Lx.PushState(Lx.IN_STRING); * }); * * Lx.rule(/[^"]+/, Lx.IN_STRING).performs(function() { * // String content * }); * * Lx.rule('"', Lx.IN_STRING).performs(function() { * // Closing " * Lx.PopState(); * }); * * @param {Integer} s */ this.setMinInputSize = function setMinInputSize(s) { _minInputSize = s; }; /** * Defines a new exclusive state, accessible as a property of the currently * running analyzer. * * Exclusive states differ from inclusive in the tokens they match. When * the analyzer is in an exclusive state it can only match tokens which are * in that state. In an inclusive state the analyzer will match tokens with * no specified state along with tokens in its own state. * * @param {String} stateName The name of the state (tip: use UPPERCASE) * @param {Boolean} exclusive True for an exclusive state, false otherwise * * @return The new state ID * @type Integer */ this.addExclusiveState = function addState(stateName) { if (typeof self[stateName] == "undefined") { self[stateName] = ++_SID; _rules[_SID] = []; } return self[stateName]; }; /** * Defines a new token ID with the given name, accessible as a property of * the current running analyzer. * * Defining a token does nothing by itself. It must then be returned by * the action associated with a rule. * * @param {String} tokenName The name of the token (tip: use UPPERCASE) * * @return The new token ID * @type Integer * * @see {@link #addRule} */ this.addToken = function addToken(tokenName) { if (typeof self[tokenName] == "undefined") { self[tokenName] = ++_TID; } return self[tokenName]; }; /** * Define a new rule matching the given pattern. * * If states is passed as a parameter this rule will only be active when the * analyzer is in one of the given states. The states parameter may be the * state ID, or an Array of state IDs. * * @param {Object} pattern A String or RegExp to match * @param {Object} states The Integer state ID, or an Array of state IDs * * @return The new rule (contains a parameter named "action") * @type Object * * @see {@link #Echo} * @see {@link #Begin} * @see {@link #PushState} * @see {@link #PopState} * @see {@link #TopState} * @see {@link #Reject} * @see {@link #More} * @see {@link #Less} * @see {@link #Unput} * @see {@link #Input} * @see {@link #Terminate} * * @see {@link #addToken} * @see {@link #addState} */ this.addRule = function addRule(pattern, states) { if (!states) { states = [0]; } if (!(states instanceof Array)) { states = [states]; } var rule = { pattern : _optimizePattern(pattern), action : LxEmptyAction }; var ruleContainer; for (var i = 0, len = states.length; i < len; ++i) { if (typeof _rules[states[i]] == "undefined") { throw "State ID " + states[i] + " does not exist"; } ruleContainer = _rules[states[i]]; ruleContainer[ruleContainer.length] = rule; } return rule; }; /** * Find the next input token, advancing through the input. * * If no user-specified token is matched, the character code of the next * character is returned instead. * * @return The ID of the found token, or 0 (zero) for EOF. * @type Integer * * @see {@link #wrap} * @see {@link #addToken} */ this.lex = function lex() { Lx = self; var tokenId; while (!tokenId && self.In.length > 0) { tokenId = _lexScan(); } return !tokenId ? self.EOF : tokenId; }; /** * Returns true if all input has been read, or false if not. * * This routine should always be called when {@link #lex} returns 0 since * the scanner may want to switch to a new input source. * * @return True if finished, false if not. * @type Boolean */ this.wrap = function wrap() { return self.In.length > 0; }; // -- Scanning routines /** * Tell the analyzer to retain whatever is in the Lx.Text property and append * the next found token to it instead of overwriting it. * * The value of Lx.Leng must not be modified. */ this.More = function More() { _wantsMore = true; }; /** * Tell the analyzer to put all but the first n characters back into the * input stream (Lx.In). * * Leng and Text are adjusted accordingly. * * @param {Integer} n Number of chars to put back starting at the rightmost */ this.Less = function Less(n) { if (n > self.Text.length) { throw "Cannot put back " + n + " characters from a " + self.Text.length + " token"; } self.In = self.Text.substr(n) + self.In; self.Leng = n; self.Text = self.Text.substring(0, self.Leng); }; /** * Place character c at the start of the input stream (Lx.In) so that it will * be scanned next. * * @param {String} c The character to place back on the input stream */ this.Unput = function Unput(c) { self.In = c + self.In; }; /** * Read the next character in the input stream and seek through the stream. * * @return The next character in the input stream * @type String */ this.Input = function Input() { if (self.In.length == 0) { return 0; } var c = self.In.charAt(0); self.In = self.In.substring(1); return c; }; /** * Append the contents of Lx.Text to the output stream (Lx.Out). */ this.Echo = function Echo() { self.Out += self.Text; }; /** * Switch the start condition to the given state. * * The next time {@link #lex} is invoked it will scan in the new state. * * @param {Integer} state The new state ID * * @see {@link #addState} */ this.Begin = function Begin(state) { if (!(state in _rules)) { throw "There is no state ID [" + state + "]"; } self.START = state; }; /** * Push the current state (Lx.START) onto the state stack and switch to the * new state via {@link #Begin}. * * @param {Integer} state The new state * * @see {@link #addState} * @see {@link #PopState} * @see {@link #TopState} */ this.PushState = function PushState(state) { _stateStack[_stateStack.length] = self.START; self.Begin(state); }; /** * Pops the top off the state stack and switches to it via {@link #Begin}. * * @see {@link #addState} * @see {@link #PushState} * @see {@link #TopState} */ this.PopState = function PopState() { self.Begin(self.TopState()); delete _stateStack[_stateStack.length - 1]; --_stateStack.length; }; /** * Returns the current top of the state stack without modifying the stack. * * @return The state ID at the top of the state stack, or INITIAL if the * stack is empty. * @type Integer * * @see {@link #addState} * @see {@link #PushState} * @see {@link #PopState} */ this.TopState = function TopState() { if (_stateStack.length == 0) { throw "Cannot read state stack since it is empty"; } return (typeof _stateStack[_stateStack.length - 1] != "undefined") ? _stateStack[_stateStack.length - 1] : self.INITIAL ; }; /** * Restart with new input, resetting the scanner (except for the START state). * * @param {String} input */ this.Restart = function Restart(input) { self.In = input; self.Out = ''; self.Text = ''; self.Leng = 0; self.LineNo = 1; self.Lval = {}; _wantsMore = false; _stateStack = []; }; // -- Private methods /** @private */ var _optimizePattern = function _optimizePattern(re) { if (typeof re.valueOf() == "string") { return re.valueOf(); } var regexString = re.toString(); var pattern = regexString.substring( regexString.indexOf('/') + 1, regexString.lastIndexOf('/') ); var flags = regexString.substring(regexString.lastIndexOf('/') + 1); if (!flags) { return new RegExp(pattern.replace(/^(?!\^)(.*)/, "^(?:$1)")); } else { return new RegExp(pattern.replace(/^(?!\^)(.*)/, "^(?:$1)"), flags); } }; /** @private */ var _scanByRegExp = function _scanByRegExp(re) { var match = ''; var matches; //FSA optimization check with re.test() if (re.test(self.In.substring(0, _minInputSize)) && (matches = re.exec(self.In)) && matches.index == 0) { match = matches[0]; } return match; }; /** @private */ var _scanByString = function _scanByString(string) { var match = ''; if (self.In.substring(0, string.length) == string) { match = string; } return match; }; /** @private */ var _lexScan = function _lexScan() { var bestLength = 0; var bestMatch = ''; var bestRule; //Inner function with access to local variables var scan = function scan(rule) { var match; if (typeof rule.pattern != "string") { //TODO: Cheaper test than typeof? match = _scanByRegExp(rule.pattern); } else /* optimize */ if (bestLength < rule.pattern.length) { match = _scanByString(rule.pattern); } if (match && match.length > bestLength) { bestLength = match.length; bestRule = rule; bestMatch = match; } }; //Test each rule for (var i = 0, len = _rules[self.START].length; i < len; ++i) { scan(_rules[self.START][i]); } //If none match, use the default rule if (!bestRule) { scan(LxDefaultRule); bestRule = LxDefaultRule; } //Adjust Text and Leng if (_wantsMore) { self.Text += bestMatch; self.Leng += bestMatch.length; } else { self.Text = bestMatch; self.Leng = bestMatch.length; } _wantsMore = false; self.Lval = bestRule; //Advanced through the input self.In = self.In.substring(bestMatch.length); //Return whatever the action specifies return bestRule.action(); }; };