Datepicker pour Bootstrap [Javascript]

Edit 5/04/2012 : d’autres personnes ont fait comme moi, et vous pouvez trouver leur repository sur https://github.com/eternicode/bootstrap-datepicker — ils ont corrigé les mêmes bugs visiblement et ont ajouté quelques petites choses comme le support i18n (internationalisation du format de la date)

J’ai découvert un datepicker qui utilise l’excellent Bootstrap de Twitter (vous savez c’est un ensemble de CSS qu’on peut utiliser pour des effets très réussis), et qui rend comme ça :

Je me suis empressé de l’utiliser dans un projet, jusqu’à ce que je me rende compte qu’il ne fonctionne pas avec Bootstrap v2.0.2, et ni avec IE7+ …. Du coup j’ai modifié le code d’origine pour outrepasser ces divers problèmes (plus d’autres petites choses). J’aurais proposé mon patch au créateur s’il utilisait GitHub, mais ce n’est pas le cas, donc j’ai créé un repository pour ce projet là : https://github.com/Aymkdn/Datepicker-for-Bootstrap

Il ressemble en tout point à la version d’origine, sauf qu’il fonctionne maintenant pour IE et pour la dernière version de Bootstrap. Il permet aussi d’avoir la date du jour comme date par défaut (au lieu du 1/1/1970 ….), et évite d’avoir une date sélectionnée automatiquement lorsqu’on ne fait que passer par le champ en utilisant la touche TAB.

Et bien sûr il y a la démo.

Public release of SharepointPlus — a JavaScript API for Sharepoint [announcement]

In my job I have to work with Sharepoint, but with no access to the back-end. I can only edit the HTML code, and hopefully I can use JavaScript. It’s really handy with the Sharepoint web services, even if they are not well-documented !

I found a couple of JS API on the Web, but there are not documented or not really easy to use. Then I developed my own API: SharepointPlus.

And today I announce the first public release of my framework available on GitHub: http://aymkdn.github.com/SharepointPlus/

Share the love 🙂

Changer le thème/skin de Pidgin [Astuce]

Pidgin est un logiciel qui permet de se connecter à MSN, GTalk, Facebook Chat, et bien d’autres protocoles.

J’ai eu quelques difficultés à trouver comment changer le thème de ce programme… Et à force de chercher je suis tombé sur la documentation (qui est très mal référencée) que je vous traduis ci-dessous :

Comment changer mon thème GTK+ ?

Depuis la version 2.7.0, Pidgin s’accompagne d’une version intégrée de GTK+ qui n’inclue pas de thèmes supplémentaires ou d’application pour en changer.

Pourtant il existe un moyen de le faire grâce à Alexander Shaduri. Remarque : il n’est pas recommandé d’utiliser l’installeur de GTK+ qu’il distribue, à moins que vous ne saviez ce que vous faites et que vous le fassiez pour de bonnes raisons.

Commencez par télécharger GTK2 Thèmes que vous allez extraire dans un dossier temporaire pour y récupérer les répertoires lib et share que vous allez ensuite placer dans <répertoire d'installation de Pidgin>\Gtk (ils existent déjà donc il faut les ajouter quand même).
Ensuite télécharger GTK2 Prefs que vous allez décompresser dans un dossier temporaire pour récupérer le fichier gtk2_prefs.exe qu’il faudra placer dans le répertoire <répertoire d'installation de Pidgin>\Gtk\bin.

Il ne vous reste plus qu’à exécuter gtk2_prefs.exe et de choisir le thème. Vous voudrez probablement choisir l’option “Apply for all users”, et vous devrez relancer Pidgin pour qu’il applique le nouveau thème.

URL dans un Workflow de Sharepoint [Astuce]

Avec les workflows de Sharepoint on peut faire un certain nombre de choses, comme envoyer des emails avec des liens.
Il existe trois variable dans la Current List à savoir :
Encoded Absolute Url : retourne une url du type http://votre.site.com/votre/rep/Lists/NomListe/2_.000 avec ‘2’ l’ID de l’item… donc pas très utile;
Server Relative Url : retourne /votre/rep/Lists/NomListe/2_.000 …. donc également pas très utile;
Path : retourne votre/rep/Lists/NomListe qui devient plus exploitable !

