Recent Topics

Best Way to Implement a New Widget?

started by on Jul 11, 2016 – Last touched: Oct 07, 2016

Jul 11, 2016 01:19    

Working with 6.7.4-stable.

Francois already said that a widget is coming to add social links for a site (rather than displaying a user's social links)(i.e., how the social icons are displayed in the Bootstrap Blog skin), but there are other needs I have for widgets as well. I've taken probably the most basic example (the Facebook Like Widget plugin) and duplicated it, changing the variables and class name name, of course, as well as replacing the code for the like button with a very simple "Hello, World!"

The FB like widget includes $params for block start and end, and body start and end. Here's the simple method I'm working with:

	function SkinTag( & $params )
	{
		/**
		 * Default params:
		 */
		$params = array_merge( array(
				// This is what will enclose the block in the skin:
				'block_start'       => '<div class="bSideItem">',
				'block_end'         => '</div>',
				// This is what will enclose the body:
				'block_body_start'  => '<h2>',
				'block_body_end'    => '</h2>'
			), $params );

		echo $params['block_start'];
		echo $params['block_body_start'];
		echo '<h2>Hello, World!</h2>';
		echo $params['block_body_end'];
		echo $params['block_end'];

		return true;
	}

As you can see, it's the FB plugin for all intents and purposes. Problem is, the block_start and block_end parameters aren't passing. Neither are the block_body_start and block_body_end params, as can be noted by me echoing out the heading tags manually. Thought it was just me not catching something, but the core Facebook Like button plugin doesn't work in that respect either. See output: http://prntscr.com/bradqe

Makes me think there's gotta be a better way. The manual is a bit slim on widget information, so I was hoping for some tips, especially if they include working params.

Thanks.

Jul 12, 2016 01:46

We'll have someone check this.

Jul 14, 2016 01:47

Hold on, again, what is it that is not working?

Your Hello world seems to display in h2.

Then if it should be something else, what are the params configured for the Sidebar container in your skin?

Jul 14, 2016 01:54

You tell me? Using defaults from the bootstrap blog skin on the sidebar container (sidebar 2, specifically).

The text string is in an h2, but only because I explicitly echoed the h2 tags with the string. Shouldn't the $params[body_block_start] and $params[body_block_end] keys where it was set have also showed up? The code says yes when I look at it. They're included, echoed, but don't show.

Jul 14, 2016 01:56

If I remove the h2 tags from line 17 of the above code block, the h2 tags aren't printed to the page. I checked.

Jul 14, 2016 03:09

Again, you define defaults but your skin has control of the values! (through the magic of array_merge())

So you need to look at what $params your skin container is passing to all its widgets. Those have precedence.

Jul 14, 2016 06:56

I'm telling you that Bootstrap Blog, the skin that was activated when I first installed b2evo, is the skin in place. I have modified CSS on the header and article p {} only, nothing else. So you already know the answer to your question. Either the skin doesn't account for it (bad practice for a default skin), or does it wrong. Hence me using all defaults in this (I didn't break this feature). I don't know what is or is not going on in the skin or container around the sidebar because I haven't touched that code.

I also didn't see an answer to my original query (title of the thread). Thanks...........

Jul 14, 2016 10:38

Hi btreece

Interested in your posts but becoming unpleasant to read as you seem > than a little frustrated I'm telling you
||
your English is rude y meant airy
&&
it's not the later

Hope you and your widget get better

Hello World!

Jul 14, 2016 17:48

I'm from Texas, dude... "I'm telling you" is just emphasis; direct. Not frustrated in the least (not messing with the widget right now, so no sweat off my back if it takes a while).

Don't read so much into it. You can't usually read tone in text, not unless it's emphatic (and if I'm pissed, I'm very emphatic :) ).

Jul 15, 2016 02:43

Ah now I wish I could find a clever way to start my reply with "I'm telling you..." ;) but I'm in such a rush I'll have to resort to some (randomly indented) bullet points :p

  • oh, you probably told me indeed in your initial question but it was not 100% clear to me.
    • I have to admit I sometimes try to answer as many questions as possible in the little time I have left at the end of the day and sometimes if it's not clear, i'll just ask again instead of starting a deeper analysis of what one may have written ;)
  • So you are basically saying that the default block_body_start param from Bootstrap Blog which is <div class="panel-body"> does NOT get passed to the widget and that you verified that?
    • This is an instance where I am indeed asking you for 100% extra clear confirmation because I didn't read it explicitly like this before.
    • And if your answer is yes I have a very concise bug report to send to the devs ;)
  • Sometimes I am answering on an iPad, which means I don't have access to the code for a quick check.
    • I would love it if you would upload your screenshots on the forum instead of making me open another page... because, on - iPad... it makes it hardly impossible to write a reply and look at the screenshot at the same time :/
  • And last but not least: yes the best way to implement a new widget is what you are doing indeed.

Cheers!

