Tutorial — Manipulating Affix Sets
Part 7 of a Guide to Function Interception in JavaScript
Contents
Iterating across Affix Sets
Affix objects provide two methods called GetNext and GetPrev, which support iteration through a set of prefixes or suffixes, either 'back' to the first in the set, or 'forward' to the last.
Note that calling GetPrev on the first affix in a set, or calling GetNext on the last will return the object on which those methods are called. This means it is impossible to navigate beyond either end of a set of affixes.
In Example Thirty-One, four prefixes are attached to MyFunc, which is then invoked. By calling GetPrev on the Affix object returned from the last call to AddAfter, the affix that was inserted on that call is retrieved, and repetition of this principle allows iteration back up the collection of prefixes. Comparison of the reference returned from the call to GetPrev with the reference to the object on which it is called enables detection of the end of the set.

 // Example 31
 //
 // Works with AJS
 // Will work only in part with AJS_HP
 //

 function Prefix_0 () { alert ("Prefix_0 executed"); }
 function Prefix_1 () { alert ("Prefix_1 executed"); }
 function Prefix_2 () { alert ("Prefix_2 executed"); }
 function Prefix_3 () { alert ("Prefix_3 executed"); }

 function MyFunc   () { alert ("MyFunc executed");   }


 var PrefixObj = AJS.AddPrefix (this, "MyFunc", Prefix_0);

 PrefixObj = PrefixObj.AddAfter (Prefix_1);
 PrefixObj = PrefixObj.AddAfter (Prefix_2);
 PrefixObj = PrefixObj.AddAfter (Prefix_3);

 MyFunc ();

 while (PrefixObj.GetPrev () !== PrefixObj)
    {
    PrefixObj = PrefixObj.GetPrev ();
    }

 PrefixObj.Remove ();

 MyFunc ();

 --------------------------------------

 Output (using AJS):

 Prefix_0 executed
 Prefix_1 executed
 Prefix_2 executed
 Prefix_3 executed
 MyFunc executed
 Prefix_1 executed
 Prefix_2 executed
 Prefix_3 executed
 MyFunc executed
            
Adding New Affix-Properties
Note that because it is possible to assign new properties to an object dynamically, it is therefore possible to assign attributes and other methods to a given Affix object. This allows tagging of prefixes and suffixes, such that they can be identified by other parts of a system, and is therefore of use in iterating through sets of affixes.
The next example illustrates this.

 // Example 32
 //
 // Works with AJS
 // Will work only in part with AJS_HP
 //

 function Prefix () { }
 function MyFunc () { }

 var PrefixObj = AJS.AddPrefix (this, "MyFunc", Prefix);

 PrefixObj.ID = "Prefix 5";

 PrefixObj.AddAfter (Prefix).ID = "Prefix 1";
 PrefixObj.AddAfter (Prefix).ID = "Prefix 2";
 PrefixObj.AddAfter (Prefix).ID = "Prefix 3";
 PrefixObj.AddAfter (Prefix).ID = "Prefix 4";

 MyFunc ();

 var OldObj = null;

 while (OldObj !== PrefixObj)
   {
   alert ("Affix ID = " + PrefixObj.ID);

   OldObj    = PrefixObj;
   PrefixObj = PrefixObj.GetNext ();

   }

 --------------------------------------

 Output (using AJS):

 Affix ID = Prefix 5
 Affix ID = Prefix 4
 Affix ID = Prefix 3
 Affix ID = Prefix 2
 Affix ID = Prefix 1
            
Promoting and Demoting Affixes
The execution order of affixes can be changed by means of the Promote and Demote methods of the Affix type. They can also be set collectively using the equivalent methods that Wrapper objects support.
To promote an affix means to move it closer to the interceptee in terms of the execution order. Therefore, to promote prefix A over prefix B means to cause A to execute after B (but before the interceptee). Similarly, to promote suffix A over suffix B will cause suffix A to execute before suffix B (but after the interceptee). The diagram illustrates these concepts.
In Example Thirty-Three, a wrapper is applied to MyFunc, which is then invoked. A second wrapper is then applied such that, on a second call to MyFunc, its prefix and suffix execute after and before (respectively) the first wrapper's affixes. The second wrapper's prefix and suffix are then both demoted, meaning that a final call to MyFunc causes those affixes to execute before and after the first wrapper's affixes.

 // Example 33
 //
 // Works with AJS
 // Will work only in part with AJS_HP
 //

 function Prefix_0 () { alert ("Prefix_0 executed"); }
 function Prefix_1 () { alert ("Prefix_1 executed"); }

 function Suffix_0 () { alert ("Suffix_0 executed"); }
 function Suffix_1 () { alert ("Suffix_1 executed"); }

 function MyFunc   () { alert ("MyFunc executed");   }


 AJS.AddWrapper (this, "MyFunc", Prefix_0, "", Infinity, Suffix_0);

 MyFunc ();

 var WrapperObj = AJS.AddWrapper (this, "MyFunc", Prefix_1, "", Infinity, Suffix_1);

 MyFunc ();

 WrapperObj.Prefix.Demote ();
 WrapperObj.Suffix.Demote ();

 MyFunc ();

 --------------------------------------

 Output (using AJS):

 Prefix_0 executed
 MyFunc   executed
 Suffix_0 executed

 Prefix_0 executed
 Prefix_1 executed
 MyFunc   executed
 Suffix_1 executed
 Suffix_0 executed

 Prefix_1 executed
 Prefix_0 executed
 MyFunc   executed
 Suffix_0 executed
 Suffix_1 executed
            
Go forward to Part 8 of this tutorial.
Go back to Part 6 of this tutorial.
Copyright © Dodeca Technologies Ltd. 2007