我有一个包含技术信息的网站。我想根据用户的偏好将英制单位(英寸)转换为公制单位(毫米)。我的托管服务提供商不允许在网页上使用php,但我可以使用Javascript。
我最初的计划是使用一个按钮来翻转开关以设置UnitPreference
cookie,其中包含客户对公制/英制单位的偏好。我发现在Javascript中使用cookie是非常笨拙的。有没有办法在没有cookie的情况下实现我的目标?
答案 0 :(得分:2)
如果您在HTML5中使用/编码,则可以使用离线/会话存储而不是cookie。语法更容易,但它依赖于允许您的站点存储数据的用户。
更新[1.9.2018]
我今天注意到这个答案收到了另一个upvote,但也许可能更好作为一个简单的评论。为了支持上述评论(重新存储),我敲了一个小演示。
<!doctype html>
<html>
<head>
<meta charset='utf-8' />
<title>Unit Preferences Storage with Javascript & localStorage</title>
<style>
body{
display:flex;
align-items:center;
justify-content:center;
height:100vh;
width:100%;
box-sizing:border-box;
padding:0;
margin:0;
}
input[type='button']{
padding:1rem;
color:green;
margin:auto;
align-self:center;
}
</style>
<script>
/* Event handler common flags */
const flags={
once:false,
capture:true,
passive:true
};
/* Unit preferences matrix */
const matrix={
1:{
name:'Metric',
unit:'mm',
conversion:25.4
},
0:{
name:'Imperial',
unit:'inches',
conversion:0.0393701
}
};
/* Simple object to manipulate storage */
const StoreFactory=function( name, type ){
'use strict';
const engine = type.toLowerCase() === 'local' ? localStorage : sessionStorage;
const set=function( data ){
engine.setItem( name, JSON.stringify( data ) );
};
const get=function(){
return exists( name ) ? JSON.parse( engine.getItem( name ) ) : false;
};
const remove=function(){
engine.removeItem( name );
};
const exists=function(){
return engine.getItem( name )==null ? false : true;
};
return Object.freeze({
set,
get,
exists,
remove
});
}
/* Run-time configuration */
const storename='UnitPreference';
const storetype='local'; // "session" is volatile ~ ie: exists only for current session
/* Invoke the storeage object */
let oStore=new StoreFactory( storename, storetype );
/* Event handler that triggers storage of user choice */
const switcher=function(e){
'use strict';
let payload = matrix[ e.target.dataset.state ];
payload.state = e.target.dataset.state;
oStore.set( payload );
e.target.dataset.state = 1 - e.target.dataset.state;
e.target.value=payload.name;
};
/* Bind DOM elements and event handlers rather than inline event handlers... */
const bindEvents=function(){
'use strict';
let json=false;
let bttn=document.querySelector( 'input[type="button"][name="units"]' );
bttn.addEventListener( 'click', switcher.bind( bttn ), flags );
/*
If the user has set his/her choice for units then we need
re-establish initial conditions for button on page load
should they leave & return etc
*/
if( json=oStore.get() ){
bttn.dataset.state = 1 - json.state;
bttn.value = json.name;
/*
potentially you can now access the value stored in the localStorage object
for whatever conversion purposes you have...
*/
}
/* other event listeners ... */
};
document.addEventListener( 'DOMContentLoaded', bindEvents, flags );
</script>
<body>
<!--
A standard button with default settings.
The value will change when clicked and
then on subsequent page loads also.
-->
<input type='button' name='units' value='Choose Units ' data-state=1 />
</body>
</html>
答案 1 :(得分:1)
这是一个更改样式规则的简单演示。有更复杂的方法可以解决这个问题,但这是一个简单的方法。默认情况下,您可以显示一个或两个单位。
要更改的规则必须存在于现有样式表中。
<style type="text/css">
.metric {
display: inline;
}
.imperial {
display: none;
}
</style>
<script>
// Search style sheets for selector. If found, set
// prop to value. Stops when first selector found
function setRuleValue(selector, prop, value) {
selector = selector.toLowerCase();
// Get the style sheets
var sheet, sheets = document.styleSheets;
var j, rule, rules;
if (sheets) {
// Search style sheets for rule
for (var i=0, iLen=sheets.length; i<iLen; i++) {
sheet = sheets[i];
j = 0;
// Choose .cssRules or .rules, whichever is supported
while (rule = (sheet.cssRules[j] || sheet.rules[j])) {
j++;
if (rule.selectorText.toLowerCase() == selector) {
rule.style[prop] = value;
// If had success, return true
return true;
}
}
}
}
// If get here, didn't find rule so return false
return false;
}
// Turn metric on, imperial off
function showMetric() {
setRuleValue('.metric', 'display', '');
setRuleValue('.imperial', 'display', 'none' );
}
// Turn imperial on, metric off
function showImperial() {
setRuleValue('.metric', 'display', 'none');
setRuleValue('.imperial', 'display', '' );
}
</script>
<div>This part is <span class="imperial">3 inches</span><span class="metric">25.4 mm</span> long</div>
<br>
<button onclick="showMetric()">Show metric</button>
<button onclick="showImperial()">Show imperial</button>
如果您有一个表,您可以为每个度量和英制创建一个colgroup,然后只需更改隐藏或显示的colgroup。默认情况下,显示两者。