Jul 15, 2016 05:23

So you are basically saying that the default block_body_start param from Bootstrap Blog which is <div class="panel-body"> does NOT get passed to the widget and that you verified that?

No, the class="panel_body" does get passed. The problem is that in my widget (code in first post above) I'm trying to override that param. I included a link to a screenshot in my first post above that shows the widget in question in Chrome's inspector tool. But since Apple and iPads still suck (hahaha), attaching that screenshot for you.

Jul 15, 2016 12:56

UPDATE: After messing with plugin and confirming parameters not passing, or recognised, I noted the extra &params in the definition and removed it. So as you noted the facebook plugin is a bit iffy.


I've installed the facebook plugin and changed the 'block_start' => '<div style="border:1px solid grey; background:blue">', to no effect.

Is this the issue?

I'm just messing with the facebook plugin

$params = array_merge( array(
				// This is what will enclose the block in the skin:
				'block_start'       => '<div style="border:1px solid grey; background:blue">',
				'block_end'         => "</div>\n",
				// This is what will enclose the body:
				'block_body_start'  => '',
				'block_body_end'    => '',
			), $params );

		global $baseurlroot;
		//$test_url = url_absolute( regenerate_url( '', '', '', '&' ), 'http://127.0.0.1' );
		$current_url = url_absolute( regenerate_url( '', '', '', '&' ), $baseurlroot );

		echo $params['block_start'];
		echo $params['block_body_start'];
		echo 'Hello World';
		echo $params['block_body_end'];
		echo $params['block_end'];

		return true;

Just get a simple Hello World, no style


I can comment out random params and/or the echo with no effect


$params = array_merge( array(
				// This is what will enclose the block in the skin:
				'block_start'       => '<div style="border:2px solid red; background:blue">',
				'block_end'         => "</div>\n",
				// This is what will enclose the body:
				//'block_body_start'  => '',
				//'block_body_end'    => '',
			), $params);

		global $baseurlroot;
		//$test_url = url_absolute( regenerate_url( '', '', '', '&' ), 'http://127.0.0.1' );
		$current_url = url_absolute( regenerate_url( '', '', '', '&' ), $baseurlroot );

		echo $params['block_start'];
		//echo $params['block_body_start'];
		echo 'Hello World!';
		echo $params['block_body_end'];
		echo $params['block_end'];


Removed ,&params from line 8 below and parameters are passed http://calstock.org.uk/elf.php (bottom of right col)

$params = array_merge( array(
				// This is what will enclose the block in the skin:
				'block_start'       => '<div style="border:2px solid red; background:blue">',
				'block_end'         => "</div>\n",
				// This is what will enclose the body:
				'block_body_start'  => '',
				'block_body_end'    => '',
			));

		echo $params['block_start'];
		echo $params['block_body_start'];
		echo 'Hello World!';
		echo $params['block_body_end'];
		echo $params['block_end'];

		return true;
	}

Jul 15, 2016 18:34

Is that all? In building the $params array inside the widget, it takes 2 args; an assoc array of params, and then a $params array (from the container in the skin, or elsewhere). They're merged together so you can customize certain things.

What you're describing about having no effect from the changes in the widget's $params appearing on the front office is what I was pointing at.

Have you tried reversing it yet? Instead of removing the the second argument (the container $params array), try moving it, like so:


$params = array_merge($params, array(
				// This is what will enclose the block in the skin:
				'block_start'       => '<div style="border:2px solid red; background:blue">',
				'block_end'         => "</div>\n",
				// This is what will enclose the body:
				//'block_body_start'  => '',
				//'block_body_end'    => '',
			));

Should still merge them all, but might let the widget's custom settings override matching values in the more global array once merged.

Jul 15, 2016 19:01

Tested it myself (on the Facebook plugin and the clone I made to output "Hello, World!"). I took the $params = array_merge() value and switched the two arguments it accepts. Now the code in the widget overrides the $params passed to the widget function.

Nice catch, @amoun.

Jul 15, 2016 19:07

OK so I would have missed second argument [the container $params array] Does it need this argument?

I'm worse than fplanque I read back to front between weeding the fields and chopping wood etc, so keep editing my posts.

Off weeding again.
Back from weeding.

OK it has two arguments, but doesn't need both, got it now: whereby the one for the default skin settings, won't get overridden if it is appended after the local ones, quite the opposite.

It seems maybe that the author and other users never wanted to override the default and so the error went unnoticed.

I tend to labour more physically than mentally but whilst digging the weeds my head got around it.

Thanks for your help in learning a bit about how the function parameters work.

Removing my plugin/widget from site so earlier link defunct

Jul 15, 2016 20:09

Well, I wouldn't say that both aren't needed. Depends on the skin really. At least in this case.

The skin defines a sidebar container and that container has a $params array. The container's $params is the $params you deleted, and that I moved into the first position.

