1

Using Symfony 2.8.24 and jQuery 3.2.1

Been googling for this for a while now and, yes, there are lots of similar cases, involving using relative paths for resource loading but, none I have found which explains what I need, so SO:

I need to include (or load or append to head or something) a css file which is (lets say for simplicity) in the same folder as the js file, I'm trying to do so (and this is the real problem) using a relative path to it, (and this is the real real problem) relative to the js file, NOT the html file.

I really don't know if this is even possible so, you know, IMPOSSIBLE is a valid answer.

Also, the whole point of this is portability of course, this plugin I'm trying to make uses several css and js files all sitting in different folders inside the plugin folder structure and I intend to include (or load or append to head or something) each one if and when necessary. If I could do that making the process oblivious of where the plugin's top folder is copied, I would not have to change the absolute paths every time I use it in a different project.

Current/unwanted state:

var cssId = 'cssId';
if (!document.getElementById(cssId)) {
    var head = document.getElementsByTagName('head')[0];
    var link = document.createElement('link');
    $(link).attr({
       'id': cssId,
       'rel': 'stylesheet',
       'type': 'text/css',
       'href': urlBase + '/js/plugins/PluginName/main.css', //PROBLEM HERE
       //ideally previous line would be like: 'href': 'main.css',
       'media': 'all'
    });    
    head.appendChild(link);
}

Insights and ideas, on me!

Scaramouche
  • 3,188
  • 2
  • 20
  • 46
  • 2
    What's the point? Relative paths in JS file are counted based on the HTML file where the JS is run, not based on the path where the JS file has been saved. – Teemu Dec 27 '17 at 17:43
  • @Teemu that's something I didn't know, thanx. Then again, how does it help me, sorry, I'm really not seeing how to use your tip for my problem, or does this mean there is no way to achieve what I want... – Scaramouche Dec 27 '17 at 19:24
  • You can change the base of a HTML document with [`base element`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base), though this may mess the navigation. – Teemu Dec 27 '17 at 19:43
  • @Teemu, does it mean it's gonna be up to the user of the plugin (me in this case) to manually include in their `html` every `css` and `js` file they need when needed because there is no way to "pull" them from where ever the files are inside the plugin folder structure? – Scaramouche Dec 27 '17 at 20:08
  • More or less yes. A consistent folder structure would help, also in some conditions you can get value for the `urlBase` variable, see https://stackoverflow.com/a/22745553/1169519 . An alternative is to use a task runner, like [Gulp](https://gulpjs.com/) or [Grunt](https://gruntjs.com/). – Teemu Dec 28 '17 at 05:26

1 Answers1

1

A tricky hack would be to use Error.stack, which is supported in current browsers but is not yet standardized.

c1CssImport = function (location) { // todo: handle absolute urls
    const e = new Error();
    const calledFile = e.stack.split('\n')[2].match(/[a-z]+:[^:]+/);
    const calledUrl = new URL(calledFile);
    calledUrl.search = '';
    const target = new URL(location, calledUrl).toString();
    for (let el of document.querySelectorAll('link[rel=stylesheet]')) {
        if (el.href === target) return; // already loaded
    }
    const link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = target;
    document.head.append(link);
    // todo: return a promise
}

Then just call c1CssImport() where you like to include relative-url based css files:

c1CssImport('./ui.css');

note:

  • you dont need jQuery
  • The script only includes the CSS once
  • absolute urls are not handled in this script
  • i dont know if js-files included from other domains can handle this technic (not tested)

For js includes i recommentd using js modules

Tobias Buschor
  • 3,075
  • 1
  • 22
  • 22