根据答案here,我一直在尝试将一个jQuery插件(addtocalendar)包装在一个angular指令中。我正在使用ui-router,以前插件可以工作,但如果我从这个孩子导航到另一个状态,addtocalendar按钮将完全消失。
现在,将插件包装在一个指令中,如果我导航到另一个子状态然后返回,我能够看到该按钮,但是,我从插件中得到一个错误,我指定了一个无效日期。似乎我从Angular提供插件的数据运行一次,然后再也不会被添加到插件中。
有解决方法吗?
这是我的HTML:
// works fine on first page load
<div addtocalendartest> // angular directive
<div class="addtocalendar"> //jQuery plugin
<div class="arrow-up"></div>
<var class="atc_event">
<var bind-once class="atc_date_start">{{event.startDate | date:'yyyy-MM-dd HH:mm:ss'}}</var>
<var bind-once class="atc_date_end">{{event.endDate | date:'yyyy-MM-dd HH:mm:ss'}}</var>
<var bind-once class="atc_timezone">America/New_York</var>
<var bind-once class="atc_title">{{event.description}}</var>
<var bind-once class="atc_description">{{event.Synopsis | characters: 200 :false }}</var>
<var bind-once class="atc_location">_</var>
</var>
</div>
</div>
这是我创建的包含插件逻辑的指令:
'use strict';
angular.module('myApp')
.directive('addtocalendartest', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
//run jQuery scripts
var w = window;
var d = document;
(function(w, d) {
var atc_url = "//addtocalendar.com/atc/",
atc_version = "1.5",
b = d.documentElement;
if (!Array.indexOf) {
Array.prototype.indexOf = function(e) {
for (var t = 0, n = this.length; t < n; t++) {
if (this[t] == e) {
return t
}
}
return -1
}
}
if (!Array.prototype.map) {
Array.prototype.map = function(e) {
var t = [];
for (var n = 0, r = this.length; n < r; n++) {
t.push(e(this[n]))
}
return t
}
}
var isArray = function(e) {
return Object.prototype.toString.call(e) === "[object Array]"
};
var isFunc = function(e) {
return Object.prototype.toString.call(e) === "[object Function]"
};
var ready = function(e, t) {
function u() {
if (!n) {
if (!t.body) return setTimeout(u, 13);
n = true;
if (i) {
var e, r = 0;
while (e = i[r++]) e.call(null);
i = null
}
}
}
function a() {
if (r) return;
r = true;
if (t.readyState === "complete") return u();
if (t.addEventListener) {
t.addEventListener("DOMContentLoaded", s, false);
e.addEventListener("load", u, false)
} else {
if (t.attachEvent) {
t.attachEvent("onreadystatechange", s);
e.attachEvent("onload", u);
var n = false;
try {
n = e.frameElement == null
} catch (i) {}
if (b.doScroll && n) f()
} else {
o = e.onload;
e.onload = function(e) {
o(e);
u()
}
}
}
}
function f() {
if (n) return;
try {
b.doScroll("left")
} catch (e) {
setTimeout(f, 1);
return
}
u()
}
var n = false,
r = false,
i = [],
s, o;
if (t.addEventListener) {
s = function() {
t.removeEventListener("DOMContentLoaded", s, false);
u()
}
} else {
if (t.attachEvent) {
s = function() {
if (t.readyState === "complete") {
t.detachEvent("onreadystatechange", s);
u()
}
}
}
}
return function(e) {
a();
if (n) {
e.call(null)
} else {
i.push(e)
}
}
}(w, d);
if (w.addtocalendar && typeof w.addtocalendar.start == "function") return;
if (!w.addtocalendar) w.addtocalendar = {};
addtocalendar.languages = {
de: "In den Kalender",
en: "Add to Calendar",
es: "Añadir al Calendario",
fr: "Ajouter au calendrier",
hi: "कैलेंडर में जोड़ें",
"in": "Tambahkan ke Kalender",
ja: "カレンダーã«è¿½åŠ ",
ko: "캘린ë”ì— ì¶”ê°€",
pt: "Adicionar ao calendário",
ru: "Добавить в календарь",
uk: "Додати в календар",
zh: "æ·»åŠ åˆ°æ—¥åŽ†"
};
addtocalendar.calendar_urls = {};
addtocalendar.loadSettings = function(element) {
var settings = {
language: "auto",
"show-list-on": "click",
calendars: ["iCalendar", "Google Calendar", "Outlook", "Outlook Online", "Yahoo! Calendar"],
secure: "auto",
"on-button-click": function() {},
"on-calendar-click": function() {}
};
for (var option in settings) {
var pname = "data-" + option;
var eattr = element.getAttribute(pname);
if (eattr != null) {
if (isArray(settings[option])) {
settings[option] = eattr.replace(/\s*,\s*/g, ",").replace(/^\s+|\s+$/g, "").split(",");
continue
}
if (isFunc(settings[option])) {
var fn = window[eattr];
if (isFunc(fn)) {
settings[option] = fn
} else {
settings[option] = eval("(function(mouseEvent){" + eattr + "})")
}
continue
}
settings[option] = element.getAttribute(pname)
}
}
return settings
};
addtocalendar.load = function() {
ready(function() {
var e = {
iCalendar: "ical",
"Google Calendar": "google",
Outlook: "outlook",
"Outlook Online": "outlookonline",
"Yahoo! Calendar": "yahoo"
};
var t = -(new Date).getTimezoneOffset().toString();
var n = addtocalendar.languages;
var r = document.getElementsByTagName("*");
for (var i = 0; i < r.length; i++) {
var s = r[i].className;
if (s.split(" ").indexOf("addtocalendar") != -1) {
var o = addtocalendar.loadSettings(r[i]);
var u = o["calendars"].length == 1;
var a = "http:";
if (o["secure"] == "auto") {
a = location.protocol == "https:" ? "https:" : "http:"
} else if (o["secure"] == "true") {
a = "https:"
}
var f = a + atc_url;
var l = r[i].id;
var c = n["en"];
if (o["language"] == "auto") {
var h = "no_lang";
if (typeof navigator.language === "string") {
h = navigator.language.substr(0, 2)
} else if (typeof navigator.browserLanguage === "string") {
h = navigator.browserLanguage.substr(0, 2)
}
if (n.hasOwnProperty(h)) {
c = n[h]
}
} else if (n.hasOwnProperty(o["language"])) {
c = n[o["language"]]
}
var p = ["utz=" + t, "uln=" + navigator.language, "vjs=" + atc_version];
var d = r[i].getElementsByTagName("var");
var v = -1;
for (var m = 0; m < d.length; m++) {
var g = d[m].className.replace("atc_", "");
var y = d[m].innerHTML;
if (g == "event") {
v++;
continue
}
if (g == d[m].className) {
if (g == "atc-body") {
c = y
}
continue
}
if (v == -1) {
continue
}
p.push("e[" + v + "][" + g + "]" + "=" + encodeURIComponent(y))
}
var b = l == "" ? "" : l + "_link";
var w = document.createElement("ul");
w.className = "atcb-list";
var E = "";
var S = "";
for (var x in o["calendars"]) {
if (!e.hasOwnProperty(o["calendars"][x])) {
continue
}
var T = e[o["calendars"][x]];
var N = l == "" ? "" : 'id="' + l + "_" + T + '_link"';
var C = f + T + "?" + p.join("&");
if (u) {
S = C
} else {
E += '<li class="atcb-item"><a ' + N + ' class="atcb-item-link" href="' + C + '" target="_blank">' + o["calendars"][x] + "</a></li>"
}
}
w.innerHTML = E;
if (r[i].getElementsByClassName("atcb-link")[0] == undefined) {
var k = document.createElement("a");
k.className = "atcb-link";
k.innerHTML = c;
k.id = b;
k.tabIndex = 1;
if (u) {
k.href = S;
k.target = "_blank"
}
r[i].appendChild(k);
if (!u) {
r[i].appendChild(w)
}
} else {
var k = r[i].getElementsByClassName("atcb-link")[0];
if (!u) {
k.parentNode.appendChild(w)
}
k.tabIndex = 1;
if (k.id == "") {
k.id = b
}
if (u) {
k.href = S;
k.target = "_blank"
}
}
r[i].getElementsByClassName("atcb-link")[0].addEventListener("click", o["on-button-click"], false);
var L = r[i].getElementsByClassName("atcb-item-link");
for (var m = 0; m < L.length; m++) {
L[m].addEventListener("click", o["on-calendar-click"], false)
}
}
}
})
};
addtocalendar.load()
})(window, document)
}
};
});
UPDATE / ANSWER 感谢@charlietfl,答案是包含$ timeout,以便Angular可以在jQuery插件之前加载,例如:
'use strict';
angular.module('myApp')
.directive('addtocalendartest', function($timeout) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
$timeout(function(){
// jQuery plugin logic goes here
}, 5000);
}
};
});
答案 0 :(得分:1)
使用$timeout
让angular首先编译文本,以便插件不会尝试读取表达式。
$timeout(function(){
addtocalendar.load();
});
如果需要首先从服务器请求解析数据,您可以在路由器中使用resolve
,以便在模板加载时存在