1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Options in XenForo JS

Discussion in 'XenForo Development Discussions' started by Robust, Dec 21, 2015.

  1. Robust

    Robust Well-Known Member

    How'd you get options in XF's JS files? I can't see any usage of XenForo's options in the core JS. I need to get a value set by the administrator in the options.
     
  2. Jake B.

    Jake B. Well-Known Member

    You'd set a js variable with the value of the option
     
  3. Robust

    Robust Well-Known Member

    Yeah, but how do I get the value of the option? I don't see any methods to interact with XenForo's options.

    I'm overriding an existing XenForo js function, btw.
     
  4. Jake B.

    Jake B. Well-Known Member

  5. Robust

    Robust Well-Known Member

  6. 0ptima

    0ptima Well-Known Member

  7. Robust

    Robust Well-Known Member

  8. Jeremy P

    Jeremy P Well-Known Member

    He means to place that in a XenForo template (like page_container_js_head) where $xenOptions can be parsed, and then access 'myVar' from your JavaScript file.

    $xenOptions is a globally-available template variable.
     
  9. Daniel Hood

    Daniel Hood Well-Known Member

    template modification on PAGE_CONTAINER:

    Code:
    $.extend(XenForo, {
    randomExample: {$xenOptions.optionId}
    });
    
    Then in your javascript call
    Code:
    XenForo.randomExample
    Something like this could work?
     
  10. cclaerhout

    cclaerhout Well-Known Member

    If you try to understand the code, especially the one in the template, it should become kinda useful (for what you are trying to achieve).
    Good luck.
     
    Robust and Jake B. like this.
  11. Robust

    Robust Well-Known Member

    Which of the above methods is better? Both make a "variable" accessible for use, is there a 'better' method? In terms of efficiency or good practice?
     
  12. Robust

    Robust Well-Known Member

    I just used one of them for now, unless the other is better. Thanks everyone! I'd say I love you, but some people might get the wrong idea, so I'll just say I love your assistance ;)
     
    SneakyDave likes this.
  13. Chris D

    Chris D XenForo Developer Staff Member

    I would go with either Cédric's solution as suggested by 0ptima or Daniel Hood's solution.

    If you look at Daniel's solution, it's essentially what XF does in the page_container_js_body template - it's how we pass things like the user ID, certain options, style properties into the JS.

    Cédric's solution is also used widely within XF which uses the HTML5 data attribute to pass arbitrary values from the HTML to be read using the data() function in jQuery. e.g. simplified example:
    HTML:
    <button class="Button" data-any-name-you-like="any value you like">Button</button>
    <script>
        var $button = $('button.Button');
        alert($button.data('any-name-you-like')); // creates an alert with the text "any value you like"
    </script>
    I guess the deciding factor depends on the rest of your code. If you are working in JS with a single element or a simple set of elements, then getting the value from the data- attribute works best, because you can just read the data attribute from that element like you can read any attribute.

    If your option needs to be accessed across a number of functions, by a number of elements and/or be available on multiple XF pages, that's where Daniel's solution maybe works best; it makes the variable available within the XenForo namespace in the JS, therefore making the scope of its use wider and potentially more convenient than applying that value to specific elements.

    Jake's solution could also work, but I feel like the other options are more elegant.
     
    eva2000, SneakyDave, Steve F and 3 others like this.
  14. Robust

    Robust Well-Known Member

    Thanks, @Chris D! I'm actually using Daniel's solution right now. I extend the profile post limitations and change those, editing a bunch of areas to add data attributes wouldn't be appropriate, however I didn't realise that was his solution. I only looked through the library and js folders, probably why it didn't all add up. That's a good solution.

    Since I'm extending an existing function, I could add a lot of template modifications or just make it global, I ended up just making it global in case the end user added profile post areas anywhere else in XF, and xenforo.js is global and the code for it is contained in there, of course. A concern was mostly that it's going to increase page load time, especially for sites with high fetch time (a lot of time wasted in waiting and receiving the data to begin the request).

    I did encounter another problem. What I often do is for small edits edit core XF files to make sure it works, then put it into an extending XFCP class (and undo the ones to the core). I noticed afterwards that extending a DataWriter preSave method is hard to extend.

    So I'm adjusting the var $maxLength, it's really basic. But then I should also be calling the parent preSave function in case other add-ons wish to extend it, as well. I mean, right now it does nothing but the message preSave but another add-on might add more stuff in and want to run a preSave there, or reference another function. So for the sake of good code implementation, the parent should be called I guess. Thing is, if I call the parent the limit with 140 will be called, making an error.

    I thought about removing the error from $_errors, but it's actually thrown as an exception so that'd be futile. I thought about changing the throw exception thing to 0 throughout the method, but it's a constant so it can't be adjusted.

    Is there any way to still make it decently call the parent function without the error being thrown? Any way to suppress DW errors for a short time?
     
  15. Jake B.

    Jake B. Well-Known Member

    You could try wrapping it in a try and use catch then check the error message, but that probably isn't the best idea. Only thing I could really think of though

    Jake
     
  16. Daniel Hood

    Daniel Hood Well-Known Member

    Untested but something like:

    PHP:
    class AddOn_DataWriter_Thing extends XFCP_AddOn_DataWriter_Thing
    {
    public function 
    __construct($errorHandler self::ERROR_EXCEPTION, array $inject null)
    {
    parent::__construct(self::ERROR_SILENT$inject);
    }
    }
    That'd make it so that when the parent datawriter is initiated, there's no error handler. Should be careful with that though. A try/catch method like Jake said might be a better route.[/php]
     
  17. Robust

    Robust Well-Known Member

    I tried this:

    PHP:
    try {
        
    parent::_messagePreSave();
    } catch (
    XenForo_Exception$e) {
        unset(
    $this->_errors['message']);
    }
    Doesn't seem to really work, throws the exception anyway (I know I'm not checking if the exception is X, I'm just doing dummy test code here)
     
  18. Robust

    Robust Well-Known Member

    However, this works:

    PHP:
    try {
        
    parent::_messagePreSave();
        unset(
    $this->_errors['message']);
    } catch (
    XenForo_Exception $e) {
        unset(
    $this->_errors[0]);
    }
     
  19. Jake B.

    Jake B. Well-Known Member

    You may want to verify exactly what error you're unsetting instead of just blindly removing an error
     
  20. Robust

    Robust Well-Known Member

    Yeah, of course, I'm just seeing what works right now.

    Edit: Actually, that's the only type of message related error in this DW, it's set to remove any others for the same field. Completely override.
     

Share This Page