0

I have a script that listens for online presence and I would like to use angular for the html that I insert, but the openChatWindow() call is not working.

 $("#i"+getMessageId(snapshot)).append('<img id="theImg" class="ui avatar image" ng-click="openChatWindow()" style="float:left;" src="'+chrome.extension.getURL("images/patrick.png")+'" />')

The ng directives work on other parts of the page. Why does the ng-click fail?

My script (that reside in app/scripts)

var name = prompt("Your name?", "Guest");
  var currentStatus = "online";

  // Get a reference to the presence data in Firebase.
  var userListRef = new Firebase("https://sizzling-inferno-2758.firebaseio.com/");

  // Generate a reference to a new location for my user with push.
  var myUserRef = userListRef.push();

  // Get a reference to my own presence status.
  var connectedRef = new Firebase("https://sizzling-inferno-2758.firebaseio.com//.info/connected");

  connectedRef.on("value", function(isOnline) {
    if (isOnline.val()) {
      // If we lose our internet connection, we want ourselves removed from the list.
      myUserRef.onDisconnect().remove();

      // Set our initial online status.
      setUserStatus("online");
    }
    else {

      // We need to catch anytime we are marked as offline and then set the correct status. We
      // could be marked as offline 1) on page load or 2) when we lose our internet connection
      // temporarily.
      setUserStatus(currentStatus);
    }
  });

  // A helper function to let us set our own state.
  function setUserStatus(status) {
    // Set our status in the list of online users.
    currentStatus = status;
    myUserRef.set({ name: name, status: status });
  }

  function getMessageId(snapshot) {
    return snapshot.key().replace(/[^a-z0-9\-\_]/gi,'');
  }

  // Update our GUI to show someone"s online status.
  userListRef.on("child_added", function(snapshot) {
    var user = snapshot.val();
if (user.name!=undefined) {

   $("<div/>")
      .attr("class","greendot")
      .attr("style","float:left")
      .appendTo("#presenceDiv");

   //  $("<img/")
     // .attr("class","ui avatar image")
      //.attr("style","float:left")
       //.attr("ng-hide","showHide")
       // .attr("ng-src","{{user.image}}")
      //.appendTo("#presenceDiv");
  $('#presenceDiv').append('<img id="theImg" class="ui avatar image" style="float:left;" src="'+chrome.extension.getURL("images/patrick.png")+'" />')
    $("<div/>")
      .attr("id", getMessageId(snapshot))
       .attr("style","color:white")
      .text(user.name + " is currently " + user.status)
      .appendTo("#presenceDiv");


  } 
  });

  // Update our GUI to remove the status of a user who has left.
  userListRef.on("child_removed", function(snapshot) {
    $("#presenceDiv").children("#" + getMessageId(snapshot))
      .remove();
  });

  // Update our GUI to change a user"s status.
  userListRef.on("child_changed", function(snapshot) {
    var user = snapshot.val();
    $("#presenceDiv").children("#" + getMessageId(snapshot))
      .text(user.name + " is currently " + user.status);
  });

  // Use idle/away/back events created by idle.js to update our status information.
  document.onIdle = function () {
    setUserStatus("idle");
  }
  document.onAway = function () {
    setUserStatus("away");
  }
  document.onBack = function (isIdle, isAway) {
    setUserStatus("online");
  }

  setIdleTimeout(5000);
  setAwayTimeout(10000);

My controller

myApp.controller("SidebarController", function ($scope) {

    var content = [
        { title: 'Andorra' },
        { title: 'United Arab Emirates' },
        { title: 'Afghanistan' },
        { title: 'Antigua' },
        { title: 'Anguilla' },
        { title: 'Albania' },
        { title: 'Armenia' },
        { title: 'Netherlands Antilles' },
        { title: 'Angola' },
        { title: 'Argentina' },
        { title: 'American Samoa' },
        { title: 'Austria' },
        { title: 'Australia' },
        { title: 'Aruba' },
        { title: 'Aland Islands' },
        { title: 'Azerbaijan' },
        { title: 'Bosnia' },
        { title: 'Barbados' },
        { title: 'Bangladesh' },
        { title: 'Belgium' },
        { title: 'Burkina Faso' },
        { title: 'Bulgaria' },
        { title: 'Bahrain' },
        { title: 'Burundi' }
        // etc
    ];

    $scope.users = [
        {name: "Olle", image: chrome.extension.getURL("images/patrick.png")},
        {name: "Llle", image: chrome.extension.getURL("images/patrick.png")},
        {name: "Slle", image: chrome.extension.getURL("images/patrick.png")},
        {name: "Kalle", image: chrome.extension.getURL("images/patrick.png")}
    ];

    $('.ui.search').search({ source: content});

    $scope.value = "Text";


    $scope.addFriendClick = function() {
        //var popupScope = angular.element($("[ng-controller='PopupDialogController']")).scope();
        //popupScope.show();
        console.log("Clicked");
        alert("hello");
    }
    $scope.openChatWindow = function () {;
        console.log("Clicked open chat");
        chrome.runtime.sendMessage({ greeting: "channels" }, function (response) {
            console.log(response.farewell);
        });
    }
    $scope.openChannels = function () {;
        console.log("Clicked open channels");

        $scope.users = [
            {name: "Kanal1"},
            {name: "Kanal2"},
            {name: "Kanal3"},
            {name: "Kanal4"}
        ];
        $scope.showHide = true;
        $scope.$apply();

    }
    $scope.openUsers = function () {;
        console.log("Clicked open users");

        $scope.users = [
            {name: "Olle", image: chrome.extension.getURL("images/patrick.png")},
            {name: "Llle", image: chrome.extension.getURL("images/patrick.png")},
            {name: "Slle", image: chrome.extension.getURL("images/patrick.png")},
            {name: "Kalle", image: chrome.extension.getURL("images/patrick.png")}
        ];
        $scope.showHide = false;

        $scope.$apply();

    }
    angular.element(document).ready(function () {
        $("#profile").attr("src", chrome.extension.getURL("images/patrick.png"));
        setTimeout(function(){

        }, 0);
    });
});

