Làm cách nào để chuyển các tham số vào thẻ Script?


89

Tôi đã đọc hướng dẫn Tự làm widget - Cách nhúng trang web của bạn vào một trang khác cho XSS Widgets của Tiến sĩ Nic.

Tôi đang tìm cách chuyển các thông số vào thẻ script. Ví dụ, để làm cho công việc sau:

<script src="http://path/to/widget.js?param_a=1&amp;param_b=3"></script>

Có cách nào để làm việc này không?


Hai liên kết thú vị:


Câu trả lời:


118

Tôi xin lỗi vì đã trả lời một câu hỏi quá cũ nhưng sau một giờ vật lộn với các giải pháp trên, tôi đã chọn những thứ đơn giản hơn.

<script src=".." one="1" two="2"></script>

Bên trong tập lệnh trên:

document.currentScript.getAttribute('one'); //1
document.currentScript.getAttribute('two'); //2

Dễ dàng hơn nhiều so với jquery HOẶC phân tích cú pháp url.

Bạn có thể cần polyfil cho doucment.currentScript từ câu trả lời của @Yared Rodriguez dành cho IE:

document.currentScript = document.currentScript || (function() {
  var scripts = document.getElementsByTagName('script');
  return scripts[scripts.length - 1];
})();

5
Lưu ý rằng currentScript không hoạt động trong IE. Chi tiết
Dehli

Tôi đã thêm một polyfill cho IE trong câu trả lời. Polyfill không hoạt động?
Richard Fox

2
polyfill không hoạt động nữa, document.currentScript chỉ được đọc và không thể được gán nếu nó đã tồn tại. có lẽ một tấm séc khác nhau như if (document.currentScript!) {*** chức năng polyfill ***} sẽ làm việc tốt hơn
fadomire

2
Tôi xin lỗi David, tôi luôn đưa ra câu trả lời chung chung để những người khác có thể sử dụng giải pháp mà không có chi tiết triển khai ban đầu làm tăng thêm vấn đề. Trong ví dụ của tôi ở trên, bạn có thể nhìn thấy src="..."này có nghĩa là để biểu thị, BẤT CỨ src, không quan trọng :)
Richard Fox

1
@RichardFox cảm ơn vì câu trả lời, nhưng chỉ phải nhận xét rằng "Không trả lời câu hỏi gốc: không sử dụng đường dẫn / to / widget.js" có lẽ là điều hài hước nhất mà tôi đã đọc cả tuần! Không thể tin rằng bạn đã trả lời độc đáo như bạn đã làm.
Skintest

63

Tốt hơn nên sử dụng tính năng trong html5 5 Thuộc tính dữ liệu

<script src="http://path.to/widget.js" data-width="200" data-height="200">
</script>

Bên trong tệp script http://path.to/widget.js, bạn có thể lấy paremeters theo cách đó:

<script>
function getSyncScriptParams() {
         var scripts = document.getElementsByTagName('script');
         var lastScript = scripts[scripts.length-1];
         var scriptName = lastScript;
         return {
             width : scriptName.getAttribute('data-width'),
             height : scriptName.getAttribute('data-height')
         };
 }
</script>

Điều gì sẽ xảy ra nếu id = "myAwesomeWigretNo1" không giống như vậy nhưng myAwesomeWigretNo2, hoặc myAwesomeWigretNo681??? Làm cách nào để sửa lỗi này để chấp nhận một biến thực?
Pathros

9
Đối với những gì nó có giá trị, có những cách khác để tham khảo các kịch bản thay vào đó, chẳng hạn như document.currentScript(chỉ hoạt động cho các kịch bản không trong tập tin riêng của họ) và chấm idtrên <script>thẻ và sau đó tìm kiếm nó bằng cách đó.
Thunderforge

Và điều gì sẽ xảy ra nếu ID bị thay đổi bởi một số lập trình viên khác trong nhóm của bạn mà không có manh mối nào cho thấy bạn sử dụng id này?
OBender

1
Nếu bạn tải các tập lệnh không đồng bộ thì sử dụng ID là lựa chọn đáng tin cậy duy nhất mà tôi muốn giới thiệu. Cảm ơn @Thunderforge ... Ngoài ra, bất kỳ lập trình viên nên ngưng refactoring mã mà không có một kế hoạch chạy nước rút thích hợp khái quát bởi một người có một đầu mối về những gì đang xảy ra;)
Luca Borrione

