Codeception Testing with Yii Framework 2.0 [Day 4]

Today’s Objective

As a user I would like to create a new unit test, implement it and test it.

Today’s Method

Yesterday’s method was rather successful, of course today I don’t have already made steps. Instead I’ll be putting each step in as a heading and the text inside each of those headings will give details on that action.

Actions

Create new unit test(s)

Using the examples from Yii basic template, I created the following “ModelTest.php” in ~\tests\codeception\unit\models:

<?php

namespace tests\codeception\unit\models;

use Yii;
use yii\codeception\TestCase;
use app\models\Model;
use Codeception\Specify;

class ModelTest extends TestCase
{
 use Specify;

 protected function tearDown()
 {
   parent::tearDown();
 }

 public function testModelString()
 {
   $model = new Model();

   $this->specify('model string function should return a string', function () use ($model) {
     expect('function should return string', $model->string())->string();
   });
 }

 public function testModelBoolean()
 {
   $model = new Model();

   $this->specify('model bool function should return a boolean opposite to boolean passed', function () use ($model) {
     expect('argument is true, result should be false', $model->bool(true))->false();
     expect('argument is false, result should be true', $model->bool(false))->true();
   });
 }

 public function testModelArray()
 {
   $model = new Model();

   $this->specify('comma seperated string should return array of items', function () use ($model) {
     expect('passing "dave,joe" should return array with ["dave","joe"]', $model->getArray("dave,joe"))->array(['dave','joe']);
     expect('execution with no argument should return empty array', $model->getArray())->array();
   });
 }

}

I really need to set up a code box for this blog… possibly a job for another daily-blog. (Edit 15/04/15: I downloaded Code Highlight plugin, which highlights code but doesn’t do everything I’d like it to do… but it’ll do for now). Anyway, what I’ve decided to do is make a Model model class and in it have functions to return different types of data and this unit test is set up to check that those functions do what they are supposed to:

  • string() – returns a string
  • bool() – returns a boolean opposite to the one passed to it
  • array() – returns an exploded comma separated string

On running my new unit test (From the tests folder in codeception-test):

codecept run unit models/ModelTest

It crashed completely with the error that “Class ‘app\models\Model’ not found”, which is completely expected since I haven’t made the Class yet. And to my understanding is how Unit testing in general is supposed to work, so let’s move to the next action on this list.

Create “Model” class for codeception-test

At this step is where I realised that Model is an already made class (yii\base\Model) for Yii Framework…. technically this is a big no-no, but since this isn’t for any sort of production I’ll carry on without going back and editing everything to “MySimpleModel”, which it should be named. Taking this as an educational play with namespaces in PHP ;)

Which proved very educational.

I created the model Model (app\models\Model) and on attempting to run my unit test I was informed that PHP cannot declare my class because the name is already in use.

I’m taking this as a 2 part lesson:

  1. Namespace does not allow for scoping class names (Which should be something I should already know, but I have my noob moments :) ).
  2. This points out to me how useful unit testing is… I know in theory how much it could help, but this was a practical lesson for me :)

So, I will rename my model as I mentioned earlier but leave in the original part of this post for posterity. So, renamed ModelTest.php to MySimpleModelTest.php and updated it to use MySimpleModel.

This what I have in ~\models\MySimpleModel.php

<?php

namespace app\models;

use Yii;
use yii\base\Model;

/**
 * Model is a model to test out unit testing.
 */
class MySimpleModel extends Model
{
 /**
 * Function to return a string
 * @param string $param
 * @return string
 */
 public function string($param = "string")
 {
   return $param;
 }

 /**
 * Function to return opposite of parameter
 * @param boolean $param
 * @return boolean opposite of $param
 */
 public function bool($param)
 {
   return !$param;
 }

 /**
 * return array of CSV string
 * @return User|null
 */
 public function getArray($csv_string)
 {
   return explode(',', $csv_string);
 }
}

Execute unit test(s)

With everything set up to use MySimpleModel, I executed my unit test and found that my initial thought that the following code:

$this->specify('model string function should return a string', function () use ($model) {
 expect('function should return string', $model->string())->string();
});

Would check for a string, was completely off base.