Ainsi vous allez pouvoir créer des liens dans vos emails de workflow qui redirige vers la liste courante grâce à Path et en y ajoutant ce qui va bien ! 🙂

Attention cependant, puisque Sharepoint gère incorrectement les espaces dans l’adresse URL, et le premier espace qu’il y aura sera tout simplement supprimé….

Permettre le retour en arrière sur une page PHP avec une session [programmation]

Si vous utilisez les sessions avec PHP et que vous avez un formulaire qui fait du POST, alors le retour en arrière (en utilisant le bouton du navigateur) risque de retourner une page blanche avec un message d’erreur du style “Le document a expiré”.

Après avoir fouillé la documentation PHP pour session_cache_limiter, j’ai découvert qu’il suffit d’ajouter session_cache_limiter('private_no_expire, must-revalidate'); au tout début du fichier, avant quoi que ce soit. Et maintenant le retour en arrière fonctionne !

Modifier les permissions d’une liste Sharepoint en utilisant permissions.aspx et JavaScript [Sharepoint]

Il est possible d’utiliser les web services de Sharepoint pour effectuer un certain nombre d’opérations. Il existe divers API (comme http://spservices.codeplex.com que j’utiliserai ici) pour aider dans ces opérations.

Cependant il est difficile de trouver de la documentation / exemples sur comment utiliser AddPermission, RemovePermission et UpdatePermissions. Après avoir longuement fouillé le Net, voici ce que j’ai trouvé.

Tout d’abord, pour assigner un rôle défini sur votre site (comme “Contribute”, “Full Control”, “Read”, etc) il va falloir trouver les droits associés. Pour cela on utilise GetRoleCollectionFromWeb

1
2
3
4
5
6
7
8
9
$().SPServices({
  operation:"GetRoleCollectionFromWeb",
  completefunc: function (xData, Status) {
    var roles=[]; // va contenir les différents rôles existants et les permissions associées
    var dom=xData.responseXML.getElementsByTagName("Role");
    for (var i=dom.length; i--;) roles[dom[i].getAttribute("Name")]=dom[i].getAttribute("BasePermissions").split(", ");
  }
});

Maintenant on va avoir un tableau associatif qui lie un rôle (par exemple “Contribute”) à un ensemble de permissions (ici ça sera “ViewListItems, AddListItems, EditListItems, DeleteListItems, OpenItems, ViewVersions, DeleteVersions, ManagePersonalViews, ViewFormPages, Open, ViewPages, CreateSSCSite, BrowseDirectories, BrowseUserInfo, AddDelPrivateWebParts, UpdatePersonalWebParts, UseClientIntegration, UseRemoteAPIs, CreateAlerts, EditMyUserInfo”).

Grâce à la documentation de Microsoft portant sur les masks de permissions on va créer un autre tableau associatif pour chacune de ces BasePermissions.
Aussi on sait qu’il faut faire un OR entre chaque mask pour avoir celui qu’on souhaite.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// @param basePermissions est un tableau
function getPermissionMask(basePermissions) {
  // on crée un tableau basé sur la doc Microsoft
  var permissions=[];
  // on rajoute "FullMask" qui est le Full Control
  permissions["FullMask"] = -1;
  permissions["ViewListItems"] = parseInt("0x0000000000000001");
  permissions["AddListItems"] = parseInt("0x0000000000000002");
  permissions["EditListItems"] = parseInt("0x0000000000000004");
  permissions["DeleteListItems"] = parseInt("0x0000000000000008");
  permissions["ApproveItems"] = parseInt("0x0000000000000010");
  permissions["OpenItems"] = parseInt("0x0000000000000020");
  permissions["ViewVersions"] = parseInt("0x0000000000000040");
  permissions["DeleteVersions"] = parseInt("0x0000000000000080");
  permissions["CancelCheckout"] = parseInt("0x0000000000000100");
  permissions["ManagePersonalViews"] = parseInt("0x0000000000000200");
  permissions["ManageLists"] = parseInt("0x0000000000000800");
  permissions["ViewFormPages"] = parseInt("0x0000000000001000");
  permissions["Open"] = parseInt("0x0000000000010000");
  permissions["ViewPages"] = parseInt("0x0000000000020000");
  permissions["AddAndCustomizePages"] = parseInt("0x0000000000040000");
  permissions["ApplyThemeAndBorder"] = parseInt("0x0000000000080000");
  permissions["ApplyStyleSheets"] = parseInt("0x0000000000100000");
  permissions["ViewUsageData"] = parseInt("0x0000000000200000");
  permissions["CreateSSCSite"] = parseInt("0x0000000000400000");
  permissions["ManageSubwebs"] = parseInt("0x0000000000800000");
  permissions["CreateGroups"] = parseInt("0x0000000001000000");
  permissions["ManagePermissions"] = parseInt("0x0000000002000000");
  permissions["BrowseDirectories"] = parseInt("0x0000000004000000");
  permissions["BrowseUserInfo"] = parseInt("0x0000000008000000");
  permissions["AddDelPrivateWebParts"] = parseInt("0x0000000010000000");
  permissions["UpdatePersonalWebParts"] = parseInt("0x0000000020000000");
  permissions["ManageWeb"] = parseInt("0x0000000040000000");
  permissions["UseClientIntegration"] = parseInt("0x0000001000000000");
  permissions["UseRemoteAPIs"] = parseInt("0x0000002000000000");
  permissions["ManageAlerts"] = parseInt("0x0000004000000000");
  permissions["CreateAlerts"] = parseInt("0x0000008000000000");
  permissions["EditMyUserInfo"] = parseInt("0x0000010000000000");
 
  //maintenant on va faire des OR selon basePermissions
  var mask = 1;
  for (var i=basePermissions.length; i--;) mask |= permissions[basePermissions[i]];
  return mask;
}

Et enfin on utilise ce mask avec AddPermission :

1
2
3
4
5
6
7
8
9
10
$().SPServices({
  operation:"AddPermission",
  objectName:"Nom de la Liste",
  objectType:"List",
  permissionIdentifier:"domain\\login", // par exemple "europe\\john_doe"
  permissionType:"user", // car c'est un username qu'on a donné... si on avait donné un Sharepoint Group alors on aurait mis "group"
  permissionMask:getPermissionMask(roles["Contribute"]),
  completefunc: function (xData, Status) { alert("Permissions ajoutés"); }
});

Plus d’infos sur les arguments disponibles dans la documentation de SPServices sur les Permissions.

On peut enfin tout mettre ensemble, ce qui donnera :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// @param basePermissions est un tableau
function getPermissionMask(basePermissions) {
  // on crée un tableau basé sur la doc Microsoft
  var permissions=[];
  // on rajoute "FullMask" qui est le Full Control
  permissions["FullMask"] = -1;
  permissions["ViewListItems"] = parseInt("0x0000000000000001");
  permissions["AddListItems"] = parseInt("0x0000000000000002");
  permissions["EditListItems"] = parseInt("0x0000000000000004");
  permissions["DeleteListItems"] = parseInt("0x0000000000000008");
  permissions["ApproveItems"] = parseInt("0x0000000000000010");
  permissions["OpenItems"] = parseInt("0x0000000000000020");
  permissions["ViewVersions"] = parseInt("0x0000000000000040");
  permissions["DeleteVersions"] = parseInt("0x0000000000000080");
  permissions["CancelCheckout"] = parseInt("0x0000000000000100");
  permissions["ManagePersonalViews"] = parseInt("0x0000000000000200");
  permissions["ManageLists"] = parseInt("0x0000000000000800");
  permissions["ViewFormPages"] = parseInt("0x0000000000001000");
  permissions["Open"] = parseInt("0x0000000000010000");
  permissions["ViewPages"] = parseInt("0x0000000000020000");
  permissions["AddAndCustomizePages"] = parseInt("0x0000000000040000");
  permissions["ApplyThemeAndBorder"] = parseInt("0x0000000000080000");
  permissions["ApplyStyleSheets"] = parseInt("0x0000000000100000");
  permissions["ViewUsageData"] = parseInt("0x0000000000200000");
  permissions["CreateSSCSite"] = parseInt("0x0000000000400000");
  permissions["ManageSubwebs"] = parseInt("0x0000000000800000");
  permissions["CreateGroups"] = parseInt("0x0000000001000000");
  permissions["ManagePermissions"] = parseInt("0x0000000002000000");
  permissions["BrowseDirectories"] = parseInt("0x0000000004000000");
  permissions["BrowseUserInfo"] = parseInt("0x0000000008000000");
  permissions["AddDelPrivateWebParts"] = parseInt("0x0000000010000000");
  permissions["UpdatePersonalWebParts"] = parseInt("0x0000000020000000");
  permissions["ManageWeb"] = parseInt("0x0000000040000000");
  permissions["UseClientIntegration"] = parseInt("0x0000001000000000");
  permissions["UseRemoteAPIs"] = parseInt("0x0000002000000000");
  permissions["ManageAlerts"] = parseInt("0x0000004000000000");
  permissions["CreateAlerts"] = parseInt("0x0000008000000000");
  permissions["EditMyUserInfo"] = parseInt("0x0000010000000000");
 
  //maintenant on va faire des OR selon basePermissions
  var mask = 1;
  for (var i=basePermissions.length; i--;) mask |= permissions[basePermissions[i]];
  return mask;
}
 
$().SPServices({
  operation:"GetRoleCollectionFromWeb",
  completefunc: function (xData, Status) {
    var roles=[]; // va contenir les différents rôles existants et les permissions associées
    var dom=xData.responseXML.getElementsByTagName("Role");
    for (var i=dom.length; i--;) roles[dom[i].getAttribute("Name")]=dom[i].getAttribute("BasePermissions").split(", ");
    $().SPServices({
      operation:"AddPermission",
      objectName:"Nom de la Liste",
      objectType:"List",
      permissionIdentifier:"domain\\login", // par exemple "europe\\john_doe"
      permissionType:"user", // car c'est un username qu'on a donné... si on avait donné un Sharepoint Group alors on aurait mis "group"
      permissionMask:getPermissionMask(roles["Contribute"]),
      completefunc: function (xData, Status) { alert("Permissions ajoutés"); }
    });
  }
});

A noter :
UpdatePermission va remplacer les permissions d’une personne;
– Toute personnalisation des permissions sur la liste va entrainer l’arrêt des droits inhérents (avec Sharepoint 2010 il sera possible de remettre les droits parents grâce à How to: Break Role Assignment Inheritance Using ECMAScript)

CSS3 PIE pour créer un border-radius sur IE [webdesign]

Si vous cherchez à faire un border-radius sur un vieux IE vous avez dû vous rendre compte que cela ne fonctionne pas… mais heureusement il existe CSS3 PIE qui est un “petit” fichier qui va permettre de créer l’effet désiré !

A noter cependant que je rencontre un problème : lorsque j’applique le fichier htc avec behavior alors j’ai ma couleur de fond (background-color) qui devient invisible / disparait. Ce problème peut-être résolu en appliquant la règle CSS suivante (solution trouvée sur leur forum):

1
* { position:relative }

Grâce à ça tout fonctionne sous IE 🙂

Transformer/convertir une vidéo vers le format mp4 et ogg (ogv) gratuitement [vidéo]

Il existe une extension pour Firefox qui permet de convertir tout type de vidéo (avi, wmv, mp4, etc) dans le format HTML5 Ogg ou WebM. Il s’agit de http://firefogg.org/.
Vous aurez besoin de Firefox 4 au moins. Cliquez sur le bouton rouge “Install Firefogg”. Vous devrez redémarrer votre Firefox, puis retournez sur http://firefogg.org/. Cette fois cliquez sur “Make web video” et suivez les instructions !

Trouver les paramètres dans une url en javascript [programmation]

[niveau débutant]

Voici une fonction courte pour récupérer l’ensemble des paramètres passés dans l’URL :

1
2
3
4
5
6
7
8
function getUrlVars(a,b,c,d){b=[];if(a=location.search.split('#')[0].match(/\?(.*)(#.*)?/)){d=a[1].split('&');for(i=d.length;i--;){c=d[i].split('=');b[i]=c[0];b]=decodeURIComponent(c[1]).replace(/\+/g," ")}}return b}
 
var params=getUrlVars();
params[0]; // -> 'foo'
params[1]; // -> 'gniii'
params["foo"]; // -> 'bar'
params["gniii"]; // -> 'ok'