2010-01-29 129 views
28

在CSS中,任何圖像路徑都是相對於CSS文件位置的。獲取腳本路徑

f.ex如果我把CSS文件中/media/css/mystyles.css和使用類似

.background:url(../images/myimage.jpg); 

該瀏覽器將尋找在/media/images/myimage.jpg圖像這是有道理的。

是否有可能在JavaScript中做同樣的事情?

F.ex如果我有/media/js/myscript.js,並把這個代碼在那裏:

var img = new Image(); 
img.src = '../images/myimage.jpg'; 

圖像爲沒有找到,因爲瀏覽器正在使用的,而不是腳本位置的HTML文件爲起點。我希望能夠使用腳本位置作爲起點,就像CSS一樣。 這可能嗎?

+3

FWIW Gecko 2.0增加了一個document.currentScript屬性。 https://developer.mozilla.org/en/DOM/document.currentScript – mjhm 2011-04-04 01:37:48

+0

可能的重複[如何從腳本中獲取腳本文件名?](http://stackoverflow.com/questions/710957/how-我可以從腳本中獲得腳本文件名) – Bergi 2013-07-17 15:41:58

+0

對於隨便的讀者,請在caniuse.com上監視由@mjhm監控的功能。 Upvote here:http://github.com/Fyrd/caniuse/issues/1099。 – Stephan 2016-03-24 15:17:35

回答

35

搜索自己<script>如上述標籤的DOM是常用的方法,是的。

但是,您通常不需要太難搜索:當您在腳本的主體中時 - 在包含時運行 - 您非常清楚您是哪個元素:最後一個。其餘的人還不能被解析。

var scripts= document.getElementsByTagName('script'); 
var path= scripts[scripts.length-1].src.split('?')[0];  // remove any ?query 
var mydir= path.split('/').slice(0, -1).join('/')+'/'; // remove last filename part of path 

function doSomething() { 
    img.src= mydir+'../images/myimage.jpeg'; 
} 

如果你的腳本已經與<script defer>(或者,在HTML5,<script async>)連接這並不成立。但是,這目前很少使用。

+0

更常用的還有一個問題,就是動態(ajax)加載,因爲包含的腳本被運行,然後拋出,並且從不出現在'scripts'數組中 – ekkis 2011-11-23 22:23:59

+7

異步加載越來越流行(也更容易),這是我不會definitelly依靠這個...... – 2014-11-22 01:45:07

+0

可選地,您可以掃描所有腳本標籤並查找包含腳本文件名的文件名,但即使是因爲某人可能已將其重命名而被擊中或錯過。 – 2015-12-14 07:26:25

1

(如果base [魯本斯的答案]不爲你工作編輯:。很顯然,他刪除它,但我認爲這是相關的;看到base在W3C網站)

這是可能的,但這是一個痛苦。 :-)您必須搜索導入腳本的script標記的DOM,然後獲取其值爲src的值。這就是script.aculo.us模塊自動加載的方式;舉例來說,您可以參考scriptaculous.js文件。

+0

沒有這麼大的痛苦。我發佈了一個簡短的腳本,可以做到這一點。 – yannis 2010-01-29 11:24:49

+0

@yannis:是的,你說得對,這不是什麼麻煩事。 – 2010-01-29 11:44:20

0

你可以翻轉<head>的childNodes,找到你的<script>標籤,獲取所述腳本的URL,並計算你的圖像的網址。

+0

也就是說,他可以做我在我的回答中提出的建議。;-) – 2010-01-29 10:13:57

+0

我通常會在''之前附加腳本,因爲不需要渲染頁面...... – 2014-11-22 01:48:11

0

一種方法是把路徑腳本本身:

var scriptPath = <?PHP echo json_encode(dirname($_SERVER['SCRIPT_NAME'])); ?>; 
6

正如其他海報提到你需要計算自己的基本網址爲腳本首先,你可以在下面的腳本來找到它。

// find the base path of a script 
var settings = {}; 
settings.basePath = null; 

if (!settings.basePath) { 
    (function (name) { 
    var scripts = document.getElementsByTagName('script'); 

    for (var i = scripts.length - 1; i >= 0; --i) { 
     var src = scripts[i].src; 
     var l = src.length; 
     var length = name.length; 
     if (src.substr(l - length) == name) { 
     // set a global propery here 
     settings.basePath = src.substr(0, l - length); 

     } 
    } 
    })('myfile.js'); 
} 

log(settings.basePath); 
+0

如果包含2個包含相同基本名稱(但來自不同位置)的腳本,則失敗。我知道這是不合理的,但人們會期望有一個簡單而可靠的解決方案來處理這樣一件基本的事情。 – 2014-11-22 01:46:36

6

受上述bobince回答的啓發,我寫了一個jQuery版本。下面是一行代碼:

var scriptpath = $("script[src]").last().attr("src").split('?')[0].split('/').slice(0, -1).join('/')+'/'; 

編輯:由src屬性過濾script標籤,使我們得到一個src去努力。

+1

我編輯了你的一行;您需要通過src屬性過濾腳本標籤(「script [src]」),以防最後一個腳本內聯。 – Timm 2012-06-06 14:30:49

0

請注意,此問題上的所有示例都帶有LAST標記,並指出不支持異步加載。所以如果你想做到完美的方式,你應該與你的腳本名稱ADDITIONALLY相匹配。實際上scriptaculous做到了這一點。

只是它的「不完整」的代碼高亮顯示,像http://areaaperta.com/nicescroll/項目中使用該版本的代碼

1

