Dev: Features, resources, info tools

This commit is contained in:
surunzi
2016-03-13 23:11:40 +08:00
parent 056f9359f0
commit d7c2ab66b2
21 changed files with 976 additions and 162 deletions

552
dist/eruda.js vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,14 @@
loadJs = function (url)
loadJs = function (url, cb)
{
var script = document.createElement('script');
script.src = url;
script.onload = function ()
{
var isNotLoaded = script.readyState &&
script.readyState != "complete" &&
script.readyState != "loaded";
cb && cb(!isNotLoaded);
};
document.body.appendChild(script);
};

14
eustia/orientation.js Normal file
View File

@@ -0,0 +1,14 @@
_('Emitter');
orientation = {};
Emitter.mixin(orientation);
window.addEventListener('orientationchange', function ()
{
setTimeout(function ()
{
orientation.emit('change');
}, 150);
}, false);

View File

@@ -207,11 +207,21 @@ export default class Log
case 'w': return this.filter('warn');
case 'l': return this.filter('log');
case 'h': return this.help();
case '$': return util.loadJs(libraries['jQuery']);
case '$': return this._loadJs('jQuery');
case '_': return this._loadJs('underscore');
default:
this.warn('Unknown command').help();
}
}
_loadJs(name)
{
util.loadJs(libraries[name], (result) =>
{
if (result) return this.log(name + ' is loaded');
this.warn('Failed to load ' + name);
});
}
_render()
{
var logs = this._filterLogs(this._logs);

View File

@@ -4,11 +4,11 @@
.logs {
height: 100%;
overflow-x: hidden;
overflow-y: scroll;
overflow-y: auto;
font-size: 14px;
li {
padding: 10px;
overflow-x: scroll;
overflow-x: auto;
&.log, &.output {
border-bottom: 1px solid #b4b4b4;
}

View File

@@ -6,5 +6,6 @@
":l": "Show normal logs only",
":h": "Show help",
":$": "Load jQuery",
":_": "Load underscore",
"/regexp": "Show logs that match given regexp"
}

View File

@@ -1,3 +1,4 @@
{
"jQuery": "//code.jquery.com/jquery-1.12.0.min.js"
"jQuery": "//cdn.bootcss.com/jquery/2.2.1/jquery.js",
"underscore": "//cdn.bootcss.com/underscore.js/1.8.3/underscore-min.js"
}

View File

@@ -21,7 +21,7 @@
height: 100%;
width: 100%;
position: relative;
overflow: scroll;
overflow: auto;
.tool {
position: absolute;
left: 0;

View File

@@ -36,15 +36,9 @@ export default class HomeBtn
}
_bindEvent()
{
this._draggabilly.on('staticClick', () => this.emit('click') );
this._draggabilly.on('staticClick', () => this.emit('click'));
window.addEventListener('orientationchange', () =>
{
setTimeout(() =>
{
this._setPos();
}, 150);
}, false);
util.orientation.on('change', () => this._setPos());
}
_makeDraggable()
{

View File

@@ -3,7 +3,7 @@
#eruda { .dev-tools {
.nav-bar {
height: 50px;
overflow-y: scroll;
overflow-y: auto;
position: absolute;
width: 100%;
left: 0;

View File

@@ -1,5 +1,10 @@
<ul>
{{#each features}}
<li class="{{#if this}}ok{{/if}}">{{@key}}</li>
<li>
<a href="http://caniuse.com/#search={{@key}}" target="_blank" class="inner-wrapper {{#if this}}ok{{/if}}">
{{@key}}
</a>
</li>
{{/each}}
</ul>
</ul>
<a class="html5test" target="_blank" href="http://html5test.com">Go to HTML5 Test</a>

View File

@@ -1,16 +1,40 @@
@import "../color";
#eruda { .dev-tools { .tools {
.features {
li {
width: 50%;
float: left;
padding: 10px;
text-align: center;
color: #fff;
background: #eda29b;
border: 1px solid #fff;
&.ok {
background: #8de191;
overflow-y: auto;
ul {
li {
width: 50%;
float: left;
padding: 10px;
.inner-wrapper {
color: #fff;
display: block;
padding: 10px;
border-radius: 4px;
text-align: center;
background: $red;
&.ok {
background: #fff;
color: $gray;
}
}
}
&::after {
display: block;
content: '';
clear: both;
}
}
.html5test {
color: #fff;
background: $blue;
display: block;
padding: 10px;
text-decoration: none;
text-align: center;
margin-top: 10px;
}
}
} } }

View File

@@ -1,13 +1,19 @@
@import "../color";
#eruda { .dev-tools { .tools {
.info {
overflow-y: auto;
font-size: 12px;
li {
overflow-x: auto;
border-bottom: 1px solid $gray;
.title, .content {
padding: 10px;
}
.title {
color: #fff;
background: #b4b4b4;
font-size: 20px;
padding-bottom: 0;
font-size: 15px;
color: $blue;
}
}
}

View File

@@ -9,18 +9,64 @@ export default class Resources extends Tool
{
super();
this.name = 'resources';
this._localStoreData = [];
this._cookieData = [];
this._scriptData = [];
this._stylesheetData = [];
this._imageData = [];
this._tpl = require('./Resources.hbs');
}
init($el)
{
super.init($el);
this.refresh();
this.refreshLocalStorage()
.refreshCookie()
.refreshScript()
.refreshStylesheet()
.refreshImage();
this._bindEvent();
}
refresh()
refreshScript()
{
var localStoreData = [],
cookieData = [];
var scriptData = [];
util.$('script').each(function ()
{
var src = this.src;
if (src !== '') scriptData.push(src);
});
scriptData = util.unique(scriptData);
this._scriptData = scriptData;
this._render();
return this;
}
refreshStylesheet()
{
var stylesheetData = [];
util.$('link').each(function ()
{
if (this.rel !== 'stylesheet') return;
stylesheetData.push(this.href);
});
stylesheetData = util.unique(stylesheetData);
this._stylesheetData = stylesheetData;
this._render();
return this;
}
refreshLocalStorage()
{
var localStoreData = [];
util.each(localStorage, function (val, key)
{
@@ -30,18 +76,103 @@ export default class Resources extends Tool
});
});
util.each(document.cookie.split(';'), function (val)
this._localStoreData = localStoreData;
this._render();
return this;
}
refreshCookie()
{
var cookieData = [];
var cookie = document.cookie;
if (util.trim(cookie) !== '')
{
val = val.split('=');
cookieData.push({
key: val[0],
val: decodeURIComponent(val[1])
util.each(document.cookie.split(';'), function (val)
{
val = val.split('=');
cookieData.push({
key: util.trim(val[0]),
val: decodeURIComponent(val[1])
});
});
}
this._cookieData = cookieData;
this._render();
return this;
}
refreshImage()
{
var imageData = [];
util.$('img').each(function ()
{
var $this = util.$(this),
src = $this.attr('src');
if ($this.data('exclude') === 'true') return;
imageData.push(src);
});
imageData = util.unique(imageData);
this._imageData = imageData;
this._render();
return this;
}
_bindEvent()
{
var self = this;
this._$el.on('click', '.refresh-local-storage', () =>
{
this.refreshLocalStorage();
}).on('click', '.refresh-cookie', () =>
{
this.refreshCookie();
}).on('click', '.refresh-script', () =>
{
this.refreshScript();
}).on('click', '.refresh-image', () =>
{
this.refreshImage();
}).on('click', '.delete-local-storage', function ()
{
var key = util.$(this).data('key');
localStorage.removeItem(key);
self.refreshLocalStorage();
}).on('click', '.delete-cookie', function ()
{
var key = util.$(this).data('key');
util.cookie.remove(key);
self.refreshCookie();
});
util.orientation.on('change', () => this._render());
}
_render()
{
this._$el.html(this._tpl({
localStoreData: localStoreData,
cookieData: cookieData
localStoreData: this._localStoreData,
cookieData: this._cookieData,
scriptData: this._scriptData,
stylesheetData: this._stylesheetData,
imageData: this._imageData
}));
if (this._imageData.length === 0) return;
setTimeout(() =>
{
var $li = this._$el.find('.image-list li');
$li.css({height: $li.get(0).offsetWidth});
}, 150);
}
}

View File

@@ -1,12 +1,18 @@
<div>
<h2 class="title">LocalStorage</h2>
<div class="section">
<h2 class="title">
LocalStorage
<span class="btn refresh-local-storage">Refresh</span>
</h2>
<table>
<tbody>
{{#if localStoreData}}
{{#each localStoreData}}
<tr>
<td>{{key}}</td>
<td class="key">{{key}}</td>
<td>{{val}}</td>
<td class="control">
<span class="delete delete-local-storage" data-key="{{key}}"></span>
</td>
</tr>
{{/each}}
{{else}}
@@ -17,8 +23,11 @@
</tbody>
</table>
</div>
<div>
<h2 class="title">Cookie</h2>
<div class="section">
<h2 class="title">
Cookie
<span class="btn refresh-cookie">Refresh</span>
</h2>
<table>
<tbody>
{{#if cookieData}}
@@ -26,6 +35,9 @@
<tr>
<td>{{key}}</td>
<td>{{val}}</td>
<td class="control">
<span class="delete delete-cookie" data-key="{{key}}"></span>
</td>
</tr>
{{/each}}
{{else}}
@@ -35,4 +47,57 @@
{{/if}}
</tbody>
</table>
</div>
<div class="section">
<h2 class="title">
Script
<span class="btn refresh-script">Refresh</span>
</h2>
<ul class="link-list">
{{#if scriptData}}
{{#each scriptData}}
<li>
<a href="{{this}}" target="_blank">{{this}}</a>
</li>
{{/each}}
{{else}}
<li>Empty</li>
{{/if}}
</ul>
</div>
<div class="section">
<h2 class="title">
Stylesheet
<span class="btn refresh-stylesheet">Refresh</span>
</h2>
<ul class="link-list">
{{#if stylesheetData}}
{{#each stylesheetData}}
<li>
<a href="{{this}}" target="_blank">{{this}}</a>
</li>
{{/each}}
{{else}}
<li>Empty</li>
{{/if}}
</ul>
</div>
<div class="section">
<h2 class="title">
Image
<span class="btn refresh-image">Refresh</span>
</h2>
<ul class="image-list">
{{#if imageData}}
{{#each imageData}}
<li>
<a href="{{this}}" target="_blank">
<img src="{{this}}" data-exclude="true"/>
</a>
</li>
{{/each}}
{{else}}
<li class="empty">Empty</li>
{{/if}}
</ul>
</div>

View File

@@ -1,18 +1,78 @@
@import "../color";
#eruda { .dev-tools { .tools {
.resources {
padding: 10px;
font-size: 12px;
overflow-y: auto;
.section {
margin-bottom: 10px;
}
.title {
padding: 10px;
color: #fff;
background: #b4b4b4;
font-size: 20px;
background: $green;
font-size: 12px;
.btn {
float: right;
background: #fff;
color: $gray;
padding: 5px;
position: relative;
top: -5px;
border-radius: 4px;
}
}
.link-list {
li {
padding: 10px;
background: #fff;
}
}
.image-list {
background: #fff;
li {
width: 25%;
float: left;
overflow-y: hidden;
img {
width: 100%;
}
&.empty {
padding: 10px;
width: 100%;
}
}
&::after {
display: block;
content: '';
clear: both;
}
}
table {
border-collapse: collapse;
width: 100%;
td {
padding: 10px;
border: 1px solid #b4b4b4;
word-break: break-all;
.delete {
color: #fff;
width: 20px;
height: 20px;
display: inline-block;
text-align: center;
border-radius: 50%;
background: $red-dark;
line-height: 20px;
}
&.key {
white-space: nowrap;
}
&.control {
width: 40px;
}
}
background: #fff;
}
}
} } }

View File

@@ -1,3 +1,6 @@
$blue: #76a2ee;
$gray: #b4b4b4;
$gray-light: #f2f2f2;
$gray-light: #f2f2f2;
$red: #eda29b;
$red-dark: #f73c37;
$green: #8de191;

View File

@@ -34,7 +34,7 @@ if (isDebugMode)
.add(new Info())
.add(new Features())
.add(new Settings())
.showTool('console')
.showTool('resources')
.show();
}

View File

@@ -392,6 +392,96 @@ module.exports = (function ()
return isNum;
})();
/* ------------------------------ cookie ------------------------------ */
var cookie;
_.cookie = (function ()
{
// TODO
/* module
* cookie: Simple api for handling browser cookies.
*/
var defOpts = { path: '/' };
function setCookie(key, val, options)
{
if (arguments.length > 1)
{
options = extend(defOpts, options);
if (isNum(options.expires))
{
var expires = new Date();
expires.setMilliseconds(expires.getMilliseconds() + options.expires * 864e+5);
options.expires = expires;
}
val = encodeURIComponent(String(val));
key = encodeURIComponent(key);
document.cookie = [
key, '=', val,
options.expires && '; expires=' + options.expires.toUTCString(),
options.path && '; path=' + options.path,
options.domain && '; domain=' + options.domain,
options.secure ? '; secure' : ''
].join('');
return cookie;
}
var cookies = document.cookie ? document.cookie.split('; ') : [],
result = key ? undefined : {};
for (var i = 0, len = cookies.length; i < len; i++)
{
var c = cookies[i],
parts = c.split('='),
name = decodeURIComponent(parts.shift());
c = parts.join('=');
c = decodeURIComponent(c);
if (key === name)
{
result = c;
break;
}
if (!key) result[name] = c;
}
return result;
}
cookie = {
/* member
* cookie.get: Read cookie.
* key(string): The cookie name.
* return(string): Returns cookie value if exists, eles undefined.
*/
get: setCookie,
/* member
* cookie.set: Set cookie.
* key(string): The cookie name.
* val(string): The cookie value.
* options(Object): Options.
*/
set: setCookie,
remove: function (key, options)
{
options = options || {};
options.expires = -1;
return setCookie(key, '', options);
}
};
return cookie;
})();
/* ------------------------------ isArrLike ------------------------------ */
var isArrLike;
@@ -599,10 +689,18 @@ module.exports = (function ()
_.loadJs = (function ()
{
loadJs = function (url)
loadJs = function (url, cb)
{
var script = document.createElement('script');
script.src = url;
script.onload = function ()
{
var isNotLoaded = script.readyState &&
script.readyState != "complete" &&
script.readyState != "loaded";
cb && cb(!isNotLoaded);
};
document.body.appendChild(script);
};
@@ -1796,6 +1894,28 @@ module.exports = (function ()
return $;
})();
/* ------------------------------ orientation ------------------------------ */
var orientation;
_.orientation = (function ()
{
orientation = {};
Emitter.mixin(orientation);
window.addEventListener('orientationchange', function ()
{
setTimeout(function ()
{
orientation.emit('change');
}, 150);
}, false);
return orientation;
})();
/* ------------------------------ rtrim ------------------------------ */
var rtrim;
@@ -1878,5 +1998,34 @@ module.exports = (function ()
return trim;
})();
/* ------------------------------ unique ------------------------------ */
var unique;
_.unique = (function ()
{
function isEqual(a, b) { return a === b }
unique = function (arr, compare)
{
compare = compare || isEqual;
return filter(arr, function (item, idx, arr)
{
var len = arr.length;
while (++idx < len)
{
if (compare(item, arr[idx])) return false;
}
return true;
});
};
return unique;
})();
return _;
})();

View File

@@ -4,13 +4,11 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Eruda</title>
<style>
body {
background: #b4bad2;
}
</style>
<link rel="stylesheet" href="style.css">
</head>
<body>
<img src="http://7xn2zy.com1.z0.glb.clouddn.com/blog_bladeAndSoul.jpg"/>
<img src="http://7xn2zy.com1.z0.glb.clouddn.com/blog_kaneziki.jpg">
<script src="../dist/eruda.js"></script>
</body>
</html>

3
test/style.css Normal file
View File

@@ -0,0 +1,3 @@
body {
background: #b4bad2;
}