PDA

View Full Version : Ext.ux.myTwitter - Twitter Client



casbar
11 Aug 2009, 1:52 AM
Hello,

this is my first Ext contribution...

FEATURES:
- Auto-Refresh option & manual refresh
- Set up of row quantity
- Groups (Public, Friends, User)
- New message field
- Char counter
- Clear option
- Login/Requirements check

REQUIREMENTS:
- PHP
- cURL

CODE:

/**
* Ext.ux.myTwitter - Twitter Client
*
* @author Caspar Baratella
* @version 1.0
*
* @license Ext.ux.myTwitter is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/

Ext.ns('Ext.ux');

var Lang =
{
Trm:
{
Username: 'Username',
Password: 'Password',
Login: 'Login',
Quantity: 'Quantity',
ShowLast: 'ShowLast',
Seconds: 'Seconds',
Minute: 'Minute',
Minutes: 'Minutes',
Edit: 'Edit',
NewMessage: 'New Message',
Post: 'Post',
Clear: 'Clear',
Exit: 'Exit'
},
Msg:
{
RequestError: 'Request failed! Please try Again!',
CurlNotInstalled: 'cURL ist not installed on your Server!',
LoginWrong: 'Login could be wrong! Please retry!'
}
};


Ext.override(Ext.Button, {
setIcon: function(url){
if (this.rendered){
var btnEl = this.getEl().child(this.buttonSelector);
btnEl.setStyle('background-image', 'url(' +url+')');
}
}
});

/**
* @class Ext.ux.myTwitter
* @extends Ext.Window
*/

