Batch Export Symbols to SVG - Illustrator - javascript

Question:
I've created a script that iterates through all symbols in an Illustrator document and exports them as PNGs.
I need it to work for SVGs as well, however, it's not as simple as just changing the file-type.
Because of Illustrator's default behaviour of making a recently saved svg the app.activeDocument, the for loop nests new directories for each symbol.
e.g.
exports/
symbol01.svg
exports/
symbol02.svg
exports/
symbol03.svg
etc..
I'm pretty sure the problem lays between //create directory and //choose directory, but I can't for the life of me figure it out.
var doc = app.activeDocument;
var symbolCount = doc.symbols.length;
if (symbolCount >= 1) {
if (confirm("Are all your layers hidden?")) {
// create temp layer
doc.layers.add();
for (var i = 0; i < doc.symbols.length; i++) {
// place a symbol instance - temp
var s = doc.symbolItems.add(doc.symbols[i]);
// create directory
var dest = new Folder(doc.path + "/exports");
if (!dest.exists) dest.create();
// choose directory
dest.changePath(doc.symbols[i].name);
// export symbols
saveSVG(dest);
// delete temp symbol instance
s.remove();
}
// remove temp layer
doc.layers[0].remove();
}
function saveSVG(file) {
// save options
var type = ExportType.SVG;
var options = new ExportOptionsSVG();
// export
doc.exportFile(file, type, options);
}
} else {
alert("You don't have any symbols in this document");
}
Having a way to store the initial app.activeDocument would probably fix the issue, but I can't figure out how to do that.. if that's even the best way?
Bonus:
Another problem with this script is the artboard doesn't resize to the symbols, so I found a function fitArtboardToSelectedArt() which I've tried implementing with no success.. can anyone can explain how it should work?
PS. Here's a link for the Illustrator scripting documentation: http://adobe.ly/1JxLlUK

Figured it out :)
Feel free to use the following script if you need to do the same.
/*
* Export Symbols as SVGs - Illustrator
* --------------------------------------
* Created By Shane Parsons - 30PT Design Inc.
* http://30ptdesign.com/
*/
var doc = app.activeDocument;
var symbolCount = doc.symbols.length;
if (symbolCount >= 1) {
if (confirm("Are all your layers hidden?")) {
// choose directory
var dest = Folder(doc.path).selectDlg();
// folder chosen
if (dest) {
// create temp layer
doc.layers.add();
// create temp artboard
doc.artboards.add(doc.artboards[0].artboardRect);
// get temp artboard
var tempAB = doc.artboards.getActiveArtboardIndex();
// loop through symbols
for (var i = 0; i < doc.symbols.length; i++) {
// place a symbol instance - temp
var symbol = doc.symbolItems.add(doc.symbols[i]);
// resize artboard
doc.artboards[tempAB].artboardRect = doc.visibleBounds;
app.redraw();
// choose directory
var filename = doc.symbols[i].name;
// export symbols
saveSVG(dest, filename);
// delete temp symbol instance
symbol.remove();
}
// remove temp layer
doc.layers[0].remove();
// remove temp artboard
doc.artboards[tempAB].remove();
}
}
function saveSVG(dest, filename) {
// save options
var type = ExportType.SVG;
var options = new ExportOptionsSVG();
// file
var file = new File(dest + "/" + filename);
// export
doc.exportFile(file, type, options);
}
} else {
alert("You don't have any symbols in this document");
}

Related

Amending a .JSX file to change the filenames of output files

I have a script but it doesn't do what I need, so I need to adjust it, but honestly, I can't find what I need to change to make it work. The script outputs a CSV file from a folder of images. It makes a list with the file path so my program knows what images to import which works fine, but also it it writes the filenames which I can then also import in my secondary program.
The problem is the filenames. It also puts the extension behind the names which I don't need in the name. What do I need to change in the code to make it work as I want it to?
Here is the script:
Array.prototype.inArray = function(obj){
var arrMax = this.length-1;
for(var i=arrMax; i>=0; i--){
if(this[i]===obj){
return true;
}
}
return false;
}
var csvParser = (function(){
var csvFile;
return{
create:function(fo){
csvFile=File(fo+"/"+fo.name+".csv");
},
write:function(csvContent){
csvFile.open('w');
csvFile.encoding="UTF-8";
csvFile.write(csvContent);
csvFile.close();
},
execute:function(){
csvFile.execute();
},
getCSV:function(){
return csvFile;
}
}
})();
function imagesToCSVthenChoose(){
var doc,
fo,
fis,
fiMax,
fi,
fiName,
fiPath,
imgFormats=["eps","jpg","tif","psd","pdf","png","ai","bmp","jpeg"],
imgFormatMax = imgFormats.length-1,
imgOk = [],
csvContent = [],
csvLine=[],
csvSep=",";
if(app.documents.length==0){
alert("No documents open !");
return
}
doc=app.activeDocument;
fo = Folder.selectDialog("Please choose a folder with images");
if(!fo) return
fis = fo.getFiles();
fiMax=fis.length;
for(var i=0; i<fiMax; i++){
fi=fis[i];
ext = fi.name.match(/\.([a-z]+)$/i);
if(ext==null) continue;
ext = ext[1].toLowerCase();
if(!imgFormats.inArray(ext)) continue;
fiName = decodeURI(fi.name);
fiPath=decodeURI(fi.fsName);
csvContent.push(fiName+csvSep+fiPath);
}
csvContent = "Name"+csvSep+"#images\r"+csvContent.join("\r");
csvParser.create(fo);
csvParser.write(csvContent);
/*
doc.dataMergeProperties.selectDataSource(csvParser.getCSV());
var myMenuAction = app.menuActions.item("$ID/DataMergePanelName");
myMenuAction.invoke();
*/
}
imagesToCSVthenChoose();
I didn't try much yet because I have no clue. And I couldn't find the right code on the internet.

