Saturday, July 19, 2008

Compile Flex 3 SDK from the Command Line

Here is a guide to setting up a Flex 3 project so that you can compile it from the command line:

  • download and set up the Flex 3 SDK, make sure the bin/ directory is on your path
  • make a directory for your project
  • in your projects directory make src/ and bin/ directories
  • copy the flex-config.xml from the flex SDK's frameworks directory into the root of your project
  • edit the flex-config.xml in your project, prepending ${flexlib}/ to all the libs/ paths and before the path references to manifest.xml and locale/
  • edit the flex-config.xml in your project, uncommenting the source-path element and setting its path-element element to src
  • create a compile file in the root of your project with the following content:
    #!/usr/bin/env bash
    mxmlc -load-config flex-config.xml src/com/dburger/HelloWorld.mxml -output bin/HelloWorld.swf
    view raw gistfile1.sh hosted with ❤ by GitHub

    Make this file executable.
  • Run the compile script to compile the project. The compiled swf will go to the bin/ directory and can be opened with your browser.

Here is a link to a zipped up version of a project where all the previously described steps have already been done for you (other than setting up the Flex 3 SDK of course).

This information primarily came from Simple Blog.

UPDATE: To use the trial data visualization components you need to copy several files over from a user that has installed flex builder. The instructions on which files and where they need to be placed in your sdk directory can be found here.

UPDATE UPDATE: The good people at Adobe have now made the data visualization components available as a separate download. You can find it here. You can download this archive and unzip it into your sdk and you will be good to go with the data visualization components - you won't need to download flex builder.

Firefox Greasemonkey Outlook Web Access Extension Part III

Other posts on OWAX: [ Part I | Part II ]

I have reverse engineered the way Microsoft Outlook Web Access uses Ajax to mark records read / unread under Internet Exploder and have added similar functionality to my Firefox Greasemonkey Outlook Web Access Extensions.

The code, also shown below, can be downloaded here.

