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

$().SPServices({
  operation:"GetRoleCollectionFromWeb",
  webURL:"http://mon.site.com/ma/collection/",
  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.

// @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 :

$().SPServices({
  operation:"AddPermission",
  webURL:"http://mon.site.com/ma/collection/",
  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 :

// @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",
  webURL:"http://mon.site.com/ma/collection/",
  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",
      webURL:"http://mon.site.com/ma/collection/",
      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):

* { 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 :

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();
// si on a http://blog.kodono.info/?foo=bar&gniii=ok#something alors :
params[0]; // -> 'foo'
params[1]; // -> 'gniii'
params["foo"]; // -> 'bar'
params["gniii"]; // -> 'ok'

Comment cropper / rogner / recadrer un film [Vidéo]

[niveau débutant]

J’ai dĂ©couvert qu’il Ă©tait très simple d’enlever des bouts du cadrage d’un film grâce Ă  AviDemux !

Il vous suffit d’ouvrir votre film avec AviDemux puis dans la colonne de gauche choisissez un format vidĂ©o de sortie. On prendra par exemple xvid et ensuite cliquez sur “Filtres” :
Copie d'écran des boutons

Parmi les filtres disponibles double cliquez sur “Crop”. A partir de lĂ  vous pouvez dĂ©finir la marge gauche, droite, haute et basse que vous voulez rogner :
FenĂŞtre de crop

Une fois terminĂ©, cliquez sur “Fermer”, puis dans la fenĂŞtre principale du logiciel, dans la colonne de gauche, sĂ©lectionner le format audio voulu (par exemple mp3), et ainsi que le format de sortie (avi).
Si jamais, au moment oĂą vous cliquez sur “Fermer” vous obtenez le message « Width is not a multiple of 8 » :
Message d'erreur
Pour rĂ©gler ce problème il faut revenir Ă  votre filtre “Crop”. Vous devez regarder la largeur de la vidĂ©o que vous allez produire :
Exemple de largeur de vidéo
Dans cet exemple on a 478, or ce n’est pas un multiple de 8 (car 478/8=59.75). Il suffit donc de modifier lĂ©gèrement la bordure droite ou gauche afin d’obtenir une taille multiple de huit. Si j’ai 480 alors ça sera bon (480/8=60).

Il ne vous reste plus qu’Ă  enregistrer votre film et le tour est jouĂ©.