[JS] Dynamic “Like” button on Cargo Collective Projects
I think you all know Cargo Collective. It’s a publishing platform for creative portfolios. It’s very sleek and comes with a lot of customization options. But one downside it’s that it still doesn’t have much third party apps compatibility.
To add a facebook “Like” button, you must go to the facebook page and set up a button for each project you have and then paste it on the project text. That’s a lot of trouble, right? So i build this JS script with a little help of my friend dennis calazans, who rock on JS coding
<script type="text/javascript">
function facebookLink()
{
var begin = 'http://www.facebook.com/plugins/like.php?href=';
var url = window.location.href;
var end = '%2F&layout=button_count&show-faces=false&width=100&action=like&colorscheme=light';
if(url.indexOf("#") > 0)
{
var inicio = url.substr(0,url.indexOf("#"));
var fim = url.substr(url.indexOf("#")+1,url.length);
url = inicio + fim;
}
var iframeCode = "<iframe src='"+begin+url+end+"' scrolling='no' frameborder='0' allowTransparency='true' style='vertical-align: middle; border:none; overflow:hidden; width:100px; height:21px; margin-left:10px; margin-bottom:2px'></iframe>";
var title = $("div.project_title")[0];
var tituloAtual = title.innerHTML;
title.innerHTML = tituloAtual + iframeCode;
}
</script>
As you can see, this is very pagmatic scripting, you JS gods can help me improve, but for now, it does the trick. To install the script, go to settings, HTML and CSS and edit the Custom HTML thing pasting the code in. Then, when you edit your project, simply paste this code on the end of the project description:
<script type="text/javascript">facebookLink()</script>
That should work ok. Please if your script doesn’t work, post here so we can try to work this out. I’m trying to create a more automatized version of this based on the link in the permalink button. Stay tuned for this
Also, notice that i added the button on the project title div so it would appear side by side with the project title. Feel free to change that. If you want the button to appear in the end of your project description, just use document.write
Hope you guys find that helpful. I’ll be back with more in no time :)
[AS3] Recursive Font Embeding
So, i’m sure that you had this problem before. You put a dynamic textfield on a MovieClip or Sprite and then set’s it to a variable coming from a XML file. Your client start using the website and complains to you that he cannot see the text in the right font on his computer, or some characters are missing.
Well….the truth is: the way Flash deals with font managing just suck! Normally, you’ll have to export the font’s characters. To do this follow these steps:
- On the Main Menu go to Text -> Font Embeding
- Click on the + thing and add a new font.
- Give a name to the font
- Select the font on the combobox, and select which group of characters to be exported.
Tip: Be sure to select only the characters you’ll actually use (it doesn’t make sense to export Japanese characters to a brazilian website, right?), because flash will export them on the SWF and this will increase filesize.
5. Go to the actionscript tab and select “Export for Actionscript”
Tip: This is actually optional, but if you are doing a lot of actionscript coding, it’s good to do this because you can use the font asset as an actionscript object and initialize with the new keyword and everything.
6. Select the Textfield you want that font for and type the name of the font you set on step 3. Notice that Flash will put an * after the font name. This is just to identify the font as a library asset.
Now there’s the trick. For every dynamic textfield you have, you must set TextField.embedFonts = true to it’s instance. This is a pain in the ass to do. I did some googling and found a cool code that seb ly implemented here. I’m reproducing the code below:
function recursiveEmbed(container : DisplayObjectContainer) : void
{
for(var i: int = 0; i < container.numChildren; i++)
{
var child : DisplayObject = container.getChildAt(i);
if(child is DisplayObjectContainer)
recursiveEmbed(child as DisplayObjectContainer);
else if (child is TextField)
TextField(child).embedFonts = true;
}
}
You can use it like this on your root movieclip or Document Class or whatever:
recursiveEmbed(this)This is nice. but, it kinda sucks having to do this to every DisplayObjectContainer, right? So, i created a new class, CustomDisplayObjectContainer so you don’t need to worry about doing it anymore.
package
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.text.TextField;
/**
* ...
* @author GUi
*/
public class CustomDisplayObjectContainer extends DisplayObjectContainer
{
super();
}
override public function addChild(p_target:DisplayObject):void
{
super.addChild(p_target);
recursiveEmbed(p_target);
}
protected function recursiveEmbed(container : DisplayObjectContainer) : void
{
for(var i: int = 0; i < container.numChildren; i++)
{
var child :DisplayObject = container.getChildAt(i);
if(child is DisplayObjectContainer) recursiveEmbed(child as DisplayObjectContainer);
else if (child is TextField) TextField(child).embedFonts = true;
}
}
}
So, let’s say that your document class extends this class..You’ll never have to deal with embed font issues again. Neat, huh?
Tip: Be sure to export all characters and all fonts before testing, or this script won’t work.
Also, check out the new Text Layout Framework video on AdobeTV to learn how to use the state of the art text in Flash.AS3 Library Linkage Class
So, you have a symbol on the library and you want to use it on your class files. You can sure use the new atribute and add to the Display List, but some of OOP Encapsulation will be lost, once the object is not on your packages but stored on the library. I personally like to use the undocumented function getDefinitionByName to get library symbols. The thing is, the implementation of getDefinitionByName always confuses me, and perhaps confuses you too, so i build a simple wrapper class to abstract this and return the library symbol with only one method. Enjoy.
package com.guinetik.kinetic.utils
{
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.utils.getDefinitionByName;
public class Linkage
{
public static function getLibrarySymbol(linkage:String):DisplayObject
{
var c :Class = getDefinitionByName(linkage) as Class;
var obj :DisplayObject = new c() as DisplayObject;
return obj;
}
public static function getLibraryImage(linkage:String):BitmapData
{
var c :Class = getDefinitionByName(linkage) as Class;
var obj :BitmapData = new c(0, 0) as BitmapData;
return obj;
}
public static function addToComponent():void
{
trace("Initialized Kinetic");
}
}
}AS3 RegExp Basics
Hi all. The idea behind this site is not really tutorials and stuff, but just be my repository of useful stuff that i create/find/improve. But i want to take this post and talk about Regular Expressions. Something that other programmers are very familiar with, but it’s kind of a new thing on actionscript. Recently i had to remove all html tags from a text before showing on my application. At first it seems like an easy task, but it’s not. It took me like 2 hours to get this script working:
public static function remove(base, piece:String):String
{
var res:String = base;
while(res.indexOf(piece)!=-1){
res = res.substr(0,res.indexOf(piece))+ res.substr(res.indexOf(piece) + piece.length);
}
return res;
}
public static function removeHTMLTags(str:String):String{
var start:int = str.indexOf("<");
var end:int = str.indexOf(">")+1;
if(start != -1 && end != -1){
var aux:String = remove(str,str.substring(start,end));
return extractText(aux);
}
return str;
}
As you can see i use a recursive function to remove parts of the text and when there’s no more tags to remove, i return the value. You can use Like this
var texto:String = "Some Text"; trace(StringUtils.extractText(texto)); // output: Some TextAt first glance, this works perfectly, but when you have a long text, the recursive function takes a lot of time to process and in some cases will crash the Flash Player. That’s because the loop runs along all the text, even the parts where there’s no html tags to be removed. That’s where the Regular Expressions come handy. You don’t have to use loops to change familiar or standardized portions of the text. With Regular Expressions, those areas are scanned on a low level basis, providing a much more effective solution. Here is the same code, using Regular Expressions:
public static function removeHTMLTags(text:String):String
{
return text.replace(/<\/?[^>]+>/igm, '');
}
Another thing that makes Regular Expressions very handy is on form validation. For instance, let’s take a look on this standard mail validation script:
private function mailValidation( text :String ) :Boolean
{
var pos :int = text.indexOf("@");
var p :int = text.indexOf(".", pos );
if ( pos = 1 && p < (pos+2) ) ) return false;
return true;
}
Looks good enough, but you notice there’s a lot of returns and it’s not a very elegant script. Check out how you can do it with Regular Expressions:
public static function validateEmail(email:String):Boolean
{
return Boolean(email.match(/^[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$/i;);
}
Se, a lot more elegant. Now, the dude from this site, wrote a preety good as2 class for Regular Expressions Validations. It’s a really cool class you can store your regExp on a xml file and provide a error description to it. I’m translating it to as3 and will post here as soon as i’m finished. Also, please check out Adobe’s as3 regExp documentation here.AS3 FullScreen Stage Resizer and Align Class
This is a simple utility class that resizes a DisplayObject to fill the stage area and align based on predefined positions such as top, top-left, top-right, bottom, bottom-left, bottom-right, center, center-left, center-right. There’s a lot of debate wheter or not to use private static on as3, i figured that if the class compiles with no errors, we are good to go.
package com.guinetik.kinetic.utils
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.display.Stage;
/**
* ...
* @author Gui
*/
public class DisplayObjectUtilsResizer
{
public static function resizeProp(align, obj:DisplayObject):void
{
if (obj.stage != null)
{
var sH:Number = obj.stage.stageHeight;
var sW:Number = obj.stage.stageWidth;
switch(align)
{
case "T": resizeTop(obj, sW, sH); break;
case "TL": resizeTopLeft(obj, sW, sH); break;
case "TR": resizeTopRight(obj, sW, sH); break;
case "C": resizeCenter(obj, sW, sH); break;
case "CL": resizeCenterLeft(obj, sW, sH); break;
case "CR": resizeCenterRight(obj, sW, sH); break;
case "B": resizeBottom(obj, sW, sH); break;
case "BL": resizeBottomLeft(obj, sW, sH); break;
case "BR": resizeBottomRight(obj, sW, sH); break;
}
} else throw new Error("the object is not on the stage");
}
static private function resizeBottomRight(obj:DisplayObject, sW:Number, sH:Number):void
{
obj.width = sW;
obj.scaleY = obj.scaleX;
if (obj.height < sH)
{
obj.height = sH;
obj.scaleX = obj.scaleY;
}
obj.x = int((obj.stage.stageWidth - obj.width));
obj.y = int((obj.stage.stageHeight - obj.height));
}
static private function resizeBottom(obj:DisplayObject, sW:Number, sH:Number):void
{
obj.width = sW;
obj.scaleY = obj.scaleX;
if (obj.height < sH)
{
obj.height = sH;
obj.scaleX = obj.scaleY;
}
obj.x = int((obj.stage.stageWidth - obj.width)/2);
obj.y = int((obj.stage.stageHeight - obj.height));
}
static private function resizeBottomLeft(obj:DisplayObject, sW:Number, sH:Number):void
{
obj.width = sW;
obj.scaleY = obj.scaleX;
if (obj.height < sH)
{
obj.height = sH;
obj.scaleX = obj.scaleY;
}
obj.x = 0;
obj.y = int((obj.stage.stageHeight - obj.height));
}
static private function resizeCenterRight(obj:DisplayObject, sW:Number, sH:Number):void
{
obj.width = sW;
obj.scaleY = obj.scaleX;
if (obj.height < sH)
{
obj.height = sH;
obj.scaleX = obj.scaleY;
}
obj.x = int((obj.stage.stageWidth - obj.width));
obj.y = int((obj.stage.stageHeight - obj.height) / 2);
}
static private function resizeCenter(obj:DisplayObject, sW:Number, sH:Number):void
{
obj.width = sW;
obj.scaleY = obj.scaleX;
if (obj.height < sH)
{
obj.height = sH;
obj.scaleX = obj.scaleY;
}
obj.x = int((obj.stage.stageWidth - obj.width) / 2);
obj.y = int((obj.stage.stageHeight - obj.height) / 2);
}
static private function resizeCenterLeft(obj:DisplayObject, sW:Number, sH:Number):void
{
obj.width = sW;
obj.scaleY = obj.scaleX;
if (obj.height < sH)
{
obj.height = sH;
obj.scaleX = obj.scaleY;
}
obj.x = 0;
obj.y = int((obj.stage.stageHeight - obj.height) / 2);
}
static private function resizeTopRight(obj:DisplayObject, sW:Number, sH:Number):void
{
obj.width = sW;
obj.scaleY = obj.scaleX;
if (obj.height < sH)
{
obj.height = sH;
obj.scaleX = obj.scaleY;
}
obj.x = int((obj.stage.stageWidth - obj.width));
obj.y = 0;
}
static private function resizeTop(obj:DisplayObject, sW:Number, sH:Number):void
{
obj.width = sW;
obj.scaleY = obj.scaleX;
if (obj.height < sH)
{
obj.height = sH;
obj.scaleX = obj.scaleY;
}
obj.x = int((obj.stage.stageWidth - obj.width) / 2);
obj.y = 0;
}
static private function resizeTopLeft(obj:DisplayObject, sW:Number, sH:Number):void
{
obj.width = sW;
obj.scaleY = obj.scaleX;
if (obj.height < sH)
{
obj.height = sH;
obj.scaleX = obj.scaleY;
}
}
}
}
You can apply to your code using a simple stage resize listener like this:
import com.guinetik.kinetic.utils.DisplayObjectUtilsResizer;
import flash.events.Event;
stage.align = "TL";
stage.scaleMode = "noScale";
stage.addEventListener(Event.RESIZE, onStageResize);
function onStageResize(e:Event):void
{
DisplayObjectUtilsResizer.resizeProp("TL", myImage);
}AS3 Pixel Precise Hit Testing
This is a simple utility function to detect pixel precise hit testing. Here i use the features of the BitmapData class to make a pixel perfect hitText
public static function hitTest(object:DisplayObject, point:Point):Boolean
{
if(object is BitmapData)
{
return (object as BitmapData).hitTest(new Point(0,0), 0, object.globalToLocal(point));
}
else
{
if(!object.hitTestPoint(point.x, point.y, true))
{
return false;
}
else
{
var bmapData:BitmapData = new BitmapData(object.width, object.height, true, 0x00000000);
bmapData.draw(object, new Matrix());
var returnVal:Boolean = bmapData.hitTest(new Point(0,0), 0, object.globalToLocal(point));
bmapData.dispose();
return returnVal;
}
}
}
You can implement on your code like this:
this.addEventListener(Event.Enter_FRAME, hitTesting);
private function hitTesting(e:Event):void
{
DisplayObjectUtils.hitTest(myTarget, new Point(this.mouseX, this.mouseY));
// DisplayObjectUtils is a class where i store all my display object related methods. you can create your own
} AS3 put itens on a grid
This is a simple utility function that grid the DisplayObjects together with a predefined horizontal and vertical spacing
public static function gridItens(itens:Array, numCols:int, spacingW:Number, spacingH:Number):void
{
for (var i:int = 0; i < itens.length; i++)
{
var item:DisplayObject = itens[i];
item.x = (i % numCols * spacingW);
item.y = Math.floor(i / numCols) * spacingH;
}
}
// usage
gridItens([mc1, mc2, mc3, mc4, mc5, mc6], 2, 10, 10);
This is a little Chrome Extension that i have been working on. It is build with Flex 4 + Java and you can see the traces from your flash movies directly on the browser. Handy, huh? Still tweaking a little and correcting some bugs, but i’ll release for public use soon enough.
Click the image to see it fullscreen
Using the Flash Player 10.1 Debugger Version on Chrome
Chrome is my favorite browser! I’m sure it’s yours too! So i installed the Flash CS5 and the Flash Builder 4, but somehow it screw up my debug player for chrome. All other browsers are still with the debug version of the player, but chrome is not. After checking some sites out, i found out that chrome keeps both plugins installed but priorizes the non debug version. The reason for this is unclear, but i think it’s because it would be the last one installed. Without further ado, you can change this by following these steps:
- Type about:plugins in the address bar
- If you have both plugins installed, you can see that Chrome lists them both so you have 2 Shockwave Flash Plugins.
- Disable the Adobe Flash Player (Shockwave player) plugin that points to a gcswf32.dll file
- Restart Chrome and you should be good to go
Wanderer Flying Sprites
This is a way to implement a wanderer flying animation to any display object. you can check out the demo on wonderfl below.
Flying Shapes - wonderfl build flash online
package
{
import flash.display.Sprite;
import flash.geom.Matrix;
public class FlashTest extends Sprite
{
public function FlashTest()
{
var matr:Matrix = new Matrix();
matr.createGradientBox(100, 100, 0, -50, -50);
for (var i:int = 0; i < 30; i++)
{
var squ:Square = new Square();
var c:Number = Math.random() * 0xFFFFFF;
squ.graphics.beginGradientFill("radial", [c, c+100], [1, 0], [0x00, 0xFF], matr);
squ.graphics.drawRect(-50, -50, 100, 100);
squ.graphics.endFill();
squ.maxW = squ.width;
squ.maxH = squ.height;
squ.offsetH = squ.offsetW = 60;
squ.growAmmount = Math.random();
squ.x = Math.random() * (stage.stageWidth - squ.width/2);
squ.y = Math.random() * (stage.stageHeight - squ.height/2);
squ.easing = Math.random()/10;
addChild(squ);
}
}
}
}
import flash.display.Sprite;
import flash.events.Event;
class Square extends Sprite
{
private var menor :Boolean = false;
private var posx :Number;
private var posy :Number;
private var targetX :Number;
private var targetY :Number;
private var vx :Number;
private var vy :Number;
public var changeDimensions :Boolean = true;
public var easing :Number = 0.01;
public var offsetW :Number = 10;
public var offsetH :Number = 10;
public var offsetX :Number = 10;
public var offsetY :Number = 10;
public var maxW :Number;
public var maxH :Number;
public var growAmmount :Number = 0.1;
public function Square()
{
this.addEventListener(Event.ADDED_TO_STAGE, startLoop);
this.addEventListener(Event.REMOVED_FROM_STAGE, clearLoop);
}
private function clearLoop(e:Event):void
{
removeEventListener(Event.REMOVED_FROM_STAGE, clearLoop);
this.removeEventListener(Event.ENTER_FRAME, float);
}
private function startLoop(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, startLoop);
this.targetX = this.x + offsetX;
this.targetY = this.y + offsetY;
this.vx = 0;
this.vy = 0;
this.addEventListener(Event.ENTER_FRAME, float);
}
public function float(e:Event):void
{
var ax:Number = (this.targetX - this.x) * Math.random()*this.easing;
var ay:Number = (this.targetY - this.y) * Math.random()*this.easing;
this.vx += ax/2;
this.vy += ay/2;
this.x += vx;
this.y += vy;
if (changeDimensions)
{
if ((this.width <= maxW || this.height <= maxH) && menor)
{
this.width +=growAmmount;
this.height +=growAmmount;
} else
{
menor = false;
this.width -= growAmmount;
this.height -= growAmmount;
if (this.width <= offsetW || this.height <= offsetH)
{
menor = true;
vx = vy = 0;
}
}
}
}
} 