ユーザーが複数の都市に複数の選択ボックスを追加できるフォームがあります。問題は、新しく生成された各選択ボックスに一意のIDが必要であるということです。これはJavaScriptでできますか?
更新:ここは都市を選択するためのフォームの一部です。また、特定の州が選択されたときに都市を埋めるためにいくつかのPHPを使用していることに注意してください。
<form id="form" name="form" method="post" action="citySelect.php">
<select id="state" name="state" onchange="getCity()">
<option></option>
<option value="1">cali</option>
<option value="2">arizona</option>
<option value="3">texas</option>
</select>
<select id="city" name="city" style="width:100px">
</select>
<br/>
</form>
Javascriptは次のとおりです。
$("#bt").click(function() {
$("#form").append(
"<select id='state' name='state' onchange='getCity()'>
<option></option>
<option value='1'>cali</option>
<option value='2'>arizona</option>
<option value='3'>texas</option>
</select>
<select id='city' name='city' style='width:100px'></select><br/>"
);
});
単に実行中のインデックスを保持することはできませんか?
var _selectIndex = 0;
...code...
var newSelectBox = document.createElement("select");
newSelectBox.setAttribute("id","select-"+_selectIndex++);
[〜#〜] edit [〜#〜]
さらに検討すると、実際には選択に配列スタイルの名前を使用することを好むかもしれません...
例えば.
<select name="city[]"><option ..../></select>
<select name="city[]"><option ..../></select>
<select name="city[]"><option ..../></select>
次に、PHPのサーバー側で、たとえば:
$cities = $_POST['city']; //array of option values from selects
編集2 OPコメントへの応答
DOMメソッドを使用してオプションを動的に作成するには、次のようにします。
var newSelectBox = document.createElement("select");
newSelectBox.setAttribute("id","select-"+_selectIndex++);
var city = null,city_opt=null;
for (var i=0, len=cities.length; i< len; i++) {
city = cities[i];
var city_opt = document.createElement("option");
city_opt.setAttribute("value",city);
city_opt.appendChild(document.createTextNode(city));
newSelectBox.appendChild(city_opt);
}
document.getElementById("example_element").appendChild(newSelectBox);
cities
配列が既に存在すると仮定します
あるいは、innerHTMLメソッドを使用することもできます。
var newSelectBox = document.createElement("select");
newSelectBox.setAttribute("id","select-"+_selectIndex++);
document.getElementById("example_element").appendChild(newSelectBox);
var city = null,htmlStr="";
for (var i=0, len=cities.length; i< len; i++) {
city = cities[i];
htmlStr += "<option value='" + city + "'>" + city + "</option>";
}
newSelectBox.innerHTML = htmlStr;
ミリ秒タイマーを使用する別の方法:
var uniq = 'id' + (new Date()).getTime();
var id = "id" + Math.random().toString(16).slice(2)
function uniqueid(){
// always start with a letter (for DOM friendlyness)
var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65));
do {
// between numbers and characters (48 is 0 and 90 is Z (42-48 = 90)
var ascicode=Math.floor((Math.random()*42)+48);
if (ascicode<58 || ascicode>64){
// exclude all chars between : (58) and @ (64)
idstr+=String.fromCharCode(ascicode);
}
} while (idstr.length<32);
return (idstr);
}
非常に短い関数はあなたにユニークなIDを与えます:
var uid = (function(){var id=0;return function(){if(arguments[0]===0)id=0;return id++;}})();
アラート(uid());
@scottへの返信:JSが非常に高速になることがあります...だから...
var uniqueId = null,
getUniqueName = function(prefix) {
if (!uniqueId) uniqueId = (new Date()).getTime();
return (prefix || 'id') + (uniqueId++);
};
私はOPと同様の問題に取り組んでいますが、@ Guyと@Scottのソリューションの要素を組み合わせて、より強固なIMOのソリューションを作成できることがわかりました。結果の一意のIDには、アンダースコアで区切られた3つのセクションがあります。
このソリューションは、非常に大きなセットでも非常にうまく機能するはずです。
function uniqueId () {
// desired length of Id
var idStrLen = 32;
// always start with a letter -- base 36 makes for a Nice shortcut
var idStr = (Math.floor((Math.random() * 25)) + 10).toString(36) + "_";
// add a timestamp in milliseconds (base 36 again) as the base
idStr += (new Date()).getTime().toString(36) + "_";
// similar to above, complete the Id using random, alphanumeric characters
do {
idStr += (Math.floor((Math.random() * 35))).toString(36);
} while (idStr.length < idStrLen);
return (idStr);
}
次のようなインスタンスを名前空間に配置します
var myns = {/*.....*/};
myns.uid = new function () {
var u = 0;
this.toString = function () {
return 'myID_' + u++;
};
};
console.dir([myns.uid, myns.uid, myns.uid]);
const uid = function(){
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
この関数は、生成された日付でソートされる非常に一意のIDを生成します。データベースのIDにも使用できます。
カウンターの作成を避け、ページ上にIDを持つ要素を作成する他のコンポーネントがある場合でもIDが一意であることを確認するには、乱数を使用し、それが十分でない場合は修正する必要があります(ただし、競合を避けるために、すぐにIDを設定してください):
var id = "item"+(new Date()).getMilliseconds()+Math.floor(Math.random()*1000);
// or use any random number generator
// whatever prefix can be used instead of "item"
while(document.getElementById(id))
id += 1;
//# set id right here so that no element can get that id between the check and setting it
タイマーを使用してIDを生成し、performance.now()
を使用して重複を回避できます。
id = 'id' + performance.now()
dup = 'id' + performance.now()
console.log(id)
console.log(id.replace('.','')) // sexy id
console.log(id === dup) // false!
.as-console-wrapper{border-top: none !important;overflow-y: auto !important;top: 0;}
高解像度時間APIはすべての最近のブラウザーで利用可能です に注意してください。
警告:この回答はこの質問の一般的な意図には適さないかもしれませんが、それでもこの問題の部分的なバージョンを解決するため、ここに投稿します。
LodashのuniqueId
(ドキュメント ここ )を使用できます。これは、dbレコードなど、ブラウザでセッションを永続化するものなどに適したuniqueIdジェネレーターではありません。しかし、私がこれを探してここに来た理由は、それを使用することで解決しました。一時的なものに一意のIDが必要な場合は、これで十分です。
ラベルとフォームコントロールを備えた再利用可能な反応コンポーネントを作成していたため、必要でした。ラベルには、実際のフォームコントロールが持つfor="controlId"
に対応するid="controlId"
属性が必要です(入力または選択要素)。このコンテキストからこのIDは必要ありませんが、共有する両方の属性に対して1つのIDを生成し、レンダリングされるページのコンテキストでこのIDが一意であることを確認する必要があります。したがって、lodashの機能は問題なく機能しました。念のため、他の人に役立ちます。
ランダムはnot一意です。時間の値はnot一意です。概念はまったく異なり、アプリケーションがスケーリングされて配布されると、その違いは見苦しいものになります。上記の回答の多くは潜在的に危険です。
ポスターの質問へのより安全なアプローチはUUIDです: Create GUID/JavaScriptのUUID?
これは、必要なid prefex/IDに基づいて一意性についてDOMを再帰的にチェックする関数(関数genID())です。
あなたの場合、あなたはそれをそのように使うかもしれません
var seedNum = 1;
newSelectBox.setAttribute("id",genID('state-',seedNum));
function genID(myKey, seedNum){
var key = myKey + seedNum;
if (document.getElementById(key) != null){
return genID(myKey, ++seedNum);
}
else{
return key;
}
}
他の人が言ったように、実行中のインデックスを使用できます。または、変数を使用するという考えが気に入らない場合は、リストの最後の都市のIDを取得し、そのIDに1を追加します。
ランダムと日付をmsで組み合わせると、衝突の変化がほとんどないトリックを実行できます。
function uniqid(){
return Math.random().toString(16).slice(2)+(new Date()).getTime()+Math.random().toString(16).slice(2);
}
alert(uniqid()+"\r"+uniqid());
作成された要素のxpathに基づいた、私自身の見解を以下に示します。
/** Returns the XPATH of an element **/
var getPathTo = function(element) {
if (element===document.body)
return element.tagName;
var ix= 0;
var siblings= element.parentNode.childNodes;
for (var i= 0; i<siblings.length; i++) {
var sibling= siblings[i];
if (sibling===element)
// stripped xpath (parent xpath + tagname + index)
return getPathTo(element.parentNode)+ element.tagName + ix+1;
if (sibling.nodeType===1 && sibling.tagName===element.tagName)
ix++;
}
}
/** hashcode function (credit http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery **/
var hashCode = function(str) {
var hash = 0, i, chr, len;
if (str.length === 0) return hash;
for (i = 0, len = str.length; i < len; i++) {
chr = str.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
};
/** Genaretes according to xpath + timestamp **/
var generateUID = function(ele)
{
return hashCode(getPathTo(ele)) + new Date().getTime();
}
最初に、要素のxpathが取得されます。
次に、xpathのハッシュコードが計算されます。したがって、xpathごとに一意のIDがあります。
ここでの問題は、一意の要素がその場で生成される場合、xpathは必ずしも一意ではないということです。したがって、最後にタイムスタンプを追加します。
最終的なMath.Random()を追加することで、よりユニークな要素を保証することもできます。
次のような関数を使用します。
function (baseId) {
return baseId + '-' + Math.random().toString(16).slice(2);
}
パラメーターbaseId
では、要素を識別しやすくするためにIDのプレフィックスを示します。
closure
を利用できます。
_var i = 0;
function generateId() {
return i++;
}
_
それを囲む場合:
_function generator() {
var i = 0;
return function() {
return i++;
};
}
var generateId = generator();
generateId(); //1
generateId(); //2
_
generator
はデフォルトのプレフィックスを受け入れることができます。 generateId
coudはオプションのサフィックスを受け入れます:
_function generator(prefix) {
var i = 0;
return function(suffix) {
return prefix + (i++) + (suffix || '');
};
}
var generateId = generator('_');
generateId('_'); //_1_
generateId('@'); //_2@
_
これは、IDにnew Date().getTime()
に非常によく似ているが読みやすいシーケンスを示す場合に便利です。