]> git.mxchange.org Git - friendica.git/commitdiff
make the addon frio_hovercard working with the frio theme (Note: some changes which...
authorrabuzarus <>
Thu, 5 May 2016 19:10:08 +0000 (21:10 +0200)
committerrabuzarus <>
Thu, 5 May 2016 19:10:08 +0000 (21:10 +0200)
The addon frio_hovercard was initatet because we need a new module for the frio theme

css/hovercard.css [new file with mode: 0644]
css/style.css
js/hovercard.js [new file with mode: 0644]
js/theme.js
php/modes/default.php
templates/search_item.tpl
templates/wall_thread.tpl

diff --git a/css/hovercard.css b/css/hovercard.css
new file mode 100644 (file)
index 0000000..54dff6a
--- /dev/null
@@ -0,0 +1,646 @@
+html {\r
+  font-family: sans-serif;\r
+  -ms-text-size-adjust: 100%;\r
+  -webkit-text-size-adjust: 100%;\r
+}\r
+body {\r
+  margin: 0;\r
+}\r
+a {\r
+  background: transparent;\r
+}\r
+a:active,\r
+a:hover {\r
+  outline: 0;\r
+}\r
+* {\r
+  -webkit-box-sizing: border-box;\r
+  -moz-box-sizing: border-box;\r
+  box-sizing: border-box;\r
+}\r
+*:before,\r
+*:after {\r
+  -webkit-box-sizing: border-box;\r
+  -moz-box-sizing: border-box;\r
+  box-sizing: border-box;\r
+}\r
+html {\r
+  font-size: 10px;\r
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\r
+}\r
+body {\r
+  font-family: "Lato", Helvetica, Arial, sans-serif;\r
+  font-size: 14px;\r
+  line-height: 1.42857143;\r
+  color: #333333;\r
+  background-color: #e9ecf0;\r
+}\r
+\r
+a {\r
+  color: #587c9b;\r
+  text-decoration: none;\r
+}\r
+a:hover,\r
+a:focus {\r
+  color: #3c556a;\r
+  text-decoration: underline;\r
+}\r
+a:focus {\r
+  outline: thin dotted;\r
+  outline: 5px auto -webkit-focus-ring-color;\r
+  outline-offset: -2px;\r
+}\r
+.main-container {\r
+  min-height: 100%;\r
+  padding-bottom: 2em;\r
+  position: relative;\r
+  margin: 0 auto;\r
+  width: 100%;\r
+}\r
+.hovercard {\r
+  position: absolute;\r
+  top: 0;\r
+  left: 0;\r
+  z-index: 1040;\r
+  display: none;\r
+  /*max-width: 276px;*/\r
+  max-width: 400px;\r
+  padding: 1px;\r
+  text-align: left;\r
+  background-color: #ffffff;\r
+  background-clip: padding-box;\r
+  border: 1px solid #cccccc;\r
+  border: 1px solid rgba(0, 0, 0, 0.2);\r
+  border-radius: 200px;\r
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\r
+  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\r
+  white-space: normal;\r
+}\r
+.hovercard.top {\r
+  margin-top: -10px;\r
+}\r
+.hovercard.right {\r
+  margin-left: 10px;\r
+}\r
+.hovercard.bottom {\r
+  margin-top: 10px;\r
+}\r
+.hovercard.left {\r
+  margin-left: -10px;\r
+}\r
+.hovercard-title {\r
+  margin: 0;\r
+  padding: 8px 14px;\r
+  font-size: 14px;\r
+  font-weight: normal;\r
+  line-height: 18px;\r
+  background-color: #f7f7f7;\r
+  border-bottom: 1px solid #ebebeb;\r
+  border-radius: 199px 199px 0 0;\r
+  display: none;\r
+}\r
+.hovercard-content {\r
+/*  padding: 9px 14px;*/\r
+  \r
+  color: #777;\r
+  padding: 0;\r
+}\r
+.hovercard > .arrow,\r
+.hovercard > .arrow:after {\r
+  position: absolute;\r
+  display: block;\r
+  width: 0;\r
+  height: 0;\r
+  border-color: transparent;\r
+  border-style: solid;\r
+}\r
+.hovercard > .arrow {\r
+  border-width: 11px;\r
+}\r
+.hovercard > .arrow:after {\r
+  border-width: 10px;\r
+  content: "";\r
+}\r
+.hovercard.top > .arrow {\r
+  left: 50%;\r
+  margin-left: -11px;\r
+  border-bottom-width: 0;\r
+  border-top-color: #999999;\r
+  border-top-color: rgba(0, 0, 0, 0.25);\r
+  bottom: -11px;\r
+}\r
+.hovercard.top > .arrow:after {\r
+  content: " ";\r
+  bottom: 1px;\r
+  margin-left: -10px;\r
+  border-bottom-width: 0;\r
+  border-top-color: #ffffff;\r
+}\r
+.hovercard.right > .arrow {\r
+  top: 50%;\r
+  left: -11px;\r
+  margin-top: -11px;\r
+  border-left-width: 0;\r
+  border-right-color: #999999;\r
+  border-right-color: rgba(0, 0, 0, 0.25);\r
+}\r
+.hovercard.right > .arrow:after {\r
+  content: " ";\r
+  left: 1px;\r
+  bottom: -10px;\r
+  border-left-width: 0;\r
+  border-right-color: #ffffff;\r
+}\r
+.hovercard.bottom > .arrow {\r
+  left: 50%;\r
+  margin-left: -11px;\r
+  border-top-width: 0;\r
+  border-bottom-color: #999999;\r
+  border-bottom-color: rgba(0, 0, 0, 0.25);\r
+  top: -11px;\r
+}\r
+.hovercard.bottom > .arrow:after {\r
+  content: " ";\r
+  top: 1px;\r
+  margin-left: -10px;\r
+  border-top-width: 0;\r
+  border-bottom-color: #ffffff;\r
+}\r
+.hovercard.left > .arrow {\r
+  top: 50%;\r
+  right: -11px;\r
+  margin-top: -11px;\r
+  border-right-width: 0;\r
+  border-left-color: #999999;\r
+  border-left-color: rgba(0, 0, 0, 0.25);\r
+}\r
+.hovercard.left > .arrow:after {\r
+  content: " ";\r
+  right: 1px;\r
+  border-right-width: 0;\r
+  border-left-color: #ffffff;\r
+  bottom: -10px;\r
+}\r
+\r
+.right-aligned {\r
+  float: right !important;\r
+}\r
+.left-align {\r
+  float: left !important;\r
+}\r
+.hidden {\r
+  display: none !important;\r
+  visibility: hidden !important;\r
+}\r
+h1,\r
+.h1,\r
+h2,\r
+.h2,\r
+h3,\r
+.h3 {\r
+  margin: 0;\r
+  padding: 0;\r
+}\r
+h3 {\r
+  font-size: 24px;\r
+}\r
+h4,\r
+.h4,\r
+h5,\r
+.h5,\r
+h6,\r
+.h6 {\r
+  margin: 0;\r
+  padding: 0;\r
+}\r
+h4.text-center {\r
+  margin-top: 10px;\r
+  margin-bottom: 5px;\r
+}\r
+sup {\r
+  top: 0;\r
+}\r
+small,\r
+.small {\r
+  font-size: 85%;\r
+}\r
+ul,\r
+ol {\r
+  margin: 0;\r
+  padding: 0;\r
+  margin-bottom: 0;\r
+}\r
+a:hover,\r
+a:active,\r
+a:focus,\r
+a:visited {\r
+  text-decoration: none !important;\r
+}\r
+\r
+\r
+/* Basic hovercard */\r
+.basic-content {\r
+  padding: 9px 14px;\r
+}\r
+.basic-image-wrapper {\r
+  background: #fff;\r
+  border: 2px #fff solid;\r
+  margin-top:10px;\r
+  display: block;\r
+  overflow: hidden;\r
+}\r
+.basic-image-wrapper > a,\r
+.basic-image-wrapper > span {\r
+  background-size: 100% !important;\r
+}\r
+\r
+/*.basic-image-wrapper:hover {\r
+  box-shadow: 0 0 0.2em #7595b1;\r
+  cursor: pointer;\r
+}*/\r
+.basic-image-wrapper.mini {\r
+  max-width: 40px;\r
+  max-height: 40px;\r
+}\r
+.basic-image-wrapper.mini > a,\r
+.basic-image-wrapper.mini > span {\r
+  height: 40px;\r
+  width: 40px;\r
+  content: " ";\r
+  display: block;\r
+}\r
+.basic-image-wrapper.mini .image-l {\r
+  width: 30px;\r
+  display: block;\r
+  height: 40px;\r
+  overflow: hidden;\r
+  float: left;\r
+  text-align: center;\r
+  margin-left: -14px;\r
+}\r
+.basic-image-wrapper.mini .image-l > span {\r
+  display: block;\r
+  width: 40px;\r
+  height: 40px;\r
+  background-size: 100% !important;\r
+}\r
+.basic-image-wrapper.mini > .image-ur,\r
+.basic-image-wrapper.mini > .image-lr {\r
+  width: 19px;\r
+  display: block;\r
+  height: 23px;\r
+  margin-top: -2px;\r
+  overflow: hidden;\r
+  float: right;\r
+  text-align: center;\r
+  z-index: -99;\r
+  margin-left: -1px;\r
+}\r
+.basic-image-wrapper.mini > .image-ur > span,\r
+.basic-image-wrapper.mini > .image-lr > span {\r
+  display: block;\r
+  width: 20px;\r
+  height: 20px;\r
+  background-size: 100% !important;\r
+}\r
+.basic-image-wrapper.normal {\r
+  max-width: 60px;\r
+  max-height: 60px;\r
+}\r
+.basic-image-wrapper.normal > a,\r
+.basic-image-wrapper.normal > span {\r
+  height: 60px;\r
+  width: 60px;\r
+  content: " ";\r
+  display: block;\r
+}\r
+.basic-image-wrapper.medium {\r
+  max-width: 70px;\r
+  max-height: 70px;\r
+}\r
+.basic-image-wrapper.medium > a,\r
+.basic-image-wrapper.medium > span {\r
+  height: 70px;\r
+  width: 70px;\r
+  content: " ";\r
+  display: block;\r
+}\r
+.basic-image-wrapper.large {\r
+  max-width: 140px;\r
+  max-height: 140px;\r
+}\r
+.basic-image-wrapper.large > a,\r
+.basic-image-wrapper.large > span {\r
+  height: 140px;\r
+  width: 140px;\r
+  content: " ";\r
+  display: block;\r
+}\r
+\r
+/* Google like */\r
+.image-wrapper {\r
+  background: #fff;\r
+  border: 2px #fff solid;\r
+/*  -webkit-border-radius: 200px;\r
+  -moz-border-radius: 200px;\r
+  border-radius: 200px;*/\r
+  display: block;\r
+  overflow: hidden;\r
+}\r
+.image-wrapper > a,\r
+.image-wrapper > span {\r
+  background-size: 100% !important;\r
+}\r
+/*.image-wrapper:hover {\r
+  box-shadow: 0 0 0.2em #7595b1;\r
+  cursor: pointer;\r
+}*/\r
+.image-wrapper.mini {\r
+  max-width: 40px;\r
+  max-height: 40px;\r
+}\r
+.image-wrapper.mini > a,\r
+.image-wrapper.mini > span {\r
+  height: 40px;\r
+  width: 40px;\r
+  content: " ";\r
+  display: block;\r
+}\r
+.image-wrapper.mini .image-l {\r
+  width: 30px;\r
+  display: block;\r
+  height: 40px;\r
+  overflow: hidden;\r
+  float: left;\r
+  text-align: center;\r
+  margin-left: -14px;\r
+}\r
+.image-wrapper.mini .image-l > span {\r
+  display: block;\r
+  width: 40px;\r
+  height: 40px;\r
+  background-size: 100% !important;\r
+}\r
+.image-wrapper.mini > .image-ur,\r
+.image-wrapper.mini > .image-lr {\r
+  width: 19px;\r
+  display: block;\r
+  height: 23px;\r
+  margin-top: -2px;\r
+  overflow: hidden;\r
+  float: right;\r
+  text-align: center;\r
+  z-index: -99;\r
+  margin-left: -1px;\r
+}\r
+.image-wrapper.mini > .image-ur > span,\r
+.image-wrapper.mini > .image-lr > span {\r
+  display: block;\r
+  width: 20px;\r
+  height: 20px;\r
+  background-size: 100% !important;\r
+}\r
+.image-wrapper.normal {\r
+  max-width: 60px;\r
+  max-height: 60px;\r
+}\r
+.image-wrapper.normal > a,\r
+.image-wrapper.normal > span {\r
+  height: 60px;\r
+  width: 60px;\r
+  content: " ";\r
+  display: block;\r
+}\r
+.image-wrapper.medium {\r
+/*  max-width: 80px;\r
+  max-height: 80px;*/\r
+}\r
+.image-wrapper.medium > a,\r
+.image-wrapper.medium > span {\r
+/*  height: 80px;\r
+  width: 80px;*/\r
+  content: " ";\r
+  display: block;\r
+}\r
+.image-wrapper.medium > a img {\r
+  height: 80px;\r
+  width: 80px;\r
+}\r
+.image-wrapper.large {\r
+  max-width: 140px;\r
+  max-height: 140px;\r
+}\r
+.image-wrapper.large > a,\r
+.image-wrapper.large > span {\r
+  height: 140px;\r
+  width: 140px;\r
+  content: " ";\r
+  display: block;\r
+}\r
+.main-body {\r
+  background: #fff;\r
+  padding: 1.25em 2em;\r
+  -webkit-border-radius: 8px;\r
+  -moz-border-radius: 8px;\r
+  border-radius: 8px;\r
+  line-height: 1.75em;\r
+}\r
+.hovercard {\r
+  -webkit-border-radius: 4px;\r
+  -moz-border-radius: 4px;\r
+  border-radius: 4px;\r
+  /*max-width: 250px;*/\r
+  max-width: 400px;\r
+  width: 400px;\r
+  -webkit-box-shadow: 0 10px 100px rgba(0, 0, 0, 0.25);\r
+  -moz-box-shadow: 0 10px 100px rgba(0, 0, 0, 0.25);\r
+  box-shadow: 0 10px 100px rgba(0, 0, 0, 0.25);\r
+  border: 1px solid rgba(0, 0, 0, 0);\r
+}\r
+.hovercard a:hover {\r
+  text-decoration: none;\r
+}\r
+.hovercard.right > .arrow {\r
+  border-right-color: rgba(0, 0, 0, 0.05);\r
+}\r
+.hovercard.left > .arrow {\r
+  border-left-color: rgba(0, 0, 0, 0.05);\r
+}\r
+.hovercard.bottom > .arrow {\r
+  border-bottom-color: rgba(0, 0, 0, 0.05);\r
+}\r
+.hovercard.top > .arrow {\r
+  border-top-color: rgba(0, 0, 0, 0.05);\r
+}\r
+.advance-hovercard + .hovercard {\r
+  max-width: 445px;\r
+}\r
+.advance-hovercard + .hovercard .hovercard-content {\r
+  padding: 5px;\r
+}\r
+\r
+.basic-hovercard + .hovercard {\r
+  max-width: 445px;\r
+}\r
+.basic-hovercard + .hovercard .hovercard-content {\r
+  padding: 5px;\r
+}\r
+\r
+.hover-card-header {\r
+  width: 100%;\r
+  /*height: 60px;*/\r
+}\r
+.hover-card-header h4 {\r
+  /*float: left;*/\r
+  display: block;\r
+  width: 310px;\r
+  /*margin-top: 25px;*/\r
+  /*clear: right;*/\r
+}\r
+.hover-card-header h4 a {\r
+  font-size: 18px;\r
+  font-weight: bold;\r
+  letter-spacing: 0.03rem;\r
+}\r
+.hover-card-header .member-title {\r
+  display: block;\r
+  color: #888;\r
+  line-height: 15px;\r
+  font-size: 13px;\r
+}\r
+.hover-card-details {\r
+  width: 100%;\r
+}\r
+.hover-card-pic {\r
+  margin-top: 0px;\r
+  /*width: 95px;*/\r
+  display: block;\r
+  /*height: 90px;*/\r
+}\r
+.hover-card-pic .image-wrapper {\r
+  /*margin: 0.5em 0.75em;*/\r
+  margin-right: 0.75em;\r
+  float: left;\r
+  position: relative;\r
+}\r
+.hover-card-content {\r
+  list-style-type: none;\r
+  width: 100%;\r
+  display: block;\r
+  background: #fff;\r
+  padding: 0.3em 0 1em;\r
+}\r
+.hover-card-content .profile-details {\r
+    font-size: 13px;\r
+}\r
+.hover-card-content li.right-aligned {\r
+  padding: .15em 1.25em;\r
+  border-left: 1px #F3F2F2 solid;\r
+}\r
+.hover-card-content li.right-aligned .content {\r
+  font-size: 14px;\r
+}\r
+.hover-card-content li.right-aligned:last-child {\r
+  border-left: none;\r
+}\r
+.hover-card-content .reputation-bar {\r
+  position: absolute;\r
+}\r
+.hover-card-content .reputation-bar span {\r
+  width: 65px;\r
+  position: absolute;\r
+  margin: 1em auto;\r
+  margin-left: 15px;\r
+  text-align: center;\r
+  border-radius: 2em;\r
+  padding: .15em 0;\r
+  background-color: #ccc;\r
+  color: #fff;\r
+}\r
+.hover-card-content .desc,\r
+.profile-label {\r
+  text-transform: uppercase;\r
+  font-size: 11px;\r
+  letter-spacing: 0.05rem;\r
+  padding-bottom: 0.5em;\r
+  padding-top: .15em;\r
+  opacity: 0.8;\r
+  display: block;\r
+}\r
+.hover-card-actions {\r
+  display: flex;\r
+}\r
+.hover-card-actions-connection {\r
+  margin-left: 30px;\r
+}\r
+.hover-card-options-wrapper {\r
+  position: relative;\r
+  display: block;\r
+  width: 430px;\r
+  float: left;\r
+  background: #F5F5F5;\r
+  padding: 0 .5em;\r
+  margin-bottom: 0.5em;\r
+  clear: both;\r
+  height: 40px;\r
+}\r
+.hover-card-options-wrapper ul {\r
+  padding: .65em 0;\r
+}\r
+.hover-card-options-wrapper li {\r
+  list-style-type: none;\r
+  line-height: 0;\r
+  display: inline-block;\r
+  padding: 0 .75em;\r
+}\r
+.hover-card-options-wrapper li i {\r
+  padding: 5px 3px;\r
+  -webkit-border-radius: 100%;\r
+  -moz-border-radius: 100%;\r
+  border-radius: 100%;\r
+  font-size: 12px;\r
+}\r
+.hover-card-options-wrapper li a {\r
+  color: #444;\r
+  padding: 0;\r
+  font-size: 13px;\r
+  font-weight: normal;\r
+  opacity: 0.8;\r
+}\r
+.hover-card-options {\r
+  color: #eee;\r
+}\r
+.hover-card-options .dropdown-menu a {\r
+  text-shadow: none;\r
+}\r
+.hover-card-footer {\r
+  background-color: #f7f7f7;\r
+  border-top: 1px solid #ebebeb;\r
+  padding: 0 10px;\r
+}\r
+.col-sm-10 label {\r
+  font-weight: normal;\r
+}\r
+.demo-content {\r
+       width: 100%;\r
+       background: #dadada;\r
+       border: solid 3px #ccc;\r
+       font-size: 12px;\r
+       width: 38%;\r
+       float: left;\r
+       margin-right: 2%;\r
+       margin: 20px 0 30px;\r
+}\r
+.demo-live {\r
+       padding: 20px;\r
+       background: #fff;\r
+       line-height: 1.4em;\r
+       min-height: 218px;\r
+}\r
+p {\r
+       display: block;\r
+       -webkit-margin-before: 1em;\r
+       -webkit-margin-after: 1em;\r
+       -webkit-margin-start: 0px;\r
+       -webkit-margin-end: 0px;\r
+}
\ No newline at end of file
index 5c55d432179875c96339a2413a842dc08df57c68..f06481112af691480872354e4a6436d6f814d713 100644 (file)
@@ -19,6 +19,7 @@ and open the template in the editor.
 @import url("frameworks/justifiedGallery/justifiedGallery.min.css");
 @import url("frameworks/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css");
 @import url("font/open_sans/open-sans.css");
+@import url("css/hovercard.css");
 
 
 body {
diff --git a/js/hovercard.js b/js/hovercard.js
new file mode 100644 (file)
index 0000000..1ca07ff
--- /dev/null
@@ -0,0 +1,282 @@
+/* 
+ * The javascript for friendicas hovercard. Bootstraps popover is needed.
+ * 
+ * Much parts of the code are from Hannes Mannerheims <h@nnesmannerhe.im> 
+ * qvitter code (https://github.com/hannesmannerheim/qvitter)
+ * 
+ * It is licensed under the GNU Affero General Public License <http://www.gnu.org/licenses/>
+ * 
+ */
+
+
+$(document).ready(function(){
+
+       // Elements with the class "userinfo" will get a hover-card.
+       // Note that this elements does need a href attribute which links to
+       // a valid profile url
+       $('.userinfo').on("mouseover", function(e) {
+                       var timeNow = new Date().getTime();
+                       removeAllhoverCards(e,timeNow);
+                       var hoverCardData = false;
+                       var hrefAttr = false;
+                       var targetElement = $(this);
+
+                       // get href-attribute
+                       if(targetElement.is('[href]')) {
+                               hrefAttr = targetElement.attr('href');
+                       } else {
+                               return true;
+                       }
+
+                       // no hover card if the element has the no-hover-card class
+                       if(targetElement.hasClass('no-hover-card')) {
+                               return true;
+                       }
+
+                       // no hovercard for anchor links
+                       if(hrefAttr.substring(0,1) == '#') {
+                               return true;
+                       }
+
+                       targetElement.attr('data-awaiting-hover-card',timeNow);
+
+                       // The serach term is the url 
+                       var term = hrefAttr;
+                       // the url to get the contact and template data
+                       var url = baseurl + "/frio_hovercard";
+
+                       // store the title in an other data attribute beause bootstrap
+                       // popover destroys the title.attribute. We can restore it later
+                       var title = targetElement.attr("title");
+                       targetElement.attr({"data-orig-title": title, title: ""});
+
+                       // Timeoute until the hover-card does appear
+                       setTimeout(function(){
+                               if(targetElement.is(":hover") && parseInt(targetElement.attr('data-awaiting-hover-card'),10) == timeNow) {
+                                       if($('.hovercard').length == 0) {       // no card if there already is one open
+                                               // get an additional data atribute if the card is active
+                                               targetElement.attr('data-hover-card-active',timeNow);
+                                               // get the whole html content of the hover card and
+                                               // push it to the bootstrap popover
+                                               getHoverCardContent(term, url, function(data){
+                                                       if(data) {
+                                                               targetElement.popover({
+                                                                       html: true,
+                                                                       placement: 'auto',
+                                                                       trigger: 'manual',
+                                                                       template: '<div class="popover hovercard" data-card-created="' + timeNow + '"><div class="arrow"></div><div class="popover-content hovercard-content"></div></div>',
+                                                                       content: data
+                                                               }).popover('show');
+                                                       }
+                                               });
+                                       }
+                               }
+                       }, 500);
+       }).on("mouseleave", function(e) { // action when mouse leaves the hover-card
+               var timeNow = new Date().getTime();
+               // copy the original title to the title atribute
+               var title = $(this).attr("data-orig-title");
+               $(this).attr({"data-orig-title": "", title: title});
+               removeAllhoverCards(e,timeNow);
+       });
+
+
+
+});
+
+
+
+// hover cards should be removed very easily, e.g. when any of these events happen
+$('body').on("mouseleave touchstart scroll click dblclick mousedown mouseup submit keydown keypress keyup", function(e){
+       var timeNow = new Date().getTime();
+       removeAllhoverCards(e,timeNow);
+});
+
+// removes all hover cards
+function removeAllhoverCards(event,priorTo) {
+       // don't remove hovercards until after 100ms, so user have time to move the cursor to it (which gives it the dont-remove-card class)
+       setTimeout(function(){
+               $.each($('.hovercard'),function(){
+                       var title = $(this).attr("data-orig-title");
+                       // don't remove card if it was created after removeAllhoverCards() was called
+                       if($(this).data('card-created') < priorTo) {
+                               // don't remove it if we're hovering it right now!
+                               if(!$(this).hasClass('dont-remove-card')) {
+                                       $('[data-hover-card-active="' + $(this).data('card-created') + '"]').removeAttr('data-hover-card-active');
+                                       $(this).popover("hide");
+                               }
+                       }
+               });
+       },100);
+}
+
+// if we're hovering a hover card, give it a class, so we don't remove it
+$('body').on('mouseover','.hovercard', function(e) {
+       $(this).addClass('dont-remove-card');
+});
+$('body').on('mouseleave','.hovercard', function(e) {
+       $(this).removeClass('dont-remove-card');
+       $(this).popover("hide");
+});
+
+// Ajax request to get json contact data
+function getHoverCardData(term, url, actionOnSuccess) {
+       var postdata = {
+               mode            : 'modal',
+               profileurl      : term,
+               datatype        : 'json',
+       };
+
+       $.ajax({
+               url: url,
+               data: postdata,
+               dataType: "json",
+               success: function(data, textStatus, request){
+                       actionOnSuccess(data, url, request);
+               },
+               error: function(data) {
+                       actionOnSuccess(false, data, url);
+               }
+       });
+}
+// current time in milliseconds, to send each request to make sure
+// we 're not getting 304 response
+function timeNow() {
+       return new Date().getTime();
+}
+// Get hover-card template data and the contact-data and transform it with
+// the help of jSmart. At the end we have full html content of the hovercard
+function getHoverCardContent(term, url, callback) {
+       // fetch the raw content of the template
+       getHoverCardTemplate(url, function(stpl) {
+               var template = unescape(stpl);
+
+               // get the contact data
+               getHoverCardData (term, url, function(data) {
+                       if(typeof template != 'undefined') {
+                               // get the hover-card variables
+                               var variables = getHoverCardVariables(data);
+                               var tpl;
+
+                               // use friendicas template delimiters instead of
+                               // the original one
+                               jSmart.prototype.left_delimiter = '{{';
+                               jSmart.prototype.right_delimiter = '}}';
+
+                               // create a new jSmart instant with the raw content
+                               // of the template
+                               var tpl = new jSmart (template);
+                               // insert the variables content into the template content
+                               var HoverCardContent = tpl.fetch(variables);
+
+                               callback(HoverCardContent);
+                       }
+               });
+       });
+
+// This is interisting. this pice of code ajax request are done asynchron.
+// To make it work getHOverCardTemplate() and getHOverCardData have to return it's 
+// data (no succes handler for each of this). I leave it here, because it could be useful.
+// https://lostechies.com/joshuaflanagan/2011/10/20/coordinating-multiple-ajax-requests-with-jquery-when/
+//     $.when(
+//             getHoverCardTemplate(url),
+//             getHoverCardData (term, url )
+//
+//     ).done(function(template, profile){
+//             if(typeof template != 'undefined') {
+//                     var variables = getHoverCardVariables(profile);
+//
+//                     jSmart.prototype.left_delimiter = '{{';
+//                     jSmart.prototype.right_delimiter = '}}';
+//                     var tpl = new jSmart (template);
+//                     var html = tpl.fetch(variables);
+//
+//                     return html;
+//             }
+//     });
+}
+
+// Ajax request to get the raw template content
+function getHoverCardTemplate (url, callback) {
+       var postdata = {
+               mode: 'modal',
+               datatype: 'tpl'
+       };
+
+       $.ajax({
+               url: url,
+               data: postdata,
+               success: function(data, textStatus) {
+                       callback(data);
+               }
+       });
+}
+
+// The Variables used for the template
+function getHoverCardVariables(object) {
+       var profile = {
+                       name:           object.name,
+                       nick:           object.nick,
+                       addr:           object.addr,
+                       thumb:          object.thumb,
+                       url:            object.url,
+                       location:       object.location,
+                       gender:         object.gender,
+                       about:          object.about,
+                       network:        object.network,
+                       tags:           object.tags,
+                       bd:             object.bd,
+                       account_type:   object.account_type,
+                       actions:        object.actions
+       };
+
+       var variables = { profile:  profile};
+
+       return variables;
+}
+
+// This is the html template for the hover-card
+// Since we grab the original hovercard.tpl we don't
+// need it anymore
+function hovercard_template() {
+       var tempate = '\
+       <div class="basic-content" >\
+               <div class="hover-card-details">\
+                       <div class="hover-card-header left-align">\
+                               <div class="hover-card-pic left-align">\
+                                       <span class="image-wrapper medium">\
+                                               <a href="{{$profile.url}}" title="{{$profile.name}}"><img href="" class="left-align thumbnail" src="{{$profile.thumb}}"></a>\
+                                       </span>\
+                               </div>\
+                               <div class="hover-card-content">\
+                                       <div class="profile-entry-name">\
+                                               <h4 class="left-align1"><a href="{{$profile.url}}">{{$profile.name}}</a></h4>{{if $profile.account_type}}<span>{{$profile.account_type}}</span>{{/if}}\
+                                       </div>\
+                                       <div class="profile-details">\
+                                               <span class="profile-addr">{{$profile.addr}}</span>\
+                                               {{if $profile.network}}<span class="profile-network"> ({{$profile.network}})</span>{{/if}}\
+                                       </div>\
+                                       {{*{{if $profile.about}}<div class="profile-details profile-about">{{$profile.about}}</div>{{/if}}*}}\
+\
+                               </div>\
+                               <div class="hover-card-actions  right-aligned">\
+                                       {{* here are the differnt actions like privat message, poke, delete and so on *}}\
+                                       {{* @todo we have two different photo menus one for contacts and one for items at the network stream. We currently use the contact photo menu, so the items options are missing We need to move them *}}\
+                                       <div class="hover-card-actions-social">\
+                                               {{if $profile.actions.pm}}<a class="btn btn-labeled btn-primary btn-sm" onclick="addToModal("{{$profile.actions.pm.1}}")" title="{{$profile.actions.pm.0}}"><i class="fa fa-envelope" aria-hidden="true"></i></a>{{/if}}\
+                                               {{if $profile.actions.poke}}<a class="btn btn-labeled btn-primary btn-sm" onclick="addToModal("{{$profile.actions.poke.1}}")" title="{{$profile.actions.poke.0}}"><i class="fa fa-heartbeat" aria-hidden="true"></i></a>{{/if}}\
+                                       </div>\
+                                       <div class="hover-card-actions-connection">\
+                                               {{if $profile.actions.edit}}<a class="btn btn-labeled btn-primary btn-sm" href="{{$profile.actions.edit.1}}" title="{{$profile.actions.edit.0}}"><i class="fa fa-pencil" aria-hidden="true"></i></a>{{/if}}\
+                                               {{if $profile.actions.drop}}<a class="btn btn-labeled btn-primary btn-sm" href="{{$profile.actions.drop.1}}" title="{{$profile.actions.drop.0}}"><i class="fa fa-user-times" aria-hidden="true"></i></a>{{/if}}\
+                                               {{if $profile.actions.follow}}<a class="btn btn-labeled btn-primary btn-sm" href="{{$profile.actions.follow.1}}" title="{{$profile.actions.follow.0}}"><i class="fa fa-user-plus" aria-hidden="true"></i></a>{{/if}}\
+                                       </div>\
+                               </div>\
+                       </div>\
+\
+                       <div class="clearfix"></div>\
+\
+               </div>\
+       </div>\
+       {{if $profile.tags}}<div class="hover-card-footer">{{$profile.tags}}</div>{{/if}}';
+}
index 23862a33584bb999f3e1c67a6eb2c18ac8a4e8f6..12172291efba13af5177939924809a52fa70bcd5 100644 (file)
@@ -96,27 +96,6 @@ $(document).ready(function(){
                }
        });
 
-       // Loading remote bootstrap remote modals
-       // This is uses to load tradional friendica pages into bootstrap modals
-       // 
-       // commentent out because we actually don't use it anymore
-//     $('a[rel=modal]').on('click', function(evt) {
-//             evt.preventDefault();
-//             var modal = $('#modal').modal();
-//             modal
-//                     .find('#modal-body')
-//                     .load($(this).attr("href"), function (responseText, textStatus) {
-//                             if ( textStatus === 'success' || 
-//                                     textStatus === 'notmodified') 
-//                             {
-//                                     modal.show();
-//
-//                                     //Get first h3 element and use it as title
-//                                     loadModalTitle();
-//                             }
-//                     });
-//     });
-
        // Add Colorbox for viewing Network page images
        //var cBoxClasses = new Array();
        $(".wall-item-body a img").each(function(){
index 81add8b078357ccc6f069a837fe8750e3216579f..5bceaee9c111a7362257314da729a7617fd552c9 100644 (file)
@@ -158,9 +158,9 @@ $("nav").bind('nav-update', function(e,data)
 <script src="<?=$frio?>/frameworks/justifiedGallery/jquery.justifiedGallery.min.js"></script>
 <script src="<?=$frio?>/frameworks/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js"></script>
 <script src="<?=$frio?>/frameworks/flexMenu/flexmenu.custom.js"></script>
-<script src="<?=$frio?>/frameworks/jsmart/jsmart.js"></script>
+<script src="<?=$frio?>/frameworks/jsmart/jsmart.custom.js"></script>
 <script src="<?=$frio?>/js/theme.js"></script>
-<script src="<?=$frio?>/js/acl.js"></script>
+<script src="<?=$frio?>/js/hovercard.js"></script>
 
 
 <!-- Modal  -->
index 3a06ae3e6a4a39c88d7fc6c2946b5051fda2235f..cffcf3fb1581afc6d3931f4913537a115eeaf8db 100644 (file)
                        {{* The avatar picture and the photo-menu *}}
                        <div class="dropdown pull-left"><!-- Dropdown -->
                                <div class="hidden-sm hidden-xs contact-photo-wrapper mframe{{if $item.owner_url}} wwfrom{{/if}}">
-                                       <a class="dropdown-toggle" type="button" id="wall-item-photo-menu-{{$item.id}}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                       <a href="{{$item.profile_url}}" class="userinfo" id="wall-item-photo-menu-{{$item.id}}">
                                                <div class="contact-photo-image-wrapper">
                                                        <img src="{{$item.thumb}}" class="contact-photo media-object {{$item.sparkle}}" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" />
-
-                                                       {{* Overlay background on hover the avatar picture *}}
-                                                       <div class="contact-photo-overlay">
-                                                               <span class="contact-photo-overlay-content"><i class="fa fa-angle-down"></i></span>
-                                                       </div>
                                                </div>
                                        </a>
-                                       <ul class="dropdown-menu contact-menu-lg contact-menu menu-popup" role="menu" aria-labelledby="wall-item-photo-menu-{{$item.id}}">
-                                               {{$item.item_photo_menu}}
-                                       </ul>
                                </div>
                                <div class="hidden-lg hidden-md contact-photo-wrapper mframe{{if $item.owner_url}} wwfrom{{/if}}">
-                                       <a class="dropdown-toggle" type="button" id="wall-item-photo-menu-{{$item.id}}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                       <a href="{{$item.profile_url}}" class="userinfo" id="wall-item-photo-menu-{{$item.id}}">
                                                <div class="contact-photo-image-wrapper">
                                                        <img src="{{$item.thumb}}" class="contact-photo-xs media-object {{$item.sparkle}}" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" />
-
-                                                       {{* Overlay background on hover the avatar picture *}}
-                                                       <div class="contact-photo-overlay">
-                                                               <span class="contact-photo-overlay-content"><i class="fa fa-angle-down"></i></span>
-                                                       </div>
                                                </div>
                                        </a>
-                                       <ul class="dropdown-menu contact-menu-xs contact-menu menu-popup" role="menu" aria-labelledby="wall-item-photo-menu-{{$item.id}}">
-                                               {{$item.item_photo_menu}}
-                                       </ul>
                                </div>
                        </div><!-- ./Dropdown -->
 
 
                        {{* contact info header*}}
                        <div role="heading " class="contact-info hidden-sm hidden-xs media-body"><!-- <= For computer -->
-                               <h4 class="media-heading"><a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-name-link"><span class="wall-item-name btn-link {{$item.sparkle}}">{{$item.name}}</span></a>
-                                       {{if $item.owner_url}}{{$item.via}} <a href="{{$item.owner_url}}" target="redir" title="{{$item.olinktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$item.osparkle}} btn-link" id="wall-item-ownername-{{$item.id}}">{{$item.owner_name}}</span></a>{{/if}}
+                               <h4 class="media-heading"><a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-name-link userinfo"><span class="wall-item-name btn-link {{$item.sparkle}}">{{$item.name}}</span></a>
+                                       {{if $item.owner_url}}{{$item.via}} <a href="{{$item.owner_url}}" target="redir" title="{{$item.olinktitle}}" class="wall-item-name-link userinfo"><span class="wall-item-name{{$item.osparkle}} btn-link" id="wall-item-ownername-{{$item.id}}">{{$item.owner_name}}</span></a>{{/if}}
                                        {{if $item.lock}}<span class="navicon lock fakelink" onClick="lockview(event,{{$item.id}});" title="{{$item.lock}}">&nbsp<small><i class="fa fa-lock"></i></small></span>{{/if}}
 
                                        <div class="additional-info text-muted">
                        {{* contact info header for smartphones *}}
                        <div role="heading " class="contact-info-xs hidden-lg hidden-md">
                                <h5 class="media-heading">
-                                       <a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-name-link"><strong>{{$item.name}}</strong></a>
+                                       <a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-name-link userinfo"><strong>{{$item.name}}</strong></a>
                                        <p class="text-muted"><small>
                                                <span class="wall-item-ago">{{$item.ago}}</span> {{if $item.location}}&nbsp;&mdash;&nbsp;({{$item.location}}){{/if}}</small>
                                        </p>
index f927846ea5e56126b1e5525c895fe2996f0ff035..37971b3bc2fe8f9709df2b3d3d1f366bb249fb58 100644 (file)
@@ -141,34 +141,18 @@ as the value of $top_child_total (this is done at the end of this file)
                <div class="dropdown pull-left"><!-- Dropdown -->
                        {{if $item.thread_level==1}}
                        <div class="hidden-sm hidden-xs contact-photo-wrapper mframe{{if $item.owner_url}} wwfrom{{/if}}">
-                               <a class="dropdown-toggle" type="button" id="wall-item-photo-menu-{{$item.id}}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                               <a class="userinfo" id="wall-item-photo-menu-{{$item.id}}" href="{{$item.profile_url}}">
                                        <div class="contact-photo-image-wrapper">
                                                <img src="{{$item.thumb}}" class="contact-photo media-object {{$item.sparkle}}" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" />
-
-                                               {{* Overlay background on hover the avatar picture *}}
-                                               <div class="contact-photo-overlay">
-                                                       <span class="contact-photo-overlay-content"><i class="fa fa-angle-down"></i></span>
-                                               </div>
                                        </div>
                                </a>
-                               <ul class="dropdown-menu contact-menu-lg contact-menu menu-popup" role="menu" aria-labelledby="wall-item-photo-menu-{{$item.id}}">
-                                       {{$item.item_photo_menu}}
-                               </ul>
                        </div>
                        <div class="hidden-lg hidden-md contact-photo-wrapper mframe{{if $item.owner_url}} wwfrom{{/if}}">
-                               <a class="dropdown-toggle" type="button" id="wall-item-photo-menu-{{$item.id}}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                               <a class="userinfo" id="wall-item-photo-menu-{{$item.id}}" href="{{$item.profile_url}}">
                                        <div class="contact-photo-image-wrapper">
                                                <img src="{{$item.thumb}}" class="contact-photo-xs media-object {{$item.sparkle}}" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" />
-
-                                               {{* Overlay background on hover the avatar picture *}}
-                                               <div class="contact-photo-overlay">
-                                                       <span class="contact-photo-overlay-content"><i class="fa fa-angle-down"></i></span>
-                                               </div>
                                        </div>
                                </a>
-                               <ul class="dropdown-menu contact-menu-xs contact-menu menu-popup" role="menu" aria-labelledby="wall-item-photo-menu-{{$item.id}}">
-                                       {{$item.item_photo_menu}}
-                               </ul>
                        </div>
 
                        {{* The litle overlay avatar picture if someone is posting directly to a wall or a forum *}}
@@ -185,19 +169,11 @@ as the value of $top_child_total (this is done at the end of this file)
                        {{* The avatar picture for comments *}}
                        {{if $item.thread_level!=1}}
                        <div class="contact-photo-wrapper mframe{{if $item.owner_url}} wwfrom{{/if}}">
-                               <a class="dropdown-toggle" type="button" id="wall-item-photo-menu-{{$item.id}}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                               <a class="userinfo" id="wall-item-photo-menu-{{$item.id}}" href="{{$item.profile_url}}">
                                        <div class="contact-photo-image-wrapper">
                                                <img src="{{$item.thumb}}" class="contact-photo-xs media-object {{$item.sparkle}}" id="wall-item-photo-{{$item.id}}" alt="{{$item.name}}" />
-
-                                               {{* Overlay background on hover the avatar picture *}}
-                                               <div class="contact-photo-overlay">
-                                                       <span class="contact-photo-overlay-content"><i class="fa fa-angle-down"></i></span>
-                                               </div>
                                        </div>
                                </a>
-                               <ul class="dropdown-menu contact-menu-xs contact-menu menu-popup" role="menu" aria-labelledby="wall-item-photo-menu-{{$item.id}}">
-                                       {{$item.item_photo_menu}}
-                               </ul>
                        </div>
                        {{/if}}
                </div><!-- ./Dropdown -->
@@ -207,8 +183,8 @@ as the value of $top_child_total (this is done at the end of this file)
                {{* contact info header*}}
                {{if $item.thread_level==1}}
                <div role="heading " aria-level="{{$item.thread_level}}" class="contact-info hidden-sm hidden-xs media-body"><!-- <= For computer -->
-                       <h4 class="media-heading"><a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-name-link"><span class="wall-item-name btn-link {{$item.sparkle}}">{{$item.name}}</span></a>
-                       {{if $item.owner_url}}{{$item.via}} <a href="{{$item.owner_url}}" target="redir" title="{{$item.olinktitle}}" class="wall-item-name-link"><span class="wall-item-name{{$item.osparkle}} btn-link" id="wall-item-ownername-{{$item.id}}">{{$item.owner_name}}</span></a>{{/if}}
+                       <h4 class="media-heading"><a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-name-link userinfo"><span class="wall-item-name btn-link {{$item.sparkle}}">{{$item.name}}</span></a>
+                       {{if $item.owner_url}}{{$item.via}} <a href="{{$item.owner_url}}" target="redir" title="{{$item.olinktitle}}" class="wall-item-name-link userinfo"><span class="wall-item-name{{$item.osparkle}} btn-link" id="wall-item-ownername-{{$item.id}}">{{$item.owner_name}}</span></a>{{/if}}
                        {{if $item.lock}}<span class="navicon lock fakelink" onClick="lockview(event,{{$item.id}});" title="{{$item.lock}}" data-toggle="tooltip">&nbsp<small><i class="fa fa-lock"></i></small></span>{{/if}}
                        </4>
 
@@ -229,7 +205,7 @@ as the value of $top_child_total (this is done at the end of this file)
                {{* contact info header for smartphones *}}
                <div role="heading " aria-level="{{$item.thread_level}}" class="contact-info-xs hidden-lg hidden-md"><!-- <= For smartphone (responsive) -->
                        <h5 class="media-heading">
-                               <a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-name-link"><strong>{{$item.name}}</strong></a>
+                               <a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-name-link userinfo"><strong>{{$item.name}}</strong></a>
                                <p class="text-muted">
                                        <small><span class="wall-item-ago">{{$item.ago}}</span> {{if $item.location}}&nbsp;&mdash;&nbsp;({{$item.location}}){{/if}}</small>
                                </p>
@@ -242,7 +218,7 @@ as the value of $top_child_total (this is done at the end of this file)
                <div class="media-body">{{*this is the media body for comments - this div must be closed at the end of the file *}}
                <div role="heading " aria-level="{{$item.thread_level}}" class="contact-info-xs">
                        <h5 class="media-heading">
-                               <a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-name-link"><strong class="btn-link">{{$item.name}}</strong></a>
+                               <a href="{{$item.profile_url}}" title="{{$item.linktitle}}" class="wall-item-name-link userinfo"><strong class="btn-link">{{$item.name}}</strong></a>
                                <span class="text-muted">
                                        <small><span title="{{$item.localtime}}" data-toggle="tooltip">{{$item.ago}}</span> {{if $item.location}}&nbsp;&mdash;&nbsp;({{$item.location}}){{/if}}</small>
                                </span>