//ImageCatalog.jsx
//An InDesign CS JavaScript 
// 
//Creates an image catalog from the graphic files in a selected folder. 
//Each file can be labeled with the file name, and the labels are placed on 
//a separate layer and formatted using a paragraph style ("label") you can 
//modify to change the appearance of the labels. 
// 
//For more information on InDesign scripting, go to http://www.adobe.com/products/indesign/scripting.html 
//Or visit the InDesign Scripting User to User forum at http://www.adobeforums.com . 
// 
//The myExtensions array contains the extensions of the graphic file types you want 
//to include in the catalog. You can remove extensions from or add extensions to this list. 
//myExtensions is a global. Mac OS users should also look at the file types in the myFileFilter function.
myExtensions = [".jpg", ".jpeg", ".eps", ".ps", ".pdf", ".tif", ".tiff", ".gif", ".psd", ".ai"] 
//Display the folder browser. 
var myFolder = Folder.selectDialog("Select the folder containing the images", ""); 
//Get the path to the folder containing the files you want to place. 
if(myFolder != null){ 
		if(File.fs == "Macintosh"){
			var myFilteredFiles = myMacOSFileFilter(myFolder);
		}
		else{
			myFilteredFiles = myWinOSFileFilter(myFolder);
		}
        if(myFilteredFiles.length != 0){ 
                myDisplayDialog(myFilteredFiles, myFolder); 
                alert("Done!");
        } 
}
//Windows version of the file filter.
function myWinOSFileFilter(myFolder){
	var myFiles = new Array;
	var myFilteredFiles = new Array; 
	for(myExtensionCounter = 0; myExtensionCounter < myExtensions.length; myExtensionCounter++){ 
		myExtension = myExtensions[myExtensionCounter]; 
        myFiles = myFolder.getFiles("*"+ myExtension); 
		if(myFiles.length != 0){ 
			for(var myFileCounter = 0; myFileCounter < myFiles.length; myFileCounter++){ 
				myFilteredFiles.push(myFiles[myFileCounter]); 
			} 
		} 
	}	
	return myFilteredFiles;
}
function myMacOSFileFilter(myFolder){
	var myFilteredFiles = myFolder.getFiles(myFileFilter);
	return myFilteredFiles;
}
//Mac OS version of file filter
//Have to provide a separate version because not all Mac OS users use file extensions
//and/or file extensions are sometimes hidden by the Finder.
function myFileFilter(myFile){
	var myFileType = myFile.type;
	switch (myFileType){
		case "JPEG":
		case "EPSF":
		case "PICT":
		case "TIFF":
		case "8BPS":
		case "GIFf":
		case "PDF ":
			return true;
			break;
		default:
		for(var myCounter = 0; myCounter<myExtensions.length; myCounter++){
			var myExtension = myExtensions[myCounter]; 	
			if(myFile.name.indexOf(myExtension)>-1){
				return true;
				break;			
			}
		}
	}
	return false;	
}
function myDisplayDialog(myFiles, myFolder){ 
        var myLabelWidth = 130; 
        var myDialog = app.dialogs.add({name:"Image Catalog"}); 
        with(myDialog.dialogColumns.add()){ 
                with(dialogRows.add()){ 
                        with(dialogColumns.add()){ 
                                staticTexts.add({staticLabel:"Information"}); 
                        } 
                } 
                with(borderPanels.add()){ 
                        with(dialogColumns.add()){ 
                                with(dialogRows.add()){ 
                                        staticTexts.add({staticLabel:"Source Folder:", minWidth:myLabelWidth}); 
                                        staticTexts.add({staticLabel:myFolder.path + "/" + myFolder.name}); 
                                } 
                                with(dialogRows.add()){ 
                                        staticTexts.add({staticLabel:"Number of Images:", minWidth:myLabelWidth}); 
                                        staticTexts.add({staticLabel:myFiles.length + ""}); 
                                } 
                        } 
                } 
                with(dialogRows.add()){ 
                        staticTexts.add({staticLabel:"Options"}); 
                } 
                with(borderPanels.add()){ 
	                with(dialogColumns.add()){ 
    	                    with(dialogRows.add()){ 
    	                            with(dialogColumns.add()){ 
    	                                    staticTexts.add({staticLabel:"Number of Rows:", minWidth:myLabelWidth}); 
    	                            } 
    	                            with(dialogColumns.add()){ 
    	                                    var myNumberOfRowsField = integerEditboxes.add({editValue:3}); 
    	                            } 
    	                    } 
    	                    with(dialogRows.add()){ 
    	                            staticTexts.add({staticLabel:"Number of Columns:", minWidth:myLabelWidth}); 
    	                            var myNumberOfColumnsField = integerEditboxes.add({editValue:3}); 
    	                    } 
    	                    with(dialogRows.add()){ 
    	                            staticTexts.add({staticLabel:"Horizontal Offset:", minWidth:myLabelWidth}); 
    	                            var myHorizontalOffsetField = measurementEditboxes.add({editValue:12, editUnits:MeasurementUnits.points}); 
    	                    } 
    	                    with(dialogRows.add()){ 
    	                            staticTexts.add({staticLabel:"Vertical Offset:", minWidth:myLabelWidth}); 
    	                            var myVerticalOffsetField = measurementEditboxes.add({editValue:12, editUnits:MeasurementUnits.points}); 
    	                    } 
							with (dialogRows.add()){
								with(dialogColumns.add()){
									staticTexts.add({staticLabel:"Label:", minWidth:myLabelWidth}); 
								}
								with(dialogColumns.add()){
									var myLabelsButtons = radiobuttonGroups.add();
									with(myLabelsButtons){
										radiobuttonControls.add({staticLabel:"None", checkedState:true});
										radiobuttonControls.add({staticLabel:"File Name", checkedState:false});
										radiobuttonControls.add({staticLabel:"Full Path", checkedState:false});
									}
								}
							}
							with (dialogRows.add()){
								with(dialogColumns.add()){
									staticTexts.add({staticLabel:"Fitting:", minWidth:myLabelWidth}); 
								}
								with(dialogColumns.add()){
									var myFitProportionalCheckbox = checkboxControls.add({staticLabel:"Proportional", checkedState:true});
									var myFitCenterContentCheckbox = checkboxControls.add({staticLabel:"Center Content", checkedState:true});
									var myFitFrameToContentCheckbox = checkboxControls.add({staticLabel:"Frame to Content", checkedState:true});
								}
							}
    	                    with(dialogRows.add()){ 
    	                            var myRemoveEmptyFramesCheckbox = checkboxControls.add({staticLabel:"Remove Empty Frames:", checkedState:true}); 
    	                    } 
    	            } 
                } 
        } 
        var myResult = myDialog.show(); 
        if(myResult == true){ 
                var myNumberOfRows = myNumberOfRowsField.editValue; 
                var myNumberOfColumns = myNumberOfColumnsField.editValue; 
                var myRemoveEmptyFrames = myRemoveEmptyFramesCheckbox.checkedState;
                var myLabels = myLabelsButtons.selectedButton;
                var myFitProportional = myFitProportionalCheckbox.checkedState;
                var myFitCenterContent = myFitCenterContentCheckbox.checkedState;
                var myFitFrameToContent = myFitFrameToContentCheckbox.checkedState;
                var myHorizontalOffset = myHorizontalOffsetField.editValue;
                var myVerticalOffset = myVerticalOffsetField.editValue;
                myMakeImageCatalog(myFiles, myNumberOfRows, myNumberOfColumns, myLabels, myRemoveEmptyFrames, myFitProportional, myFitCenterContent, myFitFrameToContent, myHorizontalOffset, myVerticalOffset); 
        } 
        myDialog.destroy(); 
} 
function myMakeImageCatalog(myFiles, myNumberOfRows, myNumberOfColumns, myLabels, myRemoveEmptyFrames, myFitProportional, myFitCenterContent, myFitFrameToContent, myHorizontalOffset, myVerticalOffset){
        var myPage, myFile, myCounter, myX1, myY1, myX2, myY2, myRectangle, myLabelStyle, myLabelLayer; 
        var myFramesPerPage = myNumberOfRows * myNumberOfColumns;  
        var myDocument = app.documents.add(); 
        myDocument.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.points; 
        myDocument.viewPreferences.verticalMeasurementUnits = MeasurementUnits.points; 
        var myDocumentPreferences = myDocument.documentPreferences;  
        var myNumberOfFrames = myFiles.length; 
        var myNumberOfPages = Math.round(myNumberOfFrames / myFramesPerPage); 
        if ((myNumberOfPages * myFramesPerPage) < myNumberOfFrames){  
                myNumberOfPages++; 
        } 
        myDocumentPreferences.pagesPerDocument = myNumberOfPages;  
        myDocumentPreferences.facingPages = false;  
        var myPage = myDocument.pages.item(0);  
        var myMarginPreferences = myPage.marginPreferences; 
        var myLeftMargin = myMarginPreferences.left;  
        var myTopMargin = myMarginPreferences.top;  
        var myRightMargin = myMarginPreferences.right;  
        var myBottomMargin = myMarginPreferences.bottom;  
		var myLiveWidth = (myDocumentPreferences.pageWidth - (myLeftMargin + myRightMargin)) + myHorizontalOffset
		var myLiveHeight = myDocumentPreferences.pageHeight - (myTopMargin + myBottomMargin)
		var myColumnWidth = myLiveWidth / myNumberOfColumns
		var myFrameWidth = myColumnWidth - myHorizontalOffset
		var myRowHeight = (myLiveHeight / myNumberOfRows)
		var myFrameHeight = myRowHeight - myVerticalOffset
        var myPages = myDocument.pages; 
        if(myLabels >0){ 
                //Create the label paragraph style if it does not already exist. 
                myLabelStyle = myDocument.paragraphStyles.item("labels"); 
                try{ 
                        myLabelStyle.name; 
                } 
                catch (myError){ 
                        myLabelStyle = myDocument.paragraphStyles.add({name:"labels"}); 
                } 
                myLabelStyle.pointSize = 8; 
                //Create the label layer if it does not already exist. 
                var myLabelLayer = myDocument.layers.item("labels"); 
                try{ 
                        myLabelLayer.name; 
                } 
                catch (myError){ 
                        myLabelLayer = myDocument.layers.add({name:"labels"}); 
                } 
        } 
        // Construct the frames in reverse order. Don't laugh--this will  
        // save us time later (when we place the graphics).  
        for (myCounter = myDocument.pages.length-1; myCounter >= 0; myCounter--){  
		myPage = myPages.item(myCounter); 
                for (var myRowCounter = myNumberOfRows; myRowCounter >= 1; myRowCounter--){  
				myY1 = myTopMargin + (myRowHeight * (myRowCounter-1));
				myY2 = myY1 + myFrameHeight;

				for (var myColumnCounter = myNumberOfColumns; myColumnCounter >= 1; myColumnCounter--){  
					myX1 = myLeftMargin + (myColumnWidth * (myColumnCounter-1));
					myX2 = myX1 + myFrameWidth;
					myRectangle = myPage.rectangles.add(myDocument.layers.item(-1), undefined, undefined, {geometricBounds:[myY1, myX1, myY2, myX2], strokeWeight:0, strokeColor:myDocument.swatches.item("None")});  
                                } 
                } 
        } 
        // Because we constructed the frames in reverse order, rectangle 1  
        // is the first rectangle on page 1, so we can simply iterate through  
        // the rectangles, placing a file in each one in turn. myFiles = myFolder.Files;  
        for (myCounter = 0; myCounter < myNumberOfFrames; myCounter++){  
                myFile = myFiles[myCounter];  
                myRectangle = myDocument.rectangles.item(myCounter); 
                myRectangle.place(File(myFile)); 
               	myRectangle.label = myFile.fsName.toString();
               	//Apply fitting options as specified.
		if(myFitProportional){
			myRectangle.fit(FitOptions.proportionally); 
		}
		if(myFitCenterContent){
			myRectangle.fit(FitOptions.centerContent); 
		}
		if(myFitFrameToContent){
			myRectangle.fit(FitOptions.frameToContent); 
		}
		//Add the label, if necessary.
                if(myLabels >0){ 
                        myX1 = myRectangle.geometricBounds[1]; 
                        myY1 = myRectangle.geometricBounds[2]; 
                        myX2 = myRectangle.geometricBounds[3]; 
                        myY2 = myRectangle.geometricBounds[2]+myVerticalOffset; 
                        switch(myLabels){
                        	case 1:
                        		myString = myFile.name;
                        		break;
                        	case 2:
                        		myString = myFile.fsName.toString();
                        		break;
                        }
                        myTextFrame = myRectangle.parent.textFrames.add(myLabelLayer, undefined, undefined,{geometricBounds:[myY1, myX1, myY2, myX2], contents:myString}); 
                        myTextFrame.textFramePreferences.firstBaselineOffset = FirstBaseline.leadingOffset; 
                        myTextFrame.paragraphs.item(0).appliedParagraphStyle = myLabelStyle; 
                } 
        } 
        if (myRemoveEmptyFrames == 1){  
                for (var myCounter = myDocument.rectangles.length-1; myCounter >= 0;myCounter--){  
                        if (myDocument.rectangles.item(myCounter).contentType == ContentType.unassigned){ 
                                myDocument.rectangles.item(myCounter).remove(); 
                        }  
                        else{ 
                                //As soon as you encounter a rectangle with content, exit the loop. 
                                break; 
                        } 
                } 
        } 
}