5 Replies Latest reply on Sep 27, 2013 9:09 AM by gdinning

    Problem with .soy and JS override

    michael_yegorov

      Hello!

       

      I think you might provide me with some help with the problem I ran into.

       

      We have a plugin that does a major customization to jive, adding an advanced feedback messages function to it. At some point I ran into a necessity to modify a way how "ask-a-question" widget works, so we made an exact copy of it in our plugin. The key was to modify a javascript behavior (rebuild a REST query that returns found questions), so I've changed the dependancy in a .soy file (first dependency):

       

      {namespace jive.widget.askaquestionfeedback}
      
      
      
      
      /**
      * @depends path=/plugins/plugin-feedback/resources/script/search.js
      * @depends i18nKeys=widget.askaquestion.*
      * @depends i18nKeys=feedback.widget.askquestion.*
      *
      * @param container com.jivesoftware.community.eae.view.stream.JiveContainerViewBean
      * @param widgetFrameID widget frame ID
      * @param wholeCommunityScope true if we should search the entire community, false if limit to container
      */
      {template .main}
          {call jive.shared.soy.resourceInlineJs}
              {param code}
                  $j(function() {lb}
                      new jive.AskAQuestionFeedback.Main({lb}
                          containerType: {$container.type},
                          containerID: {$container.id},
                          widgetFrameID: {$widgetFrameID},
                          wholeCommunityScope: {$wholeCommunityScope}
                      {rb});
                  {rb});
              {/param}
          {/call}
          <div class="ask-a-question-container an-feedback-askwidget">
              <form action="{buildUrl('/discussion/create.jspa', 'containerType', $container.type, 'containerID', $container.id, 'question', true)}" method="GET" class="j-form">
                  <input type="text" aria-required="true" required class="ask-a-question-search" autocomplete="off" placeholder="{i18nText('widget.askaquestion.type')}" />
                  <button type="submit">{i18nText('feedback.widget.askquestion.askButton')}</button>
              </form>
          </div>
      {/template}
      
      
      
      
      
      

       

       

      And placed a copies of all needed files from ask-a-question widget to this single file in our plugin:

       

       

      jive.namespace('AskAQuestionFeedback');
      
      
      /**
      * Handles interactions with the bookmark and unbookmark actions in a list view
      *
      * @class
      * @param {jQuery|DOMElement|String} element reference to element that contains bookmark links
      *
      * @depends path=/resources/scripts/apps/shared/models/rest_service.js
      */
      jive.AskAQuestionFeedback.Source = jive.RestService.extend(function(protect, _super) {
        var $ = jQuery
        , _ = jive.AskAQuestionFeedback;
      
      
        protect.resourceType = "askaquestion";
        protect.pluralizedResourceType = protect.resourceType;
      
      
        this.init = function init(options) {
        _super.init.call(this, options);
        this.options = options;
        };
      
      
        this.search = function(val) {
        return this.get('', {
        q: val,
        containerType: this.options.containerType,
        containerID: this.options.containerID,
        wholeCommunityScope: this.options.wholeCommunityScope
        });
        };
      
      
        this.referrer = function(url) {
        return this.save({
        url: url
        });
        };
      });
      
      
      
      
      
      
      /**
      * @depends path=/resources/scripts/apps/shared/views/abstract_view.js
      * @depends path=/resources/scripts/apps/content/common/validator.js
      * @depends path=/resources/scripts/jquery/jquery.placeheld.js
      */
      jive.AskAQuestionFeedback.View = jive.AbstractView.extend(function(protect) {
        var $ = jQuery
        , _ = jive.AskAQuestionFeedback;
      
      
        protect.init = function(options) {
        var view = this;
        this.frame = $('#jive-widgetframe_' + options.widgetFrameID);
        this.searchElem = this.frame.find('.ask-a-question-search');
        this.container = this.frame.find('.ask-a-question-container');
      
      
        $(function() {
        var form = view.container.find('form');
      
      
        new jive.Validator({form: form});
      
      
        var searchFunc = function() {
        var val = view.searchElem.val();
        if (val) {
        view.emit('search', val);
        }
        };
        var $input = view.container.find('input');
        $input.placeHeld();
        $input.keyup(function() {
        clearTimeout($.data(this, 'timer'));
        var wait = setTimeout(searchFunc, 500);
        $(this).data('timer', wait);
        });
      
      
        form.submit(function(e) {
      
      
        if (e.isDefaultPrevented()) {
        return;
        }
      
      
        var url = $(this).prop('action') + '&subject=' + view.searchElem.val();
      
      
        if (typeof loginApp === "undefined") {
        window.location.href = url;
        } else {
        view.emit('referrer', url);
      
      
        $('#navLogin').click();
        }
      
      
        e.preventDefault();
        });
        });
        };
      
      
        this.success = function(data) {
        var resultMarkup = jive.widget.askaquestionfeedback.results({
        bean: data
        });
      
      
        var results = this.frame.find('.ask-a-question-results');
        if (results.length) {
        results.replaceWith(resultMarkup);
        } else {
        $(this.container).find('button[type=submit]').before(resultMarkup);
        }
        };
      });
      
      
      
      
      
      
      
      
      /**
      * @depends template=jive.widget.askaquestionfeedback.*
      */
      jive.AskAQuestionFeedback.Main = jive.oo.Class.extend(function(protect) {
        var _ = jive.AskAQuestionFeedback,
        $ = jQuery;
      
      
        protect.init = function(options) {
        var main = this;
        this.view =  new _.View(options);
        this.source =  new _.Source(options);
      
      
        this.view.addListener('search', function(data) {
        main.source.search(data).addCallback(function(resp) {
        main.view.success(resp);
        });
        });
      
      
        this.view.addListener('referrer', main.source.referrer);
        };
      });
      
      
      
      
      
      

       

       

      The point is: jive namespace object "jive.AskAQuestionFeedback" is not being created, and the code from the file is nowhere to be found in a composed [hash].js files, though the file actially IS parced, because if not, the inner dependencies of a file should not be parsed, but they are. It is obvious, because when i removed these dependencies

       

       

      * @depends path=/resources/scripts/apps/ask_a_question/view.js
      * @depends path=/resources/scripts/apps/ask_a_question/source.js
      
      
      
      
      
      

       

       

      the object "jive.AskAQuestion" is stopped from being created via jive namespace engine.

       

      Can anyone tell me how to solve the case? (Sorry for lots of code)

        • Re: Problem with .soy and JS override

          Hi Michael.  It sounds like your JS file is not being loaded.  I see that you are referencing it in your @depends directive in your Soy template.  Assuming that is the correct path, (/plugins/<plugin-name-specified-in-plugin.xml-file>/resources/script/<js-filename>) you should be ok.  The only other thing you'll likely need to do in order to make your Javascript file accessible on the client side is to declare it in your plugin.xml file.

           

          <javascript src="resources/script/search.js" />
          

           

          That should do the trick!

          • Re: Problem with .soy and JS override
            gdinning

            I've found that the @depends mechanism doesn't work for Soy templates that are invoked via a PluginTemplateDefinition.  I don't know why.  I don't like the plugin.xml approach since I usually only want the logic on that template and not everywhere, so what I usually do is stick a <script> tag in the Soy head template.  Just make sure this won't lead to a script being loaded twice (I think @depends takes care of that scenario).

             

            If somebody can tell me differently, I'd love to be proven wrong!