@ -0,0 +1,295 @@ | |||
<html lang="en"> | |||
<head> | |||
<title>Clouds</title> | |||
<meta charset="utf-8"> | |||
<style type="text/css"> | |||
*{ | |||
box-sizing: border-box; | |||
margin: 0; | |||
padding: 0 | |||
} | |||
body { | |||
color: #eee; | |||
text-shadow: 0 -1px 0 rgba( 0, 0, 0, .6 ); | |||
font-family: 'Open Sans', sans-serif; | |||
font-size: 13px; | |||
line-height: 16px; | |||
overflow: hidden; | |||
} | |||
#viewport { | |||
-webkit-perspective: 1000; | |||
-moz-perspective: 1000px; | |||
-o-perspective: 1000; | |||
perspective: 1000px; | |||
position: absolute; | |||
left: 0; | |||
top: 0; | |||
right: 0; | |||
bottom: 0; | |||
overflow: hidden; | |||
background-image: url('http://www.incoplast-srl.com/SiteAssets/Cielo-despejado-1363594685_18.jpg'); | |||
background-size: cover; | |||
/*background-image: linear-gradient(bottom, rgb(69,132,180) 28%, rgb(31,71,120) 64%); | |||
background-image: -o-linear-gradient(bottom, rgb(69,132,180) 28%, rgb(31,71,120) 64%); | |||
background-image: -moz-linear-gradient(bottom, rgb(69,132,180) 28%, rgb(31,71,120) 64%); | |||
background-image: -webkit-linear-gradient(bottom, rgb(69,132,180) 28%, rgb(31,71,120) 64%); | |||
background-image: -ms-linear-gradient(bottom, rgb(69,132,180) 28%, rgb(31,71,120) 64%); | |||
background-image: -webkit-gradient( | |||
linear, | |||
left bottom, | |||
left top, | |||
color-stop(0.28, rgb(69,132,180)), | |||
color-stop(0.64, rgb(31,71,120)) | |||
);*/ | |||
} | |||
#world { | |||
position: absolute; | |||
left: 50%; | |||
top: 50%; | |||
margin-left: -256px; | |||
margin-top: -256px; | |||
height: 512px; | |||
width: 512px; | |||
-webkit-transform-style: preserve-3d; | |||
-moz-transform-style: preserve-3d; | |||
-o-transform-style: preserve-3d; | |||
transform-style: preserve-3d; | |||
pointer-events: none; | |||
} | |||
#world div { | |||
-webkit-transform-style: preserve-3d; | |||
-moz-transform-style: preserve-3d; | |||
-o-transform-style: preserve-3d; | |||
transform-style: preserve-3d; | |||
} | |||
.cloudBase { | |||
position: absolute; | |||
left: 256px; | |||
top: 256px; | |||
width: 20px; | |||
height: 20px; | |||
margin-left: -10px; | |||
margin-top: -10px; | |||
} | |||
.cloudLayer { | |||
position: absolute; | |||
left: 50%; | |||
top: 50%; | |||
width: 256px; | |||
height: 256px; | |||
margin-left: -128px; | |||
margin-top: -128px; | |||
-webkit-transition: opacity .5s ease-out; | |||
-moz-transition: opacity .5s ease-out; | |||
-o-transition: opacity .5s ease-out; | |||
transition: opacity .5s ease-out; | |||
} | |||
</style> | |||
<script src="https://code.jquery.com/jquery-1.11.3.js"></script> | |||
<script type="text/javascript"> | |||
$( document ).ready(function() { | |||
/* | |||
Defining our variables | |||
world and viewport are DOM elements, | |||
worldXAngle and worldYAngle are floats that hold the world rotations, | |||
d is an int that defines the distance of the world from the camera | |||
*/ | |||
var world = document.getElementById( 'world' ), | |||
viewport = document.getElementById( 'viewport' ), | |||
worldXAngle = 0, | |||
worldYAngle = 0, | |||
d = 0; | |||
/* | |||
Event listener to transform mouse position into angles | |||
from -180 to 180 degress, both vertically and horizontally | |||
*/ | |||
window.addEventListener( 'mousemove', function( e ) { | |||
worldYAngle = -( .5 - ( e.clientX / window.innerWidth ) ) * 360; | |||
worldXAngle = ( .5 - ( e.clientY / window.innerHeight ) ) * 360; | |||
updateView(); | |||
} ); | |||
/* | |||
Changes the transform property of world to be | |||
translated in the Z axis by d pixels, | |||
rotated in the X axis by worldXAngle degrees and | |||
rotated in the Y axis by worldYAngle degrees. | |||
*/ | |||
function updateView() { | |||
world.style.transform = 'translateZ( ' + d + 'px ) \ | |||
rotateX( ' + worldXAngle + 'deg) \ | |||
rotateY( ' + worldYAngle + 'deg)'; | |||
} | |||
/* | |||
objects is an array of cloud bases | |||
layers is an array of cloud layers | |||
*/ | |||
var objects = [], | |||
layers = []; | |||
textures = [ | |||
{ name: 'white cloud', file: 'cloud.png' , opacity: 1, weight: 0 }, | |||
{ name: 'dark cloud', file: 'darkCloud.png' , opacity: 1, weight: 0 }, | |||
{ name: 'smoke cloud', file: 'smoke.png' , opacity: 1, weight: 0 }, | |||
{ name: 'explosion', file: 'explosion.png' , opacity: 1, weight: 0 }, | |||
{ name: 'explosion 2', file: 'explosion2.png' , opacity: 1, weight: 0 }, | |||
{ name: 'box', file: 'box.png' , opacity: 1, weight: 0 } | |||
]; | |||
/* | |||
Clears the DOM of previous clouds bases | |||
and generates a new set of cloud bases | |||
*/ | |||
function generate() { | |||
objects = []; | |||
if ( world.hasChildNodes() ) { | |||
while ( world.childNodes.length >= 1 ) { | |||
world.removeChild( world.firstChild ); | |||
} | |||
} | |||
computedWeights = []; | |||
var total = 0; | |||
for( var j = 0; j < textures.length; j++ ) { | |||
if( textures[ j ].weight > 0 ) { | |||
total += textures[ j ].weight; | |||
} | |||
} | |||
var accum = 0; | |||
for( var j = 0; j < textures.length; j++ ) { | |||
if( textures[ j ].weight > 0 ) { | |||
var w = textures[ j ].weight / total; | |||
computedWeights.push( { | |||
src: textures[ j ].file, | |||
min: accum, | |||
max: accum + w | |||
} ); | |||
accum += w; | |||
} | |||
} | |||
for( var j = 0; j < 100; j++ ) { | |||
objects.push( createCloud() ); | |||
} | |||
} | |||
/* | |||
Creates a single cloud base and adds several cloud layers. | |||
Each cloud layer has random position ( x, y, z ), rotation (a) | |||
and rotation speed (s). layers[] keeps track of those divs. | |||
*/ | |||
function createCloud() { | |||
var div = document.createElement( 'div' ); | |||
div.className = 'cloudBase'; | |||
var x = 256 - ( Math.random() * 1512 ); | |||
var y = 256 - ( Math.random() * 1512 ); | |||
var z = 256 - ( Math.random() * 1512 ); | |||
var t = 'translateX( ' + x + 'px ) translateY( ' + y + 'px ) translateZ( ' + z + 'px )'; | |||
div.style.webkitTransform = | |||
div.style.MozTransform = | |||
div.style.oTransform = | |||
div.style.transform = t; | |||
world.appendChild( div ); | |||
for( var j = 0; j < 5 + Math.round( Math.random() * 10 ); j++ ) { | |||
var cloud = document.createElement( 'img' ); | |||
cloud.style.opacity = 1; | |||
var r = Math.random(); | |||
var src = 'cloud10.png'; | |||
cloud.setAttribute( 'src', src ); | |||
cloud.className = 'cloudLayer'; | |||
var x = 256 - ( Math.random() * 1512 ); | |||
var y = 256 - ( Math.random() * 1512 ); | |||
var z = 100 - ( Math.random() * 1200 ); | |||
var a = Math.random() * 360; | |||
var s = .25 + Math.random(); | |||
x *= .2; y *= .2; | |||
cloud.data = { | |||
x: x, | |||
y: y, | |||
z: z, | |||
a: a, | |||
s: s, | |||
speed: .1 * Math.random(), | |||
r: Math.random() | |||
}; | |||
var t = 'translateX( ' + x + 'px ) translateY( ' + y + 'px ) translateZ( ' + z + 'px ) rotateZ( ' + a + 'deg ) scale( ' + s + ' )'; | |||
cloud.style.webkitTransform = | |||
cloud.style.MozTransform = | |||
cloud.style.oTransform = | |||
cloud.style.transform = t; | |||
div.appendChild( cloud ); | |||
layers.push( cloud ); | |||
} | |||
return div; | |||
} | |||
generate(); | |||
function update (){ | |||
for( var j = 0; j < layers.length; j++ ) { | |||
var layer = layers[ j ]; | |||
if(Math.random() >= layer.data.r){ | |||
layer.data.a += layer.data.speed; | |||
}else{ | |||
layer.data.a -= layer.data.speed; | |||
} | |||
if(Math.random() >= layer.data.r){ | |||
layer.data.x += layer.data.speed; | |||
}else{ | |||
layer.data.x -= layer.data.speed; | |||
} | |||
if(Math.random() >= layer.data.r){ | |||
layer.data.y += layer.data.speed; | |||
}else{ | |||
layer.data.y -= layer.data.speed; | |||
} | |||
var t = 'translateX( ' + layer.data.x + 'px ) translateY( ' + layer.data.y + 'px ) translateZ( ' + layer.data.z + 'px ) rotateY( ' + ( - worldYAngle ) + 'deg ) rotateX( ' + ( - worldXAngle ) + 'deg ) rotateZ( ' + layer.data.a + 'deg ) scale( ' + layer.data.s + ')'; | |||
layer.style.webkitTransform = | |||
layer.style.MozTransform = | |||
layer.style.oTransform = | |||
layer.style.transform = t; | |||
//layer.style.webkitFilter = 'blur(5px)'; | |||
} | |||
requestAnimationFrame( update ); | |||
} | |||
update(); | |||
}); | |||
</script> | |||
</head> | |||
<body> | |||
<div id="viewport" > | |||
<div id="world" ></div> | |||
</div> | |||
</body> | |||
</html> |
@ -0,0 +1,30 @@ | |||
,-----.,--. ,--. ,---. ,--.,------. ,------. | |||
' .--./| | ,---. ,--.,--. ,-| || o \ | || .-. \ | .---' | |||
| | | || .-. || || |' .-. |`..' | | || | \ :| `--, | |||
' '--'\| |' '-' '' '' '\ `-' | .' / | || '--' /| `---. | |||
`-----'`--' `---' `----' `---' `--' `--'`-------' `------' | |||
----------------------------------------------------------------- | |||
Hi there! Welcome to Cloud9 IDE! | |||
To get you started, we have created a small hello world application. | |||
1) Open the hello-world.php file | |||
2) Follow the run instructions in the file's comments | |||
3) If you want to look at the Apache logs, check out ~/lib/apache2/log | |||
And that's all there is to it! Just have fun. Go ahead and edit the code, | |||
or add new files. It's all up to you! | |||
Happy coding! | |||
The Cloud9 IDE team | |||
## Support & Documentation | |||
Visit http://docs.c9.io for support, or to learn more about using Cloud9 IDE. | |||
To watch some training videos, visit http://www.youtube.com/user/c9ide |
@ -0,0 +1,111 @@ | |||
<!DOCTYPE html> | |||
<html ng-app="myApp"> | |||
<head> | |||
<style type="text/css"> | |||
body{ | |||
margin: 8px; | |||
background: gray; | |||
cursor: none; | |||
} | |||
div.pixel{ | |||
position: absolute; | |||
width: 8px; | |||
height: 8px; | |||
} | |||
div.pixel:hover{ | |||
opacity: .5; | |||
} | |||
</style> | |||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script> | |||
<script type="text/javascript"> | |||
/*var size = 8; | |||
var pixels= []; | |||
var max = { x: 100, y: 80}; | |||
var click = false; | |||
for(var i = 1; i<max.x; i++){ | |||
for(var j = 1; j<max.y; j++){ | |||
pixels.push({position:{x: i, y: j}, color: 'blue'}); | |||
} | |||
} | |||
function createPixel(pixel){ | |||
var div = $(document.createElement("div")); | |||
function painter(color) { | |||
if(click){ | |||
div.css({ | |||
background: color | |||
}); | |||
} | |||
} | |||
div.html = "Text."; | |||
div.css({ | |||
left: pixel.position.x * size, | |||
top: pixel.position.y * size, | |||
background: pixel.color, | |||
width: size, | |||
height: size | |||
}); | |||
div.addClass('pixel'); | |||
div.mouseover(painter(div, 'black')); | |||
$("body").append(div); | |||
} | |||
$( document ).ready(function() { | |||
$.each( pixels, function( key, pixel ){ | |||
createPixel(pixel); | |||
}); | |||
$("body").mousedown(function() { | |||
click = true; | |||
}).mouseup(function() { | |||
click = false; | |||
}); | |||
});*/ | |||
var app = angular.module("myApp", []); | |||
app.controller("myCtrl", function($scope) { | |||
$scope.size = 8; | |||
$scope.pixels= []; | |||
$scope.click = false; | |||
var max = { x: 50, y: 50}; | |||
var id = 1; | |||
for(var i = 1; i<max.y; i++){ | |||
for(var j = 1; j<max.x; j++){ | |||
$scope.pixels.push({id: id,position:{x: j, y: i}, color: 'blue'}); | |||
id++; | |||
} | |||
} | |||
$scope.painter = function(pixel){ | |||
if($scope.click){ | |||
pixel.color = 'black'; | |||
} | |||
}; | |||
}); | |||
</script> | |||
</head> | |||
<body ng-controller="myCtrl" ng-mousedown="click = true" ng-mouseup="click = false"> | |||
<div ng-repeat="pixel in pixels" | |||
class="pixel" | |||
ng-mouseover="painter(pixel)" | |||
style=" | |||
left: {{pixel.position.x * size}}px; | |||
top: {{pixel.position.y * size}}px; | |||
background: {{pixel.color}}; | |||
width: {{size}}px; | |||
height: {{size}}px;" | |||
> | |||
</div> | |||
</body> | |||
</html> |
@ -0,0 +1,150 @@ | |||
<!DOCTYPE html> | |||
<html ng-app="myApp"> | |||
<head> | |||
<style type="text/css"> | |||
body{ | |||
margin: 8px; | |||
background: gray; | |||
} | |||
#menu{ | |||
width: 100px; | |||
margin-top: 28px; | |||
text-align: center; | |||
} | |||
#board{ | |||
cursor: crosshair; | |||
} | |||
div.pixel{ | |||
position: absolute; | |||
width: 8px; | |||
height: 8px; | |||
} | |||
div.pixel:hover{ | |||
opacity: .5; | |||
} | |||
</style> | |||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script> | |||
<script src="js/filesaver.js"></script> | |||
<script type="text/javascript"> | |||
var decodeBase64 = function(s) { | |||
var e={},i,b=0,c,x,l=0,a,r='',w=String.fromCharCode,L=s.length; | |||
var A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |||
for(i=0;i<64;i++){e[A.charAt(i)]=i;} | |||
for(x=0;x<L;x++){ | |||
c=e[s.charAt(x)];b=(b<<6)+c;l+=6; | |||
while(l>=8){((a=(b>>>(l-=8))&0xff)||(x<(L-2)))&&(r+=w(a));} | |||
} | |||
return r; | |||
}; | |||
var app = angular.module("myApp", []); | |||
app.directive('appFilereader', function($q) { | |||
var slice = Array.prototype.slice; | |||
return { | |||
restrict: 'A', | |||
require: '?ngModel', | |||
link: function(scope, element, attrs, ngModel) { | |||
if (!ngModel) return; | |||
ngModel.$render = function() {}; | |||
element.bind('change', function(e) { | |||
var element = e.target; | |||
$q.all(slice.call(element.files, 0).map(readFile)) | |||
.then(function(values) { | |||
if (element.multiple) ngModel.$setViewValue(values); | |||
else ngModel.$setViewValue(values.length ? values[0] : null); | |||
}); | |||
function readFile(file) { | |||
var deferred = $q.defer(); | |||
var reader = new FileReader(); | |||
reader.onload = function(e) { | |||
deferred.resolve(e.target.result); | |||
}; | |||
reader.onerror = function(e) { | |||
deferred.reject(e); | |||
}; | |||
reader.readAsDataURL(file); | |||
return deferred.promise; | |||
} | |||
}); //change | |||
} //link | |||
}; //return | |||
}) | |||
app.controller("myCtrl", function($scope) { | |||
$scope.size = 4; | |||
$scope.pixels= []; | |||
$scope.click = false; | |||
$scope.color = "#000" | |||
var max = { x: 100, y: 100}; | |||
var id = 1; | |||
for(var i = 1; i<max.y; i++){ | |||
for(var j = 1; j<max.x; j++){ | |||
$scope.pixels.push({id: id,position:{x: j, y: i}, color: '#fff'}); | |||
id++; | |||
} | |||
} | |||
$scope.painter = function(pixel){ | |||
if($scope.click){ | |||
pixel.color = $scope.color; | |||
} | |||
}; | |||
$scope.export = function(){ | |||
var text = JSON.stringify($scope.pixels); | |||
var element = document.createElement('a'); | |||
element.setAttribute('href', 'data:json/plain;charset=utf-8,' + encodeURIComponent(text)); | |||
element.setAttribute('download', 'painter.jgf'); | |||
element.style.display = 'none'; | |||
document.body.appendChild(element); | |||
element.click(); | |||
document.body.removeChild(element); | |||
}; | |||
$scope.import = function(file){ | |||
$scope.pixels = angular.fromJson(decodeBase64(file.split(',')[1])); | |||
}; | |||
}); | |||
</script> | |||
</head> | |||
<body ng-controller="myCtrl"> | |||
<div id="menu"> | |||
<input type="color" ng-model="color"/> | |||
<button ng-click="export()"> | |||
Exportar | |||
</button> | |||
<input type="file" ng-model="file" accept=".jgf" app-filereader ng-change="import(file)"/> | |||
</div> | |||
<div id="board" ng-mousedown="click = true;" ng-mouseup="click = false"> | |||
<div ng-repeat="pixel in pixels" | |||
ng-mouseover="painter(pixel)" | |||
class="pixel" | |||
style=" | |||
left: {{(pixel.position.x * size) + 120 }}px; | |||
top: {{(pixel.position.y * size) + 20}}px; | |||
background: {{pixel.color}}; | |||
width: {{size}}px; | |||
height: {{size}}px;" | |||
> | |||
</div> | |||
</div> | |||
</body> | |||
</html> |
@ -0,0 +1,176 @@ | |||
<!DOCTYPE html> | |||
<html ng-app="myApp"> | |||
<head> | |||
<style type="text/css"> | |||
body{ | |||
margin: 8px; | |||
background: gray; | |||
} | |||
#menu{ | |||
width: 100px; | |||
margin-top: 28px; | |||
text-align: center; | |||
} | |||
#board{ | |||
cursor: crosshair; | |||
border: 1px solid black; | |||
background: white; | |||
} | |||
div.pixel{ | |||
position: absolute; | |||
width: 8px; | |||
height: 8px; | |||
} | |||
div.pixel:hover{ | |||
opacity: .5; | |||
} | |||
</style> | |||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script> | |||
<script src="js/filesaver.js"></script> | |||
<script type="text/javascript"> | |||
var decodeBase64 = function(s) { | |||
var e={},i,b=0,c,x,l=0,a,r='',w=String.fromCharCode,L=s.length; | |||
var A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |||
for(i=0;i<64;i++){e[A.charAt(i)]=i;} | |||
for(x=0;x<L;x++){ | |||
c=e[s.charAt(x)];b=(b<<6)+c;l+=6; | |||
while(l>=8){((a=(b>>>(l-=8))&0xff)||(x<(L-2)))&&(r+=w(a));} | |||
} | |||
return r; | |||
}; | |||
var app = angular.module("myApp", []); | |||
app.directive('appFilereader', function($q) { | |||
var slice = Array.prototype.slice; | |||
return { | |||
restrict: 'A', | |||
require: '?ngModel', | |||
link: function(scope, element, attrs, ngModel) { | |||
if (!ngModel) return; | |||
ngModel.$render = function() {}; | |||
element.bind('change', function(e) { | |||
var element = e.target; | |||
$q.all(slice.call(element.files, 0).map(readFile)) | |||
.then(function(values) { | |||
if (element.multiple) ngModel.$setViewValue(values); | |||
else ngModel.$setViewValue(values.length ? values[0] : null); | |||
}); | |||
function readFile(file) { | |||
var deferred = $q.defer(); | |||
var reader = new FileReader(); | |||
reader.onload = function(e) { | |||
deferred.resolve(e.target.result); | |||
}; | |||
reader.onerror = function(e) { | |||
deferred.reject(e); | |||
}; | |||
reader.readAsDataURL(file); | |||
return deferred.promise; | |||
} | |||
}); //change | |||
} //link | |||
}; //return | |||
}) | |||
app.controller("myCtrl", function($scope,$interval) { | |||
$scope.size = 1; | |||
$scope.pixels= []; | |||
$scope.click = false; | |||
$scope.color = "#000"; | |||
$scope.mouse = { | |||
x: 0, | |||
y: 0 | |||
} | |||
var board = document.getElementById("board"); | |||
$(board).css({width:'200px', height:'200px'}); | |||
var ctx = board.getContext("2d"); | |||
var max = { x: board.width, y: board.height}; | |||
var id = 1; | |||
for(var i = 0; i<max.y; i++){ | |||
for(var j = 0; j<max.x; j++){ | |||
$scope.pixels.push({id: id,position:{x: j, y: i}, color: '#fff'}); | |||
id++; | |||
} | |||
} | |||
var painter = { | |||
draw: function(pixel) { | |||
if (board.getContext) { | |||
angular.forEach($scope.pixels, function(value, key) { | |||
ctx.fillStyle = pixel.color; | |||
ctx.fillRect(pixel.position.x, pixel.position.y, $scope.size, $scope.size); | |||
}); | |||
} | |||
}, | |||
update: function(){ | |||
angular.forEach($scope.pixels, function(value, key) { | |||
value.color = 'black'; | |||
console.log(22); | |||
}); | |||
}, | |||
clear: function() { | |||
if (board.getContext) { | |||
ctx.clearRect(0,0, board.width, board.height); | |||
} | |||
} | |||
}; | |||
/* $interval(function(){ | |||
angular.forEach($scope.pixels, function(value, key) { | |||
squareDrawer.clear(); | |||
squareDrawer.draw(value); | |||
}); | |||
}, 1000);*/ | |||
board.onmousedown = function(e) { | |||
painter.update(); | |||
painter.draw(); | |||
} | |||
board.onmousemove = function(e) { | |||
var rect = this.getBoundingClientRect(); | |||
$scope.mouse = { | |||
x : e.clientX - rect.left, | |||
y : e.clientY - rect.top | |||
} | |||
//ctx.clearRect(0, 0, board.width, board.height); // for demo | |||
/* | |||
while(r = $scope.pixels[i++]) { | |||
// add a single rect to path: | |||
ctx.beginPath(); | |||
ctx.rect(r.position.x, r.position.y, $scope.size, $scope.size); | |||
// check if we hover it, fill red, if not fill it blue | |||
ctx.fillStyle = ctx.isPointInPath(x, y) ? "red" : "blue"; | |||
ctx.fill(); | |||
} | |||
*/ | |||
}; | |||
}); | |||
</script> | |||
</head> | |||
<body ng-controller="myCtrl"> | |||
<canvas id="board"></canvas> | |||
</body> | |||
</html> |
@ -0,0 +1,25 @@ | |||
<!DOCTYPE html> | |||
<html ng-app="myApp"> | |||
<head> | |||
<style type="text/css"> | |||
</style> | |||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script> | |||
<script src="js/filesaver.js"></script> | |||
<script type="text/javascript"> | |||
var app = angular.module("myApp", []); | |||
app.controller("myCtrl", function($scope) { | |||
$scope.cm = []; | |||
for(var i = 0; i < 100; i++){ | |||
$scope.cm.push(i); | |||
} | |||
}); | |||
</script> | |||
</head> | |||
<body ng-controller="myCtrl"> | |||
<div ng-repeat="i in cm" > | |||
<img src="http://trafico.sevilla.org/camaras/cam{{i}}.jpg"/> | |||
</div> | |||
</body> | |||
</html> |
@ -0,0 +1,11 @@ | |||
<html><body> | |||
<?php | |||
// A simple web site in Cloud9 that runs through Apache | |||
// Press the 'Run' button on the top to start the web server, | |||
// then click the URL that is emitted to the Output tab of the console | |||
echo 'Hello world from Cloud9!'; | |||
?> | |||
</body> | |||
</html> |
@ -0,0 +1,45 @@ | |||
<html> | |||
<head> | |||
<script type="text/javascript"> | |||
var gl; // Un variable global para el contexto WebGL | |||
function start() { | |||
var canvas = document.getElementById("glcanvas"); | |||
gl = initWebGL(canvas); // Inicializar el contexto GL | |||
// Solo continuar si WebGL esta disponible y trabajando | |||
if (gl) { | |||
gl.clearColor(0.0, 0.0, 0.0, 1.0); // Establecer el color base en negro, totalmente opaco | |||
gl.enable(gl.DEPTH_TEST); // Habilitar prueba de profundidad | |||
gl.depthFunc(gl.LEQUAL); // Objetos cercanos opacan objetos lejanos | |||
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT); // Limpiar el buffer de color asi como el de profundidad | |||
} | |||
} | |||
function initWebGL(canvas) { | |||
gl = null; | |||
try { | |||
// Tratar de tomar el contexto estandar. Si falla, retornar al experimental. | |||
gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); | |||
} | |||
catch(e) {} | |||
// Si no tenemos ningun contexto GL, date por vencido ahora | |||
if (!gl) { | |||
alert("Imposible inicializar WebGL. Tu navegador puede no soportarlo."); | |||
gl = null; | |||
} | |||
return gl; | |||
} | |||
</script> | |||
</head> | |||
<body onload="start()"> | |||
<canvas id="glcanvas" width="640" height="480"> | |||
Tu navegador parece no soportar el elemento HTML5 <code><canvas></code>. | |||
</canvas> | |||
</body> | |||
</html> |
@ -0,0 +1,60 @@ | |||
/** | |||
* @author alteredq / http://alteredqualia.com/ | |||
* @author mr.doob / http://mrdoob.com/ | |||
*/ | |||
Detector = { | |||
canvas : !! window.CanvasRenderingContext2D, | |||
webgl : ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(), | |||
workers : !! window.Worker, | |||
fileapi : window.File && window.FileReader && window.FileList && window.Blob, | |||
getWebGLErrorMessage : function () { | |||
var domElement = document.createElement( 'div' ); | |||
domElement.style.fontFamily = 'monospace'; | |||
domElement.style.fontSize = '13px'; | |||
domElement.style.textAlign = 'center'; | |||
domElement.style.background = '#eee'; | |||
domElement.style.color = '#000'; | |||
domElement.style.padding = '1em'; | |||
domElement.style.width = '475px'; | |||
domElement.style.margin = '5em auto 0'; | |||
if ( ! this.webgl ) { | |||
domElement.innerHTML = window.WebGLRenderingContext ? [ | |||
'Sorry, your graphics card doesn\'t support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation">WebGL</a>' | |||
].join( '\n' ) : [ | |||
'Sorry, your browser doesn\'t support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation">WebGL</a><br/>', | |||
'Please try with', | |||
'<a href="http://www.google.com/chrome">Chrome 10</a>, ', | |||
'<a href="http://www.mozilla.com/en-US/firefox/all-beta.html">Firefox 4</a> or', | |||
'<a href="http://nightly.webkit.org/">Safari 6</a>' | |||
].join( '\n' ); | |||
} | |||
return domElement; | |||
}, | |||
addGetWebGLMessage : function ( parameters ) { | |||
var parent, id, domElement; | |||
parameters = parameters || {}; | |||
parent = parameters.parent !== undefined ? parameters.parent : document.body; | |||
id = parameters.id !== undefined ? parameters.id : 'oldie'; | |||
domElement = Detector.getWebGLErrorMessage(); | |||
domElement.id = id; | |||
parent.appendChild( domElement ); | |||
} | |||
}; |
@ -0,0 +1 @@ | |||
var saveAs=saveAs||function(e){"use strict";if("undefined"==typeof navigator||!/MSIE [1-9]\./.test(navigator.userAgent)){var t=e.document,n=function(){return e.URL||e.webkitURL||e},o=t.createElementNS("http://www.w3.org/1999/xhtml","a"),r="download"in o,i=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},a=/Version\/[\d\.]+.*Safari/.test(navigator.userAgent),c=e.webkitRequestFileSystem,f=e.requestFileSystem||c||e.mozRequestFileSystem,u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},d="application/octet-stream",s=0,l=4e4,v=function(e){var t=function(){"string"==typeof e?n().revokeObjectURL(e):e.remove()};setTimeout(t,l)},p=function(e,t,n){t=[].concat(t);for(var o=t.length;o--;){var r=e["on"+t[o]];if("function"==typeof r)try{r.call(e,n||e)}catch(i){u(i)}}},w=function(e){return/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob(["\ufeff",e],{type:e.type}):e},y=function(t,u,l){l||(t=w(t));var y,m,S,h=this,R=t.type,O=!1,g=function(){p(h,"writestart progress write writeend".split(" "))},b=function(){if(m&&a&&"undefined"!=typeof FileReader){var o=new FileReader;return o.onloadend=function(){var e=o.result;m.location.href="data:attachment/file"+e.slice(e.search(/[,;]/)),h.readyState=h.DONE,g()},o.readAsDataURL(t),void(h.readyState=h.INIT)}if((O||!y)&&(y=n().createObjectURL(t)),m)m.location.href=y;else{var r=e.open(y,"_blank");void 0===r&&a&&(e.location.href=y)}h.readyState=h.DONE,g(),v(y)},E=function(e){return function(){return h.readyState!==h.DONE?e.apply(this,arguments):void 0}},N={create:!0,exclusive:!1};return h.readyState=h.INIT,u||(u="download"),r?(y=n().createObjectURL(t),void setTimeout(function(){o.href=y,o.download=u,i(o),g(),v(y),h.readyState=h.DONE})):(e.chrome&&R&&R!==d&&(S=t.slice||t.webkitSlice,t=S.call(t,0,t.size,d),O=!0),c&&"download"!==u&&(u+=".download"),(R===d||c)&&(m=e),f?(s+=t.size,void f(e.TEMPORARY,s,E(function(e){e.root.getDirectory("saved",N,E(function(e){var n=function(){e.getFile(u,N,E(function(e){e.createWriter(E(function(n){n.onwriteend=function(t){m.location.href=e.toURL(),h.readyState=h.DONE,p(h,"writeend",t),v(e)},n.onerror=function(){var e=n.error;e.code!==e.ABORT_ERR&&b()},"writestart progress write abort".split(" ").forEach(function(e){n["on"+e]=h["on"+e]}),n.write(t),h.abort=function(){n.abort(),h.readyState=h.DONE},h.readyState=h.WRITING}),b)}),b)};e.getFile(u,{create:!1},E(function(e){e.remove(),n()}),E(function(e){e.code===e.NOT_FOUND_ERR?n():b()}))}),b)}),b)):void b())},m=y.prototype,S=function(e,t,n){return new y(e,t,n)};return"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob?function(e,t,n){return n||(e=w(e)),navigator.msSaveOrOpenBlob(e,t||"download")}:(m.abort=function(){var e=this;e.readyState=e.DONE,p(e,"abort")},m.readyState=m.INIT=0,m.WRITING=1,m.DONE=2,m.error=m.onwritestart=m.onprogress=m.onwrite=m.onabort=m.onerror=m.onwriteend=null,S)}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content);"undefined"!=typeof module&&module.exports?module.exports.saveAs=saveAs:"undefined"!=typeof define&&null!==define&&null!==define.amd&&define([],function(){return saveAs}); |
@ -0,0 +1,216 @@ | |||
<html lang="en"><head> | |||
<title>Clouds</title> | |||
<meta charset="utf-8"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> | |||
<style type="text/css"> | |||
body { | |||
background-color: #326696; | |||
margin: 0px; | |||
overflow: hidden; | |||
font-family:Monospace; | |||
font-size:13px; | |||
text-align:center; | |||
font-weight: bold; | |||
text-align:center; | |||
} | |||
a { | |||
color:#0078ff; | |||
} | |||
.cabin{ | |||
background: url('x-wing.png'); | |||
background-size: cover; | |||
background-position: center bottom; | |||
position: absolute; | |||
top: 0px; | |||
left: 0px; | |||
height: 100vh; | |||
width: 100vw; | |||
cursor:crosshair; | |||
} | |||
</style> | |||
<body> | |||
<script type="text/javascript" src="js/three.min.js"></script> | |||
<script type="text/javascript" src="js/Detector.js"></script> | |||
<script id="vs" type="x-shader/x-vertex"> | |||
varying vec2 vUv; | |||
void main() { | |||
vUv = uv; | |||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); | |||
} | |||
</script> | |||
<script id="fs" type="x-shader/x-fragment"> | |||
uniform sampler2D map; | |||
uniform vec3 fogColor; | |||
uniform float fogNear; | |||
uniform float fogFar; | |||
varying vec2 vUv; | |||
void main() { | |||
float depth = gl_FragCoord.z / gl_FragCoord.w; | |||
float fogFactor = smoothstep( fogNear, fogFar, depth ); | |||
gl_FragColor = texture2D( map, vUv ); | |||
gl_FragColor.w *= pow( gl_FragCoord.z, 20.0 ); | |||
gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor ); | |||
} | |||
</script> | |||
<script type="text/javascript"> | |||
if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); | |||
var container; | |||
var camera, scene, renderer; | |||
var mesh, geometry, material; | |||
var mouseX = 0, mouseY = 0; | |||
var start_time = Date.now(); | |||
var windowHalfX = window.innerWidth / 2; | |||
var windowHalfY = window.innerHeight / 2; | |||
init(); | |||
function init() { | |||
container = document.createElement( 'div' ); | |||
document.body.appendChild( container ); | |||
// Bg gradient | |||
var canvas = document.createElement( 'canvas' ); | |||
canvas.width = 32; | |||
canvas.height = window.innerHeight; | |||
var context = canvas.getContext( '2d' ); | |||
var gradient = context.createLinearGradient( 0, 0, 0, canvas.height ); | |||
gradient.addColorStop(0, "#1e4877"); | |||
gradient.addColorStop(0.5, "#4584b4"); | |||
context.fillStyle = gradient; | |||
context.fillRect(0, 0, canvas.width, canvas.height); | |||
container.style.background = 'url(' + canvas.toDataURL('image/png') + ')'; | |||
container.style.backgroundSize = '32px 100%'; | |||
// | |||
camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 1, 3000 ); | |||
camera.position.z = 6000; | |||
scene = new THREE.Scene(); | |||
geometry = new THREE.Geometry(); | |||
var texture = THREE.ImageUtils.loadTexture( 'cloud10.png', null, animate ); | |||
texture.magFilter = THREE.LinearMipMapLinearFilter; | |||
texture.minFilter = THREE.LinearMipMapLinearFilter; | |||
var fog = new THREE.Fog( 0x4584b4, - 100, 3000 ); | |||
material = new THREE.ShaderMaterial( { | |||
uniforms: { | |||
"map": { type: "t", value: texture }, | |||
"fogColor" : { type: "c", value: fog.color }, | |||
"fogNear" : { type: "f", value: fog.near }, | |||
"fogFar" : { type: "f", value: fog.far }, | |||
}, | |||
vertexShader: document.getElementById( 'vs' ).textContent, | |||
fragmentShader: document.getElementById( 'fs' ).textContent, | |||
depthWrite: false, | |||
depthTest: false, | |||
transparent: true | |||
} ); | |||
var plane = new THREE.Mesh( new THREE.PlaneGeometry( 64, 64 ) ); | |||
for ( var i = 0; i < 8000; i++ ) { | |||
plane.position.x = Math.random() * 1000 - 500; | |||
plane.position.y = - Math.random() * Math.random() * 200 - 15; | |||
plane.position.z = i; | |||
plane.rotation.z = Math.random() * Math.PI; | |||
plane.scale.x = plane.scale.y = Math.random() * Math.random() * 1.5 + 0.5; | |||
THREE.GeometryUtils.merge( geometry, plane ); | |||
} | |||
mesh = new THREE.Mesh( geometry, material ); | |||
scene.add( mesh ); | |||
mesh = new THREE.Mesh( geometry, material ); | |||
mesh.position.z = - 8000; | |||
scene.add( mesh ); | |||
renderer = new THREE.WebGLRenderer( { antialias: false } ); | |||
renderer.setSize( window.innerWidth, window.innerHeight ); | |||
container.appendChild( renderer.domElement ); | |||
document.addEventListener( 'mousemove', onDocumentMouseMove, false ); | |||
window.addEventListener( 'resize', onWindowResize, false ); | |||
} | |||
function onDocumentMouseMove( event ) { | |||
mouseX = ( event.clientX - windowHalfX ) * 0.25; | |||
mouseY = ( event.clientY - windowHalfY ) * 0.15 + 80; | |||
} | |||
function onWindowResize( event ) { | |||
camera.aspect = window.innerWidth / window.innerHeight; | |||
camera.updateProjectionMatrix(); | |||
renderer.setSize( window.innerWidth, window.innerHeight ); | |||
} | |||
function animate() { | |||
requestAnimationFrame( animate ); | |||
position = ( ( Date.now() - start_time ) * 0.03 ) % 8000; | |||
camera.position.x += ( mouseX - camera.position.x ) * 0.01; | |||
camera.position.y += ( - mouseY - camera.position.y ) * 0.01; | |||
camera.position.z = - position + 8000; | |||
renderer.render( scene, camera ); | |||
} | |||
</script> | |||
<div style="background: url("data:image/png;base64,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");"> | |||
<canvas width="1920" height="995" style="width: 1920px; height: 995px;"></canvas> | |||
<div class="cabin"></div> | |||
</div> | |||
</body> | |||
</html> |
@ -0,0 +1,34 @@ | |||
Carácteristicas/ Mejoras a implementar a implementar | |||
TAREAS: | |||
-COMPLEJAS: | |||
- Eliminar Vendor del repositorio <-----SUCCESS -----> (Quedar un dia por hangout para dejarlo subido y bien) (Daniel, Dani y Gustavo) | |||
- Integración de login con redes sociales usando Ouath.io (Modulo independiente) (Gustavo) | |||
- Testear seguridad del framework. (Alejandro) | |||
-Ha pasado la primera face!!!! Va a intentar algo mas chungo... :D | |||
- Crear una nomemclatura para los ficheros que evite los ficheros con nombres duplicados (Todos) | |||
- PROPUESTA -> Juntar todos los js de un controlador en un fichero de nombre <nombremodelo>controller.js | |||
- Generar formularios acordes al tipo de cada campo del modelo. (Daniel) | |||
- include de php -> usar PS-4 (Daniel y Gustavo) | |||
-PHP: | |||
-Mejorar function print_s() (Imprimir arrays de forma visible) | |||
-Mejorar posicion de la llamada al compilador de less (solo cuando se carga el layaout..) | |||
-JS: | |||
-Ver sistemas de alertas en angular(Para colorear la consola) | |||
BUGS: | |||
IDEAS: | |||
- Modulo para google maps. | |||
@ -0,0 +1,192 @@ | |||
###### ####### ######## #### ###### ® | |||
## ## ## ### ## ## ## ## ## | |||
## ## # ## ## ## ## ## | |||
###### ## # ## ######## ## ## | |||
## ## # ## ## ## ## ## | |||
## ## ### ## ## ## ## ## ## | |||
###### ####### ######## #### ###### | |||
================================================ | |||
## 1. Introducción | |||
Sobic es un framework basado en el patrón Modelo-Vista-Controlador que combina los lenguajes PHP y AngularJS. Sobic ha sido y continua siendo desarrollado por NextSun Limited. | |||
## 2. Requisitos de Sobic: | |||
- Apache2. | |||
- PHP 5.5 o superior, aunque se recomienda tener la última versión. | |||
- Composer instalado en el sistema o en la carpeta. | |||
- Activar la extensión de PDO en PHP para el acceso a bases de datos. | |||
- Gestor de bases datos como MySQL, Oracle SQL, SQLite, etc. | |||
- Activar los módulos de PHP mod_rewrite y cURL. | |||
## 3. Estructura de Sobic | |||
Sobic tiene una estructura de carpetas y archivos básica que ha de ser respetada para el correcto funcionamiento de una aplicación desarrollada con Sobic. La estructura es la siguiente: | |||
- App. | |||
En la carpeta “App” se almacenan los archivos que se podrían denominar como la api del servicio, es el software que se ejecuta en el servidor y que se comunica con la base de datos y gestiona la información y como esta es tratada y almacenada. Contiene los controladores, las rutas y los modelos. | |||
- Config. | |||
Contiene los archivos de configuración de la base de datos y el estado de la plataforma. | |||
- Database. | |||
En la carpeta “Database” se almacenan los archivos que contienen el conjunto de operaciones que se pueden realizar en la base de datos, operaciones tales como las migraciones o las semillas. | |||
- Public. | |||
La carpeta “Public” corresponde con el “front-end” o la parte visible de la aplicación, es el software que ejecuta el cliente y que le añade estilo y ordena la información mostrada y proveída por la api o “back-end”. Contiene las imágenes mostradas, las librerías y fuentes, los estilos CSS, etc. | |||
- Vendor. | |||
La carpeta “Vendor” incluye los componentes utilizados por el sistema Sobic, también se incluyen aquí los complementos o plugins así como todo el software de terceros utilizado. Es una carpeta auto-generada por Composer al instalarse junto con otros componentes esenciales como Slim o Eloquent. No se recomienda modificar el contenido ya existente de esta carpeta, si se añade algún componente aparecerá aquí el nuevo. | |||
- Composer.json. | |||
- Composer.lock. | |||
- Sobic. | |||
Por último se encuentran tres ficheros de configuracion, “composer.json”, “composer.lock” y “sobic”. | |||
Los dos primeros pertenecen a composer y el último es el alma de sobic, en el se almacenan las operaciones que crearán todo el sistema, se recomienda no modificar ninguno de estos tres archivos. | |||
## 4. Comenzando con Sobic | |||
Descargar el git desde la dirección de Sobic en github (https://github.com/nextsun-limited/sobic/ "Sobic") y guardalo en la raíz del servidor web. A continuación se actualiza "Composer" con el comando: | |||
composer install/update | |||
Una vez realizada la tarea y con el sistema gestor de base de datos configurado, se modificará el acceso a la misma para que conecte satisfactoriamente, para esto Sobic ofrece varios entornos de producción. | |||
En la carpeta "config" y gestionado por el archivo "enviroment.php" se establece el estado de la plataforma entre desarrollo, prueba y producción, en cada uno podemos tener una base de datos diferente. Cada uno tiene su archivo donde establecer las variables de entorno y se hace de la siguiente manera: | |||
$capsule->addConnection(array( | |||
'driver' => 'mysql', //Llamamos al driver que conecta con la base de datos. | |||
'host' => getenv('IP'), //Establecemos el host de la base de datos. | |||
'port' => 3306, //Seleccionamos el puerto de connexión. | |||
'database' => 'c9', //Indicamos el nombre de la base de datos a utilizar. | |||
'username' => getenv('C9_USER'), //Usuario de la base de datos. | |||
'password' => '', //Password del usuario. | |||
'prefix' => '', //Indicamos el prefijo | |||
'charset' => "utf8", //Se indica el juego de carácteres. | |||
'collation' => "utf8_unicode_ci" | |||
)); | |||
- Nota 1: El ejemplo utilizado es para un sistema implementado en c9.io, por eso se deja la contraseña en blanco, recuerda cambiarla antes de publicar el trabajo. | |||
- Nota 2: Ya que el ORM utilizado es ELOQUENT, la estructura y sentencias utilizadas es la misma que podemos encontrar en la documentación oficial de ELOQUENT. | |||
Ahora se puede comenzar a introducir las diferentes instrucciones de Sobic, pero antes de hacer ninguna prueba recuerda que la configuración de acceso web se hace desde el archivo '.htaccess' ubicado en la raíz y por defecto, si se accede directamente a la carpeta "/public", invocará un error 404. | |||
## 5. Instrucciones de Sobic | |||
#### 5.1 Creación de migraciones: | |||
Las migraciones son un tipo de control de versiones para la base de datos. Hace posible que los diferentes miembros del equipo modifiquen la estructura de la base de datos y que el resto de miembros esten informados sobre el estado actual. | |||
Para crear una migración introduce la siguiente orden en consola: | |||
php sobic create migrate [name] | |||
Ejemplo: | |||
php sobic create migrate shop "string('name')" "integer('price')" [...] | |||
Se creará un archivo parecido a este "app/database/migrations/ExamplesMigration.php". | |||
#### 5.1.2 Ejecutar la migración: | |||
Inicializará la base de datos con la estructura existente, en el caso de no haber creado previamente una migración se ejecutará la migraciones por defecto. | |||
php sobic migrate [--seed] | |||
Al ejecutar una migración creada por defecto se borrarán las tablas de las bases de datos y se volverán a crear, por lo que los datos se perderán, para evitar esto comenta o borra esta línea dentro del archivo "NameMigration.php": | |||
Capsule::schema()->dropIfExists('name'); | |||
#### 5.2 Creación de Seed y Poblado de datos: | |||
Crea una semilla que poblará la base de datos con datos de prueba. | |||
php sobic create seed [name] | |||
Se creará un archivo parecido a este "app/database/seeds/ExamplesSeed.php". | |||
#### 5.3 Creación de Modelos: | |||
El Modelo es la representación de la información con la cual el sistema opera, por lo tanto gestiona todos los accesos a dicha información, tanto consultas como actualizaciones, implementando también los privilegios de acceso que se hayan descrito en las especificaciones de la aplicación (lógica de negocio). | |||
Para crear un modelo introducimos la siguiente orden: | |||
php sobic create model [name] [atributo:nombre_atributo],[..,] | |||
Ejemplo: | |||
php sobic create model shop "string('name')" "integer('price')" [...] | |||
Se creará un archivo parecido a este "app/models/Examples.php". | |||
Después de crear un modelo ha de actualizarse composer, para cargar el modelo creado, introduciendo: | |||
composer dump-autoload | |||
#### 5.4 Creación de Controladores: | |||
El controlador responde a eventos (usualmente acciones del usuario) e invoca peticiones al 'modelo' cuando se hace alguna solicitud sobre la información (por ejemplo, editar un documento o un registro en una base de datos). | |||
Para crear un controlador introducimos la siguiente orden: | |||
php sobic create controller [name] | |||
Se creará un archivo parecido a este "app/controllers/example.php". | |||
#### 5.5 Creación de Scaffold: | |||
La orden Scaffold genera una estructura base de una aplicación con todas las instrucciones anteriormente descritas. | |||
Para crear un controlador introducimos la siguiente orden: | |||
php sobic create scaffold [name] [arguments],[..,] | |||
Ejemplo: | |||
php sobic create scaffold shop "string('name')" "integer('price')" [...] | |||
Durante la creación del scaffold se modifican los siguientes archivos: | |||
- En "app/main.php" bajo la etiqueta "/** Scaffold PHP Controller **/" donde se añade el método "include" con la ubicación del controlador. | |||
- En "public/js/main.js" bajo la etiqueta "/* Es importante que estas lineas siempre esten al final para que funcione el scaffolg. */" donde se indica la ubicación de los controladores. | |||
- En "public/partials/layout.html" bajo las etiquetas "< !-- Scaffold JS -- >" y "< !-- Scaffold HTML -- >" donde primeramente se carga la libreria js y después se crea el enlace en la vista HTML. | |||
Después de crear un modelo ha de actualizarse composer, para cargar el modelo creado, introduciendo: | |||
composer dump-autoload | |||
También hay que ejecutar la migración que se creó con el scaffold, con el siguiente comando: | |||
php sobic migrate [--seed] | |||
#### 5.6 Creación de Vistas: | |||
La vista presenta el 'modelo' (información y lógica de negocio) en un formato adecuado para interactuar (usualmente la interfaz de usuario) por tanto requiere de dicho 'modelo' la información que debe representar como salida. | |||
Para crear un controlador introducimos la siguiente orden: | |||
php sobic create views [name] [atributo:nombre_atributo],[..,] | |||
Se crearán los siguientes archivos y directorios: | |||
- public/partials/example | |||
- public/partials/example/form.html | |||
- public/partials/example/form.html | |||
- public/js/controllers/example | |||
- public/js/controllers/example/form.js | |||
- public/js/controllers/example/show.js | |||
## 6. Recomendaciones | |||
#### 6.1 Se recomienda que en caso de implementar la gestion de usuarios proporcionada, se haga sobre el protocolo HTTPS y no sobre HTTP. | |||
## 7. Licencia | |||
Sobic ha sido desarrollado por el equipo de NextSun UK Limited, bajo licencia MIT. | |||
Sobic utiliza los siguientes frameworks: | |||
- Illuminate con Slim y Eloquent pertenecientes al framework Laravel registrado bajo <a href="https://es.wikipedia.org/wiki/Licencia_MIT"> licencia MIT. </a> | |||
- Composer como gestor de dependencias, publicado bajo <a href="https://es.wikipedia.org/wiki/Licencia_MIT"> licencia MIT. </a> | |||
## 8. Desarrolladores | |||
Idea and implementation by: | |||
- Gustavo Adolfo Mesa Roldán | |||
Supported by: | |||
- Daniel rodriguez (Assistant, something more than itching code & doc, corrections and moral support) | |||
- Rafael Bustamante (Manager, css artist and moral support) |
@ -0,0 +1,65 @@ | |||
<?php | |||
/** | |||
* Personal Controller | |||
*/ | |||
$app->group('/personals', function () use ($app) { | |||
$app->get('/', function () use ($app) { | |||
$results = []; | |||
$results['personals'] = Personal::all(); | |||
$results["success"]= "true"; | |||
echo json_encode($results); | |||
}); | |||
$app->get('/show/:id', function ($id) use ($app) { | |||
$results = []; | |||
$results["personal"] = Personal::find($id); | |||
$results["success"]= "true"; | |||
echo json_encode($results); | |||
}); | |||
$app->post('/form', function () use ($app) { | |||
$data = json_decode($app->request->getBody(), true); | |||
$results = []; | |||
$results["success"]= "false"; | |||
if (validatedKey($data['user'])) { | |||
if(isset($data['personal']['id'])){ | |||
Personal::find($data['personal']['id'])->update($data['personal']); | |||
}else{ | |||
Personal::create($data['personal']); | |||
} | |||
$results["success"]= "true"; | |||
$results["value"]= "New"; | |||
} else { | |||
$results["success"]= "false"; | |||
$results["error"]= "No auth"; | |||
} | |||
echo json_encode($results); | |||
}); | |||
$app->post('/delete', function () use ($app) { | |||
$data = json_decode($app->request->getBody(), true); | |||
$results = []; | |||
$results["success"]= "false"; | |||
if (validatedKey($data['user'])) { | |||
$personal = Personal::find($data['personal']['id']); | |||
$personal->delete(); | |||
$results["personals"] = Personal::all(); | |||
$results["success"]= "true"; | |||
$results["value"]= "delete"; | |||
} else { | |||
$results["success"]= "false"; | |||
$results["error"]= "No auth"; | |||
} | |||
echo json_encode($results); | |||
}); | |||
}); |
@ -0,0 +1,146 @@ | |||
<?php | |||
$app->group('/user', function () use ($app) { | |||
$app->get('/', function () use ($app) { | |||
$data = json_decode($app->request->getBody(), true); | |||
$results = []; | |||
$results["user"] = []; | |||
$results["success"]= "false"; | |||
if (validatedKey($data["user"]["id"], $data["user"]["key"])) { | |||
$user = user::where('id', '=', $data["user"]["id"])->first(); | |||
$results["user"] = $user; | |||
$results["success"]= "true"; | |||
} else { | |||
$results["success"]= "false"; | |||
$results["error"]= "No auth"; | |||
} | |||
echo json_encode($results); | |||
}); | |||
$app->post('/photo', function () use ($app) { | |||
$data = json_decode($_POST['data'], true); | |||
$results = []; | |||
$results["success"]= "false"; | |||
if (validatedKey($data['user'])) { | |||
if($_FILES['file']['name'] != ""){ // El campo foto contiene una imagen... | |||
// Primero, hay que validar que se trata de un JPG/GIF/PNG | |||
$allowedExts = array("jpg", "jpeg", "gif", "png", "JPG", "GIF", "PNG"); | |||
$ext = end(explode(".", $_FILES["file"]["name"])); | |||
if ((($_FILES["file"]["type"] == "image/gif") | |||
|| ($_FILES["file"]["type"] == "image/jpeg") | |||
|| ($_FILES["file"]["type"] == "image/png") | |||
|| ($_FILES["file"]["type"] == "image/pjpeg")) | |||
&& in_array($ext, $allowedExts)) { | |||
$ext = end(explode('.', $_FILES['file']['name'])); | |||
$photo = substr(md5(uniqid(rand())),0,10).".".$ext; | |||
$dir = dirname(__FILE__).'/../../public/img/users'; // directorio de tu elección | |||
if(move_uploaded_file($_FILES['file']['tmp_name'], $dir.'/'.$photo)){ | |||
$user = User::find($data['user']['id']); | |||
$user->img = "img/users/".$photo; | |||
$user->save(); | |||
$img = new Imagick($dir.'/'.$photo); | |||
$img->cropThumbnailImage(50, 50); | |||
$img->writeImage ($dir.'/'.$photo); | |||
$results['img'] = "img/users/".$photo; | |||
$results["success"]= "true"; | |||
} | |||
} else { | |||
$results["error"]= "Invalid format"; | |||
} | |||
} else { | |||
$results["error"]= "Not exist file"; | |||
} | |||
} else { | |||
$results["success"]= "false"; | |||
$results["error"]= "No auth"; | |||
} | |||
echo json_encode($results); | |||
}); | |||
$app->post('/new', function () use ($app) { | |||
$data = json_decode($app->request->getBody(), true); | |||
$results = []; | |||
$results["success"]= "false"; | |||
if(!User::where('email', '=', $data["user"]["email"])->exists()){ | |||
$user = new User(); | |||
$user->email = $data["user"]["email"]; | |||
$user->password = hash('sha512',$data["user"]["password"]); | |||
$user->save(); | |||
$encriptedKey = hash('sha512', $user->id.$user->email.$user->created_at); | |||
$results["id"] = $user->id; | |||
$results["email"] = $user->email; | |||
$results["isAdmin"] = $user->isAdmin; | |||
$results["key"] = $encriptedKey; | |||
$results["success"]= "true"; | |||
} | |||
echo json_encode($results); | |||
}); | |||
$app->post('/login', function () use ($app) { | |||
$data = json_decode($app->request->getBody(), true); | |||
$results = []; | |||
$results["success"]= "false"; | |||
$veri = User::where('email', '=', $data['user']['email'])->where('email', '=', $data['user']['email'])->where('password', '=', hash('sha512', $data['user']['password']))->first(); | |||
if(User::where('email', '=', $data['user']['email'])->where('password', '=', hash('sha512', $data['user']['password']))->exists()){ | |||
$results["id"] = $veri->id; | |||
$results["email"] = $veri->email; | |||
$results["isAdmin"] = $veri->isAdmin; | |||
$results["key"] = hash('sha512', $veri->id.$veri->email.$veri->created_at); | |||
$results["success"]= "true"; | |||
} | |||
echo json_encode($results); | |||
}); | |||
$app->get('/list', function () use ($app) { | |||
$users = User::all(); | |||
$results["users"] = $users; | |||
echo json_encode($results); | |||
}); | |||
$app->post('/social', function () use ($app) { | |||
$data = json_decode($app->request->getBody(), true); | |||
$pass = hash('sha512', $data['social']."-".$data['user']['email']."-".hash('sha512', $data['user']['name'])); | |||
$results = []; | |||
$results["success"]= "false"; | |||
if($data['social'] =="twitter"){ | |||
$data["user"]["email"] = "@".$data["user"]["alias"]; | |||
} | |||
$query = User::where('email', '=', $data["user"]["email"])->where('password', '=', $pass); | |||
//print_s($pass); | |||
if($query->exists()){ | |||
$user = $query->first(); | |||
}else{ | |||
$user = new User(); | |||
$user->email = $data["user"]["email"]; | |||
$user->password = $pass; | |||
$user->img = $data["user"]["avatar"]; | |||
$user->social = $data["social"]; | |||
$user->save(); | |||
} | |||
$encriptedKey = hash('sha512', $user->id.$user->email.$user->created_at); | |||
$results["id"] = $user->id; | |||
$results["email"] = $user->email; | |||
$results["isAdmin"] = $user->isAdmin; | |||
$results["img"] = $user->img; | |||
$results["social"] = $user->social; | |||
$results["key"] = $encriptedKey; | |||
$results["success"]= "true"; | |||
echo json_encode($results); | |||
}); | |||
}); |
@ -0,0 +1,42 @@ | |||
<?php | |||
function print_s($var){ | |||
echo "<pre>".print_r($var)."</pre>"; | |||
} | |||
//** Compilacion de css a less **// | |||
function autoCompileLess($inputFile, $outputFile) { | |||
// load the cache | |||
$cacheFile = $inputFile.".cache"; | |||
if (file_exists($cacheFile)) { | |||
$cache = unserialize(file_get_contents($cacheFile)); | |||
} else { | |||
$cache = $inputFile; | |||
} | |||
$less = new lessc; | |||
$less->setFormatter("compressed"); | |||
$newCache = $less->cachedCompile($cache); | |||
if (!is_array($cache) || $newCache["updated"] > $cache["updated"]) { | |||
file_put_contents($cacheFile, serialize($newCache)); | |||
file_put_contents($outputFile, $newCache['compiled']); | |||
} | |||
} | |||
//** Validacion del cliente AngularJS **/ | |||
function validatedKey($user) { | |||
try { | |||
$veri = User::where('id', '=', $user['id'])->first(); | |||
$encriptedKey = hash('sha512', $veri->id.$veri->email.$veri->created_at); | |||
if($user['key'] == $encriptedKey) { | |||
return true; | |||
} else { | |||
return false; | |||
} | |||
} catch (Exception $e) { | |||
return false; | |||
} | |||
} |
@ -0,0 +1,21 @@ | |||
<?php | |||
$app->notFound(function () use ($app) { | |||
require '../public/partials/layout.html'; | |||
}); | |||
$app->get('/',function(){ | |||
require '../public/partials/layout.html'; | |||
}); | |||
$app->group('/api', function () use ($app) { | |||
include ('controllers/user.php'); | |||
/* Es importante que respetes estos comentarios para general scaffold sin probremas. */ | |||
/** Scaffold PHP Controller **/ | |||
include ('controllers/personal.php'); | |||
}); |
@ -0,0 +1,11 @@ | |||
<?php | |||
/** | |||
* Personal Model | |||
*/ | |||
class Personal extends \Illuminate\Database\Eloquent\Model | |||
{ | |||
protected $table = "personals"; | |||
protected $fillable = ['candidate_id','title','name','surname','dateBirth','phoneNumber','address','postalCode','city','country','summary','linkedin']; | |||
} |
@ -0,0 +1,29 @@ | |||
<?php | |||
/** | |||
* User Model | |||
*/ | |||
class User extends \Illuminate\Database\Eloquent\Model | |||
{ | |||
protected $table = "users"; | |||
protected $hidden = array('password'); | |||
/* | |||
Example of relations: | |||
--------------------- | |||
public function questions() { | |||
return $this->hasMany('Questions'); | |||
} | |||
public function personal() { | |||
return $this->hasOne('Personal'); | |||
} | |||
public function job() { | |||
return $this->belongsTo('Job'); | |||
} | |||
*/ | |||
} |
@ -0,0 +1,34 @@ | |||
{ | |||
"name": "NextSun/Sobic", | |||
"description": "Sobic power", | |||
"type": "project", | |||
"authors":[ | |||
{ | |||
"name": "Gustavo Adolfo Mesa Roldan", | |||
"email": "gs.gore@gmail.com", | |||
"homepage": "http://blog.nextsun.eu", | |||
"role": "God" | |||
}, | |||