My app.js

var myApp = angular.module('AngularChromeEx', ["firebase"], function($compileProvider) {
    $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|chrome-extension):|data:image\//);
    $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|chrome-extension):/);
});
/*
myApp.factory('Server', ['$http', function ($http) {
  return {
    get: function(url) {
      return $http.get(url);
    },
    post: function(url) {
      return $http.post(url);
    },
  };
}]);
*/

myApp.controller('SidebarController', function($scope) {

  $scope.showHide = false;

});

myApp.controller("SidebarController", function($scope, $firebaseArray) {
  var ref = new Firebase("https://sizzling-inferno-2758.firebaseio.com/messages");
  // create a synchronized array
  // click on `index.html` above to see it used in the DOM!
  $scope.messages = $firebaseArray(ref);
});

My manifest.js

{
  "name": "__MSG_appName__",
  "version": "0.0.2",
  "manifest_version": 2,
  "description": "__MSG_appDescription__",
  "icons": {
    "16": "images/icon-16.png",
    "128": "images/icon-128.png"
  },
  "default_locale": "en",
  "background": {
    "scripts": [
      "bower_components/jquery/dist/jquery.min.js",
      "scripts/chromereload.js",
      "scripts/jsclasses/Injection.js",
      "scripts/background.js"
    ]
  },
  "browser_action": {
    "default_icon": {
      "19": "images/icon-19.png",
      "38": "images/icon-38.png"
    },
    "default_title": "angular injection",
   "default_popup": "browser_action/browser_action.html"
  },
  "options_page": "options.html",
  "content_scripts": [
    {
      "matches": [
        "http://*/*",
        "https://*/*"
      ],
      "css": [
        "styles/reset.css",
        "bower_components/angular/angular-csp.css",
        "bower_components/semantic/dist/semantic.css",
        "bower_components/jquery/dist/jquery-ui.min.css",
        "styles/main.css"
      ],
      "js": [
        "bower_components/jquery/dist/jquery.min.js",
        "bower_components/jquery/dist/jquery-ui.min.js",
        "bower_components/semantic/dist/semantic.min.js",
        "bower_components/angular/angular.min.js",
        "scripts/app.js",
        "scripts/controllers/PopupDialogController.js",
        "scripts/controllers/SidebarController.js",
        "scripts/contentscript.js",
        "scripts/firebase.js",
        "bower_components/angularfire/index.js",
           "bower_components/angular/index.js"

      ],
      "run_at": "document_end",
      "all_frames": false
    }
  ],
   "content_security_policy": "script-src 'self' https://cdn.firebase.com https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js https://*.firebaseio.com https://*.firebaseio-demo.com; object-src 'self'",
  "web_accessible_resources": [
    "bower_components/angular/*",
    "bower_components/semantic/*",
    "images/*",
    "bower_components/semantic/dist/themes/default/assets/fonts/*",
    "bower_components/semantic/dist/themes/default/assets/fonts/icons.woff",
    "scripts/views/*"
  ],
  "permissions": [
    "tabs",
    "http://*/*",
    "https://*/*"
  ]
}

My view

<!doctype html>
<html ng-app="SidePanelModule" ng-csp="">
<head>
  <link href="../../styles/sidepanelmodule.css" rel="stylesheet">
  <link href="../../bower_components/angular/angular-csp.css" rel="stylesheet">
  <link href="../../bower_components/semantic/dist/semantic.css" rel="stylesheet">
  <link href="../../bower_components/jquery/dist/jquery-ui.min.css" rel="stylesheet">
  <script src="../../bower_components/jquery/dist/jquery.min.js"></script>
  <script src="../../bower_components/jquery/dist/jquery-ui.min.js"></script>
  <script src="../../bower_components/semantic/dist/semantic.min.js"></script>
  <script src="../../bower_components/angular/angular.min.js"></script>
  <script src="../sidepanelapp.js"></script>
  <script src="../controllers/SidebarController.js"></script>
    <script src="../../scripts/idle.js"></script>
        <script src="../../scripts/firebase.js"></script>
