Skip to content

Instantly share code, notes, and snippets.

@Studira
Last active April 29, 2019 13:29
Show Gist options
  • Save Studira/5354e2548a6e121d6dd1 to your computer and use it in GitHub Desktop.
Save Studira/5354e2548a6e121d6dd1 to your computer and use it in GitHub Desktop.
Facebook Profile Pictures - Flag Over

Facebook Profile Pictures - Flag Over

This pen aims to let the user upload their facebook profile picture then overlay their country's flag and a hashtag before saving it back to your desktop.

Inspired by Facebook's facility to do this during the Paris Attacks.

A Pen by Ian Joubert on CodePen.

License.

<div class="md-body-1" ng-app="app" ng-controller="appCtrl as ctrl">
<div id="header">
<img src="https://dl.dropboxusercontent.com/u/106021493/paris-image.jpg" />
<div layout="column" layout-padding layout-align="center center">
<span class="md-display-1">Change your Propic</span>
<span>Show support for <strong>#Paris Attacks</strong> and use this to <i>overlay your propic</i> with the French flag (or your own country) and add a #tag of support.</span>
</div>
</div>
<div ng-cloak>
<md-tabs md-dynamic-height md-align-tabs="bottom" md-center-tabs="true">
<md-tab label="Home">
<md-content id="center" layout="row" layout-padding>
<span flex="15"></span>
<div layout="column" ng-if="!ctrl.loaded" flex>
<img src="https://dl.dropboxusercontent.com/u/106021493/paris-propic.jpg" />
<div id="hashtag">
<form name="tagForm">
<md-input-container>
<label>#tag</label>
<input name="hashtag" ng-model="ctrl.hashtag" md-maxlength="16">
<div ng-messages="tagForm.hashtag.$error">
<div ng-message="md-maxlength">Maximum of 16 characters</div>
</div>
</md-input-container>
</form>
</div>
<span class="md-title" layout-padding>Upload your Facebook profile picture</span>
<div id="drop-zone">
<div ng-file-drop ng-file-select ng-file-change="ctrl.dropBox(file)" ng-model="file" drag-over-class="{accept:'dragover', reject:'dragover-err', delay:200}" class="drop-box" ng-multiple="false" allow-dir="true" ng-accept="'image/*'" layout="column">
<span layout-padding>Drop IMAGE file or click to select</span>
</div>
</div>
</div>
<div id="result" layout="column" layout-align="center center" ng-if="ctrl.loaded" flex="grow">
<div propic layout="row" layout-padding loaded="ctrl.loaded" hashtag="ctrl.hashtag" flag="ctrl.flag" imgblob="ctrl.imgblob"></div>
<div layout="row" layout-align="center center">
<md-button class="md-raised" ng-click="ctrl.saveImgblob()"><span class="md-subhead">Save your new profile picture</span></md-button>
<md-button class="md-raised" ng-click="ctrl.loaded=null"><span class="md-subhead">Clear</span></md-button>
</div>
</div>
<span flex="15" flex></span>
</md-content>
</md-tab>
<md-tab label="Flags">
<md-content id="flags" layout="column" layout-padding layout-fill>
<md-list-item class="md-2-line" flex>
<img ng-src="{{ctrl.flag.url}}" class="md-avatar" />
<div layout="column" class="md-list-item-text">
<span class="md-title">Current selection:<psan>
</span>{{ctrl.flag.title}}</span>
</div>
</md-list-item>
<div layout="row" layout-wrap>
<div ng-repeat="flag in ctrl.flags">
<div layout="column" layout-align="center center" class="flag">
<img ng-src="{{flag.url}}" />
<md-button ng-click="ctrl.setFlag(flag)">{{flag.title}}</md-button>
</div>
</div>
</div>
</md-content>
</md-tab>
</md-tabs>
</div>
<div id="footer" layout="row" layout-align="center center" layout-padding>
<span>Support the French colours or choose your own country's flag.</span>
</div>
</div>

Removing Characters from String in Array