Foolish, but educational process. After reading through documentation on unit tests from Codeception and some documentation on PHPUnit I decided to go with the following:

$this->assertInternalType('string', $model->string());

Since I only want to know that the returned value is a string it works in this instance, but the experience and brief reading through links above has shown me that there’s a whole world of possibilities that I should learn before I can say that I’m at most “decent” with unit testing in Yii Framework.

The testModelBoolean() test went off without a hitch, and I’m not completely sure why. By that I mean that I have no idea how the expect method works, which requires further analysis.

And testModelArray() test fails, which is very true, since I didn’t name my model’s function “array()” because of a naming issue. Instead I named it “getArray()”. Although even with that correction I do not believe that my unit test will bare fruit due to the initial issue I had with string.

Think I will close off on that note, with a rather nice objective for tomorrow :)

Tomorrow’s Objective

As a user…. I’m gonna stop this “As a user…” thing. It’s agile and all that, but I don’t think it will be worthwhile in the long run of this experiment. So just going to list upcoming objectives that I can think of in order of decided priority on the day and pick one for the next day (If there are multiples).

Upcoming Objective(s)

  1. Update testModelArray() unit test to confirm that returned object is an array with correct values
  2. Explore and understand the basic functions of basic test methods (Understand what is going on in testModelBoolean() function to be precise).
  3. Try to use the entire $I->wantTo(‘load all values’); style of Codeception

Codeception Testing with Yii Framework 2.0 [Day 3]

Today’s Objective

As a user I would like to run tests on the basic template for Yii Framework. (Continued)

Today’s method

Going to use the instructions from the yii2 basic template (after everything set up from yesterday) and just add any notes of my own or any issues I run into.

Instructions from basic template

Install faker extension by running the following from template root directory where “composer.json” is:

composer require --dev yiisoft/yii2-faker:*

Template root directory in this instance is “C:\wamp\www\codeception-test”

Create “yii2_basic_tests” database and update it by applying migrations:

codeception/bin/yii migrate

Ran into an error when trying to execute this instruction. My thought is that it’s only necessary if my application used the database (Which isn’t the case for the basic template). But this points out that I should learn how to properly use migrations for Yii Framework.

 

Very nifty to be able to set up a test database with a simple execution, think this will be another tutorial/learning series after this one.

Build the test suites:

codecept build

Executed from C:\wamp\www\codeception-test\tests

In order to be able to run acceptance tests you need to start a webserver. The simplest way is to use PHP built in webserver. In the “web” directory execute the following:

php -S localhost:8080

Since I already have a webserver set up, I chose to skip this step and instead set up the tests to use my webserver instead by editing

C:\wamp\www\codeception-test\tests\codeception.yml

replace

http://localhost:8080/index-test.php

to

http://localhost/codeception-test/web/index-test.php

There’s a way to remove the “web” part out of that, which I have, but it’s out of scope for this… possibly later ;)

Now you can run the tests with the following commands:

# run all available tests
codecept run
# run acceptance tests
codecept run acceptance
# run functional tests
codecept run functional
# run unit tests
codecept run unit

Found that acceptance tests failed, but functional and unit tests completed successfully. Believe the issue with my acceptance tests is thanks to a configuration setting and not using PHP built in webserver.

 

Needed to edit

C:\wamp\www\codeception-test\tests\codeception\acceptance.suite.yml

replace

http://localhost:8080

to

http://localhost/codeception-test/web

Conclusion

Hurrah! We’ve successfully run tests on the basic template for Yii Framework. With that completed there are a few questions I have:

  1. Is there a way to execute tests and view results from a browser? The reason for this question is thanks to the following:
    • Don’t enjoy the idea of executing command line arguments after each change
    • Don’t like the output from windows command line, believe it would look better in unix… but I’m not using unix.
  2. What’s the best practice for unit tests?
    • Does it entail testing function calls on model only, or controller and model. Believe this will be answered with a look into the current tests provided.
  3. What’s the best practice for acceptance/functional tests?
    • This is more my lack of understanding for the process than anything else and requires further education

And that’s about it. With those questions I can make an objective for tomorrow :)

Tomorrow’s Stumble

As a user I would like to create a new unit test, implement it and test it.