Ext.ux.myTwitter=Ext.extend(Ext.Window,{

version: "1.0",
showImage: true,
showUsername: true,
showTime: true,
showLinks: true,
showQuantity: 10,
autoRefresh: false,
refreshSecs: 10,
group: 'friends',

initComponent: function()
{
this.renderTo = Ext.getBody();
this.height = 420;
this.width = 860;

this.title = 'myTwitter '+this.version,
this.maximizable = true;
this.collapsible = true;
this.layout = 'border',
this.iconCls = 'myTwitterWindow';



this.groupBtn = new Ext.Button({
text: 'Friends',
disabled: true,
icon: './apps/myTwitter/images/group16.png',
scope: this,
menu: [
{
xtype: 'menucheckitem',
text: 'Public',
group: 'group',
handler: function() {
this.groupBtn.setText('Public');
this.group = 'public';
this.storeReload();
},
scope: this
},{
xtype: 'menucheckitem',
text: 'Friends',
group: 'group',
checked: true,
handler: function() {
this.groupBtn.setText('Friends');
this.group = 'friends';
this.storeReload();
},
scope: this
},{
xtype: 'menucheckitem',
text: 'User',
group: 'group',
handler: function() {
this.groupBtn.setText('User');
this.group = 'user';
this.storeReload();
},
scope: this
}
]
});

this.showLastBtn = new Ext.Button({
text: Lang.Trm.Quantity,
disabled: true,
icon: './apps/myTwitter/images/showlast16.png',
scope: this,
menu: [
{
xtype: 'menucheckitem',
group: 'showLast',
text: Lang.Trm.ShowLast+' 3',
handler: function() {
this.showQuantity = 3;
this.storeReload();
},
scope: this
},{
xtype: 'menucheckitem',
group: 'showLast',
text: Lang.Trm.ShowLast+' 5',
handler: function() {
this.showQuantity = 5;
this.storeReload();
},
scope: this
},{
xtype: 'menucheckitem',
group: 'showLast',
checked: true,
text: Lang.Trm.ShowLast+' 10',
handler: function() {
this.showQuantity = 10;
this.storeReload();
},
scope: this
},{
xtype: 'menucheckitem',
group: 'showLast',
text: Lang.Trm.ShowLast+' 20',
handler: function() {
this.showQuantity = 20;
this.storeReload();
},
scope: this
}
]
});



this.autoRefreshBtn = new Ext.SplitButton({
disabled: true,
text: 'Auto Refresh',
icon: './apps/myTwitter/images/wireless-off16.png',
handler: this.changeAutoRefresh,
scope: this,
menu: [
{
xtype: 'menucheckitem',
group: 'autoRefresh',
text: '5 '+Lang.Trm.Seconds,
handler: function(cmp) {
this.refreshSecs = 5;
this.initTask();

},
scope: this
},{
xtype: 'menucheckitem',
group: 'autoRefresh',
checked: true,
text: '10 '+Lang.Trm.Seconds,
handler: function(cmp) {
this.refreshSecs = 10;
this.initTask();
},
scope: this
},{
xtype: 'menucheckitem',
group: 'autoRefresh',
text: '30 '+Lang.Trm.Seconds,
handler: function() {
this.refreshSecs = 30;
this.initTask();
},
scope: this
},{
xtype: 'menucheckitem',
group: 'autoRefresh',
text: '1 '+Lang.Trm.Minute,
handler: function() {
this.refreshSecs = 60;
this.initTask();
},
scope: this
},{
xtype: 'menucheckitem',
group: 'autoRefresh',
text: '5 '+Lang.Trm.Minutes,
handler: function() {
this.refreshSecs = 300;
this.initTask();
},
scope: this
},{
xtype: 'menucheckitem',
group: 'autoRefresh',
text: '10 '+Lang.Trm.Minutes,
handler: function() {
this.refreshSecs = 600;
this.initTask();
},
scope: this
}
]
});

this.myTBar = new Ext.Toolbar({
items:[
{
xtype: 'label',
text: Lang.Trm.Username+': ',
style: 'margin-left:5px;'
},{
xtype: 'textfield',
name: 'loginUser',
id: 'myTwitterUserField',
listeners: {
specialkey: function(field, ev){
if(ev.getKey() == ev.ENTER){
ev.preventDefault();
this.saveLogin();
}
},
scope:this

}
},{
xtype: 'label',
text: Lang.Trm.Password+': ',
style: 'margin-left:5px;'
},{
xtype: 'textfield',
name: 'loginPass',
inputType: 'password',
id: 'myTwitterPassField',
listeners: {
specialkey: function(field, ev){
if(ev.getKey() == ev.ENTER){
ev.preventDefault();
this.saveLogin();
}
},
scope:this

}
},"-",{
xtype: 'tbbutton',
text: Lang.Trm.Login,
icon: './apps/myTwitter/images/ok.png',
handler: this.saveLogin,
scope: this
},{
xtype: 'tbbutton',
text: Lang.Trm.Edit,
disabled: true,
icon: './apps/myTwitter/images/edit_user16.png',
handler: this.editLogin,
scope: this
},'-',
this.groupBtn,
this.showLastBtn,
this.autoRefreshBtn,
'->',{
xtype: 'tbbutton',
icon: './apps/myTwitter/images/refresh.png',
handler: function() { this.storeReload(); },
scope: this,
disabled: true
}]

});

this.tbar = this.myTBar;

this.twitterStore = new Ext.data.JsonStore({

url: './apps/myTwitter/php/twitterAction.php',
root: 'twitterRecords',
fields: ['userimage', 'username','time','text']

});



this.recordPanel = new Ext.grid.GridPanel({
region:'center',
store: this.twitterStore,
border: true,
loadMask: true,
disabled: true,
disableSelection:true,
columns: [

//{ id: 'userimage', header: "Image", width: 50, sortable: false, dataIndex: 'userimage' },
{id: 'userimage', header: 'Image', dataIndex: 'userimage', width: 60, resizable: false, sortable: false, renderer: function(v){
return '<img src="' + v + '" />';
}},
{ id:'username', css: 'color:grey; font-style: italic;padding-top:15px;', header: "Username", width: 90, sortable: true, dataIndex: 'username' },
{ id:'time', css: 'padding-top:15px;', header: "Time", width: 100, sortable: false, dataIndex: 'time' },
{ id:'text', css: 'padding-top:15px;', header: "Text", sortable: true, dataIndex: 'text' }


],
sm: null,
stripeRows: true,

autoExpandColumn: 'text'

});

this.newMessagePanel = new Ext.Panel({
region: 'south',
layout: 'border',
disabled: true,
border: false,
height: 50,
split: false, // enable resizing
margins: '5 5 5 5',
items: [{
region: 'center',
xtype: 'textarea',
name: 'messageField',
enableKeyEvents: true,
id: 'myTwitterInputArea',
listeners: {
keyup: {
fn: this.countChars,
scope: this
},

focus: {
fn: this.countChars,
scope: this
}
},
emptyText: Lang.Trm.NewMessage
//style: 'width:99%;',
},{
region: 'east',
width: 50,
xtype: 'label',
id: 'remainingChartsLabel',
border: false,
text: '140',
margins : '0 0 0 5',
cls: 'remainingCharQuantity'
}]
});

this.items = [this.recordPanel, this.newMessagePanel];

this.postBtn = new Ext.Button({
text: Lang.Trm.Post,
icon: './apps/myTwitter/images/ok.png',
handler: this.postTweet,
disabled: true,
scope:this
});

this.clearBtn = new Ext.Button({
text: Lang.Trm.Clear,
icon: './apps/myTwitter/images/clear16.png',
handler: this.clearInput,
disabled: true,
scope: this
});

this.exitBtn = new Ext.Button({
text: Lang.Trm.Exit,
icon: './apps/myTwitter/images/exit16.png',
handler: function() { this.close(); },
scope:this
});

this.buttons = [this.postBtn, this.clearBtn, this.exitBtn];



this.task = {
run: function(){
this.storeReload();
},
scope:this,
interval: (this.refreshSecs*1000)
};



// Requirements check

Ext.Ajax.request({
url: './apps/myTwitter/php/twitterAction.php',
params: {
action: 'checkRequirements'
},
success: function(response){
if(response.responseText == 0)
{
this.disable();
Ext.Msg.show({title: "Error", msg: Lang.Msg.CurlNotInstalled, buttons: Ext.Msg.OK, icon: Ext.Msg.ERROR });
}
},
failure: function(response){
Ext.Msg.show({title: "Error", msg: Lang.Msg.RequestError, buttons: Ext.Msg.OK, icon: Ext.Msg.ERROR });
},
scope:this
});


Ext.ux.myTwitter.superclass.initComponent.apply(this);
},
onRender: function(){
Ext.ux.myTwitter.superclass.onRender.apply(this, arguments);
},

editLogin: function()
{
this.twitterStore.removeAll();

this.myTBar.getComponent(1).enable();
this.myTBar.getComponent(3).enable();
this.myTBar.getComponent(5).enable();
this.myTBar.getComponent(6).disable();

this.myTBar.getComponent(8).disable();
this.myTBar.getComponent(9).disable();
this.myTBar.getComponent(10).disable();
this.myTBar.getComponent(12).disable();

this.getComponent(0).disable();
this.getComponent(1).disable();


this.postBtn.disable();
this.clearBtn.disable();

Ext.TaskMgr.stop(this.task);

},
saveLogin: function() {

this.myTBar.getComponent(1).disable();
this.myTBar.getComponent(3).disable();
this.myTBar.getComponent(5).disable();

Ext.Ajax.request({
url: './apps/myTwitter/php/twitterAction.php',
params: {
action: 'login',
'user': Ext.get('myTwitterUserField').getValue(),
'pass': Ext.get('myTwitterPassField').getValue(),
'group': this.group
},
success: function(response){
if(response.responseText == 1)
{

this.getComponent(0).enable();
this.getComponent(1).enable();

this.myTBar.getComponent(5).disable();
this.myTBar.getComponent(6).enable();

this.myTBar.getComponent(8).enable();
this.myTBar.getComponent(9).enable();
this.myTBar.getComponent(10).enable();
this.myTBar.getComponent(12).enable();

this.postBtn.enable();
this.clearBtn.enable();


this.storeReload();
}
else
{
Ext.Msg.show({title: "Error", msg: Lang.Msg.LoginWrong, buttons: Ext.Msg.OK, icon: Ext.Msg.ERROR });
this.myTBar.getComponent(1).enable();
this.myTBar.getComponent(3).enable();
this.myTBar.getComponent(5).enable();
}
},
failure: function(response){
return 0;
},
scope:this
});


},

storeReload: function()
{
this.twitterStore.load({params:{
'action': 'getTweets',
'user': Ext.get('myTwitterUserField').getValue(),
'pass': Ext.get('myTwitterPassField').getValue(),
'group': this.group,
'showQuantity': this.showQuantity
}});
},

postTweet: function()
{
this.postBtn.disable();
this.clearBtn.disable();
this.getComponent(1).disable();

Ext.Ajax.request({
url: './apps/myTwitter/php/twitterAction.php',
params: {
action: 'postTweet',
'user': Ext.get('myTwitterUserField').getValue(),
'pass': Ext.get('myTwitterPassField').getValue(),
'msg': Ext.get('myTwitterInputArea').getValue(),
'group': this.group
},
success: function(response){
if(response.responseText == 1)
{

this.getComponent(1).enable();
this.postBtn.enable();
this.clearBtn.enable();

this.getComponent(1).getComponent(0).reset();

this.storeReload();
}
else
{
Ext.Msg.show({title: "Error", msg: Lang.Msg.RequestError, buttons: Ext.Msg.OK, icon: Ext.Msg.ERROR });
this.myTBar.getComponent(1).enable();
this.myTBar.getComponent(3).enable();
this.myTBar.getComponent(5).enable();
}
},
failure: function(response){
return 0;
},
scope:this
});
},

initTask: function()
{
if(this.autoRefresh == true)
Ext.TaskMgr.stop(this.task);

this.task = {
run: function(){
this.storeReload();
},
scope:this,
interval: (this.refreshSecs*1000)
};

if(this.autoRefresh == true)
Ext.TaskMgr.start(this.task);



},
changeAutoRefresh: function()
{
if(this.autoRefresh == true)
{
this.autoRefreshBtn.setIcon('./apps/myTwitter/images/wireless-off16.png');
this.autoRefresh = false;
Ext.TaskMgr.stop(this.task);
}
else
{
this.autoRefreshBtn.setIcon('./apps/myTwitter/images/wireless-on16.png');
this.autoRefresh = true;

Ext.TaskMgr.start(this.task);
}
},

clearInput: function()
{
this.getComponent(1).getComponent(0).reset();
},

countChars: function(tf)
{
tf.setValue(tf.getValue().substring(0, 140));
Ext.getCmp('remainingChartsLabel').setText(140-parseInt(tf.getValue().length));

}
});SCREENSHOTS:
http://img35.imageshack.us/img35/8434/mytwitter.jpg
http://img21.imageshack.us/img21/8381/mytwitter2.jpg

DEMO:
http://www.casbarro.de/labs/myTwitter

DOWNLOAD:
http://www.casbarro.de/labs/myTwitter/myTwitter.zip

MrRoyce
27 Aug 2009, 11:43 AM
Hi there, I am trying your extension and ran into the following issue - the recordPanel display is shrunk to about 10px high.

Here is the image,

http://www.joomflix.com/desktop/tmp/twitterExtJs.jpg

and here is the application

http://www.joomflix.com/desktop

Arno.Nyhm
28 Aug 2009, 3:45 AM
REQUIREMENTS: - cURL you forgot php as requirement.

but: is it not possible to fetch the data direct from twitter?

MrRoyce
28 Aug 2009, 5:31 AM
I am using the PHP programs correctly - I can see all of the valid posts/responses in firebug. But the display is not showing up correctly.

I may be able to directly access the tweets, but why should I reinvent that process if this class does that and much more?

SOLVED: I had removed a 'border' parameter from the recordPanel. Put it back and all is well!