<!DOCTYPE html>
<html>
<head>
<link href="http://www.picnicss.com/nut/picnic_3_2.min.css" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<script src="//rawgit.com/magnumjs/mag.js/master/mag.min.js"></script>
<meta charset="utf-8">
<title>Mag.JS</title>
</head>
<body>
<h1>Hello Mag.JS!</h1>
<a href="https://github.com/magnumjs/mag.js" target="top">GitHub</a>
<hr/>
<div class="loader">
-- Loading images --
</div>
<div id="app">
<div id="pictureList">
<div>
<h1>Popular Instagram pics</h1>
<div class="container">
<div class="pictures">{pictures}</div>
</div>
<h1>Your favorites</h1>
<div class="container">
<div class="favorites">{favorites}</div>
</div>
</div>
</div>
</div>
<div id="picture" class="hide">
<div>
<img width="200" />
</div>
</div>
<script src="//rawgit.com/magnumjs/mag.js/master/src/addons/ajax.js"></script>
<script src="//rawgit.com/magnumjs/mag.js/master/src/mag.addons.js"></script>
<script src="picture.js"></script>
<script src="picture-list.js"></script>
<script src="app.js"></script>
</body>
</html>
var app = {}
app.view = function(state, props) {
// load picture list
mag.module('pictureList', PictureList, {
apiKey: props.apiKey,
pictures: mag.prop([]),
favorites: mag.prop([])
})
}
var props = {
apiKey: "642176ece1e7445e99244cec26f4de1f"
}
mag.module("app", app, props)
.hide {
display: none;
}
a {
display: block;
}
a: after {
content: " \bb";
}
* {
padding:0;
margin:0;
}
html{
font:14px normal Arial, sans-serif;
color:#626771;
background-color:#fff;
}
body{
padding:20px;
text-align: center;
}
h1{
font-size: 18px;
margin-bottom: 30px;
padding-top: 20px;
}
div.picture{
display: inline-block;
margin: 5px;
cursor:pointer;
position: relative;
}
div.picture.favorite:after{
content: '❤';
position: absolute;
font-size: 80px;
line-height: 200px;
color: #FF224D;
width: 100%;
text-align: center;
left: 0;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
font-weight: bold;
}
.container, .pictures, .favorites{
white-space: nowrap;
overflow-y: hidden;
margin-bottom: 20px;
height: 230px;
background-color: #F3F3F3;
}
.container div {
display:inline-block;
}
.pictures p, .favorites p {
padding-top: 100px;
font-size: 13px;
}
#Mag.JS
##Image app with AJAX
From: http://tutorialzine.com/2014/07/5-practical-examples-for-learning-facebooks-react-framework/
var Picture = {
// This component doesn't hold any state - it simply transforms
// whatever was passed as attributes into HTML that represents a picture.
clickHandler: function() {
// When the component is clicked, trigger the onClick handler that
// was passed as an attribute when it was constructed:
this.onClick(this.id);
},
controller: function() {
mag.addons.show(this)
},
view: function(state, props) {
var cls = 'picture ' + (props.favorite ? 'favorite' : '');
state.div = {
_class: cls,
_onclick: this.clickHandler.bind(props)
}
state.img = {
_src: props.src,
_title: props.title
}
/*
<div className={cls} onClick={this.clickHandler}>
<img src={this.props.src} width="200" title={this.props.title} />
</div>
*/
}
}
var PictureList = {
getInitialState: function() {
// The pictures array will be populated via AJAX, and
// the favorites one when the user clicks on an image:
return {
pictures: [],
favorites: []
};
},
controller: function(props) {
// When the component loads, send a jQuery AJAX request
var self = this;
// API endpoint for Instagram's popular images for the day
var url = 'https://api.instagram.com/v1/media/popular?client_id=' + props.apiKey + '&callback=?';
mag.addons.requestWithFeedback({
url: url,
dataType: 'jsonp'
}).then(function(result) {
if (!result || !result.data || !result.data.length) {
return;
}
var pictures = result.data.map(function(p) {
return {
id: p.id,
url: p.link,
src: p.images.low_resolution.url,
title: p.caption ? p.caption.text : '',
favorite: false
};
});
// Update the component's state. This will trigger a render.
// Note that this only updates the pictures property, and does
// not remove the favorites array.
props.pictures(pictures)
});
},
pictureClick: function(id) {
// id holds the ID of the picture that was clicked.
// Find it in the pictures array, and add it to the favorites
var favorites = this.favorites,
pictures = this.pictures;
for (var i = 0, size = pictures().length; i < size; i++) {
// Find the id in the pictures array
if (pictures()[i].id == id) {
if (pictures()[i].favorite) {
//already a fave - remove
return PictureList.favoriteClick.bind(this, id);
}
// Add the picture to the favorites array,
// and mark it as a favorite:
favorites().push(pictures()[i]);
pictures()[i].favorite = true;
break;
}
}
// Update the state and trigger a render
this.pictures(pictures())
this.favorites(favorites())
},
favoriteClick: function(id) {
// Find the picture in the favorites array and remove it. After this,
// find the picture in the pictures array and mark it as a non-favorite.
var favorites = this.favorites,
pictures = this.pictures;
for (var i = 0, size = favorites().length; i < size; i++) {
if (favorites()[i].id == id) break;
}
// Remove the picture from favorites array
favorites().splice(i, 1);
for (i = 0, size = pictures().length; i < size; i++) {
if (pictures()[i].id == id) {
pictures()[i].favorite = false;
break;
}
}
// Update the state and trigger a render
this.pictures(pictures())
this.favorites(favorites())
},
view: function(state, props) {
var self = this;
var pictures = props.pictures().map(function(p) {
p.onClick = self.pictureClick.bind(props)
return mag.module('picture', Picture, p, 1)
});
mag.addons.when(pictures, function(htmls) {
state.pictures = htmls
})
var favorites = props.favorites().map(function(p) {
p.onClick = self.favoriteClick.bind(props)
return mag.module('picture', Picture, p, 1)
});
if (!favorites.length) {
state.favorites = {
_html: 'Click an image to mark it as a favorite'
}
}
mag.addons.when(favorites, function(htmls) {
state.favorites = htmls
})
}
}