Codeception Testing with Yii Framework 2.0 [Day 2]

Today’s Objective

As a user I would like to run tests on the basic template for Yii Framework.

Prerequisites

I have a few things already set up that I would like to state for the record:

Installing Basic Yii Template

With those items installed, let’s begin with installing Yii (Thorough instructions here).

First we inform composer of the required global package we will need (Only need to do this once)

composer global require "fxp/composer-asset-plugin:1.0.0"

Then we create the project (using Yii’s basic template), you should run this command in your www folder of WampServer (For me it’s C:\wamp\www)

composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic codeception-test

The last piece of that is the project name, in this case it’s ‘conception-test’ and now I have a folder codeception-test in C:\wamp\www, and Yii is installed!

Installing Codeception

With Yii up and running, we’ll need Codeception installed to execute tests:

composer global require "codeception/codeception=2.0.*"
composer global require "codeception/specify=*"
composer global require "codeception/verify=*"

With Codeception downloaded, we need to be able to run it from the command line by adding the path of Composer’s global vendor\bin directory, to get Composer’s global director we run the following:

composer global status

That command shows the following:

Changed current directory to C:/Users/<user>/AppData/Roaming/Composer

Now we add “C:\Users\<user>\AppData\Roaming\Composer\vendor\bin” to PATH for Windows Advanced system settings. Once done you should be able to run the following without an error:

codecept

You may need to restart your command line session for the changes to take effect.

Conclusion

Alrightey, we now have Codeception set up for use and a basic Yii application set up to execute tests on. I would’ve liked to at least execute a test by now, but haven’t made a lot of progress with this current method of describing/detailing the process involved. Think I will be making it far more shorthand in future posts and actually complete the objective before writing.

Signing off for now, the objective should be done tomorrow ;)

 

Codeception Testing with Yii Framework 2.0 [Day 1]

Introduction

I’ve been moving into developing Web applications/sites from scratch over using WordPress, and the framework that I’ve committed a good portion of time to learning has been the Yii Framework. Which has proved to be completely worth it, but this post is not about how awesome Yii Framework is… I’m creating this post because there’s one area I’ve found to be lacking in my education and that is using Codeception for testing my projects. There are a lot of articles out there of how to install/use codeception, but these all seem to leave me more confused than anything.

And so I’ve decided to publish my stumbling around the topic in a daily blog so I can better understand it and hopefully help somebody else better understand it too.

P1030362-Edit-Edit

How it’s going to work

I’ve found that aimless stumbling has rather poor results, so I’m putting myself on a more focused approach using this blog. I’ll be updating daily on what I’ve done during that day to progress my understanding of the subject at hand (Namely Codeception testing for Yii Framework 2.0, but I might do this with a few other topics as well). Once updated for the day a goal for the next day will be made and the cycle repeats until the job is done. A sort of agile/scrum approach to learning.

Tomorrow’s Stumble

As a user I would like to run tests on the basic template for Yii Framework.

jQuery UI – Accordion

I’ve started to add the Accordion widget to PJ jQuery UI Helper and thought I would share with the world my experience with it, so to begin we have…

What is an Accordion?

A physical accordion
A physical accordionsource: kleptones

While the image is a physical accordion, this is not what I am referring to. It is, however, a very good example of what a jQuery UI Accordion is. And the image is hilarious to me!

jQuery UI’s Accordion is a collection of ‘sections’ of information that can be shown when the section’s title is selected, ie:

Section Title 1

Section 1 Contents

Section Title 2

Section 2 Contents

How do you make an Accordion?

First you have the basics (Include jQuery and jQueryUI scripts and stylesheets). Which I have glossed over because it’s a separate instructional on it’s own, perhaps I’ll create a post on it and link to that later… Keep you folks guessing.

Now for the basic Accordion you will need a div tag that has an ID, inside of that div we have an h3 tag to set the title of a section. And lastly an extra div tag that contains the section’s content. Here is the HTML code for the example above:
<div id="accordion">
 <h3>Section Title 1</h3>
 <div>Section 1 Contents</div>
 <h3>Section Title 2</h3>
 <div>Section 2 Contents</div>
</div>

