≡ Menu

When JavaScript’s deleteRow() Method Doesn’t Work

A section of JavaScript code that uses the method deleteRow() was giving me a headache in IE 11. I did not encounter this when using Chrome.

In the code segment below, the variable “oHtmlTable” is assigned to an HTML table that already exists on a webpage.

//delete prior entries
while(oHtmlTable.rows.length > 1)					
{
	oHtmlTable.deleteRow(-1);
}

For no apparent reason, during the execution of the while loop, the deleteRow() method would quit working, but did not cause an exception to be thrown. Since the condition on the while loop would never be met if the rows in the table were no longer being deleted, this became an infinite loop.

IE gave no obvious indication as to what the problem was, just the standard “[domain name] is not responding” message at the bottom of the screen.

not responding

The code inside the while loop deletes the last row in the table. Whatever was inside the last row was keeping IE from successfully deleting it. First, I tried emptying the innerHTML contents of the last row to see if that would allow the deletion to continue. This had no effect. However, deleting the outerHTML contents of the row did the trick.

I created a variable in which to store the number of rows in the table, then an if statement to determine whether the row count changed after the deleteRow method was executed. If it was not, then on the next pass through the loop, the row would be deleted.

//delete prior entries
var nLength = 0;
while(oHtmlTable.rows.length > 1)					
{
	nLength = oHtmlTable.rows.length;
	oHtmlTable.deleteRow(-1);
	if (nLength == oHtmlTable.rows.length)
	{
		oHtmlTable.rows[nLength-1].outerHTML = '';
	}					
}

SQL Script to Find Text in all Database Tables and Views…Revised! Again!

The SQL script below, which modifies one I wrote last year, has been modified to work with SQL Server 2008 and newer versions. On these versions, when querying SQL Server to output the schema of a database table, length values of MAX are returned as -1. Since this script builds table variables that mimic the schema of the actual table, this needed to be accounted for so no errors would occur as a result of the MAX length being used.

If MAX values are not used, the output of this script should be no different than on the previous version.

-- Set database to search
USE dbname
GO
SET NOCOUNT ON
SET ANSI_WARNINGS OFF
------------------------------------------------------------------------------------------------------------------------------------
-- Set test value here and set @SearchViews to 1 if views are to be included - 0 if not; no other code below changes
-- Set @PrintAllSQLStmts to 1 if you want all of the statements printed as messages
DECLARE @TestValue VARCHAR(8000) 
DECLARE @SearchViews BIT 
DECLARE @PrintAllSQLStmts BIT

SET @PrintAllSQLStmts = 0
SET @SearchViews = 0
SET @TestValue = 'text to search'
------------------------------------------------------------------------------------------------------------------------------------

/* If the version of SQL Server is 2005 or newer, these can be set to MAX rather than 8000 */
DECLARE @SQL VARCHAR(8000)
DECLARE @varSQL VARCHAR(8000)
DECLARE @WhereClause VARCHAR(8000)
/******************************************************************************************/

DECLARE @TableName VARCHAR(128)
DECLARE @varTableName VARCHAR(128)
DECLARE @TableSchema VARCHAR(128)
DECLARE @ColumnName VARCHAR(128)
DECLARE @MaxLength VARCHAR(4)
DECLARE @NMaxLength VARCHAR(4)

IF @@VERSION LIKE 'Microsoft SQL Server  2000%'
	BEGIN
		SET @MaxLength = '8000'		
		SET @NMaxLength = '4000'		
	END
ELSE
	BEGIN
		SET @MaxLength = 'MAX'
		SET @NMaxLength = 'MAX'
	END
	
DECLARE @SchemaObjects TABLE (
	TABLE_NAME VARCHAR(128), 
	TABLE_SCHEMA VARCHAR(128)
)

DECLARE @TypeTable TABLE (
	UserType VARCHAR(128) PRIMARY KEY,
	BaseType VARCHAR(128)
)

DECLARE @SizableTypes TABLE (
	TypeName VARCHAR(128) PRIMARY KEY
)

INSERT INTO @SizableTypes VALUES ('VARBINARY')
INSERT INTO @SizableTypes VALUES ('VARCHAR')
INSERT INTO @SizableTypes VALUES ('NVARCHAR')
INSERT INTO @SizableTypes VALUES ('CHAR')
INSERT INTO @SizableTypes VALUES ('NCHAR')

INSERT INTO @TypeTable
SELECT ut.name, bt.name FROM SysTypes ut, SysTypes bt
 WHERE ut.xusertype > 256 AND bt.xusertype < 256
 AND ut.xtype = bt.xtype

INSERT INTO @SchemaObjects
SELECT TABLE_NAME, TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES
	WHERE TABLE_TYPE = 'BASE TABLE'

IF @SearchViews = 1
BEGIN
	INSERT INTO @SchemaObjects
	SELECT TABLE_NAME, TABLE_SCHEMA FROM INFORMATION_SCHEMA.VIEWS
END