Chắc chắn bạn có thể yêu cầu một Đạo đức mạnh mẽ từ Nhà phát triển, nhưng nó sẽ không hoạt động về lâu dài ... Mọi người quên thứ .... Trong một thiết kế phần mềm tốt Mỗi khối Shod được tách biệt, tuyệt vời-pixels.tumblr.com/post/101930002170 /… Vi.wikipedia.org/wiki/SOLID_(object-oriented_design) Vì vậy, tôi không tranh luận rằng đó là một giải pháp tốt hay xấu, nó chỉ phức tạp hơn để duy trì ID thay vì duy trì :-) tải tập lệnh Async Tôi không thấy lý do gì để tải bằng ID
OBender

17

Hiểu rồi. Loại hack, nhưng nó hoạt động khá tốt:

var params = document.body.getElementsByTagName('script');
query = params[0].classList;
var param_a = query[0];
var param_b = query[1];
var param_c = query[2];

Tôi chuyển các tham số trong thẻ script dưới dạng các lớp:

<script src="http://path.to/widget.js" class="2 5 4"></script>

Bài báo này đã giúp rất nhiều.


1
Bài báo thật tuyệt vời!
Bartek Skwira

14
Các lớp nên được sử dụng để tạo kiểu cho phần tử không chuyển các tham số.
kspacja

5
@kspacja Vâng và HTML chỉ nên chứa nội dung mà không có kiểu dáng, ngoại trừ việc chúng ta phải sắp xếp chính xác các thẻ DIV của mình cho bố cục float và cột vì CSS thực sự không thể thực hiện công việc và bằng cách nào đó chúng tôi vẫn ổn với điều đó. Tôi nói là hack đi. Nhưng bạn có thể sử dụng thuộc tính "data-" nếu bạn muốn tránh xung đột hoặc bạn thuộc loại mất ngủ vì nó.
Jason C

13

Một cách khác là sử dụng thẻ meta. Bất kỳ dữ liệu nào được cho là được chuyển đến JavaScript của bạn đều có thể được gán như sau:

<meta name="yourdata" content="whatever" />
<meta name="moredata" content="more of this" />

Sau đó, dữ liệu có thể được lấy từ các thẻ meta như thế này (thực hiện tốt nhất trong trình xử lý sự kiện DOMContentLoaded):

var data1 = document.getElementsByName('yourdata')[0].content;
var data2 = document.getElementsByName('moredata')[0].content;

Hoàn toàn không gặp rắc rối với jQuery hoặc những thứ thích, không cần hack và giải pháp thay thế, và hoạt động với bất kỳ phiên bản HTML nào hỗ trợ thẻ meta ...


Tôi nghĩ rằng phương pháp này cho đến nay là phương pháp dễ dàng nhất. Nó hoạt động như một sự quyến rũ và mang lại cho tôi chính xác những gì tôi cần. Câu hỏi hay và giải pháp tuyệt vời!
arios

10

JQuery có một cách để chuyển các tham số từ HTML sang javascript:

Đặt cái này vào myhtml.htmltệp:

<!-- Import javascript -->
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
<!-- Invoke a different javascript file called subscript.js -->
<script id="myscript" src="subscript.js" video_filename="foobar.mp4">/script>

Trong cùng một thư mục, hãy tạo một subscript.jstệp và đặt tệp này vào đó:

//Use jquery to look up the tag with the id of 'myscript' above.  Get 
//the attribute called video_filename, stuff it into variable filename.
var filename = $('#myscript').attr("video_filename");

//print filename out to screen.
document.write(filename);

Phân tích kết quả:

Đang tải trang myhtml.html có 'foobar.mp4' được in ra màn hình. Biến có tên video_filename đã được chuyển từ html sang javascript. Javascript đã in nó ra màn hình và nó xuất hiện dưới dạng được nhúng vào html trong cha mẹ.

jsfiddle bằng chứng rằng những điều trên hoạt động:

http://jsfiddle.net/xqr77dLt/


7

Nếu bạn đang sử dụng jquery, bạn có thể muốn xem xét phương pháp dữ liệu của họ.

Tôi đã sử dụng một cái gì đó tương tự như những gì bạn đang thử trong phản hồi của mình nhưng như thế này:

