Disappearing JSTree when using Themeroller

I am currently working on a project that utilizes a MySQL Nested Folder database design and a JQuery component called JSTree. The implementation actually works great. The system allows users to create “folders” for content and provides the ability to Drag and Drop to move folders, create new folders and sub-folders, etc.

After entering the testing phase of the project we discovered that the folder tree view, powered by JSTree, was not working. The tree would load on the page and then disappear. I spent a solid 12 hours trying to debug what the issue was because it works flawlessly in IE8, IE9, Fire Fox, Chrome, Safari, and Opera. This problem seemed to be isolated to IE7 only. I flipped flopped between potential causes several times — could it be a Javascript issue? could it be a CSS issue? could it be both?

Here is a sample of how I am setting up the JSTree View:

$("#workout-folders").jstree({
		"plugins" : ["html_data","ui","themeroller", "crrm", "cookies", "dnd", "contextmenu"],
		"ui": {
			"select_limit": 1,
			"selected_parent_open": true,
			"selected_parent_close": "select_parent"
		},
		"dnd": {
			"drop_finish" : function () {
				alert( "Drop" ) ;
			},
			"drag_check" : function (data) {
				//console.dir( data ) ;

				if( data.r.attr( "id" ).replace( "rnode_", "" ) == "root" )
				{
					if( data.p == "after" || data.p == "before" ) {
						return false ;
					}
				}

				if( data.r.attr( "id" ) == "phtml_1" ) {
					return false ;
				}

				return {
					after:false,
					before: false,
					inside:true
				};
			},
			"drag_finish" : function(data) {
				var workout_id = $(data.o.parentNode).attr("id").replace( "work_", "" )  ;
				var target_folder_id = $(data.r).attr("id").replace( "rnode_", "" ) ;
				$(data.o.parentNode).remove( ) ;
				var params = "ajax_task=move_workout&wid="+workout_id+"&fid="+target_folder_id ;
				// Ajax call to load the category menu items
				$.ajax({
				  type: "POST",
				  url: "template/pfitprov2/ajax/workoutfolders.php",
				  data: params,
				  dataType: "json",
				  success: handleMoveWorkoutComplete
				});
			}
		},
		"themeroller" : {
			"item_leaf": "ui-icon-folder-collapsed"
		},
		"contextmenu" : {
			"select_node" : false
		}
	})
	.bind("before.jstree", function( event, data ) {
		//console.dir( data ) ;
		//var node = 	data.args.parent.attr("id").replace("rnode_","") ;
		//alert ( node ) ;
		if( data.func === "close_node") {
			var node = $(data.args[0].parentNode).attr("id").replace("rnode_", "" ) ;
			if( node == "root" ) {
				return false ;
			}
		} else if( data.func === "show_contextmenu" ) {
			var node = $(data.args[0].parentNode).attr("id").replace("rnode_", "" ) ;
			if( node == "root" ) {
				return false ;
			}
		}
	})
	.bind("select_node.jstree", function (event, data) {
		var node = 	data.rslt.obj.attr("id").replace("rnode_","") ;
		if( node == "root" ) { node = current_system_folder; }
		load_workouts( node ) ;
	})
	.bind( "create.jstree", function( event, data ) {
		selected_folder = data.rslt.parent.attr("id").replace("rnode_","") ;
		var params = "ajax_task=create_folder&systemfolder="+current_system_folder+"&sfid="+selected_folder+"&newname="+data.rslt.name ;
		// Ajax call to load the category menu items
		$.ajax({
		  type: "POST",
		  url: "template/pfitprov2/ajax/workoutfolders.php",
		  data: params,
		  dataType: "json",
		  success: handleCreateFolderComplete
		});
	})
	.bind( "rename.jstree", function( event, data ) {
		selected_folder = data.rslt.obj.attr("id").replace("rnode_","") ;
		var params = "ajax_task=rename_folder&systemfolder="+current_system_folder+"&sfid="+selected_folder+"&newname="+data.rslt.new_name ;
		// Ajax call to load the category menu items
		$.ajax({
		  type: "POST",
		  url: "template/pfitprov2/ajax/workoutfolders.php",
		  data: params,
		  dataType: "json",
		  success: handleRenameFolderComplete
		});
	})
	.bind( "remove.jstree", function( event, data ) {
		selected_folder = data.rslt.obj.attr("id").replace("rnode_","") ;
		$("#dialog-confirm-delete").dialog("open");
		// Ajax call to load the category menu items
	})
	.bind( "move_node.jstree", function( event, data ) {
		//console.dir( data ) ;
		data.rslt.o.each( function(i) {
			var id = $(this).attr("id").replace( "rnode_", "" ) ;
			var lat = data.rslt.r.attr("id").replace( "rnode_", "" ) ;
			//var ref = data.rslt.cr === -1 ? 1 : data.rslt.np.attr("id").replace( "rnode_", "" ) ;
			var position = data.rslt.p ;
			//var copy = data.rslt.cy ? 1 : 0 ;
			var params = "ajax_task=move_folder&systemfolder="+current_system_folder+"&sfid="+id+"&np="+lat+"&pos="+position ;
			// Ajax call to load the category menu items
			$.ajax({
			  type: "POST",
			  url: "template/pfitprov2/ajax/workoutfolders.php",
			  data: params,
			  dataType: "json",
			  success: handleMoveFolderComplete
			});
		});
	}).bind("dblclick", function (event, data) {
		event.preventDefault();
		var trgt = $(event.target);
		if ( $("#workout-folders").jstree("is_open", event.target) ){
			$("#workout-folders").jstree("close_node", event.target);
		}else{
			$("#workout-folders").jstree("open_node", event.target);
		}
	})

