JSFiddle - React, Tailwind, and code Playground
MapleStory News
by MegaScience
HTML
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular-sanitize.js"></script>
<input ng-model="filterText" id="search" class="form-control" placeholder="Filter text">
<select ng-model="pageSize" id="pageSize" class="form-control">
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
</select>
<button ng-disabled="currentPage == 0" ng-click="currentPage = currentPage - 1">Previous</button>
{{currentPage+1}}/{{numberOfPages()}}
<button ng-disabled="currentPage >= getData().length/pageSize - 1" ng-click="currentPage = currentPage + 1">Next</button>
<button ng-disabled="loading" ng-click="getNews(true)">Recent</button>
<button ng-disabled="loading" ng-click="getNews(false)">All</button>
<div id="newsContainer">
<div ng-repeat="news in newsPosts | filter:filterText | startFrom:currentPage*pageSize | limitTo:pageSize" class="{{news.Category}}" ng-click="openPage(news.Id)">
<div class="photo" ng-style="{'background-image' : 'url(' + (news.ImageThumbnail || news.ImageThumbnail2) + ')'}">
<img class="shim" src="http://nxcache.nexon.net/maplestory/assets-new/img/shim_16x9.png">
<div class="label">{{news.Category}}</div>
</div><span>{{convertTime(news.LiveDate)}}</span>
<h3>{{news.Title}}</h3><div>{{news.Summary}}</div></div>
</div>
<input id="toggle" name="toggle" type="checkbox" ng-model="toggleWebpage" />
<div id="webpage">
<div id="webpageContent" ng-bind-html="webpage"></div>
<label for="toggle">X</label>
</div>
CSS
body {
font-family: Arial, Helvetica, sans-serif;
}
input#toggle {
position: fixed;
left: -9999px;
}
label[for="toggle"] {
position: absolute;
right: 0;
top: 0;
width: 1.3em;
height: 1.3em;
box-sizing: border-box;
border: 1px dotted black;
background-color: #2980B9;
color: white;
text-align: center;
}
input#toggle:not(:checked) + div#webpage {
display: none;
}
div#webpage {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
height: 80%;
width: 80%;
background-color: white;
border: 1px solid black;
padding: 5px;
}
div#webpageContent {
height: 100%;
width: 100%;
overflow-y: scroll;
}
div#webpageContent img {
max-width: 100%;
}
div#newsContainer > div {
border: 1px solid gray;
box-sizing: border-box;
float: left;
clear: both;
margin: 3px;
padding-right: 3px;
width: 100%;
}
div#newsContainer > div span {
float: right;
}
div#newsContainer h3 {
margin-top: 0;
}
/*div#newsContainer img {
float: left;
padding-right: 5px;
max-width: 150px;
}*/
div#newsContainer div.photo {
float: left;
width: 20%;
margin: 0 3% 0 0;
position: relative;
background-position: 50% 50%;
background-repeat: no-repeat;
background-size: cover;
}
div#newsContainer div.photo img {
width: 100%;
}
div#newsContainer div.photo div.label {
position: absolute;
bottom: 0;
left: 0;
padding: 2px 12px;
font-size: 14px;
font-weight: 500;
font-family: "Titillium Web", Arial, sans-serif;
color: #fff;
text-transform: uppercase;
}
div#newsContainer div.general {
border-left: 3px solid #7519ff;
background-color: rgba(117, 25, 255, 0.1);
}
div#newsContainer div.general div.photo div.label {
background-color: #7519ff;
}
div#newsContainer div.events {
border-left: 3px solid #7acca3;
background-color: rgba(122, 204, 163, 0.1);
}
div#newsContainer div.events div.photo div.label {
background-color: #7acca3;
}
div#newsContainer div.sale {
border-left: 3px...
JavaScript
const newsApp = angular.module('newsApp', ['ngSanitize']);
newsApp.controller('newsController', ['$scope', '$filter', '$http', '$sce', mainController]);
function mainController($scope, $filter, $http, $sce) {
const gameID = 10100;
const lang = 'en-US';
const region = '1';
// https://gist.github.com/jesperorb/6ca596217c8dfba237744966c2b5ab1e#bypass-client-side-for-production
const sites = {
cors: ['https://cors.io/?', 'https://crossorigin.me/', 'https://cors-anywhere.herokuapp.com/'],
corsIndex: 0,
currentEndpoint: 'new',
endpoints: {
old: {
recentURL: `http://nxl.nxfs.nexon.com/news/${gameID}/${lang}/recent.json`,
newsURL: `http://nxl.nxfs.nexon.com/news/${gameID}/${lang}/list.json`,
newsPage: 'http://nxl.nxfs.nexon.com/news/items/'
},
new: {
recentURL: `https://nxl.nxfs.nexon.com/news/regions/${region}/${gameID}/${lang}/recent.json`,
newsURL: `https://nxl.nxfs.nexon.com/news/regions/${region}/${gameID}/${lang}/list.json`,
newsPage: 'https://nxl.nxfs.nexon.com/news/items/'
}
}
};
const getCORS = index => sites.cors[typeof index !== 'undefined' ? index : sites.corsIndex];
const cycleCORS = () => {
if (++sites.corsIndex >= sites.cors.length) return 'END'; //sites.corsIndex = 0;
};
const errorHandler = (response, cb) => {
console.error(response);
if (cycleCORS() !== 'END') cb();
else {
alert('CORS could not be resolved.');
$scope.loading = false;
}
};
const setNews = data => {
$scope.loading = false;
$scope.newsPosts = typeof data === 'undefined' ? [] : data;
};
// Pagination: https://codepen.io/khilnani/pen/qEWojX
$scope.currentPage = 0;
$scope.pageSize = 10;
$scope.filterText = '';
let lastWebpage = '';
$scope.newsPosts = [];
...