This pen use a custom function to remove any character at any position in a string that is within a string array.

Params: stringArray, charArray, posArray

A Pen by Ian Joubert on CodePen.

License.

(function() {
'use strict';
// --------------------------------------------------------------------------------
// GLOBALS - Global variables and functions
// --------------------------------------------------------------------------------
var _ = window._;
var app = angular.module('app', [ 'ngAnimate','ngAria','ngMessages','ngMaterial','angularFileUpload' ]);
var Promise = window.Promise;
// --------------------------------------------------------------------------------
// CONTROLLER - Application controller
// --------------------------------------------------------------------------------
function buildFlagsGrid( template,flags ){
var tile;
return _.map( flags,function (flag){
tile = _.merge( {},template );
tile.url = tile.url + flag + '.' + tile.type;
tile.title = flag.replace('_',' ');
return tile;
});
}
app.controller('appCtrl', ['$scope', function ($scope){
var scope = this;
var reader = new FileReader();
var flags = ['Afghanistan','Albania','Algeria','Andorra','Angola','Antigua','Argentina','Armenia','Australia','Malawi','Austria','Malaysia','Azerbaijan','Maldives','Bahamas','Mali','Bahrain','Malta','Bangladesh','Mauritania','Barbados','Mauritius','Belarus','Mexico','Belgium','Moldova','Belize','Monaco','Benin','Mongolia','Bermuda','Montenegro','Bhutan','Morocco','Bolivia','Mozambique','Bosnia_and_Herzegovina','Myanmar','Botswana','Namibia','Brazil','Nauru','Brunei','Nepal','Bulgaria','Netherlands','Burkina_Faso','New_Caledonia','Burundi','New_Zealand','Cambodia','Nicaragua','Cameroon','Niger','Canada','Nigeria','Cape_Verde','North_Korea','Cayman_Islands','Norway','Central_African_Republic','Oman','Chad','Pakistan','Chile','Palau','China','Palestine','Colombia','Panama','Comoros','Papua_New_Guinea','Cook_Islands','Paraguay','Costa_Rica','Peru','Croatia','Philippines','Cuba','Poland','Cyprus','Portugal','Czech_Republic','Puerto_Rico','Democratic_Republic_of_the_Congo','Qatar','Denmark','Republic_of_the_Congo','Djibouti','Romania','Dominica','Russia','Dominican_Republic','Rwanda','East_Timor','Saint_Kitts_and_Nevis','Ecuador','Saint_Lucia','Egypt','Saint_Vincent_and_the_Grenadines','El_Salvador','Samoa','England','San_Marino','Equatorial_Guinea','Sao_Tome_and_Principe','Eritrea','Saudi_Arabia','Estonia','Scotland','Ethiopia','Senegal','Fiji','Serbia','Finland','Seychelles','France','Sierra_Leone','Gabon','Singapore','Georgia','Slovakia','Germany','Slovenia','Ghana','Solomon_Islands','Greece','Somalia','Greenland','South_Africa','Grenada','South_Korea','Guam','South_Sudan','Guatemala','Spain','Guinea-Bissau','Sri_Lanka','Guinea','Sudan','Guyana','Suriname','Haiti','Swaziland','Honduras','Sweden','Hong_Kong','Switzerland','Hungary','Syria','Iceland','Taiwan','India','Tajikistan','Indonesia','Tanzania','Iran','Thailand','Iraq','Togo','Ireland','Tonga','Israel','Trinidad_and_Tobago','Italy','Tunisia','Ivorycoast','Turkey','Jamaica','Turkmenistan','Japan','Tuvalu','Jordan','Uganda','Kazakhstan','Ukraine','Kenya','United_Arab_Emirates','Kiribati','United_Kingdom','Kuwait','United_States','Kyrgyzstan','Uruguay','Laos','Uzbekistan','Latvia','Vanuatu','Lebanon','Venezuela','Lesotho','Vietnam','Liberia','Wales','Libya','Yemen','Liechtenstein','Zambia','Lithuania','Zimbabwe','Luxembourg','Macedonia','Gambia','Madagascar']
var tileTemplate = {
url : 'https://dl.dropboxusercontent.com/u/106021493/',
type: 'jpg'
};
scope.imgblob = {};
scope.file = {};
scope.flags = buildFlagsGrid(tileTemplate, _.sortBy(flags) );
scope.flag = scope.flags[0];
scope.dropBox = function(dropped) {
dropped = dropped[0];
reader.onload = function(event){
dropped.src = event.target.result;
scope.loaded = dropped;
$scope.$apply();
};
reader.readAsDataURL(dropped);
};
scope.setFlag = function(flag){
scope.flag = flag;
};
scope.saveImgblob = function(){
saveAs(scope.imgblob, "facebook-profile-picture");
};
}]);
// --------------------------------------------------------------------------------
// DIRECTIVES - Application canvas directive
// --------------------------------------------------------------------------------
app.directive('propic',[function (){
var template = '<div id="propics" layout="row" layout-wrap><img width="230" height="230" />' +
'<div flex></div><canvas width="230" height="230"></canvas></div>';
// --------------------------------------------------------------------------------
// DIRECTIVE LINK
// --------------------------------------------------------------------------------
function link( scope,element,attrs ){
var propic = element.find('img')[0];
var canvas = element.find('canvas')[0];
var ctx = canvas.getContext('2d');
var img1 = new Image();
function drawImageScaled(img){
var ratio = Math.min( canvas.width / img.width, canvas.height / img.height );
var centerX = ( canvas.width - img.width*ratio ) / 2;
var centerY = ( canvas.height - img.height*ratio ) / 2;
ctx.clearRect( 0,0,
canvas.width,
canvas.height
);
ctx.drawImage( img,0,0,
img.width,img.height,
centerX, centerY,
img.width*ratio, img.height*ratio
);
}
function drawImageStretched(img){
ctx.globalAlpha = 0.4;
ctx.drawImage( img,0,0,
canvas.width,canvas.height
);
}
function drawHashtag(text){
if(text){
var gradient = ctx.createLinearGradient( 0,0,canvas.width,0 );
gradient.addColorStop("0", "rgba(255,255,255,0.9)");
gradient.addColorStop("0.5", "rgba(255,255,255,1)");
gradient.addColorStop("1.0", "rgba(255,255,255,0.9)");
ctx.globalAlpha = 1;
ctx.font = "bold 16px Century Gothic";
ctx.fillStyle = gradient;
ctx.textAlign = "center";
ctx.fillText('#' + text,( canvas.width / 2 ),( canvas.height - 16 ) );
}
}
function convertDataUrlToFile(dataurl){
var array = _.reduce( atob( dataurl.split(',')[1] ),
function( result,item,key,array ){
result.push( array.charCodeAt(key) );
return result;
},[]);
var blob = new Blob([ new Uint8Array(array)],{ 'type':'image/jpg' });
blob.src = window.URL.createObjectURL(blob);
return blob;
}
// --------------------------------------------------------------------------------
// DIRECTIVE EVENTS - Event listeners
// --------------------------------------------------------------------------------
window.addEventListener('resize',function(){
scope.$apply();
});
img1.addEventListener('load',function(){
var img2 = new Image();
img2.addEventListener('load',function(){
drawImageScaled(img1);
drawImageStretched(img2);
drawHashtag(scope.hashtag);
scope.imgblob = convertDataUrlToFile( canvas.toDataURL() );
scope.$apply();
});
img2.setAttribute('crossOrigin', 'anonymous');
img2.src = scope.flag.url;
});
// --------------------------------------------------------------------------------
// DIRECTIVE SCOPE - Isolated scope
// --------------------------------------------------------------------------------
scope.$watch('loaded',function(loaded){
if( !_.isEmpty(loaded.src) ){
propic.src = loaded.src;
img1.setAttribute('crossOrigin', 'anonymous');
img1.src = loaded.src;
}
});
}
return ({
'restrict':'A',
'template':template,
'scope':{
'loaded':'=',
'hashtag': '=',
'flag': '=',
'imgblob': '='
},
'replace':true,
'link':link,
});
}]);
}());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react-with-addons.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react-dom.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.0.5/bluebird.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.1/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/0.11.4/angular-material.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.1/angular-animate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.1/angular-aria.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.1/angular-messages.js"></script>
<script src="https://cdn.rawgit.com/Studira/mediawiki-js/master/MediawikiJS.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/danialfarid-angular-file-upload/3.0.7/angular-file-upload-all.min.js"></script>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.15.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.0/papaparse.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.js"></script>
body {
box-sizing: border-box;
}
img {
width: 100%;
display: block
}
.md-body-1 {
font-size: 1rem;
}
.md-title {
color: rgba(0, 0, 0, 0.4)
}
md-grid-list md-grid-tile md-grid-tile-header, md-grid-list md-grid-tile md-grid-tile-footer {
height:auto;
}
md-tabs-canvas{
background: rgba(0, 0, 0, 0.2);
}
md-tabs > md-tabs-wrapper > md-tabs-canvas > md-pagination-wrapper > md-tab-item:not([disabled]) {
color: rgba(156,0,0,1);
}
md-tabs > md-tabs-wrapper > md-tabs-canvas > md-pagination-wrapper > md-tab-item:hover {
color: rgba(0, 18, 155, 1);
}
md-tabs > md-tabs-wrapper > md-tabs-canvas > md-pagination-wrapper > md-tab-item:not([disabled]).md-active {
color: rgba(0, 18, 155, 1);
}
md-list-item.md-2-line {
padding: 0;
margin: 0 auto;
}
.md-1-line{
margin: 24px 0;
}
md-list-item > .md-avatar{
margin-right: 8px;
width:60px;
height:60px;
}
.layout-padding,
.layout-padding > .flex,
.layout-padding > .flex-gt-sm,
.layout-padding > .flex-md,
.layout-padding > .flex-lt-lg {
padding: 24px;
}
#header {
background: rgba(0, 0, 0, 0.2);
}
#header span {
text-align: center;
}
#center span {
text-align: center;
}
#center md-input-container{
padding:16px 0;
}
#center #drop-zone > span:first-child {
padding-bottom: 24px;
}
#center .drop-box {
box-sizing: border-box;
background: rgba(0, 0, 0, 0.1);
border-radius:24px;
border: 8px dotted rgba(0, 18, 155, 1);
color: rgba(0, 0, 0, 0.20);
margin: 0;
width: 100%;
h5 {
margin: 0;
}
}
#center .dragover {
border: 8px dotted rgba(0, 0, 0, 0.60);
;
}
#center .dragover-err {
border: 8px dotted rgba(156, 0, 0, 1);
}
#center #propics img{
width:initial;
}
#center #propics img, #propics canvas{
min-height:0;
min-width:0;
}
#center .md-char-counter{
color: rgba(0, 0, 0, 0.40);
}
#result .md-raised{
color:rgba(0, 18, 155, 1);
text-align:center;
text-transform:none;
font-size:1.4em;
border-radius:16px;
padding:8px 16px;
}
#flags .flag{
max-width:150px;
margin:4px;
background: rgba(0, 0, 0, 0.1);
overflow:hidden;
}
#flags .flag img{
height:100px;
}
#flags .md-button:hover{
color:rgba(0, 18, 155, 1);
}
#flags .md-button{
color:rgba(0, 0, 0, 0.6);
padding:4px;
margin:0;
min-height:24px;
line-height:1;
}
#footer {
background: rgba(0, 0, 0, 0.2);
}
#footer span {
text-align: center;
}
/*
#tab-content-1 .layout-row{
border:15px solid rgba(0,127,127,1);
}
#tab-content-1 .layout-column{
border:15px solid rgba(127,127,0,1);
}
.layout-column{
border:15px solid rgba(127,127,0,1);
}
.layout-row{
border:15px solid rgba(0,127,127,1);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/0.11.4/angular-material.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment