what is the best way to do this?

Discussion in 'General Webmaster Support' started by Slapshot136, Feb 4, 2013.

  1. Slapshot136

    Slapshot136 Divide et impera

    Ratings:
    +483 / 2 / -0
    I have a bunch of data that will be repeated on many pages of site, and I want to store all that data in a just a couple files, but I can't use any server-side technologies (this website needs to live on a NAS where I only have read/write access, no execute), which means HTML, CSS, and JS (unless I am forgetting something), but that would likely be rather complicated - what I have tried is using JS imports and CSS set to display:none; but that has issues with me being unable to overrrule the display:none; is there some way of hiding all but couple elements per page? or is there some easy way of JS reading from something like a .CSV?

    I have also tried setting the visibility to false as opposed to display: none, but that leads to page formatting issues (especially when printing!)

    I am not very good with JS so I am probably missing something.. but ideally I would like to just have a class/subclass structure for my data and just insert 1 variable at a time via JS

    if this is going to be complicated, I suppose I could program something elsewhere and run it to create my static site, and then re-run it if I ever change the data..
     
  2. Artificial

    Artificial Without Intelligence

    Ratings:
    +325 / 0 / -0
    I am unsure of what your situation quite is. Is the repeated data stuff like headers and footers that are present on all pages and what you're trying to hide and show the actual content? Overruling display: none; should indeed be quite easy to do, but I can't say what's wrong with your code for it without seeing it.

    Besides your approach, which sends all of the data on your site on every request, I would consider the approach of loading the content dynamically with JS. I'll give you an example of how I'd do this to make it a bit clearer.

    File structure:
    Code:
    /index.html - These HTML files are all the same file, the layout file
    /page1.html
    /page2.html
    /data/index.html - These files store the actual content of the pages.
    /data/page1.html
    /data/page2.html
    
    So /data/index.html could contain for example the following:
    HTML:
    <p>Hello world!</p>
    <p>This is text!</p>
    
    And the layout files the following:
    HTML:
    <!doctype html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>My Site</title>
      </head>
      <body>
        <header>
          <h1>Header</h1>
        </header>
        <div id="content"></div>
        <footer>
          Footer here
        </footer>
        
        <script>
            var req = new XMLHttpRequest();
            req.onreadystatechange = function () {
              if (req.readyState == 4) {
                document.getElementById('content').innerHTML = req.response;
              }
            };
            req.open('GET', '/data' + window.location.pathname);
            req.send();
        </script>
      </body>
    </html>
    
    What the JavaScript here does is request the contents of /data/name-of-the-file-you're-viewing and insert that inside the div#content element.

    Quite a lot of people actually do that for their blogs and stuff. If you are to do this, I would suggest taking a look at Jekyll, a static site generator that has quite a bit of flexibility for things like this.
     
    • Like Like x 1
  3. Slapshot136

    Slapshot136 Divide et impera

    Ratings:
    +483 / 2 / -0
    the data is the actual main content, only the site itself is to organize that content and be like a drill-down menu, like the index page would be "fleet", and then it goes into "cars" and "trucks", and then further down into the details of each "car" and "truck" like "car1" "car2" etc. - the thing is if the name of "car1" changes, I want to change it only in the data file, and have those changes show on all the pages where it appeared

    is there any way to use JS to grab only a specific part of an html file, like only that matching id="car1"? as I don't want to have tons of data files to import into each site

    alternatively can I have a large JS class with sub-classes and variables, and just read those variables wherever I need them?

    or can JS read information from like a CSV file in an easy way?
     
  4. Artificial

    Artificial Without Intelligence

    Ratings:
    +325 / 0 / -0
    In that case the solution I suggested isn't that great. While JS can't that easily read CSV files, it can read JSON files, which would be a better fit for representing the data anyway. A simple example of a JSON file containing data fitting your case:
    Code:
    {
      "fleet": {
        "cars": {
          "car1": {
            "weight": 600,
            "capacity": 4
          },
          "car2": {
            "weight": 900,
            "capacity": 5
          }
        },
        "trucks": {
          "truck1": {
            "weight": 2200,
            "capacity": 3
          }
        }
      }
    }
    
    As you can see, this is a sub-syntax of JavaScript's object literals (JSON stands for JavaScript Object Notation), so turning this data into a JavaScript object is a breeze.

    It sounds like you what you need to do is create a single-page application, which gets quite a bit trickier than the earlier suggestion as template rendering and URL routing become necessary. I wouldn't recommend building these components yourself, but using a library made for creating single-page applications, such as Backbone or Ember. Based on my experience the libraries can be slightly difficult to get started with, though, but quite powerful once you've learned to use them.

    If you go for this route, the only thing you'd need to do when data changes is changing it in the JSON - no editing the templates or HTML or anything should be necessary.
     
    • Like Like x 1
  5. Slapshot136

    Slapshot136 Divide et impera

    Ratings:
    +483 / 2 / -0
    I will try that, but I forgot to add my CSS issue (which still bugs me because it's unresolved) - I tried doing this:


    <span id="car1" class="hide">
    car1 info
    </span>

    <span id="car2" class="hide">
    car2 info
    </span>

    and importing those via JS - that worked, but then I tried using this CSS:

    #car1
    {
    display:inline;
    }
    .hide
    {
    display:none;
    }
    and for some reason both would be hidden - but if I changed display with visibility, then it would show only car1 (and a blank space occupied by what would have been car 2)
     
  6. Artificial

    Artificial Without Intelligence

    Ratings:
    +325 / 0 / -0
    That display: inline; should indeed override the display: none;, as you can see in this simple demo. There must be something else in your CSS not causing it to work.
     
    • Like Like x 1
  7. Slapshot136

    Slapshot136 Divide et impera

    Ratings:
    +483 / 2 / -0
    i fail at importing (turns out that is what broke my CSS earlier), can i ask what the import should look like for the JSON data?
     
  8. Slapshot136

    Slapshot136 Divide et impera

    Ratings:
    +483 / 2 / -0
    bump - how exactly should the JS import of the .JSON file look like, and how would it be inserted into the html page?
     
  9. Artificial

    Artificial Without Intelligence

    Ratings:
    +325 / 0 / -0
    There are two ways of getting that JSON to your JavaScript code. The first is to just embed it directly into your JavaScript code (as JSON is just a small subset of JS):
    Code:
    var data = {"fleet": {...}};
    The second way is to use an XMLHttpRequest to request the JSON file from the server, and then parse it into an object using JSON.parse:
    Code:
    var req = new XMLHttpRequest();
    req.onreadystatechange = function () {
      if (req.readyState == 4) {
        var data = JSON.parse(req.response);
        doSomethingWithData(data);
      }
    };
    req.open('GET', '/data.json');
    req.send();
    
    A perhaps easier way of doing this is using jQuery:
    Code:
    $.getJSON(
      '/data.json',
      function (data) {
        doSomethingWithData(data);
      }
    );
    
    Using the request style lets you have the data in a pure JSON file, which can make it easier to maintain, especially if you create the file programmatically (most languages have a way to export data to a JSON format).
     
  10. Slapshot136

    Slapshot136 Divide et impera

    Ratings:
    +483 / 2 / -0
    the direct way means I can't use it in it's own individual data file, and the xmlrequest doesn't seem to work with local files for some reason...
     
  11. Artificial

    Artificial Without Intelligence

    Ratings:
    +325 / 0 / -0
    With the direct way, you could have a JavaScript file that contains nothing but the variable assignment, which makes it pretty close to being just a data file.

    And yes, browsers prevent websites from making requests to your local file system - how would you feel if for example TH would crawl through your file system and send information about it to the server? In order to test them you need to have a server running. If you have Python installed, a simple way of doing this would be to open up a terminal, cd to your working directory (the directory containing the files you're working on), and running "python -m SimpleHTTPServer". Then you point your browser to http://localhost:8000, and the XMLHttpRequest will work normally.
    Code:
    $ cd Projects/mysite/
    $ python -m SimpleHTTPServer
    Serving HTTP on 0.0.0.0 port 8000 ...
    Any other server capable of serving static files is also acceptable for the job.
     
  12. Slapshot136

    Slapshot136 Divide et impera

    Ratings:
    +483 / 2 / -0
    I won't have a server running.. I can import HTML and CSS just fine, but not JSON?

     
  13. Artificial

    Artificial Without Intelligence

    Ratings:
    +325 / 0 / -0
    How do you access the files on the NAS server using your browser? Do you use a URL starting with "file://" or "http://" (or "https://")? If you use a "http(s)://" URL, there is server software running to serve those HTML, CSS, and JS files - whether or not you're able to make said software run any of your server-side technologies is irrelevant. If it is a URL starting with "file://", then you will indeed not be able to make XMLHttpRequests to it, you will have to fall back on having a JS file with the data being assigned to a variable.
     
  14. Slapshot136

    Slapshot136 Divide et impera

    Ratings:
    +483 / 2 / -0
    I am using file:// - CSS and html imports work, and JS runs, but can't seem to access any files - if I save the JSON within a html, can I access that from a different html?
     
  15. Artificial

    Artificial Without Intelligence

    Ratings:
    +325 / 0 / -0
    You should save the JSON in a .js file, for example "data.js", which would contain only something like this:
    Code:
    var data = {fleet: {...}};
    Then you can include this JS file in multiple files using the tag
    Code:
    <script src="data.js"></script>
    Then any scripts included after that will be able to access the global variable 'data', which contains your data.
     
    • Like Like x 1
  16. monoVertex

    monoVertex I'm back!

    Ratings:
    +459 / 0 / -0
    First off, XHRs do not work (in Chrome, at least), on the local file system because there are security risks involved. In Chrome you can override that in the dev tools, but I am not sure about other browsers.

    Second, in your code you should never import stuff using the absolute path (file://...), but rather use relative paths. This is in case you are not already using them.

    What Artifical suggested, the JS files containing your data, is a good idea, but it can get ugly if you start having HTML inside those strings and JavaScript also sucks for not allowing multi-line strings.

    Thus, I come with another solution: m4. This is a macro processor, which can be easily installed on an Unix system and can also be used on Windows through Cygwin or similar methods. It allows you to do various actions which are afterwards compiled with the m4 processor and one of this actions is the 'include' procedure. It will allow you to keep the HTML code in various files and include them however you like. You can find a tutorial here.

    After getting your entire HTML in a single file, you can use JavaScript to hide / show your content. This saves you the work with XHRs (which are asynchronous, by the way, and that might prove to be a pain in the ass) and also lets you group your common content in various files. You can also use a combination of the two methods, it's up to you. They are not mutually exclusive, because m4 is a pre-processor, while XHRs will be used at run-time.

    I also have a third suggestion for you: if you can open ports to the server, you could use node.js and code your own HTTP server using the express package (yes, this means using JavaScript both server-side and client-side, which is awesome, in my opinion :D). But this might be overkill, if your project is small in size.
     
    • Like Like x 1

Share This Page