After you’ve added the HTML to your page, you need to get it looking spiffy and there’s only one way to do this… MAGIC! Of course by ‘MAGIC’ I mean Marginally Accurate…. who am I kidding? I can’t make an acronym out of that, but before you fully understand it it does seem a lot like magic.

What I really mean is you need to tell jQueryUI that your div tag with the ID ‘accordion’ is in fact an Accordion, this can be done with JavaScript using jQuery’s great selectors and jQueryUI’s accordion function. Like this:
<script>
jQuery( document ).ready(function($) { $( '#accordion' ).accordion()});
</script>
Magic! :)

Kind of threw you in the deep end on that one, but let’s break it down into manageable chunks.

First you have the JavaScript inside of script tag to tell the browser that you’re using JavaScript.

Now for the actual JavaScript used let’s work it from the inside out:

  • $( '#accordion' ).accordion()
    This is technically all you need if you’re using this in a regular HTML file, we’ll get into that a bit further on.What this code is doing is selecting the div tag with the ID (#) of accordion and applying the accordion() function to it. This is a very simple use of the accordion function, if you’d like to see more of the advanced uses you can check out it’s full reference.

  • jQuery( document ).ready(function($) { });
    This beautiful piece of code does quite a few things, most importantly it prevents the code inside the curly brackets ({ }) from being executed until the whole web page is ready to be displayed. This is useful for a lot of things, although in the instance of using this Accordion inside of a normal HTML page it is not necessarily needed (Especially if you add the script tag directly below your HTML or in the footer, but if your script tag is in the Header of your HTML, you’ll want this code to wait until the actual HTML has been created before executing).

    Will get into the why’s of all of this further in this post, I promise.

    I’ve realized that the rest of the explanation for this code snippet will also be explained further in the post… So I’ll leave it at this for now.

And that is how you can make your very own jQueryUI Accordion! It’s basic, but it works ;) So if you came here to find out how to make your own Accordion, job done… I hope. And now we’ll get into the meat of this post, and the major reason why I decided to make it, with…

Pitfalls I found while adding Accordion to my Plugin

Source
Source: jitterbit

jQuery in WordPress is loaded in compatibility mode

Technically this was not a pitfall for this part of the plugin, it was a pitfall when I started the plugin overall. But I promised further explanation on the whys of the complication in the JavaScript above and I will now deliver.

Usually in jQuery, when you want to do anything jQuery-ish you just need to use the $ symbol followed by whatever you fancy jQuery-wise. And what compatibility mode does is make jQuery more compatible with other JavaScript libraries that might use the $ shortcut, so $ is replaced with jQuery.Which isn’t that much of a problem, especially when you’re just doing the one line of code. But when your code starts to become more than that, it’s a helluva lot easier to simply type $ than it is to type out jQuery all of the time (Remember that it’s case-sensitive as well, meaning the Q has to be capitalised EVERY time ;) ).

So to allow for $ in the JavaScript, we need to first start off with jQuery( document ) to select our document as a jQuery object. Now we can call jQuery functions on that object using . followed by the function name, in this case ready() and inside of the parenthesis of the ready function you can insert a function to be executed. The function could be a function you’ve already declared or, as is in this case, simply declare it in the ready function.

The ready function also allows for the function you create to receive a variable, which you can name however you like and this variable is the global jQuery object itself. Which is why we had function($) { } inside of the ready function above and from then used $ as jQuery.

You could also do something like this:
jQuery( document ).ready(function(Hulk) {
  Hulk("head").empty()
});
Granted this does nothing useful… except showcase that you can now use anything as your global jQuery object and make me giggle :) .

To clarify, this will theoretically strip out the tags inside of your HTML’s head. I had originally put in the ‘theoretically’ because I wasn’t prepared to test this snippet of code… but curiosity got the best of me.

Further reading:
Using ‘$’ instead of ‘jQuery’ in WordPress
jQuery.noConflict()

StyleSheets can be a royal pain in the ass

After completing the additions required to allow for Accordion in the plugin, I played around with it. Which ended up with me having an Accordion inside of a Tab… because nesting objects inside of other objects is my version of hallucinogenic drugs :) . This little test showed me a fatal flaw in my theory of simply using jQueryUI’s themes to style the plugin.