Google Appscript - Scripting to copy existing folders with files by creating new folder

I am trying to use a script that creates a Parent folder and subfolders and also copies any templates within a drive
The sheet is here: https://docs.google.com/spreadsheets/d/1zc_ZWGXHcM5qM4uPvVcchPWObQLDJysxbL0x2j4Kr6E/copy
I got this from https://www.techupover.com/create-google-drive-folder-structure-files/
I am trying to change this script to copy an existing folder with files to the newly created folder. OR if possible change this script to copy multiple files within the newly created folders (This one restricts it to copy only 1 file). Could someone guide me here as I am new to this.
const CUSTOM_MENU_NAME = 'Neat Features'; // the name of the new menu in your google sheet
const CUSTOM_MENU_ITEM = 'Generate Folders Now'; // the menu item you'll click to run the script
const DATA_TAB_NAME = 'folder_data'; // name for the sheet tab that contains the folder info that will be created/processed
const LOG_TAB_NAME = 'log'; // name of the sheet tab that will store the log messages from this script
const DATE_FORMAT = 'yyyy-MM-dd HH:mm:ss'; // date format to use for the log entries. Probably dont change this unless you really really want to.
/**
*
* DO NOT CHANGE ANYTHING UNDER THIS LINE
*
* ONLY CHANGE THINGS IN THE CONFIG.GS FILE
*
*/
/**
* When the spreadsheet is open, add a custom menu
*/
function onOpen() {
var spreadsheet = SpreadsheetApp.getActive();
var customMenuItems = [
{name: CUSTOM_MENU_ITEM, functionName: 'processGoogleSheetData_'}
];
spreadsheet.addMenu(CUSTOM_MENU_NAME, customMenuItems);
}
/**
* Bulk create Google Folders from data within a Google Sheet.
* This is the function to call from the custom menu item.
* Others are referenced by this one.
*/
function processGoogleSheetData_() {
// get current spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Log starting of the script
logEventToGoogleSheet('Script has started');
// display Toast notification
ss.toast('Starting!!!', 'Yep, we are starting...now.');
// get TimeZone
var timeZone = ss.getSpreadsheetTimeZone();
// get Data sheet
var dataSheet = ss.getSheetByName(DATA_TAB_NAME);
// get all data as a 2-D array
var data = dataSheet.getDataRange().getValues();
// create a name:value pair array to send the data to the next Function
var spreadsheetData = {ss:ss, timeZone:timeZone, dataSheet:dataSheet, data:data};
// run Function to create Google Folders
var doCreateFolders = createFolders(spreadsheetData);
// check success status
if (doCreateFolders) {
// display Toast notification
ss.toast('Script complete', 'Finished');
}
else {
// script completed with error
// display Toast notification
ss.toast('Got some errors. Check the logs', 'Finished');
}
// Log starting of the script
logEventToGoogleSheet('Script finished');
}
/**
* Loop through each row and create folders, set permissions
*/
function createFolders(spreadsheetData) {
// extract data from name:value pair array
var ss = spreadsheetData['ss'];
var timeZone = spreadsheetData['timeZone'];
var dataSheet = spreadsheetData['dataSheet'];
var data = spreadsheetData['data'];
// get last row number so we know when to end the loop
var lastRow = dataSheet.getLastRow();
var folderIdMap = new Object();
// start of loop to go through each row iteratively
for (var i=1; i<lastRow; i++) {
// extract values from row of data for easier reference below
var rootFolderId = data[i][0];
var templateDocId = data[i][1]
var newFolderName = data[i][2];
var parentFolderName = data[i][3];
var folderId = data[i][4];
var permissionEmailViewer = data[i][5];
var permissionEmailEditor = data[i][6];
// only perform this row if the folder ID is blank
if(folderId == '') {
// if the sheet doesn't have a specified parent folder name, then it goes in the root.
// if the parent folder name is supplied then it had to have been created by this script,
// so get it from script properties (where the ID is saved during an earlier loop)
if(parentFolderName == '') {
destinationFolderId = rootFolderId;
} else {
var thisMapKey = createMapString(rootFolderId + '___' + parentFolderName);
var destinationFolderId = folderIdMap[thisMapKey];
}
// display Toast notification
ss.toast(newFolderName, 'Creating New Folder');
// run Function to create Google Folder and return its URL/ID
var folderDetails = createFolder(newFolderName, destinationFolderId);
// check new Folder created successfully
if (folderDetails) {
// extract Url/Id for easier reference later
var newFolderUrl = folderDetails['newFolderUrl'];
var newFolderId = folderDetails['newFolderId'];
//push the key/folder id to the array map so we can use it later in the loop
var thisMapKey = createMapString(destinationFolderId + '___' + newFolderName);
folderIdMap[thisMapKey] = newFolderId;
// copy the template doc into the new directory (if specified)
if(templateDocId != '') {
makeCopy(templateDocId, newFolderId, newFolderName + ' Template Document');
}
// set the Folder ID value in the google sheet, inserting it as a link
var newFolderLink = '=HYPERLINK("' + newFolderUrl + '","' + newFolderName + '")';
dataSheet.getRange(i+1, 5).setFormula(newFolderLink);
// check if Viewer Permissions need adding - if there are emails in the column for this row
if (permissionEmailViewer != '') {
// run Function to add Folder permissions
var currentRow = i+1;
var addPermissionsFlag = addPermissions('VIEWER', timeZone, dataSheet, permissionEmailViewer,
newFolderId, currentRow, 8);
// if problem adding Permissions return for status message
if (addPermissionsFlag == false) {
// display Toast notification and return false flag
ss.toast('Error when adding Viewer Permissions to: ' + newFolderName, 'Error');
return false;
}
}
// check if Editor Permissions need adding - if there are emails in the column for this row
if (permissionEmailEditor != '') {
// run Function to add Folder permissions
var currentRow = i+1;
var addPermissionsFlag = addPermissions('EDITOR', timeZone, dataSheet, permissionEmailEditor,
newFolderId, currentRow, 9);
// if problem adding Permissions return for status message
if (addPermissionsFlag == false) {
// display Toast notification and return false flag
ss.toast('Error when adding EDITOR Permissions to: ' + newFolderName, 'Error');
return false;
}
}
// write all pending updates to the google sheet using flush() method
SpreadsheetApp.flush();
} else {
// write error into 'Permission Added?' cell and return false value
dataSheet.getRange(i+1, 4).setValue('Error creating folder. Please see Logs');
// new Folder not created successfully
return false;
}
} else {
ss.toast('Skipping Row - Folder ID already set', 'Moving onto the next row to process');
}
} // end of loop to go through each row in turn **********************************
// completed successfully
return true;
}
function makeCopy(sourceDocumentId, destinationFolderId, destinationFileName) {
var destinationFolder = DriveApp.getFolderById(destinationFolderId);
return DriveApp.getFileById(sourceDocumentId).makeCopy(destinationFileName,destinationFolder);
}
/**
* Function to create new Google Drive Folder and return details (url, id)
*/
function createFolder(folderName, destinationFolderId) {
try {
// get destination Folder
var destinationFolder = DriveApp.getFolderById(destinationFolderId);
}
catch(e) {
logEventToGoogleSheet('Error getting destination folder: ' + e + e.stack);
var destinationFolder = false;
}
// proceed if successfully got destination folder
if (destinationFolder) {
var documentProperties = PropertiesService.getDocumentProperties();
try {
// create new Folder in destination
var newFolder = destinationFolder.createFolder(folderName);
// get new Drive Folder Url/Id and return to Parent Function
var newFolderUrl = newFolder.getUrl();
var newFolderId = newFolder.getId();
var folderDetails = {newFolderUrl:newFolderUrl, newFolderId:newFolderId};
return folderDetails;
}
catch(e) {
logEventToGoogleSheet('Error creating new Folder: ' + e + e.stack);
return false;
}
}
else {
// return false as unable to get destination folder
return false;
}
}
/**
* Function to add permissions to each Folder using the provided email address(es).
*
* role var can be either VIEWER or EDITOR
*/
function addPermissions(role, timeZone, dataSheet, permissionEmail, newFolderId, currentRow, permAddedCol) {
// split up email address array to be able to loop through them separately
var emailAddresses = permissionEmail.split(',');
logEventToGoogleSheet(role + ' emailAddress array is: ' + emailAddresses);
// get length of array for loop
var emailAddressesLength = emailAddresses.length;
try {
// get Google Drive Folder
var newFolder = DriveApp.getFolderById(newFolderId);
}
catch(e) {
logEventToGoogleSheet('Error getting destination folder: ' + e + e.stack);
var newFolder = false;
}
// proceed if successfully got destination folder
if (newFolder) {
// loop through each email address and add as 'Editor' *******************
for (var i=0; i<emailAddressesLength; i++) {
var emailAddress = emailAddresses[i].trim();
logEventToGoogleSheet(role + ' emailAddress for adding permission is: ' + emailAddress);
try {
if(role == 'VIEWER') {
logEventToGoogleSheet('Adding ' + emailAddress + ' as ' + role);
newFolder.addViewer(emailAddress);
var success = true;
}
if(role == 'EDITOR') {
logEventToGoogleSheet('Adding ' + emailAddress + ' as ' + role);
newFolder.addEditor(emailAddress);
var success = true;
}
// add 'Edit' permission using email address
if (success) {
// write timestamp into 'Permission Added?' cell
var date = new Date;
var timeStamp = Utilities.formatDate(date, timeZone, DATE_FORMAT);
dataSheet.getRange(currentRow, permAddedCol).setValue(timeStamp);
}
else {
// write error into 'Permission Added?' cell and return false value
dataSheet.getRange(currentRow, permAddedCol).setValue('Error adding ' + role + ' permission. Please see Logs');
return false;
}
}
catch(e) {
logEventToGoogleSheet('Error adding ' + role + ' permission: ' + e + e.stack);
}
}
}
else {
// write error into cell and return false value
dataSheet.getRange(currentRow, permAddedCol).setValue('Error getting folder. Please see Logs');
// return false as unable to get Google Drive Folder
return false;
}
// return true as all permissions added successfully
return true;
}
/**
* Write log message to Google Sheet
*/
function logEventToGoogleSheet(text_to_log) {
// get the user running the script
var activeUserEmail = Session.getActiveUser().getEmail();
// get the relevant spreadsheet to output log details
var ss = SpreadsheetApp.getActiveSpreadsheet();
var googleSheet = ss.getSheetByName(LOG_TAB_NAME);
// create and format a timestamp
var now = new Date();
var timeZone = ss.getSpreadsheetTimeZone();
var niceDateTime = Utilities.formatDate(now, timeZone, DATE_FORMAT);
// create array of data for pasting into log sheet
var logData = [niceDateTime, activeUserEmail, text_to_log];
// append details into next row of log sheet
googleSheet.appendRow(logData);
}
/**
* Create a string that can easily be used as an object/array key for reference
* during the create folder loop. (Helps with identifying the parent folder dynamically)
*/
function createMapString(input_string) {
return input_string.replace(/\W/g, '');
}
I hope I figured out the solution. You need to make these three modifications:
Column B should contain Folder IDs (these folder contain files you want to copy) instead of Google Document IDs.
In line 136 you have to change the variable name templateDocId to templateFolderId this way:
var templateFolderId = data[i][1]
After the line 152 the code should look like this:
// copy the template doc into the new directory (if specified)
// if(templateDocId != '') {
// makeCopy(templateDocId, newFolderId, newFolderName + ' Template Document');
// }
if (templateFolderId != '') copy_files(newFolderId);
function copy_files(newFolderId) {
var src_folder = DriveApp.getFolderById(templateFolderId);
var dest_folder = DriveApp.getFolderById(newFolderId);
var files = src_folder.getFiles();
while (files.hasNext()) files.next().makeCopy(dest_folder);
}
After that the script will copy all the files from template folders into the new created folders (like 'Team A1', 'Team A2', etc).
The sheet with the changed script is here.
You can try this modification after the line 136:
// copy the template doc into the new directory (if specified)
// if(templateDocId != '') {
// makeCopy(templateDocId, newFolderId, newFolderName + ' Template Document');
// }
copy_files(folderId, newFolderId);
function copy_files(folderId, newFolderId) {
var src_folder = DriveApp.getFolderById(folderId);
var dest_folder = DriveApp.getFolderById(newFolderId);
var files = src_folder.getFiles();
while (files.hasNext()) files.next().makeCopy(dest_folder);
}
A haven't tried it. It's just a guess.
function start() {
var sourceFolder = 'source';
var targetFolder = 'target';
var source = DriveApp.getFoldersByName(sourceFolder);
var target = DriveApp.createFolder(targetFolder);
if (source.hasNext()) {
copyFolder(source.next(), target);
}
}
function copyFolder(source, target) {
var folders = source.getFolders();
var files = source.getFiles();
while (files.hasNext()) {
var file = files.next();
file.makeCopy(file.getName(), target);
}
while (folders.hasNext()) {
var subFolder = folders.next();
var folderName = subFolder.getName();
var targetFolder = target.createFolder(folderName);
copyFolder(subFolder, targetFolder);
}
}