Both arrays define the same things by default, and so when it comes time to merge them, the former (assoc array in the plugin, by default) is overwritten by the latter. But the inheritance structure in b2e is Container (parent) -> Widget (child). Only the child's specific settings should be defined when it is created, and they should override the parent's settings where they match (i.e., both parent and child have a block_start key, so the child's version should overwrite the parent's version).

I suspect that digging through other, more fruitful widgets in b2e would reveal that most order the child and parent arrays correctly, but the merely demonstrative Facebook widget didn't get that attention, as you mentioned. Only using one (not both) would violate the D.R.Y. principle and b2e is pretty good at following it (the parent-child structure is based on it).

Jul 15, 2016 20:14

Thanks for that, yeap! got it, you have a more professional way of putting :)
All the best

Jul 15, 2016 20:16

Oh yeah, didn't finish that thought. Since it depends on the skin, if the skin doesn't define those parameters in the sidebar container, then no, it doesn't need both.

Jul 15, 2016 20:17

Yeap! Nice to know I'm not too dumb :)
It's 19:20 here, time to light the stove and cook, bye.

Jul 15, 2016 20:21

Now see, that comes off as rude. Makes me think I inadvertently made you feel dumb.

BUT

Then I remember that you're British. You use English just a little differently than I do :) Especially on sarcasm and self-deprecating remarks, if Monte Python taught me anything haha

Good chatting. And luckily for Francois, no screenshots for him to not look at on his sucky iPad (I hate Apple products).

Jul 16, 2016 02:05

Ok guys you put your finger on the issue... except it's not an issue ;)

Let me explain. By design b2evolution does not imply you should use Apple products. However, by design, b2evolution implies that plugins should adapt their rendering to what the skin tells them to do (but the Manual may be faulty in not conveying that correctly)

  • If a skin says "display all titles in <h2>", then all plugins should abide.
  • If a skin says "display all titles in <div class="panel-title">", then all plugins should abide.

Therefore it is absolutely normal that the array_merge order we use lets the skin override the plugin defaults. The plugin defaults are there only if a skin does not pass all the params that a plugin expects. For example, if your plugin accepts a param "button_size", no skin passes that, so you need a default/fallback in your coding.

Furthermore, if you just want your plugin to act selfishly without listening to what the skin is asking for, why do you even bother with $params and with array_merge(). In that case, you can just hardcode your <h2>s in the code, plain and simple :p

I hope I got it right this time (without scrolling up but after looking at the screenshot you gently attached).

And I realize there might be some explanations missing in the manual about this. Can you please point me to the first couple of man pages you looked at when you started this "building a widget" project? (so I know where to best start editing)

Thanks!

Jul 16, 2016 02:34

Alright, that makes sense. Not what I expected, but makes sense. The array_merge just isn't needed in most widgets; just apply the container's $params and design your widget contextually. Simple enough.

Honestly, I looked and looked, but I didn't find any man pages on building/creating a widget, just using a widget. I should have titled this thread better because I was really looking for how to go about making a widget. I searched the manual for "widget" and it returned 2 results. Just figured you hadn't gotten around to it yet.

So yeah, start from the beginning :)

Jul 19, 2016 00:04

So fplanque was correct from the start and I've benefited by knowing the structure of the function and how the parameters are overriden.
So I'm thinking the widget is a good base to start, as btreece initiated, and all that is required is that the formatting should go in the stylesheet for the blog in use [/media/blogs/b*l*o*g*n*a*m*e*/style.css] under [.widget_plugin_evo_facebook]
Works! Simples!

Jul 19, 2016 01:28

Still leaves some questions. Like when adding multiple widgets, is it one plugin for each widget, multiple widgets instantiated in a single plugin, or is the plugin actually needed? Pretty sure all of the above are correct, but I'd like to know which is best suited. So I'm hoping the new man pages address that, specifically, and more.

Jul 19, 2016 02:18

Quick answers:

  • A plugin can implement a widget that does a specific thing.
  • When you install the plugin, the widget becomes available for use.
  • You can use the same widget in multiple containers, with different params if you want. E-g: 1 plugin implements weather widget which can be used 3 times for 3 different cities.
  • However if you want 2 widgets that do different things (e-g: weather vs movie schedule), you should make 2 different plugins.
  • If you uninstall the plugin, the widgets offered by that plugin can no longer be displayed.

Oct 07, 2016 19:04

@btreece wrote earlier:

Alright, that makes sense. Not what I expected, but makes sense. The array_merge just isn't needed in most widgets; just apply the container's $params and design your widget contextually. Simple enough.

Honestly, I looked and looked, but I didn't find any man pages on building/creating a widget, just using a widget. I should have titled this thread better because I was really looking for how to go about making a widget. I searched the manual for &quot;widget&quot; and it returned 2 results. Just figured you hadn't gotten around to it yet.

So yeah, start from the beginning :)


Form is loading...

blogging tool – This forum is powered by b2evolution CMS, a complete engine for your website.