So far the theory has worked out rather smashingly. Apart from a few minor tweaks to each CSS (Cascading StyleSheet), the widgets look good to me. But the walls crumbled, even before the nesting test, to reveal that I may need to put a little more effort into the styling… And so I devised workarounds!

Here’s a list of the flaws found and their current workarounds:

  1. Gap between Section title and Section
    This flaw was find in the first Accordion my plugin created, my theme’s h3 tag specifies a margin-bottom of 20 pixels (20px). So what this means is that the Section title has a margin (Could also call it a boundary) below it of 20 pixels.

    The workaround I devised for this little issue was to add an inline style to each Section title of margin-bottom:0, nullifying the h3 tag’s margin-bottom because inline styles take preference. Inline styles are generally frowned upon, but I’m going with this one for now in the spirit of completing the task at hand and then polishing out the kinks.

  2. Section title font becomes smaller when nested inside of another object
    This is a tricky beast, that I still haven’t fully wrapped my head around. The major problem is that the Section title’s font-size attribute is not set specifically to a size and instead is set to 100% which then sets it to 100% of it’s parent tag’s font-size which causes an issue due to my meddling with jQueryUIs font-size to make it a bit more appealing to my eye. At least that’s my current theory.

    The workaround… once again inline style :) but for this one I set it to be dependent on the user wanting it. So the section shortcode allows for an attribute of title_font_size which the user can define if he/she believes the font-size should be adjusted. In the spirit of completeness, I also added allowance for a section_font_size attribute to allow the user to set font-size of the Section contents.

    The downside to this sort of workaround is that it means the user will have to play with it to find the right size for his/her site, and upon writing this I realize that doing it in the section shortcode means it will need to be repeated for each section of the Accordion… Think I’ll allow the attribute in the Accordion shortcode to be used for all sections in the released version :) .

Further reading:
CSS margin-bottom Property
CSS font-size Property

A basic Accordion’s height can vary

This flaw became apparent when I filled 1 out of 2 sections with Lorem Ipsum and the other with one line of content. I noticed that the height of the Accordion was then based on the content from the first section, and when clicking on the second section’s title it would float up to the first section title leaving the browser where it was.

Imagine this scenario, you have 2 sections ‘Chapter 1′ and ‘Chapter 2′ respectively. In each of those sections you have content that fills 2 screens. Your user happily starts reading the first section, upon reaching the bottom is intrigued to find out what happens in the second section and eagerly clicks on ‘Chapter 2′. ‘Chapter 2′ floats to the heavens and disappears out of the browser window and your user is now reading the conclusion of the second section…

If I was that user, I would either indignantly scroll up to the start and be fairly irritated at the inconvenience (I’m a rather lazy user) or I would just discard the second section and carry on down the webpage. So being the developer of this Accordion I don’t want to irritate the user in me. I decided to adjust the JavaScript for my accordion, which came to this little beauty:
$("#accordion").accordion({
 beforeActivate: function( event, ui ) {
  newHeadOffset = ui.newHeader[0].offsetTop;
  oldHeadOffset = ui.oldHeader[0].offsetTop;
  if (newHeadOffset > oldHeadOffset && oldHeadOffset < $(document).scrollTop()) {
   $("html,body").animate({ scrollTop: oldHeadOffset });
  }
 }
});
Glorious! No?

As you can see we have $("#accordion").accordion() as you’ve seen before, just with a whole lot more inside of the accordion function’s parenthesis. This is one of the great things about jQueryUI’s widgets, you can simply call the function () if you like or you can pass it a key:value array (Technically speaking this is an object in JavaScript, but I like to refer to them as arrays). In that array you can set options, override methods or even add functions to events (using the specific key of course).

In the JavaScript above we are defining our array inside of the function… I think I can explain this a bit better with psuedocode:
array = {key:value}; – Defining an array. And in our code above, we have this:
$("#accordion").accordion( {key:value} ) – Very simple version ;)