</head>
<body>
<nav ng-controller="SidebarController" class="rightSlider">
<div class="siderbar-inner">
  <div class="ui aligned padded grid">
    <div class="row">
      <div class="five wide column">
        <img width="50px" height="50px" id="profile" class="ui circular image">
      </div>
      <div class="five wide column">
        <h3 style="margin-top: 15px;">Patrick</h3>
      </div>
    </div>
    <div class="centered row">
      <div style="width: 200px; height: 30px;" class="ui icon input">
        <input id="search" class="prompt" type="text" placeholder="Search animals...">
        <i class="search icon"></i>
      </div>
    </div>
    <div class="row">
      <div class="column">
        <div class="ui clearing divider"></div> 
        <div ng-show="showHide" ng-hide="!showHide" style="color:white;">
          <b>Your recent discussions</b>
        </div>

         <div id="presenceDiv" class="l-demo-container example-base">
</div>
    <script src="../../scripts/presence.js"></script>
        <!--
        <div class="ui middle aligned selection list" ng-repeat="user in users">
          <div class="item">
            <div ng-hide="showHide" ng-show="!showHide" class="greendot"></div>
            <i ng-show="showHide" ng-hide="!showHide" class="remove circle outline icon large" style="float:left;color:white;"></i>
            <img ng-hide="showHide" ng-src="{{user.image}}" class="ui avatar image">
            <div class="content">
              <a ng-click="openChatWindow()" class="header, reader">{{user.name}}</a>
            </div>
          </div>
        </div>
        -->
      </div>
    </div>
    <div class="centered row">
      <div class="ui clearing divider"></div>
      <button ng-click="addFriendClick()" class="ui primary button">
        Add friends {{value}}
      </button>
    </div>



    <div class="centered row">
        <div class="four ui buttons">
          <div class="ui icon button home" data-content="Home">
            <i class="home icon"></i>
          </div>
          <button class="mini ui button"><i class="tags icon"></i></button>
          <button ng-click="openChannels()" class="mini ui button"><i class="history icon"></i></button>
          <button  ng-click="openUsers()" class="mini ui button"><i class="users icon"></i></button>
        </div>
      </div>
    </div>
  </div>
</div>
</nav>
</body>
</html>
4
  • 1
    must use $compile for angular to recognize directives/expressions you insert in dom. Most likely if you got rid of using jQuery for this and used data model to drive view you wouldn't have any issues Commented Sep 13, 2015 at 23:33
  • @charlietfl Can you please show me how I use it? I never did that before. Commented Sep 13, 2015 at 23:33
  • 1
    perhaps, but why are you using jQuery to insert html in the first place? Also have no idea where you are using this code Commented Sep 13, 2015 at 23:36
  • @charlietfl I took the code from an example (online presence sytem) that not uses angular. so I'm not sure if angular is known in the file. I'm developing a google chrome plugin in this script is included where angular is used for the view and controller. the code is not in the controller but in a parallel file. Commented Sep 13, 2015 at 23:40

1 Answer 1

1

Documentation for $compile

EDIT :

Well,

After looking at your code, I think you want append the new element using a function positioned in a non-angular component. And I'm sure you are not using the classic way for $compile, a directive.

If you want add an element to the DOM with a directive as attribute, outside of a directive, you have to do :

$(function() {
    var img = '<img id="theImg" class="ui avatar image" ng-click="openChatWindow()" style="float:left;" src="'+chrome.extension.getURL("images/patrick.png")+'" />';
    angular.element(document).injector().invoke(function($compile, $rootScope) {
        $("#i"+getMessageId(snapshot)).append($compile(img)($rootScope));
        $rootScope.$apply();
    });
});

This should work and update the invoked existing scope (know new elements).

If injector is undefined, create your own like that :

$(function() {
    var $injector = angular.injector(['ng']);
    var img = '<img id="theImg" class="ui avatar image" ng-click="openChatWindow()" style="float:left;" src="'+chrome.extension.getURL("images/patrick.png")+'" />';
    $injector.invoke(function($compile, $rootScope) {
        $("#i"+getMessageId(snapshot)).append($compile(img)($rootScope));
        $rootScope.$apply();
    });
});

This will work

Sign up to request clarification or add additional context in comments.

12 Comments

angular.element() does not use $compile. This will do no different than using jQuery
still missing the scope argument and if OP is loading jQuery in extension only (after angular loads in page) angular.element won't work with ID selector
@Programmer400 it won't be because it needs to be injected into an angular component
@Programmer400 please insert your code in a gist or fiddle and edit your answer with it, we will help you
@Programmer400 Thank's for sharing your code. But the line of code you given before add your code is not present in your files. In which file (and function ?) you want append the element with ng-click directive as attribute ? In your script (first) or in an angular component (like your controller) ?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.