DECLARE TableCursor CURSOR FAST_FORWARD FOR
SELECT TABLE_NAME, TABLE_SCHEMA FROM @SchemaObjects

OPEN TableCursor
FETCH NEXT FROM TableCursor INTO @TableName, @TableSchema
WHILE @@FETCH_STATUS = 0
BEGIN
	SET @WhereClause = ''

	DECLARE ColumnCursor CURSOR FAST_FORWARD FOR
	SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
		WHERE TABLE_NAME = @TableName AND TABLE_SCHEMA = @TableSchema AND ((DATA_TYPE IN ('CHAR','NCHAR','VARCHAR','NVARCHAR')) AND (CHARACTER_MAXIMUM_LENGTH IS NOT NULL) AND (CHARACTER_MAXIMUM_LENGTH >= LEN(@TestValue)) OR DATA_TYPE IN ('TEXT','NTEXT'))
	OPEN ColumnCursor
	FETCH NEXT FROM ColumnCursor INTO @ColumnName
	WHILE @@FETCH_STATUS = 0
	BEGIN
		IF LEN(@WhereClause) > 0 SET @WhereClause = @WhereClause + ' OR '
		SET @WhereClause = @WhereClause + '(CONVERT(VARCHAR,[' + @ColumnName + ']) LIKE ''%' + @TestValue + '%'')'
		FETCH NEXT FROM ColumnCursor INTO @ColumnName
	END
	CLOSE ColumnCursor
	DEALLOCATE ColumnCursor	
	IF LEN(@WhereClause) > 0
	BEGIN		
		SET @varTableName = REPLACE(@TableName,' ','_') 
		SET @varSQL = 'DECLARE @' + @varTableName + ' TABLE (' + CHAR(10) 		
		SELECT @varSQL = @varSQL + ' [' + sc.name + '] ' + 		
		CASE WHEN st.name = 'TIMESTAMP' THEN 'DATETIME' 			 
			 WHEN tt.UserType IS NOT NULL THEN UPPER(tt.BaseType) 			 
		ELSE UPPER(st.name) END +
		CASE WHEN tt.BaseType IN (SELECT TypeName FROM @SizableTypes) OR st.name IN (SELECT TypeName FROM @SizableTypes) THEN '(' + 
			CASE WHEN (LEFT(tt.BaseType,3) = 'VAR' OR LEFT(st.name,3) = 'VAR') AND (sc.[length] >= 8000 OR sc.[length] = -1) THEN @MaxLength
				 WHEN (LEFT(tt.BaseType,3) = 'NVA' OR LEFT(st.name,3) = 'NVA') AND (sc.[length] >= 4000 OR sc.[length] = -1) THEN @NMaxLength			 				 
			ELSE CAST(sc.[length] AS VARCHAR) END + ') ' 
		ELSE ' ' END +
		CASE WHEN sc.isnullable = 1 THEN 'NULL' ELSE 'NOT NULL' END + ',' + CHAR(10)
		FROM SysObjects so
		JOIN SysColumns sc ON sc.id = so.id
		JOIN SysTypes st ON st.xusertype = sc.xusertype
		LEFT OUTER JOIN @TypeTable tt ON st.name = tt.UserType
		WHERE so.name = @TableName
		ORDER BY sc.colid		
		
		SET @SQL =  CHAR(10) + 'SELECT ''[' + @TableSchema + '].[' + @TableName + ']'' AS [Table Schema/Table Name], * FROM [' + @TableSchema + '].[' + @TableName + '] WHERE ' + @WhereClause + ';' 
		SELECT @varSQL = SUBSTRING(@varSQL,1,LEN(@varSQL) - 2) + CHAR(10) + ');' + CHAR(10)
		
		SET @varSQL = @varSQL + 'INSERT INTO @' + @varTableName + CHAR(10) + 'SELECT * FROM [' + @TableSchema + '].[' + @TableName + ']' + CHAR(10) + 'WHERE ' + @WhereClause + ';' + CHAR(10)
		SET @varSQL = @varSQL + 'IF EXISTS(SELECT * FROM @' + @varTableName + ')' + CHAR(10) 
		SET @varSQL = @varSQL + 'BEGIN' + CHAR(10)
		SET @varSQL = @varSQL + '   SET NOCOUNT OFF;' + CHAR(10)		
		
		IF @PrintAllSQLStmts = 0
			SET @varSQL = @varSQL + '   PRINT ''' + CHAR(10) + CHAR(10) + CHAR(10) + '/* New Query */' + CHAR(10) + REPLACE(@SQL,'''','''''') + ''';'  + CHAR(10)
		ELSE
			PRINT CHAR(10) + CHAR(10) + CHAR(10) + '/* New Query */' + @SQL + CHAR(10)		

		SET @varSQL = @varSQL + '   SELECT ''[' + @TableSchema + '].[' + @TableName + ']'' AS [Table Schema/Table Name], * FROM @' + @varTableName + ';' + CHAR(10)		
		
		SET @varSQL = @varSQL + '   SET NOCOUNT ON;' + CHAR(10)
		SET @varSQL = @varSQL + 'END' + CHAR(10)
		SET @varSQL = @varSQL + CHAR(10) + CHAR(10) + CHAR(10)
		--PRINT @varSQL
		EXEC (@varSQL)
		IF @@ERROR <> 0
		BEGIN 
			PRINT '/* Statement causing error */' + CHAR(10) + CHAR(10) + @varSQL + CHAR(10) + '/* End Statement */' + CHAR(10) 
			PRINT 'Length of SQL statement: ' + CONVERT(VARCHAR,LEN(@varSQL)) + CHAR(10)
		END
	END
	FETCH NEXT FROM TableCursor INTO @TableName, @TableSchema
END
CLOSE TableCursor
DEALLOCATE TableCursor

Scheduled Tasks and Anonymous Access in ColdFusion 11

I have been converting applications from ColdFusion 8 to CF 11 over the last several months, and some of the challenges have been quite a bit more daunting than this one. Even so, I felt this was worth mentioning.

After copying all the code for my most recent upgrade candidate from the old server to the new one and setting it up in IIS, I proceeded to set up the CF Scheduled Tasks on the new server.

One of the tasks that I set up runs under a blank user name. In order for that to work, you have to make certain that several settings related to authentication are set properly in IIS. First of all, if the app as a whole runs under anything other than Anonymous Authentication (such as Windows Integrated Authentication or Forms Authentication), your Scheduled Task URL will have to be inside a folder that has Anonymous Authentication enabled, even if it’s turned off for the rest of the app.

Secondly, you have to make sure that the “jakarta” virtual folder that is set up during IIS configuration of the website also has Anonymous Authentication enabled.

Having Anonymous Authentication disabled on the jakarta folder will cause no end of irritation if you don’t have the output of the URL sent to a file, as neither the application log file nor the Security log in Windows Event Viewer will tell you exactly why the task is failing. If you send output to a text file, you can rename that text file with an HTML extension (I’m still not sure why Adobe doesn’t just allow output as HTML for this…) and then see more clearly why your task was failing.

IIS authentication error

So set your authentication properties correctly to avoid this frustration!

Windows Disks Keep Filling Up with Small Log Files

I noticed that a Windows server I use for development with Visual Studio 2013 Ultimate had begun filling its system drive with log files in C:\Windows\Temp for no apparent reason.

The initial response of our infrastructure group was to simply delete the log files on a weekly basis, as no one could find the cause of the problem. Since this issue was apparently in the purview of that group, I let this solution stand initially. However, as I feared, the problem became worse and the server began crashing on a weekly basis.

The log files had many messages that contain “Product: Microsoft Visual Studio Professional 2013 — Configuration completed successfully.”

I wasn’t sure that the log files were the cause of the crashes, but it became apparent that the two were likely connected when I saw many similar errors in the Application log under Event Viewer: “Detection of product ‘{9C593464-7F2F-37B3-89F8-7E894E3B09EA}’, feature ‘Testing_Tools_for_Pro_x86_enu’, component ‘{55E69908-5292-4B15-A56D-822A6050848F}’ failed. The resource ” does not exist.”

Application log entry

There are a couple of fixes that should be applied here. The first is very simple. In all likelihood, a folder named “Microsoft.NETFrameworkURTInstall_GAC” is missing from the %SystemRoot% (usually C:\Windows) folder.

If this folder is, in fact, missing, add it using either
1.an elevated Command Prompt with this command:
mkdir %SystemRoot%Microsoft.NETFrameworkURTInstall_GAC
or
2. PowerShell:
mkdir $env:SystemRoot\Microsoft.NETFrameworkURTInstall_GAC

The second fix is to repair Visual Studio 2013 in the Control Panel.

Open Control Panel, open Programs and Features, select Microsoft Visual Studio 2013 [Professional/Ultimate/etc.], click Change, and click Repair on the VS splash screen.

In most cases, this will fix your problem.

Sources:
Visual Studio 2013 continuously repairs producing many small log files

Missing Components After Moving a ColdFusion Site

Last week I was tasked with moving several of my applications from one CF 8 server to another one, due to the first server’s VM host having some kind of problem requiring daily restarts of the VM by our infrastructure team.

After moving two applications, the users began complaining that one of the functions in one of the applications that had previously worked perfectly was not working at all for some users now.

IE 11 Developer Tools window

IE 11 Developer Tools window showing debugger options

By opening Developer Tools in Internet Explorer (this is not a Chrome-compatible application), and setting the “Break on all exceptions” option in the debugger, I was able to begin troubleshooting the problem.

The exceptions in JavaScript that were being thrown dealt with missing classes, including declared ColdFusion components and ColdFusion.Ajax functions.

I remembered at that point that I had forgotten to do something that all ColdFusion developers should do on each application: to create the CFIDE virtual directory in IIS.

Once this simple task was done, everything worked as expected.