So… now let’s change out that simple version for what we have:
key is beforeActivate which is an event triggered before a section is activated (It’s kind of in the name).
value is a function that will be run when the event happens, and when this event occurs jQuery calls the function passing two variables to it (event, ui), the event variable is an Event which we don’t use for this function. And the ui variable is an Object which we use to get the height offset (How many pixel’s the top of an object is from it’s parent object) of our oldHeader (The header that used to be activated) and our newHeader (The header that was clicked on).

After getting our height offsets for old and new headers we can have some fun with them:
if (newHeadOffset > oldHeadOffset && oldHeadOffset < $(document).scrollTop())
In this if statement we’re checking firstly whether newHeadOffset is greater than oldHeadOffset, reason for that is if the new header’s height offset is less than the old header we don’t need to do anything (The newly activated header is higher on the browser than the old header, which means we don’t need to do any scrolling). And then… (hehe, just made me think of Dude Where’s My Car) we check if the old header is still in the browser by checking that it’s offset is less than the current scroll position ($(document).scrollTop()) which would also mean no scroll necessary if our old header offset is less than the scrollbar’s current position.

Now if all of those conditions are met (New header is below the old header and the old header is out of view in the browser) we run the following code:
$("html,body").animate({ scrollTop: oldHeadOffset });
Here we are using a jQuery function animate() to animate the selected objects ($("html,body") – selects either the html or the body of the web page) to change the property (scrollTop), to the value (oldHeadOffset), set inside of the function ({ scrollTop: oldHeadOffset }). This will make the page scroll nice and fluidly to the top of the old header, saving the user from having to do it.

This is the simplest and easiest way of doing this, possibly further down the line I would like it to scroll to just the top of the new header (With the given solution, if you have 4 sections and with the first section active you select the 3rd section, the page will scroll to the top of the first section. But if you select the 3rd section from the 2nd section, it will scroll to the top of the 2nd section), but this requires a bit more complexity in the JavaScript and I don’t see it as absolutely necessary for now.

Further reading:
Accordion API (List of options/methods/events)
Reason for using both html and body selectors

My height solution has it’s own flaw

The above solution is awesome, but after a few tests I found a bit of a bug. I found that when I clicked on a nested Accordion’s lower header with the upper header still in view, the page scrolled up… which shouldn’t happen.

I looked into this and found that (as I described above) the height offset I’m getting in the JavaScript is an offset based on the placement of the Accordion. Here’s a little example for you:

Height Offset Bug Example

As you can see in the image above, we have an Accordion inside of a Tab. Now what happens when you activate the second section of the Accordion, the JavaScript laid out in the last segment will check whether the new header is lower than the old header which is true. After that it checks whether the offset of the old header is less than the offset of the scrollbar from the top of the page… which will be returned as true in the above example. The reason for this, is that the old header offset is not the offset between it and the top of the page but instead the offset between old header and the top of it’s parent (The top of the Tab). Which is far less than the offset of the scrollbar and will scroll the page even higher than it already is.

So… how do we get the old header’s total offset?
From a little debugging I found that the oldHeader object also contains a value of offsetParent which is the parent of the Accordion AND has it’s own offsetTop :)

Happy days, we’ve found a solution! And in the given situation we could simply alter the JavaScript to look like this:
$("#accordion").accordion({
 beforeActivate: function( event, ui ) {
  newHeadOffset = ui.newHeader[0].offsetTop;
  oldHeadOffset = ui.oldHeader[0].offsetTop;
  totalOffset = oldHeadOffset + ui.oldHeader[0].offsetParent.offsetTop;
  if (newHeadOffset > oldHeadOffset && totalOffset < $(document).scrollTop()) {
   $("html,body").animate({ scrollTop: totalOffset });
  }
 }
});
Fortunately this code will work even if the Accordion doesn’t have a parent, because in a case like that the parent would be the body of the HTML which has an offset of 0 (Saving us from errors of trying to use an undefined variable and not affecting the calculation of our totalOffset).