我寫一個類來找到獲得腳本,與延遲加載和異步腳本標籤工作的路徑問題。它基於檢查堆棧跟蹤,並且有幾個函數可以對結果進行格式化,但它的目標是基本的。如果沒有其他人使用它作爲參考。

function ScriptPath() { 
    var scriptPath = ''; 
    try { 
    //Throw an error to generate a stack trace 
    throw new Error(); 
    } 
    catch(e) { 
    //Split the stack trace into each line 
    var stackLines = e.stack.split('\n'); 
    var callerIndex = 0; 
    //Now walk though each line until we find a path reference 
    for(var i in stackLines){ 
     if(!stackLines[i].match(/http[s]?:\/\//)) continue; 
     //We skipped all the lines with out an http so we now have a script reference 
     //This one is the class constructor, the next is the getScriptPath() call 
     //The one after that is the user code requesting the path info (so offset by 2) 
     callerIndex = Number(i) + 2; 
     break; 
    } 
    //Now parse the string for each section we want to return 
    pathParts = stackLines[callerIndex].match(/((http[s]?:\/\/.+\/)([^\/]+\.js)):/); 
    } 

    this.fullPath = function() { 
    return pathParts[1]; 
    }; 

    this.path = function() { 
    return pathParts[2]; 
    }; 

    this.file = function() { 
    return pathParts[3]; 
    }; 

    this.fileNoExt = function() { 
    var parts = this.file().split('.'); 
    parts.length = parts.length != 1 ? parts.length - 1 : 1; 
    return parts.join('.'); 
    }; 
} 

Full source

+1

只適用於http(s)。 https://gist.github.com/eligrey/5426730支持任何協議 – 2014-04-30 18:39:10

0

在我的情況下,沒有scripts.length-1
示例:
在調試模式中的JS文件的位置://server/js/app.js
在PROD模式js文件位置://server/js-build/app.js
文件名是已知的;通過其名稱查找路徑的單一方式:

getExecutionLocationFolder() { 
    var fileName = "app.js"; 
    var scriptList = $("script[src]"); 
    var jsFileObject = $.grep(scriptList, function(el) { 
     var currentElement = el.src.contains(fileName); 
     return currentElement; 
    }); 
    var jsFilePath = jsFileObject[0].src; 
    var jsFileDirectory = jsFilePath.substring(0, jsFilePath.lastIndexOf("/") + 1); 
    return jsFileDirectory; 
}; 
0

您可以通過解析文檔標記並將其與文檔位置進行比較來檢索腳本路徑。

// get relative document path to script folder 
var pathToScript=function(scriptFileName){ 
    // scan document to get script location 
    var sclist = document.getElementsByTagName("script"); 
    var found = null; 
    for(var i=0;i<sclist.length&&!found;i++){ 
     // check if tag have source (avoid local scripts tags) 
     if(typeof(sclist[i].src)=="string"){ 
      // remove arguments and extract file basename 
      var file = sclist[i].src.split("?")[0].split("/").pop(); 
      // get path if found 
      if(file==scriptFileName)found = sclist[i].src.split("?")[0]; 
     } 
    } 
    // compare with document location 
    if(found){ 
     var _from = document.location.href.split("/"); 
     var _to__ = found.split("/"); 
     // remove files names 
     _from.pop();_to__.pop(); 
     // remove common pathes 
     while(_from.length>0&&_to__.length>0&&_from[0]==_to__[0]){ 
      _from.shift();_to__.shift(); 
     } 
     // add parent dir offset if any 
     while(_from.length>0){ 
      _to__.unshift("..");_from.pop(); 
     } 
     // return relative document path to script folder 
     return _to__.length>0?(_to__.join("/")+"/"):""; 
    }else{ 
     throw("\npathToScript Error :\nscript source '"+scriptFileName+"' not found in document."); 
    } 
}; 

// use in script file "myscript.js" : 
var pathToMe = pathToScript("myscript.js"); 
console.log("my dir : "+pathToMe); 
2

對於異步腳本,腳本標記行走將不會執行。 所以,如果: - performance.timing exists(如在新的非Safari瀏覽器) &你還沒有達到最大,或者已經被頂起它的最大承載 &你的腳本之前在最近一次的事裝:

performance.getEntries().slice(-1)[0].name 

要俯臥撐最大,做這樣的事情:

performance.webkitSetResourceTimingBufferSize(10000) 
+0

嗨..是否有任何瀏覽器性能相關的影響resourceBufferSize增加? – lucky 2015-05-23 15:54:36

+0

用於記錄的內存有一小部分,但我認爲它幾乎在每個客戶端都不起作用 – user1212212 2015-05-24 17:17:57

8

更多最新的瀏覽器,你可以使用document.currentScript屬性獲取HTMLScript eleme nt對應的那個腳本,然後查詢它的src屬性。

Can I use表示在撰寫本文時,網絡用戶的70%支持。顯然Internet Explorer不支持它,但Edge會。 MDC列出了對Chrome 29+,Edge,Firefox 4.0+,Gecko 2.0+,Opera 16+和Safari 8+的支持。 comment by @mjhm已經指出了這個功能,但當時它聽起來非常實驗性。

+0

http://caniuse.com尚未監視此功能。你可以在這裏獲得幫助:http://github.com/Fyrd/caniuse/issues/1099。 – Stephan 2016-03-24 15:19:07

+0

@Stephan:已經[完成](https://github.com/Fyrd/caniuse/issues/1099#issuecomment-153670757)。但其他人閱讀這個答案可能也想貢獻一下。 – MvG 2016-03-24 21:47:23

+0

很酷:)這個功能本月收到5個upvotes。它在添加列表的功能上排名第8。 – Stephan 2016-03-24 23:15:40