My plugin codes runs just once!(My own script shouldn't be cached)

Hi.
I wrote a plugin and I run my code. my code run just for the first page of my website.even if it is a simple alert.for example if you open front page and go to categories page the alert doesn’t work on new page.

It isn’t cached, What you are seeing is your script likely only runs on page load, and page load only happens once. The page gets repainted and you likely need to subscribe to a different event.

Can you paste your script here? Or a link to it on GitHub (if it is located there)?

6 Likes

It can be anything like:

export default {
  name: 'tag-resize',
  initialize() {
    alert("hello");
  }
};

this work just on first Page

this is my whole code:

export default {
  name: 'dynamic-table',
  initialize() {
    $(document).ready(function() {
        var elements = document.querySelectorAll(".topic-list .main-link a.title");
        var elements2 = document.querySelectorAll(".badge-wrapper.box span.badge-category");
        var i = 0;
        var a1 = -1, a2 = -1, a3 = -1;
        for(i = 0 ;i < elements2.length ; i++)   //Finding the position of wanted topics
        {
            if (elements2[i].innerHTML == "ورزشی")
            {               if(a1 == -1)
            a1 = i;
            else if (a2 == -1)
            a2 = i;
            else if(a3 == -1)
            a3 = i;
            }
            }
            document.getElementById('dyn1').innerHTML = elements[a1].innerHTML;
            document.getElementById('dyn1').href = elements[a1].href;
            document.getElementById('dyn2').innerHTML = elements[a2].innerHTML;
            document.getElementById('dyn2').href = elements[a2].href;
            document.getElementById('dyn3').innerHTML = elements[a3].innerHTML;
            document.getElementById('dyn3').href = elements[a3].href;
            });
  }
};

Yeah, $(document).ready will only fire once, as page repaints will not reload the DOM. You need to subscribe to a different event.

The API seems to offer a onPageChange event.

You would invoke it like so

import { withPluginApi } from 'discourse/lib/plugin-api';

function initializePlugin(api)
{
  api.onPageChange((url, title) => {
        // your code here
        console.log('the page changed to: ' + url + ' and title ' + title);
  });
}

export default {
  name: 'dynamic-table',
  initialize: function(container)
  {
    withPluginApi('0.1', api => initializePlugin(api));
  }
};
4 Likes

thank you very much. It helps me and was so useful

1 Like

Thank you.Can you explain this code?
I don’t understand exactly what this is?

In short, it is importing the plugin-api library and then using that API’s onPageChange event to execute code of your choosing.

So when the user navigates to a “different page”, it will invoke anything in the //your code here area.

2 Likes

Hi,

Based on your example is this the correct syntax?

import { withPluginApi } from 'discourse/lib/plugin-api';

function initializePlugin(api)
{
  api.onPageChange((url, title) => {
  name: 'optin',
  initialize() {
    alert('alert boxes are annoying!');
  }
    console.log('the page changed to: ' + url + ' and title ' + title);
  });
}

export default {
  name: 'optin',
  initialize: function(container)
  {
    withPluginApi('0.1', api => initializePlugin(api));
  }
};

https://github.com/BRoz/discourseoptin/blob/master/assets/javascripts/discourse/initializers/alert.js.es6

1 Like

You don’t need this

  name: 'optin',
  initialize() {
    alert('alert boxes are annoying!');
  }

That would simply be

    alert('alert boxes are annoying!');

Making the full script

import { withPluginApi } from 'discourse/lib/plugin-api';

function initializePlugin(api)
{
  api.onPageChange((url, title) => {
        // your code here
        alert('alert boxes are annoying!');
        console.log('the page changed to: ' + url + ' and title ' + title);
  });
}

export default {
  name: 'dynamic-table',
  initialize: function(container)
  {
    withPluginApi('0.1', api => initializePlugin(api));
  }
};
2 Likes

Hi, i’ve tried in every way but still the code isn’t loaded.
I let you check the plugin:
https://github.com/BRoz/discourseoptin/blob/master/assets/javascripts/lib/discourse-markdown/discourse-opt-in.js.es6

Do i miss something? Should i change the file name or the file extension to make the last part work?Because the first one work as it should.

Thank you very much for the help you gave me last time :heartbeat:

You put the code in the wrong file. That file is for whiteListing tags only.

You need to put the following
https://github.com/BRoz/discourseoptin/blob/master/assets/javascripts/lib/discourse-markdown/discourse-opt-in.js.es6#L21-L82

in https://github.com/BRoz/discourseoptin/blob/master/assets/javascripts/discourse/initializers/alert.js.es6

I would also rename alert.js.es6 to be discourse-opt-in.js.es6 so it more closely matches your plugin name.

3 Likes

I’ve tried this way, and i did that also now, you can try the plugin, and as you will see the code isn’t loaded.
Maybe you can try to achieve this result with a simple alert, but actually i’ve tried it and still don’t work.

:sweat:

https://github.com/BRoz/discourseoptin

I hadn’t looked at the actual code you had in there, but now after looking at it, it seems you may want to place the majority of this code in a separate JS file and in your plugin.rb you would do a register_asset "path to js file", :server_side

You can see something similar at
https://github.com/discourse/discourse-pirate-speak/blob/master/plugin.rb

Then you would call your external javascript function in the plugin api onPageChange.

Right now, you have a lot of code in there that likely doesn’t belong. It isn’t meant to be housing functions, but more for calling them.

1 Like

How to do that?
I created the js file
https://github.com/BRoz/discourseoptin/blob/master/assets/javascripts/discourse/initializers/discourse-opt-in.js

And included it in the plugin.rb
https://github.com/BRoz/discourseoptin/blob/master/plugin.rb

Thanks

I’m pretty well guessing at this point, but I think you have to change ! function to be var myFunction = function

Then remove (document, "script", "omapi-script")

And in your plugin api, do something like
myFunction(document, "script", "omapi-script");

I’m not even sure this is fully correct, but your javascript doesn’t like to be embeded in such an API, and it seems you haven’t a clue as to what it is doing… so we’re sort of at an impasse here because unless you know what it is doing, it is hard to tell you how to change it so it can be executed.

3 Likes

Note that “register_asset” starts from the asset folder.

so it should be more like
register_asset "javascripts/discourse/....
instead of
register_asset "assets/javascripts/discourse/....

Also, AFAIK if you name the files with the extension “.js.es6” it lets magic happen and you don’t need to register them.

Using more descriptive naming would be a help. Names like “r”, “t”, “e” and “s” don’t make it any easier to read the code.

1 Like

@broz

If you can figure out how to make your javascript a function and not execute it immediately, then you can simply put that function statement at the bottom of your initializer and call it from within the onPageChange invocation.

Similar to what the poll plugin is doing here