1

What I want is very simple, I want the Expand All button to be auto clicked when I open this pluralsight course page. Its HTML is:

<a id="expandAll"
   ng-click="expandAllModules()"
   ng-hide="allModulesExpanded()">
    Expand All
</a>

So it seems easy and we just need to call the function expandAllModules(). However I don't know why it give me undefined when I check its type:

typeof expandAllModules
=> "undefined"

Generally typeof a function should give me "function" like this:

function a(){}
=> undefined
typeof a
=> "function"

Since the function expandAllModules() is not available, I can't call it. Anyone can give me a hand on this issue?


Edit

Perhaps I need to elaborate on my question. I'm not the author of that page. I just want to make a simple greasemonkey or tempermonkey script and expand the modules automatically when I enter the page.

James Donnelly
  • 126,410
  • 34
  • 208
  • 218
Just a learner
  • 26,690
  • 50
  • 155
  • 234
  • 1
    That's using Angular binding to call a function on the model. – SLaks Sep 30 '14 at 02:30
  • you would have to check the $scope for that function rather than just the function I think. – JanR Sep 30 '14 at 02:30
  • the $scope is not available too. – Just a learner Sep 30 '14 at 02:43
  • It's not a normal function, it's an angular thing, and it doesn't exist. Angular just kind've uses the name, and then the name acts as an "id" that links with the id of a function, but the name of the function isn't the same as the id. You can still simulate this same thing though by doing synthesized events or just using `click()` – markasoftware Oct 16 '14 at 03:58
  • Ignoring for a minute that this is using Angular, how did you intend to add this functionality to that page? I'm assuming of course that you are not the author of said page – Phil Oct 16 '14 at 03:59
  • 2
    Well, what exactly are you trying to make? Are you just trying to do this in the javascript/developer console? Are you trying to make a browser extension? Or a bookmarklet? – markasoftware Oct 16 '14 at 04:00
  • Where is the `expandAllModules` function defined? Is it in a controller/service/factory/directive/closure/`window`? – Michal Charemza Oct 16 '14 at 07:15
  • and i have a simple solution for you also =) – sss Oct 16 '14 at 08:21
  • i tried my answer in your website using developer console, you need to have scope.$digest() after calling the expandAllModules() method -- may not be in the actual code. – sss Oct 16 '14 at 09:01

3 Answers3

4

The Problem

The reason calling just expandAllModules() doesn't work is because this function belongs to one of Angular's scopes and isn't a method assigned to window. This function is defined in Plural Sight's table-of-contents-controller-v9.js like so:

"use strict";

pluralsightModule
    .controller("TableOfContentsController", ['$scope', ..., function ($scope, ...) {
        ...

        $scope.expandAllModules = function() {
            _.each($scope.courseModules, function (module) { module.visible= true; });
        };

        ...
    }])

The Solution

In order for us to call this function ourselves, we have to go through this scope.

scope is an object that refers to the application model. It is an execution context for expressions. Scopes are arranged in hierarchical structure which mimic the DOM structure of the application. Scopes can watch expressions and propagate events.
AngularJS: Developer Guide

The scope is part of the element which triggers the function. We can access this particular scope by passing the element's id attribute into angular.element(), then calling scope() on that object:

angular.element('#expandAll').scope()

This will give us the following data, where we can see the expandAllModules() function:

Console Example

Unfortunately AngularJS doesn't let us simply execute scope().expandAllModules(); instead we have to go through it's $apply and $eval methods:

var scope = angular.element('#expandAll').scope();

scope.$apply(function() {
    scope.$eval(scope.expandAllModules())
});

We can now also collapse the modules as well by calling:

scope.$apply(function() {
    scope.$eval(scope.collapseAllModules())
});

Working Screenshot

James Donnelly
  • 126,410
  • 34
  • 208
  • 218
1

I apologize if I am off-base here. Are you trying to "link" into that page and 'force' the page to "expand all", or do you have access to the page, and want to trigger the click with some code on the page, by you inserting the code? Just doing something like this seems to work from commandline.

   jQuery(function(){
      jQuery('#expandAll').trigger('click');
   });

Since I do not know your need, my thought is that this is a bit simplistic and not what you are looking for. From the responses of others, it appears you want to create your own directive to initiate the click?

james emanon
  • 11,185
  • 11
  • 56
  • 97
1

I might have some typos -- but the idea is there.

angular.element(document.body).ready(function() {

    var el = angular.element( document.getElementById('expandAll') );

    var scope = el.scope();

    scope.expandAllModules();

    scope.$digest(); <--- might not be needed, but when i check your site, it needs to have this

});

updates

if it was just 'onclick' instead of 'ng-click', you do not need to get the scope; and just call the function directly.

updates

I have tried this on your site, you need to have scope.$digest(). When I tried it, i was using the developer console.

see the developer console below

I was playing with it on your site. enter image description here

sss
  • 1,259
  • 9
  • 23