<script src="http://path.to/widget.js" param_a = "2" param_b = "5" param_c = "4">
</script>

Bạn cũng có thể tạo một hàm cho phép bạn lấy trực tiếp các thông số GET (đây là những gì tôi thường sử dụng):

function $_GET(q,s) {
    s = s || window.location.search;
    var re = new RegExp('&'+q+'=([^&]*)','i');
    return (s=s.replace(/^\?/,'&').match(re)) ? s=s[1] : s='';
}

// Grab the GET param
var param_a = $_GET('param_a');

4

nó là một chủ đề rất cũ, tôi biết nhưng điều này cũng có thể hữu ích nếu ai đó đến đây khi họ tìm kiếm giải pháp.

Về cơ bản, tôi đã sử dụng document.currentScript để lấy phần tử từ nơi mã của tôi đang chạy và tôi lọc bằng cách sử dụng tên của biến mà tôi đang tìm kiếm. Tôi đã mở rộng currentScript với một phương thức được gọi là "get", vì vậy chúng tôi sẽ có thể tìm nạp giá trị bên trong tập lệnh đó bằng cách sử dụng:

document.currentScript.get('get_variable_name');

Bằng cách này, chúng ta có thể sử dụng URI chuẩn để truy xuất các biến mà không cần thêm các thuộc tính đặc biệt.

Đây là mã cuối cùng

document.currentScript.get = function(variable) {
    if(variable=(new RegExp('[?&]'+encodeURIComponent(variable)+'=([^&]*)')).exec(this.src))
    return decodeURIComponent(variable[1]);
};

Tôi đã quên về IE :) Nó không thể dễ dàng hơn ... Tôi không đề cập rằng document.currentScript là một thuộc tính HTML5. Nó chưa được bao gồm cho các phiên bản IE khác nhau (tôi đã thử nghiệm cho đến IE11, và nó vẫn chưa có). Để tương thích với IE, tôi đã thêm phần này vào mã:

document.currentScript = document.currentScript || (function() {
  var scripts = document.getElementsByTagName('script');
  return scripts[scripts.length - 1];
})();

Những gì chúng ta đang làm ở đây là xác định một số mã thay thế cho IE, mã này trả về đối tượng script hiện tại, được yêu cầu trong giải pháp để trích xuất các tham số từ thuộc tính src. Đây không phải là giải pháp hoàn hảo cho IE vì có một số hạn chế; Nếu tập lệnh được tải không đồng bộ. Các trình duyệt mới hơn nên bao gồm thuộc tính ".currentScript".

Tôi hy vọng nó sẽ giúp.


3

Nhờ jQuery, một giải pháp tuân thủ HTML5 đơn giản là tạo một thẻ HTML bổ sung, như div, để lưu trữ dữ liệu.

HTML :

<div id='dataDiv' data-arg1='content1' data-arg2='content2'>
  <button id='clickButton'>Click me</button>
</div>

JavaScript :

$(document).ready(function() {
    var fetchData = $("#dataDiv").data('arg1') + 
                    $("#dataDiv").data('arg2') ;

    $('#clickButton').click(function() {
      console.log(fetchData);
    })
});

Bản demo trực tiếp với mã ở trên: http://codepen.io/anon/pen/KzzNmQ?editors=1011#0

Trên bản demo trực tiếp, người ta có thể thấy dữ liệu từ các thuộc tính data- * của HTML5 được nối và in vào nhật ký.

Nguồn: https://api.jquery.com/data/


1
Đã xem qua một số giải pháp khác, nhưng đây là giải pháp hoạt động tốt nhất và cũng khá đơn giản để thực hiện. cảm ơn!
Erik Kalkoken

Đây phải là giải pháp được chấp nhận, vì nó cho phép bạn tham chiếu tập lệnh theo ID và là HTML5 hợp lệ.
Tim S

2

Đặt các giá trị bạn cần ở một nơi nào đó mà tập lệnh khác có thể truy xuất chúng, chẳng hạn như đầu vào ẩn và sau đó kéo các giá trị đó từ vùng chứa của chúng khi bạn khởi tạo tập lệnh mới của mình. Bạn thậm chí có thể đặt tất cả các tham số của mình dưới dạng chuỗi JSON vào một trường ẩn.