Other than the binding function calls, the setup of the treeview itself isn’t anything special. It is working great in all the major browsers except for Internet Explorer 7 (native and compatibility mode).

This problem was mind-boggling because the JSTree demo’s worked fine in all browsers. I wasn’t doing anything “out of the ordinary”. I finally thought to myself, “what am I doing that’s different from the JSTree demo pages”? At first I thought it might be as simple as the page DOC TYPE. But that turned out to be a bust. And then thought it could be JQuery Themeroller. I started digging through the CSS code and found a style being applied to the icon class “text-indent:-999999px”. Using IE’s web developer toolkit I dynamically changed this value to 0px and viola everything displayed and started functioning as intended.

JSTree supports JQuery Themeroller – which makes RIA development a breeze. However, this simple CSS style caused the entire tree to indent -99999px off the page. After digging deeper into Themeroller I realized since Themeroller uses sprite images to load and display their default icons, the text-indent property was doing just that. It was loading the sprite image off screen as a pre-loading technique. But because of the HTML structure and loading steps of JSTree this particular style was inherently causing the entire tree to load off screen.

PROBLEM: JSTree is not be displayed. It flashes on the screen then disappears.

SCENARIO: Using JSTree (latest build)
Using JQuery (latest build)
Using JQuery UI (latest build)
Using Themeroller Plugin for JSTree

SOLUTION: Check to see if the <ins> tags being generated by JSTree (which contain the icons, and node text) has a CSS style property called text-indent:-9999999px. Override the ui-icon class and add the following property: #text-indent:0px I am using the # selector which will ensure only IE7 uses this style.

mfrank

About mfrank

Professional Developer of SwhistleSoft
This entry was posted in css, Html, Javascript Development and tagged , , , , . Bookmark the permalink.

5 Responses to Disappearing JSTree when using Themeroller

  1. Jonn says:

    Great post! You saved me a lot of wasted hours trying to hunt down this bug. Who would’ve thought that jquery ui css conflicted with jstree?

  2. Jose R says:

    Tranks for the info, this was the key to solving my problems.

    Just as an extra info, you can edit the file jquery.ui.core.css with the following code that will help you with jstree

    /* states and images */

    .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }


    .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }


    Best regards

  3. check it out says:

    Hello there! I just would like to give a massive thumbs up for that fantastic information you have here on this submit. I will be coming back for your weblog for a lot more soon.

  4. Ellis V says:

    You sir, are an absolute star. Thank you.

  5. Also a thing to mention is that an online business administration training course is designed for college students to be able to well proceed to bachelor degree courses. The 90 credit certification meets the other bachelor diploma requirements when you earn the associate of arts in BA online, you will possess access to the modern technologies within this field. Some reasons why students would like to get their associate degree in business is because they can be interested in the field and want to get the general knowledge necessary previous to jumping in a bachelor diploma program. Thanks for the tips you provide in your blog.

Leave a Reply to Jose R Cancel reply

Your email address will not be published. Required fields are marked *