I could leave it there, but this brings a question to mind “What if the Accordion is nested 3 levels down instead of just 2?”. So I figured it would be best to solve that before it became an issue, let’s start with the code first:
function getParentOffset(offsetParent) {
 returnInt = offsetParent.offsetTop;
 if (offsetParent.offsetParent) {
  if (offsetParent.offsetParent.offsetTop > 0) {
   returnInt = returnInt + getParentOffset(offsetParent.offsetParent);
  }
 }
 return returnInt;
}
$("#accordion").accordion({
 beforeActivate: function( event, ui ) {
  newHeadOffset = ui.newHeader[0].offsetTop;
  oldHeadOffset = ui.oldHeader[0].offsetTop;
  if (newHeadOffset > oldHeadOffset) {
   totalOffset = oldHeadOffset + getParentOffset(ui.oldHeader[0].offsetParent);
   if (totalOffset < $(document).scrollTop()) {
    $("html,body").animate({ scrollTop: totalOffset });
   }
  }
}
});
Thanks to recursion with this snippet of code we are able to place an Accordion n levels deep :)

For this explanation I’ll just go through the new function getParentOffset that has been added. This function receives an offsetParent as a variable and stores it’s offsetTop. Once we have that value we check whether the current offsetParent has it’s own offsetParent (We don’t want to try using the offsetParent if it’s not defined). After that we check whether the defined offsetParent has an offsetTop greater than 0, if it is we need to get that value. We could just add offsetTop to our current offsetTop, but that would only allow us to account for 3 levels. So instead, we call getParentOffset again to increment our current offset (Which will loop until either the next parent is null or it’s offsetTop is 0) and lastly return the total for use in our Accordion function.

You’ll also notice that I no longer use && in the if statement for the beforeActivate function, I did this mainly because I don’t like to call functions if I don’t have to ;) so we will only use the getParentOffset function if the new header is below our old header.

Further reading:
Recursion

If you’re reading this, you’re a weird one. But if this has been of any use to you or you think I’ve gotten something wrong, please let me know in the comments.

Use of global variables within plugin – WordPress Development Stack Exchange

In the words of Gru, “Light~bulb!”

How to move Data from PHP to JS

Simple as it is: wp_localize_script()

Example: (can be used with login_enqueue_scripts and admin_enqueue_scripts hooks as well)

add_action( 'wp_enqueue_scripts', 'wpse115840_scripts' );
function wpse115840_scripts()
{
wp_enqueue_script( 'wpse_handle', etc... );
// Here goes the magic:
wp_localize_script( 'wpse_handle', 'wspeObject', array(
'foo' => 'bar',
'bar' => get_option( 'baz' )
) );
}

Now you can access all the data from the wp_localize_script() array (the 3rd arg) in your javascript file that you just registered/enqueued simply by calling wpseObject. The following example would now give you the value bar:

console.log( wpseObject.foo );

and your wpseObject.bar would hold your baz setting value.

via Use of global variables within plugin – WordPress Development Stack Exchange.

This is absolutely inspired… Posting it just as a reminder to use it in the future.

Updated (28 May 2014)

I finally incorporated this into a plugin I’m working on (PJ jQuery UI Helper to be exact). And it was surprisingly more difficult than I thought it would be.

The difficulty really lay in my being rather rusty in JavaScript, my final bump in the road was in using a greater than sign instead of a less than sign in my for loop… feel sheepish for that mistake, but it’s all learning even if it is stuff that I knew before (Practice makes perfect).

I plan to make a full post on the changes made to PJ jQuery UI Helper this weekend to further improve on the perfection from the practice and hopefully help somebody else who may fall into the same traps that I did.

7 Reasons Why You’ll Never Do Anything Amazing With Your Life

Techno EyeballI’m looking you in the eyes, (ok well, not really since you are probably reading this article, but figuratively, I am burning a cyclops type hole in your face right now) and telling you that you don’t stand a chance.

I’m telling you that if you can read this article, look through this list and not claim it as your own, then you should be a little worried.

via 7 Reasons Why You’ll Never Do Anything Amazing With Your Life.

Absolutely awesome article, give it a read or listen when you can.

WordPress Settings API Tutorial » Otto on WordPress

Found this to be a godsend for updating plugin settings. Hoping to use this to create a more generalised plugin options function, which will be able to make plugin settings from an array created in my model class. Hopefully make a new post on this generalised function once I have it up and running.

In the meantime I give you this as a stopgap :)

WordPress Settings API Tutorial » Otto on WordPress.