Cảm ơn vì đã trả lời. Các tham số thực sự được nhập bởi người dùng (người nhúng thẻ tập lệnh này vào mã của họ). Sau đó là gì?
Tomer Lichtash

Điều duy nhất tôi có thể nghĩ đến nếu bạn không có quyền kiểm soát cả hai tập lệnh máy khách / máy chủ là sử dụng dữ liệu đầu vào của người dùng và sử dụng nó để tạo tệp .js cụ thể với đầu vào của họ được nhúng trong đó và điều đó giả sử bạn nắm quyền kiểm soát thu thập và xử lý đầu vào của họ.
bwest

Không trả lời câu hỏi ban đầu: đặt các đối số ở đâu khi không có biểu mẫu để giữ trường Ẩn?
David Spector

2

Tạo một thuộc tính có chứa danh sách các tham số, như sau:

<script src="http://path/to/widget.js" data-params="1, 3"></script>

Sau đó, trong JavaScript của bạn, hãy lấy các tham số dưới dạng một mảng:

var script = document.currentScript || 
/*Polyfill*/ Array.prototype.slice.call(document.getElementsByTagName('script')).pop();

var params = (script.getAttribute('data-params') || '').split(/, */);

params[0]; // -> 1
params[1]; // -> 3

Nhược điểm của phương pháp này là gì?
Tronathan

@Tronathan không có nhược điểm thực sự nào đối với phương pháp này và có một polyfill đi kèm để hỗ trợ trình duyệt tốt hơn. Nhược điểm duy nhất mà tôi thấy ở đây là không thể bao gồm dấu phẩy trong các tham số, điều này thường không phải là vấn đề và bạn có thể bù đắp điều đó bằng cách thay đổi dấu phân cách thành một ký tự mà bạn không định sử dụng.
Mystical

2

Tôi muốn có các giải pháp với sự hỗ trợ của các trình duyệt cũ càng nhiều càng tốt. Nếu không, tôi muốn nói rằng currentScript hoặc phương thức thuộc tính dữ liệu sẽ là phong cách nhất.

Đây là phương pháp duy nhất chưa được đưa ra ở đây. Đặc biệt, nếu vì lý do nào đó bạn có lượng lớn dữ liệu, thì tùy chọn tốt nhất có thể là:

lưu trữ cục bộ

/* On the original page, you add an inline JS Script: */
<script>
   localStorage.setItem('data-1', 'I got a lot of data.');
   localStorage.setItem('data-2', 'More of my data.');
   localStorage.setItem('data-3', 'Even more data.');
</script>

/* External target JS Script, where your data is needed: */
var data1 = localStorage.getItem('data-1');
var data2 = localStorage.getItem('data-2');
var data3 = localStorage.getItem('data-3');

localStorage có hỗ trợ trình duyệt hiện đại đầy đủ và hỗ trợ tốt đáng ngạc nhiên cho các trình duyệt cũ hơn, trở lại IE 8, Firefox 3,5 và Safari 4 [11 năm trở lại] trong số những trình duyệt khác.

Nếu bạn không có nhiều dữ liệu, nhưng vẫn muốn hỗ trợ trình duyệt rộng rãi, có thể lựa chọn tốt nhất là:

Thẻ meta [bởi Robidu]

/* HTML: */
<meta name="yourData" content="Your data is here" />

/* JS: */
var data1 = document.getElementsByName('yourData')[0].content;

Lỗ hổng của điều này là vị trí chính xác để đặt thẻ meta [cho đến khi HTML 4] nằm trong thẻ head và bạn có thể không muốn dữ liệu này ở đó. Để tránh điều đó hoặc đặt thẻ meta trong nội dung, bạn có thể sử dụng:

Đoạn ẩn

/* HTML: */
<p hidden id="yourData">Your data is here</p>

/* JS: */
var yourData = document.getElementById('yourData').innerHTML;

Để được hỗ trợ nhiều hơn cho trình duyệt, bạn có thể sử dụng lớp CSS thay vì thuộc tính ẩn:

/* CSS: */
.hidden {
   display: none;
}

/* HTML: */
<p class="hidden" id="yourData">Your data is here</p>

2

Đây là Giải pháp cho jQuery 3.4

<script src="./js/util.js" data-m="myParam"></script>
$(document).ready(function () {
    var m = $('script[data-m][data-m!=null]').attr('data-m');
})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.