Function returns array with dates of tiles

I have js code which returns dates of layers (Using OpenLayers and Momentjs) that stored on my PC.
As we see that the function returns all the dates between two dates from the folder (folder) with a 60-second step. But I want to return just the dates which I have files (layers) on my PC because I don't have layers for all the dates.
So what I need is a function returns an array of dates for which I have tiles only, and then add from this layer to the map depends on the entered dates
function loopLayer() {
const FromDateTime = document.getElementById("fromdate").value;
const dateFrom = moment(FromDateTime, "YYYY-MM-DD HH:mm:ss", true);
if (!dateFrom.isValid()) {
log("something");
return;
}
const ToDateTime = document.getElementById("todate").value;
const dateTo = moment(ToDateTime, "YYYY-MM-DD HH:mm:ss", true);
if (!dateTo.isValid()) {
log("something");
return;
}
let loopDate = dateFrom;
for(let i=0; dateFrom.isSameOrBefore(dateTo) && i < 100; i++) {
// preventing from loading thousands of layers
loopLayerByDate(loopDate);
loopDate = loopDate.add(60, 'seconds');
}
}
function loopLayerByDate(dateObject) {
const folderDate = dateObject.format("YYYY-MM-DD_HHmmss");
const source = new ol.source.XYZ({
projection: 'EPSG:3854',
// adapt url and source tile type to your setup
url: "folder/" + folderDate + "/{z}/{x}/{-y}.png"
});
const layer = new ol.layer.Tile({
source: source,
title: "layer"
});
map.addLayer(layer)
}
An Website usually cannot read data from your local file system for security reasons. Otherwise any website could spy on your harddisk.
As you already found out, there is an exception to that rule: when you open a local HTML file, it can read file content from the harddisk. But you can't crawl through folders, so we cannot read a list of the available dates.
you have two options now:
add an <input type="file" multiple>, upload the files and use the FileAPI (example here).
your thing is a local html file which you open from your harddisk. You could use a trial-and-error guess approach
find a method to build a list of dates without the need to guess them, e.g. naming the folders with an increasing number instead of timestamps!
Use a server software which serves everything. The server can access the file-system and send the "front-end" the required list of dates. I won't provide an how-to here, there are tons of software-solutions and how-tos on stackoverflow and in search engines.
Option 2, local html:
Since you know roughly in what ranges the filenames is, you could use a brute-force approach and just query for all dates in a range and see which ones actually respond. Be aware that this approach is far from ideal and probably quite slow.
function guessValidDates(arrayOfDates){
const validDates = [];
arrayOfDates.forEach((date) => {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "time/" + date + "/1.png", true);
xhttp.send();
console.log('request returned', xhttp);
if (xhttp.response) {
validDates.push(date;
}
});
return validDates;
}
Example usage:
// example from loopLayer function
let loopDate = dateFromObject;
const allDates = [];
for(let i=0; dateFromObject.isSameOrBefore(dateToObject) && i < 100; i++) {
// the i counts as a failsafe, preventing us from loading billions of
// or whatever the pattern is for your file path
allDates.push(loopDate.format("YYYY-MM-DD_HHmmss"));
// step forward by X
loopDate = loopDate.add(1, 'minutes');
}
const validDates = guessValidDates(allDates);
// now you know the valid dates and can use them. Example:
validDates.forEach(function(someDate){
loopLayerByDate(someDate);
});
Or if you have a pattern where all layers for a single day have an increasing number, eg "time/" + yearMontDay + '_' + increasingNumber + "/{z}/{x}/{-y}.png", just keep adding layers until you get a non-valid response:
function isValidLayer(someDateString, someNumber) {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "time/" + someDateString + "_" + someNumber + "/1.png", true);
xhttp.send();
if (xhttp.response) {
return true;
}
return false;
}
// you can now count up until you don't get a valid response anymore:
let someDateString = dateObject.format("YYYY-MM-DD_HHmmss");
let increasingNumber = 0;
while(increasingNumber < 1000) {
// the condition is just a failsafe
if(isValidLayer(someDateString, increasingNumber) {
// add layer with that number to your map
const source = new ol.source.XYZ({
projection: 'EPSG:4326',
wrapX: false,
url: "time/" + folderDate + "_" + increasingNumber + "/{z}/{x}/{-y}.png"
});
// TODO add layer here and so on....
} else {
// no more layers, stop!
console.log('stopped after' + increasingNumber + 'layers on date ' + someDateString);
break;
}
}

Access of undefined property error in Flash using ExternalInterface

I am new to flash, so the solution to this problem may be simple. Unfortunately I have been unable to find a working solution, so I am hoping you guys can help. I am developing a site using 3rd party flash - Coverflow, for an album. It looks great and you can download it here: http://www.weberdesignlabs.com/blog/2009/12/flash-10-coverflow/. My challenge is that I want to progress the albums from a Javascript call within my HTML. In my search I have discovered ExternalInterface, but I can't get it to work. When I try to export the movie I get an "Access of undefined property gotoCoverFlowItem" error.
Below follows the code contained in the Coverflow.ai file which I am trying to modify, with the modification in it. The full code can be found at the link above. I am using the Flash 10 version.
////////////////////////////////////////////
// Project: Flash 10 Coverflow
// Date: 10/3/09
// Author: Stephen Weber
////////////////////////////////////////////
package {
////////////////////////////////////////////
// IMPORTS
////////////////////////////////////////////
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.MovieClip;
import flash.display.BlendMode;
import flash.display.Loader;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.IOErrorEvent;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.geom.ColorTransform;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.net.navigateToURL;
import flash.display.Stage;
import flash.utils.setTimeout;
import flash.external.ExternalInterface;
//TweenLite - Tweening Engine - SOURCE: http://blog.greensock.com/tweenliteas3/
import com.greensock.*;
import com.greensock.easing.*;
import com.greensock.plugins.*;
public class Coverflow extends Sprite {
////////////////////////////////////////////
// VARIABLES
////////////////////////////////////////////
// size of the stage
private var sw:Number;
private var sh:Number;
private var background:Background;
// padding between each cover, can be customed via xml
private var coverflowSpacing:Number=30;
// transition time for movement
private var transitionTime:Number=0.75;
// the center of the stage
private var centerX:Number;
private var centerY:Number;
// store each image cover's instance
private var coverArray:Array=new Array();
// title of each image
private var coverLabel:CoverflowTitle = new CoverflowTitle();
// the slider under the image cover
private var coverSlider:Scrollbar;
// how many image covers
private var coverflowItemsTotal:Number;
// how to open the link
private var _target:String;
// size of the image cover
private var coverflowImageWidth:Number;
private var coverflowImageHeight:Number;
//Holds the objects in the data array
private var _data:Array = new Array();
// the y position of the item's title
private var coverLabelPositionY:Number;
//Z Position of Current CoverflowItem
private var centerCoverflowZPosition:Number=-125;
// display the middle of the cover or not
private var startIndexInCenter:Boolean=true;
// which cover to display in the beginning
private var startIndex:Number=0;
// the slide's Y position
private var coverSlidePositionY:Number;
//Holder for current CoverflowItem
private var _currentCover:Number;
//CoverflowItem Container
private var coverflowItemContainer:Sprite = new Sprite();
//XML Loading
private var coverflowXMLLoader:URLLoader;
//XML
private var coverflowXML:XML;
// the image cover's white border padding
private var padding:Number=4;
// stage reference
private var _stage:Stage;
//reflection
private var reflection:Reflect;
//Reflection Properties
private var reflectionAlpha:Number;
private var reflectionRatio:Number;
private var reflectionDistance:Number;
private var reflectionUpdateTime:Number;
private var reflectionDropoff:Number;
////////////////////////////////////////////
// CONSTRUCTOR - INITIAL ACTIONS
////////////////////////////////////////////
public function Coverflow(_width:Number, _height:Number, __stage:Stage = null):void {
_stage=__stage;
sw=_width;
sh=_height;
centerX=_width>>1;
centerY=(_height>>1) - 20;
loadXML();
//Grabs Background color passed in through FlashVars
var backgColor:String = _stage.loaderInfo.parameters["backgroundColor"];
if(backgColor == null) {
//Black
backgColor = "0x000000";
//White
//backgColor = "0xFFFFFF";
}
//Creates Background MovieClip
background = new Background();
//Set Background To Provided Width/Height
background.width = _width;
background.height = _height;
//Adds background MovieClip to DisplayList
addChild(background);
//Tints Background MovieClip with provided tint
TweenPlugin.activate([TintPlugin]);
TweenLite.to(background, 0, {tint:backgColor});
//Grabs Background color passed in through FlashVars
var labelColor:String = _stage.loaderInfo.parameters["labelColor"];
//Check for value and then default
if(labelColor == null) {
//Black
//labelColor = "0x000000";
//White
labelColor = "0xFFFFFF";
}
//Tint Coverflow label to color provided
TweenLite.to(coverLabel, 0, {tint:labelColor});
if (_stage) {
_stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
}
}
////////////////////////////////////////////
// FUNCTIONS
////////////////////////////////////////////
private function keyDownHandler(e:KeyboardEvent):void {
if (e.keyCode==37||e.keyCode==74) {
clickPre();
}
if (e.keyCode==39||e.keyCode==75) {
clickNext();
}
// 72 stand for "H" key, 191 stand for "?" key
if (e.keyCode==72||e.keyCode==191) {
}
}
// display the previous image
private function clickPre(e:Event=null):void {
_currentCover--;
if (_currentCover<0) {
_currentCover=coverflowItemsTotal-1;
}
coverSlider.value=_currentCover;
gotoCoverflowItem(_currentCover);
}
// display the next image
private function clickNext(e:Event=null):void {
_currentCover++;
if (_currentCover>coverflowItemsTotal-1) {
_currentCover=0;
}
coverSlider.value=_currentCover;
gotoCoverflowItem(_currentCover);
}
// loading the XML
private function loadXML():void {
//Loads XML passed through FlashVars
var xml_source:String = _stage.loaderInfo.parameters["xmlPath"];
//If XML not found through FlashVars then defaults to xml path below
if(xml_source == null) {
xml_source = 'xml/data.xml';
}
// loading the cover xml here
coverflowXMLLoader = new URLLoader();
coverflowXMLLoader.load(new URLRequest("xml/data.xml"));
coverflowXMLLoader.addEventListener(Event.COMPLETE, coverflowXMLLoader_Complete);
coverflowXMLLoader.addEventListener(IOErrorEvent.IO_ERROR, coverflowXMLLoader_IOError);
}
// parse the XML
private function coverflowXMLLoader_Complete(e:Event):void {
coverflowXML=new XML(e.target.data);
coverflowItemsTotal=coverflowXML.cover.length();
coverflowSpacing=Number(coverflowXML.#coverflowSpacing);
coverflowImageWidth=Number(coverflowXML.#imageWidth);
coverflowImageHeight=Number(coverflowXML.#imageHeight);
coverLabelPositionY=Number(coverflowXML.#coverLabelPositionY);
coverSlidePositionY=Number(coverflowXML.#coverSlidePositionY);
transitionTime=Number(coverflowXML.#transitionTime);
centerCoverflowZPosition=Number(coverflowXML.#centerCoverflowZPosition);
//Image Border
padding = Number(coverflowXML.#imagePadding)
//Reflection Attributes
reflectionAlpha=Number(coverflowXML.#reflectionAlpha);
reflectionRatio=Number(coverflowXML.#reflectionRatio);
reflectionDistance=Number(coverflowXML.#reflectionDistance);
reflectionUpdateTime=Number(coverflowXML.#reflectionUpdateTime);
reflectionDropoff=Number(coverflowXML.#reflectionDropoff);
startIndex=Number(coverflowXML.#startIndex);
startIndexInCenter = (coverflowXML.#startIndexInCenter.toLowerCase().toString()=="yes");
_target=coverflowXML.#target.toString();
for (var i=0; i<coverflowItemsTotal; i++) {
//Make An Object To Hold Values
var _obj:Object = new Object();
//Set Values To Object from XML for each CoverflowItem
_obj.image = (coverflowXML.cover[i].#img.toString());
_obj.title = (coverflowXML.cover[i].#title.toString());
_obj.link = (coverflowXML.cover[i].#link.toString());
_data[i] = _obj;
}
loadCover();
}
private function coverflowXMLLoader_IOError(event:IOErrorEvent):void {
trace("Coverflow XML Load Error: "+ event);
}
// load the image cover when xml is loaded
private function loadCover():void {
for (var i:int = 0; i < coverflowItemsTotal; i++) {
var cover:Sprite=createCover(i,_data[i].image);
coverArray[i]=cover;
cover.y=centerY;
cover.z=0;
coverflowItemContainer.addChild(cover);
}
if (startIndexInCenter) {
startIndex=coverArray.length>>1;
gotoCoverflowItem(startIndex);
} else {
gotoCoverflowItem(startIndex);
}
_currentCover=startIndex;
coverSlider=new Scrollbar(coverflowItemsTotal,_stage);
coverSlider.value=startIndex;
coverSlider.x = (_stage.stageWidth/2) - (coverSlider.width/2);
coverSlider.y=_stage.stageHeight-40;
coverSlider.addEventListener("UPDATE", coverSlider_Update);
coverSlider.addEventListener("PREVIOUS", coverSlider_Previous);
coverSlider.addEventListener("NEXT", coverSlider_Next);
addChild(coverSlider);
//coverLabel.x = (sw - coverLabel.width)>>1;
coverLabel.x = (_stage.stageWidth/2) - (coverLabel.width/2);
coverLabel.y=coverLabelPositionY;
addChild(coverLabel);
addChild(coverSlider);
addChild(coverLabel);
}
private function coverSlider_Update(e:Event):void {
var value:Number=(coverSlider.value);
gotoCoverflowItem(value);
e.stopPropagation();
}
private function coverSlider_Previous(e:Event):void {
clickPre();
}
private function coverSlider_Next(e:Event):void {
clickNext();
}
// move to a certain cover via number
private function gotoCoverflowItem(n:int):void {
_currentCover=n;
reOrderCover(n);
if (coverSlider) {
coverSlider.value=n;
}
}
ExternalInterface.addCallback("gotoCover", gotoCoverflowItem);
private function cover_Selected(event:CoverflowItemEvent):void {
var currentCover:uint=event.data.id;
if (coverArray[currentCover].rotationY==0) {
try {
// open the link if user click the cover in the middle again
if (_data[currentCover].link!="") {
navigateToURL(new URLRequest(_data[currentCover].link), _target);
}
} catch (e:Error) {
//
}
} else {
gotoCoverflowItem(currentCover);
}
}
// change each cover's position and rotation
private function reOrderCover(currentCover:uint):void {
for (var i:uint = 0, len:uint = coverArray.length; i < len; i++) {
var cover:Sprite=coverArray[i];
if (i<currentCover) {
//Left Side
TweenLite.to(cover, transitionTime, {x:(centerX - (currentCover - i) * coverflowSpacing - coverflowImageWidth/2), z:(coverflowImageWidth/2), rotationY:-65});
} else if (i > currentCover) {
//Right Side
TweenLite.to(cover, transitionTime, {x:(centerX + (i - currentCover) * coverflowSpacing + coverflowImageWidth/2), z:(coverflowImageWidth/2), rotationY:65});
} else {
//Center Coverflow
TweenLite.to(cover, transitionTime, {x:centerX, z:centerCoverflowZPosition, rotationY:0});
//Label Handling
coverLabel._text.text=_data[i].title;
coverLabel.alpha=0;
TweenLite.to(coverLabel, 0.75, {alpha:1,delay:0.2});
}
}
for (i = 0; i < currentCover; i++) {
addChild(coverArray[i]);
}
for (i = coverArray.length - 1; i > currentCover; i--) {
addChild(coverArray[i]);
}
addChild(coverArray[currentCover]);
if (coverSlider) {
addChild(coverSlider);
addChild(coverLabel);
}
}
//Create CoverflowItem and Set Data To It
private function createCover(num:uint, url:String):Sprite {
//Setup Data
var _data:Object = new Object();
_data.id=num;
//Create CoverflowItem
var cover:CoverflowItem=new CoverflowItem(_data);
//Listen for Click
cover.addEventListener(CoverflowItemEvent.COVERFLOWITEM_SELECTED, cover_Selected);
//Set Some Values
cover.name=num.toString();
cover.image=url;
cover.padding=padding;
cover.imageWidth=coverflowImageWidth;
cover.imageHeight=coverflowImageHeight;
cover.setReflection(reflectionAlpha, reflectionRatio, reflectionDistance, reflectionUpdateTime, reflectionDropoff);
//Put CoverflowItem in Sprite Container
var coverItem:Sprite = new Sprite();
cover.x=- coverflowImageWidth/2-padding;
cover.y=- coverflowImageHeight/2-padding;
coverItem.addChild(cover);
coverItem.name=num.toString();
return coverItem;
}
}
}
The code I added is:
ExternalInterface.addCallback("gotoCover", gotoCoverflowItem);
Please help!
Putting the ExternalInterface call at the end of the Coverflow constructor should work as desired. The current line you have is not inside a function.
I don't know what your javascript looks like, but this code requires a parameter for gotoCoverflowItem, so I am assuming you are passing the appropriate data.
I haven't gone through all the code, but keep in mind that the current code might have certain things that it does - that might not get done if you are feeding it just the index of the next cover. I do see code in the gotoColorflowItem function that updates variables for the slider and current cover based on the selection, so it might be just fine.
Also, you are most likely going to get a runtime error if you try to test this outside of a browser for any reason, so you might want to put a try/catch for that case.
The author included his wisdom on the page :
"NOTE: I would not recommend trying to learn flash with this file. There are a lot of people asking how to change text color, if you are having these requests I would suggest going through some Lynda.com Flash tutorials to get you familiar with Flash or hiring a Flash developer to help you out."
Well, you can't just dump the ExternalInterface call anywhere you want to. It needs to be inside a function such as the constructor.

Javascript returning empty array (which shoudn't) on IE

I've written some code to display my bookmarks on IE8. The code works fine except the array of favorites I should have ("favs") as output exists but is empty (when I put "favs" in the developer tools console I get {...}).
var fso, favs = [];
var favString="";
function GetFavourites(Folder) {
var FavFolder = fso.GetFolder(Folder);
//Gets Favourite Names & URL's for given folder.
var files = new Enumerator(FavFolder.Files);
for (; !files.atEnd(); files.moveNext()) {
var fil = files.item();
if (fil.Type == "Internet Shortcut") {
var textReader = fso.OpenTextFile(fil.Path, 1, false, -2);
var favtext = textReader.ReadAll();
var start = favtext.indexOf("URL", 16);
var stop = favtext.indexOf("\n", start);
favString = fil.Name.replace(/.url/, "");
favString += ":URL:";
//to separate favourite name & favorite URL
favString += favtext.substring(start + 4, stop - 1);
favs.push(favString);
}
}
//Checks any subfolder exists
var subfolders = new Enumerator(FavFolder.SubFolders);
for (; !subfolders.atEnd(); subfolders.moveNext()) {
var folder = subfolders.item();
GetFavourites(folder.Path);
}
}
function Import() {
try {
fso = new ActiveXObject("Scripting.FileSystemObject");
if (fso !== null) {
//Create windows script shell object to access Favorites folder in user system.
var object = new ActiveXObject("WScript.Shell");
var favfolderName = object.SpecialFolders("Favorites");
if (favString === "") {
GetFavourites(favfolderName);
}
}
}
catch (err) {
alert("Security settings to be modified in your browser ");
}
}
I've found where my mistake is : I forgot I was using IE in French so the test "if (fil.Type == "Internet Shortcut")" doesn't work; I must replace "Internet Shortcut" with the French equivalent "Raccourci Internet". :-))

Categories