// ==UserScript==
// @name Outlook Web Access Extensions
// @namespace http://www2.hawaii.edu/~dburger
// @description Extensions to using the bastard child Outlook Web Access
// ==/UserScript==
(
function() {
var UNREAD_IMG = '/exchweb/img/icon-msg-unread.gif';
var READ_IMG = '/exchweb/img/icon-msg-read.gif';
function walkTheDom(node, func) {
func(node);
node = node.firstChild;
while(node) {
walkTheDom(node, func);
node = node.nextSibling;
}
}
function getToolbarTable() {
var tables = document.getElementsByTagName('table');
for (var i = 0; i < tables.length; i++) {
var table = tables[i];
if (table.className === 'trToolbar') return table;
}
return null;
}
function getFindNamesForm() {
var forms = document.getElementsByTagName('form');
return (forms.length == 1 && forms[0].name == 'galfind') ? forms[0] : null;
}
function getBaseHref() {
var bases = document.getElementsByTagName('base');
return (bases) ? bases[0].href : null;
}
function addToolbarButton(toolbarTable, text, func) {
var row = toolbarTable.tBodies[0].rows[0];
var newCell = row.insertCell(row.cells.length - 1);
newCell.setAttribute('valign', 'middle');
newCell.setAttribute('nowrap', 'nowrap');
var font = document.createElement('font');
font.setAttribute('size', '2');
font.appendChild(document.createTextNode(text));
var nobr = document.createElement('nobr');
nobr.appendChild(font);
var a = document.createElement('a');
a.href = 'javascript:void(0);';
a.addEventListener('click', func, true);
a.appendChild(nobr);
newCell.appendChild(a);
}
function changeSelectState(state) {
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
var evt = document.createEvent('MouseEvents');
if (input.type == 'checkbox' && input.checked != state) {
// this won't fire the events to color the row
// input.checked = true;
// so dispatch as an event instead
evt.initEvent('click', true, false);
input.dispatchEvent(evt);
}
}
}
function addSelectAll(toolbarTable) {
addToolbarButton(toolbarTable, 'Select All', function() {
changeSelectState(true);
});
}
function addSelectNone(toolbarTable) {
addToolbarButton(toolbarTable, 'Select None', function () {
changeSelectState(false);
});
}
function setProps(sXml, loadFunc, errorFunc) {
GM_xmlhttpRequest({
method: 'BPROPPATCH',
url: getBaseHref(),
headers: {
'Accept-Language': 'en-us',
'Content-Type': 'text/xml'
},
data: sXml,
onload: loadFunc,
onerror: errorFunc
});
}
function changeReadStatus(status) {
var selInputs = [];
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
if (input.type == 'checkbox' && input.checked) selInputs.push(input);
}
if (selInputs.length > 0) {
var sFlags = 'd:flags="1"'; // suppress receipt
var sXml = '<?xml version="1.0"?\><a:propertyupdate xmlns:a="DAV:"><a:set><a:prop><d:read xmlns:d="urn:schemas:httpmail:" ' + sFlags + '>';
sXml += (status) ? '1':'0';
sXml += '</d:read></a:prop></a:set><a:target>';
for (var i = 0; i < selInputs.length; i++) {
var input = selInputs[i];
sXml += '<a:href>' + getBaseHref() + input.value + '</a:href>';
}
sXml += '</a:target></a:propertyupdate>';
var loadFunc = function(res) {
var parser = new DOMParser();
var doc = parser.parseFromString(res.responseText, 'text/xml');
var responses = doc.getElementsByTagNameNS('DAV:', 'response');
var baseHrefLength = getBaseHref().length;
for (var i = 0; i < responses.length; i++) {
var response = responses[i];
var href = response.getElementsByTagNameNS('DAV:', 'href')[0];
var id = href.firstChild.nodeValue.substring(baseHrefLength - 1);
for (var j = 0; j < selInputs.length; j++) {
var input = selInputs[j];
if (input.type == 'checkbox' && input.value == id) {
var tr = input.parentNode.parentNode;
walkTheDom(tr, function(node) {
if (node.nodeType == 3) {
var text = node.nodeValue;
var parent = node.parentNode;
var grandParent = parent.parentNode;
if (status && parent.tagName == 'B') {
grandParent.removeChild(parent);
var font = document.createElement('font');
font.size = 2;
font.color = 'black';
font.appendChild(document.createTextNode(text));
grandParent.appendChild(font);
} else if (!status && parent.tagName == 'FONT') {
grandParent.removeChild(parent);
var b = document.createElement('b');
b.appendChild(document.createTextNode(text));
grandParent.appendChild(b);
}
} else if (node.nodeType == 1 && node.tagName == 'IMG') {
if (status && node.src.match(UNREAD_IMG + '$')) {
node.src = READ_IMG;
} else if (!status && node.src.match(READ_IMG + '$')) {
node.src = UNREAD_IMG;
}
}
});
}
}
}
};
var errorFunc = function(res) {
alert('Change of read status failed, code: ' + res.status);
};
setProps(sXml, loadFunc, errorFunc);
}
}
function addMarkRead(row) {
addToolbarButton(toolbarTable, 'R', function() {
changeReadStatus(true);
});
}
function addMarkUnread(row) {
addToolbarButton(toolbarTable, 'U', function() {
changeReadStatus(false);
});
}
var toolbarTable = getToolbarTable();
if (toolbarTable) {
addSelectAll(toolbarTable);
addSelectNone(toolbarTable);
addMarkRead(toolbarTable);
addMarkUnread(toolbarTable);
}
// if this is the find names popup form let <enter> work as submit
var findNamesForm = getFindNamesForm();
if (findNamesForm) {
var inputs = document.getElementsByTagName('input');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
if (input.type == 'text') {
input.addEventListener('keypress', function(evt) {
if (evt.keyCode == 13) findNamesForm.submit();
}, true);
}
}
}
}
)();
view raw gistfile1.js hosted with ❤ by GitHub