Happy Addons for Elementor (Mega Menu, Post Grid, Woocommerce Product Grid, Table, Event Calendar, Slider Elementor Widget) - Version 1.5.0

Version Description

  • 27 August 2019 =

  • New: Image Grid Widget

  • New: Scheme data for Review Widget

  • New: Background Overlay - global extension for any widget

  • New: Step Flow Widget - direction arrow offset control

  • New: Happy Icons - Custom icon font library

  • Update: Dynamic Tags support

  • Update: New icon manager support with backward compatibility

  • Update: Step Flow Widget default view

  • Update: On demand caching manager

  • Fix: Review ratting icon missing issue

  • Fix: Justified Grid Widget filter menu style issue

  • Fix: Icon Box Widget badge style missing issue

  • Fix: Global widget CSS class missing issue

  • Fix: Section and global widget cache missing issue

  • Fix: Step Flow arrow alignment issue

  • Fix: Skill Bars Widget animation issue

Download this release

Release Info

Developer thehappymonster
Plugin Icon 128x128 Happy Addons for Elementor (Mega Menu, Post Grid, Woocommerce Product Grid, Table, Event Calendar, Slider Elementor Widget)
Version 1.5.0
Comparing to
See all releases

Code changes from version 1.4.1 to 1.5.0

Files changed (52) hide show
  1. assets/admin/js/happy-addons.js +53 -0
  2. assets/admin/js/happy-addons.min.js +1 -1
  3. assets/css/main.css +157 -249
  4. assets/css/main.min.css +1 -1
  5. assets/css/widgets/badge.min.css +1 -0
  6. assets/css/widgets/card.min.css +1 -1
  7. assets/css/widgets/common.min.css +1 -1
  8. assets/css/widgets/hover-box.min.css +0 -1
  9. assets/css/widgets/image-grid.min.css +1 -0
  10. assets/css/widgets/pricing-table.min.css +1 -1
  11. assets/css/widgets/review.min.css +1 -1
  12. assets/css/widgets/steps-flow.min.css +1 -1
  13. assets/fonts/happy-icons.js +403 -0
  14. assets/fonts/style.css +2 -1
  15. assets/fonts/style.min.css +1 -1
  16. assets/js/happy-addons.js +98 -52
  17. assets/js/happy-addons.min.js +1 -1
  18. assets/vendor/jquery-numerator/jquery-numerator.js +137 -0
  19. assets/vendor/jquery-numerator/jquery-numerator.min.js +1 -0
  20. assets/vendor/jquery.isotope.js +4016 -0
  21. base.php +27 -22
  22. base/widget-base.php +1 -1
  23. classes/admin-bar.php +16 -17
  24. classes/asset-manager.php +0 -237
  25. classes/assets-cache.php +189 -0
  26. classes/assets-manager.php +258 -0
  27. classes/cache-manager.php +82 -0
  28. classes/class.ondemand-loader.php +0 -246
  29. classes/extensions-manager.php +21 -0
  30. classes/icons-manager.php +438 -0
  31. classes/updater.php +53 -0
  32. classes/widgets-cache.php +166 -0
  33. classes/{widget-manager.php → widgets-manager.php} +52 -34
  34. extensions/background-overlay.php +198 -0
  35. {classes → extensions}/happy-effects.php +0 -1
  36. inc/functions.php +59 -13
  37. inc/happy-icons.php +0 -409
  38. plugin.php +7 -6
  39. readme.txt +28 -3
  40. widgets/card/widget.php +83 -41
  41. widgets/dual-button/widget.php +124 -112
  42. widgets/flip-box/widget.php +93 -37
  43. widgets/gradient-heading/widget.php +8 -2
  44. widgets/icon-box/widget.php +54 -18
  45. widgets/image-compare/widget.php +12 -0
  46. widgets/image-grid/widget.php +721 -0
  47. widgets/infobox/widget.php +116 -54
  48. widgets/member/widget.php +20 -2
  49. widgets/number/widget.php +4 -1
  50. widgets/pricing-table/widget.php +65 -19
  51. widgets/review/widget.php +297 -246
  52. widgets/step-flow/widget.php +96 -17
assets/admin/js/happy-addons.js CHANGED
@@ -59,4 +59,57 @@
59
  initCssTransformEffects(model);
60
  });
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  }(elementor, jQuery, window));
59
  initCssTransformEffects(model);
60
  });
61
 
62
+ if ( elementor.modules.controls.Icons ) {
63
+ var WithHappyIcons = elementor.modules.controls.Icons.extend({
64
+ getControlValue: function() {
65
+ var value = this.constructor.__super__.getControlValue.call(this),
66
+ model = this.model,
67
+ valueToMigrate = this.getValueToMigrate(),
68
+ newValue = { value: '', library: 'happy-icons' };
69
+
70
+ if ( _.isObject( value ) && value.library !== 'svg' && value.value.indexOf( 'fashm' ) === 0 ) {
71
+ newValue.value = value.value.substr( value.value.indexOf( 'hm hm-' ) );
72
+ this.elementSettingsModel.set( model.get( 'name' ), newValue );
73
+ return newValue;
74
+ }
75
+
76
+ if ( ! _.isObject( value ) && valueToMigrate && valueToMigrate.indexOf('hm hm-') === 0 ) {
77
+ newValue.value = valueToMigrate;
78
+ this.elementSettingsModel.set( model.get( 'name' ), newValue );
79
+ return newValue;
80
+ }
81
+
82
+ if ( ! this.isMigrationAllowed() ) {
83
+ return valueToMigrate;
84
+ }
85
+
86
+ // Bail if no migration flag or no value to migrate
87
+ if ( ! valueToMigrate ) {
88
+ return value;
89
+ }
90
+
91
+ var didMigration = this.elementSettingsModel.get( this.dataKeys.migratedKey ),
92
+ controlName = model.get( 'name' );
93
+
94
+ // Check if migration had been done and is stored locally
95
+ if ( this.cache.migratedFlag[ controlName ] ) {
96
+ return this.cache.migratedFlag[ controlName ];
97
+ }
98
+ // Check if already migrated
99
+ if ( didMigration && didMigration[ controlName ] ) {
100
+ return value;
101
+ }
102
+
103
+ // Do migration
104
+ return this.migrateFa4toFa5( valueToMigrate );
105
+ }
106
+ });
107
+
108
+ elementor.addControlView( 'icons', WithHappyIcons );
109
+ }
110
+
111
+ window.ha_has_icon_library = function() {
112
+ return ( elementor.helpers && elementor.helpers.renderIcon );
113
+ };
114
+
115
  }(elementor, jQuery, window));
assets/admin/js/happy-addons.min.js CHANGED
@@ -1 +1 @@
1
- !function(e,n,t){"use strict";function o(){return{translate:["x","y","x_tablet","y_tablet","x_mobile","y_mobile"],skew:["x","y","x_tablet","y_tablet","x_mobile","y_mobile"],scale:["x","y","x_tablet","y_tablet","x_mobile","y_mobile"],rotate:["x","y","z","x_tablet","y_tablet","z_tablet","x_mobile","y_mobile","z_mobile"]}}function a(n,t,o){n="ha_transform_fx_"+n,t="ha_transform_fx_"+t,o.on("change:"+n,function(n,a){if(!a){var l=e.getPanelView().getCurrentPageView().children.find(function(e){return e.model.get("name")===t});o.set(t,_.extend({},o.defaults[t])),l&&l.render()}})}function l(n){var t=elementorFrontend.config.elements.data[n.cid];_.each(o(),function(e,n){_.each(e,function(e){a(n+"_toggle",n+"_"+e,t)})}),e.getPanelView().getCurrentPageView().model.on("editor:close",function(){_.each(o(),function(e,n){t.off("change:ha_transform_fx_"+n+"_toggle")})})}e.on("panel:init",function(){n("#elementor-panel-elements-search-input").on("keyup",_.debounce(function(){n("#elementor-panel-elements").find(".hm").parents(".elementor-element").addClass("happy-addons-addon")},100))}),e.hooks.addAction("panel/open_editor/widget",function(e,n){l(n)})}(elementor,jQuery,window);
1
+ !function(e,t,n){"use strict";function a(){return{translate:["x","y","x_tablet","y_tablet","x_mobile","y_mobile"],skew:["x","y","x_tablet","y_tablet","x_mobile","y_mobile"],scale:["x","y","x_tablet","y_tablet","x_mobile","y_mobile"],rotate:["x","y","z","x_tablet","y_tablet","z_tablet","x_mobile","y_mobile","z_mobile"]}}function i(t,n,a){t="ha_transform_fx_"+t,n="ha_transform_fx_"+n,a.on("change:"+t,function(t,i){if(!i){var o=e.getPanelView().getCurrentPageView().children.find(function(e){return e.model.get("name")===n});a.set(n,_.extend({},a.defaults[n])),o&&o.render()}})}function o(t){var n=elementorFrontend.config.elements.data[t.cid];_.each(a(),function(e,t){_.each(e,function(e){i(t+"_toggle",t+"_"+e,n)})}),e.getPanelView().getCurrentPageView().model.on("editor:close",function(){_.each(a(),function(e,t){n.off("change:ha_transform_fx_"+t+"_toggle")})})}if(e.on("panel:init",function(){t("#elementor-panel-elements-search-input").on("keyup",_.debounce(function(){t("#elementor-panel-elements").find(".hm").parents(".elementor-element").addClass("happy-addons-addon")},100))}),e.hooks.addAction("panel/open_editor/widget",function(e,t){o(t)}),e.modules.controls.Icons){var l=e.modules.controls.Icons.extend({getControlValue:function(){var e=this.constructor.__super__.getControlValue.call(this),t=this.model,n=this.getValueToMigrate(),a={value:"",library:"happy-icons"};if(_.isObject(e)&&"svg"!==e.library&&0===e.value.indexOf("fashm"))return a.value=e.value.substr(e.value.indexOf("hm hm-")),this.elementSettingsModel.set(t.get("name"),a),a;if(!_.isObject(e)&&n&&0===n.indexOf("hm hm-"))return a.value=n,this.elementSettingsModel.set(t.get("name"),a),a;if(!this.isMigrationAllowed())return n;if(!n)return e;var i=this.elementSettingsModel.get(this.dataKeys.migratedKey),o=t.get("name");return this.cache.migratedFlag[o]?this.cache.migratedFlag[o]:i&&i[o]?e:this.migrateFa4toFa5(n)}});e.addControlView("icons",l)}n.ha_has_icon_library=function(){return e.helpers&&e.helpers.renderIcon}}(elementor,jQuery,window);
assets/css/main.css CHANGED
@@ -65,6 +65,35 @@
65
  display: none;
66
  }
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  .ha-card > .elementor-widget-container,
69
  .ha-infobox > .elementor-widget-container,
70
  .ha-icon-box > .elementor-widget-container,
@@ -126,6 +155,64 @@
126
  margin-left: 5px;
127
  }
128
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  .ha-card > .elementor-widget-container,
130
  .ha-infobox > .elementor-widget-container,
131
  .ha-icon-box > .elementor-widget-container,
@@ -248,64 +335,6 @@
248
  position: absolute;
249
  }
250
 
251
- .ha-badge {
252
- padding: .475rem 1.1rem;
253
- border-radius: 50px;
254
- background-color: #fff;
255
- font-size: 12px;
256
- }
257
- .ha-badge--top-left {
258
- top: 1rem;
259
- left: 1rem;
260
- }
261
- .ha-badge--top-center {
262
- top: 1rem;
263
- left: 50%;
264
- -webkit-transform: translateX(-50%);
265
- -ms-transform: translateX(-50%);
266
- transform: translateX(-50%);
267
- }
268
- .ha-badge--top-right {
269
- top: 1rem;
270
- right: 1rem;
271
- }
272
- .ha-badge--middle-left {
273
- top: 50%;
274
- left: 1rem;
275
- -webkit-transform: translateY(-50%);
276
- -ms-transform: translateY(-50%);
277
- transform: translateY(-50%);
278
- }
279
- .ha-badge--middle-center {
280
- top: 50%;
281
- left: 50%;
282
- -webkit-transform: translate(-50%, -50%);
283
- -ms-transform: translate(-50%, -50%);
284
- transform: translate(-50%, -50%);
285
- }
286
- .ha-badge--middle-right {
287
- top: 50%;
288
- right: 1rem;
289
- -webkit-transform: translateY(-50%);
290
- -ms-transform: translateY(-50%);
291
- transform: translateY(-50%);
292
- }
293
- .ha-badge--bottom-left {
294
- bottom: 1rem;
295
- left: 1rem;
296
- }
297
- .ha-badge--bottom-center {
298
- bottom: 1rem;
299
- left: 50%;
300
- -webkit-transform: translateX(-50%);
301
- -ms-transform: translateX(-50%);
302
- transform: translateX(-50%);
303
- }
304
- .ha-badge--bottom-right {
305
- right: 1rem;
306
- bottom: 1rem;
307
- }
308
-
309
  .ha-card > .elementor-widget-container,
310
  .ha-infobox > .elementor-widget-container,
311
  .ha-icon-box > .elementor-widget-container,
@@ -598,38 +627,12 @@
598
  .ha-review-ratting--num {
599
  padding: .25em .66em;
600
  border-radius: 2.5em;
601
- background-color: #287dfe;
602
  color: #fff;
603
  }
604
 
605
  .ha-review-ratting--star {
606
- display: inline-block;
607
  color: #ffbf36;
608
- font-family: "Fontawesome";
609
- }
610
- .ha-review-ratting--star > span {
611
- position: relative;
612
- overflow: hidden;
613
- height: 1em;
614
- }
615
- .ha-review-ratting--star span > span {
616
- position: absolute;
617
- top: 0;
618
- left: 0;
619
- overflow: hidden;
620
- padding-top: 1.5em;
621
- }
622
- span .ha-review-ratting--star:before,
623
- .ha-review-ratting--star span > span:before {
624
- position: absolute;
625
- top: 0;
626
- left: 0;
627
- }
628
- .ha-review-ratting--star span:before {
629
- content: "\f006\f006\f006\f006\f006";
630
- }
631
- .ha-review-ratting--star span > span:before {
632
- content: "\f005\f005\f005\f005\f005";
633
  }
634
 
635
  .ha-review-desc {
@@ -820,6 +823,56 @@ span .ha-review-ratting--star:before,
820
  clear: both;
821
  }
822
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
823
  .ha-justified-gallery-item,
824
  .ha-justified-gallery-item > img {
825
  border-radius: 6px;
@@ -1963,155 +2016,6 @@ span .ha-review-ratting--star:before,
1963
  clear: both;
1964
  }
1965
 
1966
- .ha-hover-box {
1967
- overflow: hidden;
1968
- }
1969
- .ha-hover-box .ha-hover-box-main {
1970
- position: relative;
1971
- overflow: hidden;
1972
- }
1973
-
1974
- .ha-hover-box-wrapper {
1975
- position: relative;
1976
- display: -webkit-box;
1977
- display: -webkit-flex;
1978
- display: -ms-flexbox;
1979
- display: flex;
1980
- overflow: hidden;
1981
- -webkit-box-align: center;
1982
- -webkit-align-items: center;
1983
- align-items: center;
1984
- -ms-flex-align: center;
1985
- padding: 50px;
1986
- max-height: 100%;
1987
- width: 100%;
1988
- height: 400px;
1989
- -webkit-transition-duration: .4s;
1990
- transition-duration: .4s;
1991
- }
1992
- .ha-hover-box-wrapper:before {
1993
- position: absolute;
1994
- top: 0;
1995
- left: 0;
1996
- z-index: 1;
1997
- width: 100%;
1998
- height: 100%;
1999
- content: "";
2000
- }
2001
- .ha-hover-box-wrapper:hover {
2002
- -webkit-transition-duration: .3s;
2003
- transition-duration: .3s;
2004
- -webkit-transform: scale(1.06);
2005
- -ms-transform: scale(1.06);
2006
- transform: scale(1.06);
2007
- }
2008
- .ha-hover-box-wrapper:hover .ha-hover-box-content {
2009
- opacity: 0;
2010
- -webkit-transition-delay: 0ms;
2011
- transition-delay: 0ms;
2012
- -webkit-transition-timing-function: cubic-bezier(.57, .21, .69, 1);
2013
- transition-timing-function: cubic-bezier(.57, .21, .69, 1);
2014
- -webkit-transition-duration: .1s;
2015
- transition-duration: .1s;
2016
- -webkit-transition-property: opacity,-webkit-transform;
2017
- transition-property: opacity,-webkit-transform;
2018
- transition-property: transform,opacity;
2019
- transition-property: transform,opacity,-webkit-transform;
2020
- -webkit-transform: translate(0, 36px);
2021
- -ms-transform: translate(0, 36px);
2022
- transform: translate(0, 36px);
2023
- }
2024
- .ha-hover-box-wrapper .ha-hover-box-content {
2025
- position: relative;
2026
- z-index: 99;
2027
- display: -webkit-box;
2028
- display: -webkit-flex;
2029
- display: -ms-flexbox;
2030
- display: flex;
2031
- -webkit-box-orient: vertical;
2032
- -webkit-box-direction: normal;
2033
- -webkit-flex-direction: column;
2034
- -ms-flex-direction: column;
2035
- flex-direction: column;
2036
- width: 100%;
2037
- text-align: left;
2038
- opacity: 1;
2039
- -webkit-transition: opacity .2s ease-in-out,-webkit-transform .2s ease-in-out;
2040
- transition: opacity .2s ease-in-out,-webkit-transform .2s ease-in-out;
2041
- transition: opacity .2s ease-in-out,transform .2s ease-in-out;
2042
- transition: opacity .2s ease-in-out,transform .2s ease-in-out,-webkit-transform .2s ease-in-out;
2043
- -webkit-transition-delay: .1s;
2044
- transition-delay: .1s;
2045
- -webkit-transition-duration: .1s;
2046
- transition-duration: .1s;
2047
- -webkit-transform: translate(0, 0);
2048
- -ms-transform: translate(0, 0);
2049
- transform: translate(0, 0);
2050
- }
2051
- .ha-hover-box-wrapper .ha-hover-sub-title {
2052
- display: inline-block;
2053
- margin-bottom: 20px;
2054
- color: #222;
2055
- }
2056
- .ha-hover-box-wrapper .ha-hover-title {
2057
- margin-top: 0;
2058
- margin-bottom: 10px;
2059
- color: #222;
2060
- }
2061
- .ha-hover-box-wrapper .ha-hover-description {
2062
- margin: 0;
2063
- color: #222;
2064
- }
2065
-
2066
- .ha-hover-box-wrapper.reverse:hover .ha-hover-box-content {
2067
- opacity: 1;
2068
- -webkit-transition-delay: .1s;
2069
- transition-delay: .1s;
2070
- -webkit-transform: translate(0, -16px);
2071
- -ms-transform: translate(0, -16px);
2072
- transform: translate(0, -16px);
2073
- }
2074
-
2075
- .ha-hover-box-wrapper.reverse .ha-hover-box-content {
2076
- opacity: 0;
2077
- -webkit-transition-delay: 0s;
2078
- transition-delay: 0s;
2079
- }
2080
-
2081
- .ha-pre--column .ha-hover-sub-title {
2082
- margin-bottom: 20px;
2083
- }
2084
-
2085
- .ha-pre--column-reverse p.ha-hover-sub-title {
2086
- margin-top: 20px;
2087
- margin-bottom: 0;
2088
- }
2089
-
2090
- .ha-card > .elementor-widget-container,
2091
- .ha-infobox > .elementor-widget-container,
2092
- .ha-icon-box > .elementor-widget-container,
2093
- .ha-member > .elementor-widget-container,
2094
- .ha-review > .elementor-widget-container,
2095
- .ha-image-compare > .elementor-widget-container,
2096
- .ha-pricing-table > .elementor-widget-container {
2097
- border-radius: .5rem;
2098
- background-color: #fff;
2099
- box-shadow: 0 .2rem 2.8rem rgba(36, 36, 36, .1);
2100
- word-wrap: break-word;
2101
-
2102
- overflow-wrap: break-word;
2103
- }
2104
-
2105
- .ha-logo-grid-wrapper:before,
2106
- .ha-logo-grid-wrapper:after {
2107
- display: table;
2108
- content: " ";
2109
- }
2110
-
2111
- .ha-logo-grid-wrapper:after {
2112
- clear: both;
2113
- }
2114
-
2115
  .ha-flip-box-container:after {
2116
  display: block;
2117
  visibility: hidden;
@@ -2431,7 +2335,7 @@ span .ha-review-ratting--star:before,
2431
 
2432
  .ha-pricing-table-badge {
2433
  position: absolute;
2434
- top: 0;
2435
  padding: .8rem 1rem;
2436
  background-color: #e2498a;
2437
  color: #fff;
@@ -2561,22 +2465,25 @@ span .ha-review-ratting--star:before,
2561
  .ha-step-arrow {
2562
  position: absolute;
2563
  top: 49%;
2564
- left: calc(100% + 50px);
2565
  display: inline-block;
2566
  width: 100px;
2567
- border-top: 1px dashed #ddd;
2568
  }
2569
  .ha-step-arrow:after {
2570
  position: absolute;
2571
- right: -6px;
2572
- height: 1.5em;
 
 
 
 
 
2573
  color: #ddd;
2574
- content: "\e90b";
2575
- font-size: 18px;
2576
- font-family: "Happy Icons" !important;
2577
- -webkit-transform: translateY(-50%);
2578
- -ms-transform: translateY(-50%);
2579
- transform: translateY(-50%);
2580
  }
2581
 
2582
  .ha-steps-icon {
@@ -2585,8 +2492,9 @@ span .ha-review-ratting--star:before,
2585
  margin-bottom: 2rem;
2586
  padding: 40px;
2587
  border-radius: 50%;
2588
- background-color: #f1f4f8;
2589
- color: #242424;
 
2590
  text-align: center;
2591
  font-size: 46px;
2592
  }
@@ -2607,10 +2515,10 @@ span .ha-review-ratting--star:before,
2607
  position: absolute;
2608
  top: 5px;
2609
  right: 0;
2610
- padding: 10px 12px;
2611
  border: 3px solid #fff;
2612
  border-radius: 20px;
2613
- background-color: #e2498a;
2614
  color: #fff;
2615
  font-size: 12px;
2616
  line-height: 0;
65
  display: none;
66
  }
67
 
68
+ .ha-screen-reader-text {
69
+ position: absolute;
70
+ overflow: hidden;
71
+ clip: rect(1px, 1px, 1px, 1px);
72
+ margin: -1px;
73
+ padding: 0;
74
+ width: 1px;
75
+ height: 1px;
76
+ border: 0;
77
+ word-wrap: normal !important;
78
+
79
+ -webkit-clip-path: inset(50%);
80
+ clip-path: inset(50%);
81
+ }
82
+
83
+ .ha-has-background-overlay > .elementor-widget-container {
84
+ position: relative;
85
+ z-index: 1;
86
+ }
87
+ .ha-has-background-overlay > .elementor-widget-container:before {
88
+ position: absolute;
89
+ top: 0;
90
+ left: 0;
91
+ z-index: -1;
92
+ width: 100%;
93
+ height: 100%;
94
+ content: "";
95
+ }
96
+
97
  .ha-card > .elementor-widget-container,
98
  .ha-infobox > .elementor-widget-container,
99
  .ha-icon-box > .elementor-widget-container,
155
  margin-left: 5px;
156
  }
157
 
158
+ .ha-badge {
159
+ padding: .475rem 1.1rem;
160
+ border-radius: 50px;
161
+ background-color: #fff;
162
+ font-size: 12px;
163
+ }
164
+ .ha-badge--top-left {
165
+ top: 1rem;
166
+ left: 1rem;
167
+ }
168
+ .ha-badge--top-center {
169
+ top: 1rem;
170
+ left: 50%;
171
+ -webkit-transform: translateX(-50%);
172
+ -ms-transform: translateX(-50%);
173
+ transform: translateX(-50%);
174
+ }
175
+ .ha-badge--top-right {
176
+ top: 1rem;
177
+ right: 1rem;
178
+ }
179
+ .ha-badge--middle-left {
180
+ top: 50%;
181
+ left: 1rem;
182
+ -webkit-transform: translateY(-50%);
183
+ -ms-transform: translateY(-50%);
184
+ transform: translateY(-50%);
185
+ }
186
+ .ha-badge--middle-center {
187
+ top: 50%;
188
+ left: 50%;
189
+ -webkit-transform: translate(-50%, -50%);
190
+ -ms-transform: translate(-50%, -50%);
191
+ transform: translate(-50%, -50%);
192
+ }
193
+ .ha-badge--middle-right {
194
+ top: 50%;
195
+ right: 1rem;
196
+ -webkit-transform: translateY(-50%);
197
+ -ms-transform: translateY(-50%);
198
+ transform: translateY(-50%);
199
+ }
200
+ .ha-badge--bottom-left {
201
+ bottom: 1rem;
202
+ left: 1rem;
203
+ }
204
+ .ha-badge--bottom-center {
205
+ bottom: 1rem;
206
+ left: 50%;
207
+ -webkit-transform: translateX(-50%);
208
+ -ms-transform: translateX(-50%);
209
+ transform: translateX(-50%);
210
+ }
211
+ .ha-badge--bottom-right {
212
+ right: 1rem;
213
+ bottom: 1rem;
214
+ }
215
+
216
  .ha-card > .elementor-widget-container,
217
  .ha-infobox > .elementor-widget-container,
218
  .ha-icon-box > .elementor-widget-container,
335
  position: absolute;
336
  }
337
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  .ha-card > .elementor-widget-container,
339
  .ha-infobox > .elementor-widget-container,
340
  .ha-icon-box > .elementor-widget-container,
627
  .ha-review-ratting--num {
628
  padding: .25em .66em;
629
  border-radius: 2.5em;
630
+ background-color: #562dd4;
631
  color: #fff;
632
  }
633
 
634
  .ha-review-ratting--star {
 
635
  color: #ffbf36;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
636
  }
637
 
638
  .ha-review-desc {
823
  clear: both;
824
  }
825
 
826
+ .ha-image-grid-item {
827
+ float: left;
828
+ }
829
+
830
+ .ha-image-grid-inner {
831
+ position: relative;
832
+ display: block;
833
+ overflow: hidden;
834
+ margin: 10px;
835
+ text-decoration: none;
836
+ }
837
+ .ha-image-grid-inner img {
838
+ display: block;
839
+ width: 100%;
840
+ -webkit-transition: all .25s;
841
+ transition: all .25s;
842
+ }
843
+
844
+ .ha-image-grid--layout-even .ha-image-grid-inner {
845
+ height: 250px;
846
+ }
847
+ .ha-image-grid--layout-even .ha-image-grid-inner > img {
848
+ height: 100%;
849
+ }
850
+
851
+ .ha-card > .elementor-widget-container,
852
+ .ha-infobox > .elementor-widget-container,
853
+ .ha-icon-box > .elementor-widget-container,
854
+ .ha-member > .elementor-widget-container,
855
+ .ha-review > .elementor-widget-container,
856
+ .ha-image-compare > .elementor-widget-container,
857
+ .ha-pricing-table > .elementor-widget-container {
858
+ border-radius: .5rem;
859
+ background-color: #fff;
860
+ box-shadow: 0 .2rem 2.8rem rgba(36, 36, 36, .1);
861
+ word-wrap: break-word;
862
+
863
+ overflow-wrap: break-word;
864
+ }
865
+
866
+ .ha-logo-grid-wrapper:before,
867
+ .ha-logo-grid-wrapper:after {
868
+ display: table;
869
+ content: " ";
870
+ }
871
+
872
+ .ha-logo-grid-wrapper:after {
873
+ clear: both;
874
+ }
875
+
876
  .ha-justified-gallery-item,
877
  .ha-justified-gallery-item > img {
878
  border-radius: 6px;
2016
  clear: both;
2017
  }
2018
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2019
  .ha-flip-box-container:after {
2020
  display: block;
2021
  visibility: hidden;
2335
 
2336
  .ha-pricing-table-badge {
2337
  position: absolute;
2338
+ top: -1px;
2339
  padding: .8rem 1rem;
2340
  background-color: #e2498a;
2341
  color: #fff;
2465
  .ha-step-arrow {
2466
  position: absolute;
2467
  top: 49%;
2468
+ left: calc( 100% + 20px);
2469
  display: inline-block;
2470
  width: 100px;
2471
+ border-top: 1px solid #ddd;
2472
  }
2473
  .ha-step-arrow:after {
2474
  position: absolute;
2475
+ top: -2px;
2476
+ right: 5px;
2477
+ display: inline-block;
2478
+ width: 12px;
2479
+ height: 12px;
2480
+ border-top: 1px solid #ddd;
2481
+ border-right: 1px solid #ddd;
2482
  color: #ddd;
2483
+ content: "";
2484
+ -webkit-transform: rotate(45deg) translateY(-50%);
2485
+ -ms-transform: rotate(45deg) translateY(-50%);
2486
+ transform: rotate(45deg) translateY(-50%);
 
 
2487
  }
2488
 
2489
  .ha-steps-icon {
2492
  margin-bottom: 2rem;
2493
  padding: 40px;
2494
  border-radius: 50%;
2495
+ background-color: #e9ecf0;
2496
+ box-shadow: 0 2px 6px -2px #989898;
2497
+ color: #8056ee;
2498
  text-align: center;
2499
  font-size: 46px;
2500
  }
2515
  position: absolute;
2516
  top: 5px;
2517
  right: 0;
2518
+ padding: 12px 8px;
2519
  border: 3px solid #fff;
2520
  border-radius: 20px;
2521
+ background-color: #8056ee;
2522
  color: #fff;
2523
  font-size: 12px;
2524
  line-height: 0;
assets/css/main.min.css CHANGED
@@ -1 +1 @@
1
- .happy-addon,.happy-addon *{box-sizing:border-box}.happy-addon img{max-width:100%;height:auto;-o-object-fit:cover;object-fit:cover}.happy-addon p:empty{display:none}.ha-btn{display:inline-block;vertical-align:middle;text-align:center;text-decoration:none;font-size:14px;line-height:1;-webkit-transition:all .3s;transition:all .3s}.ha-btn:not(.ha-btn--link){padding:15px 25px;border-radius:.25rem;background-color:#562dd4;color:#fff}.ha-btn:not(.ha-btn--link):focus,.ha-btn:not(.ha-btn--link):hover{background-color:#e2498a}.ha-btn.ha-btn--link{color:#562dd4}.ha-btn.ha-btn--link:focus,.ha-btn.ha-btn--link:hover{color:#e2498a}.ha-btn-icon{-webkit-transition:all .3s;transition:all .3s}.ha-btn-icon+.ha-btn-text,.ha-btn-text+.ha-btn-icon{margin-left:5px}.ha-card-figure{position:relative;height:250px}.ha-card-figure>img{border-top-left-radius:calc(.5rem - 1px);border-top-right-radius:calc(.5rem - 1px)}.ha-card-body{padding:1.5rem}.ha-card-title{margin-top:0;margin-bottom:.75rem;color:#151515;font-weight:700;font-size:22px}.ha-card-text{margin-bottom:2rem;color:#616161;font-size:16px;line-height:1.7}.ha-card-text>p,.ha-infobox-text>p{margin-top:0;margin-bottom:0}.ha-card--top .ha-card-figure{display:inline-block;width:100%}.ha-card--left>.elementor-widget-container,.ha-card--right>.elementor-widget-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center}.ha-card--left>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.ha-card--left .ha-card-body,.ha-card--left .ha-card-figure,.ha-card--right .ha-card-body,.ha-card--right .ha-card-figure{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.ha-card--left .ha-card-body,.ha-card--right .ha-card-body{padding:2.5rem}.ha-card--left .ha-card-figure>img{border-radius:calc(.5rem - 1px) 0 0 calc(.5rem - 1px)}.ha-card--right>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;text-align:right}.ha-card--right .ha-card-figure>img{border-radius:0 calc(.5rem - 1px) calc(.5rem - 1px) 0}.ha-card .ha-badge{position:absolute}.ha-badge{padding:.475rem 1.1rem;border-radius:50px;background-color:#fff;font-size:12px}.ha-badge--top-left{top:1rem;left:1rem}.ha-badge--top-center{top:1rem;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-badge--top-right{top:1rem;right:1rem}.ha-badge--middle-left{top:50%;left:1rem;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.ha-badge--middle-center{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.ha-badge--middle-right{top:50%;right:1rem;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.ha-badge--bottom-left{bottom:1rem;left:1rem}.ha-badge--bottom-center{bottom:1rem;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-badge--bottom-right{right:1rem;bottom:1rem}.ha-infobox>.elementor-widget-container{padding:1.5rem}.ha-infobox-title{margin-top:0;margin-bottom:1rem;color:#151515;font-size:24px}.ha-infobox-figure{display:inline-block;margin:0 0 1.5rem!important}.ha-infobox-figure--icon{text-align:center;font-size:3rem}.ha-icon-box-icon>i,.ha-infobox-figure>i{position:relative;display:block;width:1em;height:1em}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-flip-icon i:before,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-icon i:before,.ha-icon-box-icon>i:before,.ha-infobox-figure>i:before{position:absolute;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-card-figure>img,.ha-infobox-figure>img,.ha-member-figure img{width:100%;height:100%;vertical-align:bottom}.ha-infobox-text+.ha-btn--link{margin-top:1rem}.ha-icon-box>.elementor-widget-container{position:relative;padding:1.25rem}.ha-icon-box-title{margin-top:0;margin-bottom:0;color:#151515;font-size:24px;-webkit-transition:color .3s;transition:color .3s}.ha-icon-box-icon{display:inline-block;margin-bottom:1rem;color:#151515;text-align:center;font-size:3rem;-webkit-transition:border .3s,background .3s,color .3s,-webkit-transform .3s;transition:transform .3s,border .3s,background .3s,color .3s;transition:transform .3s,border .3s,background .3s,color .3s,-webkit-transform .3s}.ha-icon-box-icon>i{-webkit-transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.ha-icon-box-link{display:block;color:transparent;text-decoration:none}.ha-icon-box .ha-badge{position:absolute;z-index:9999;background-color:#e2498a;color:#fff}.ha-member>.elementor-widget-container{padding:1.25rem}.ha-member-figure{display:inline-block;margin:0 0 1.5rem!important}.ha-member-name{margin-top:0;margin-bottom:.5rem;color:#151515;font-size:18px}.ha-member-position{margin-bottom:1.5rem;color:#7f7f7f;font-size:14px}.ha-member-bio{margin-bottom:1.5rem;font-size:14px;line-height:1.6}.ha-member-links>a{display:inline-block;color:#9895ad;text-align:center;line-height:1;-webkit-transition:all .2s;transition:all .2s}.ha-member-links>a:focus,.ha-member-links>a:hover{color:#222}.ha-member-links>a>i{width:1em;height:1em}.ha-member-links>a:not(:last-child){margin-right:.3rem}.ha-review-header{margin-top:1.5rem}.ha-review-desc p,.ha-review-figure{margin:0}.ha-review-figure>img{width:100%;height:100%;border-radius:50%;vertical-align:bottom}.ha-review-reviewer{margin-top:0;margin-bottom:.3rem;color:#151515;font-size:18px}.ha-review-position{margin-bottom:.5rem;color:#7f7f7f;font-size:15px}.ha-review-ratting{display:inline-block;font-size:12px;line-height:1}.ha-review-ratting--num{padding:.25em .66em;border-radius:2.5em;background-color:#287dfe;color:#fff}.ha-review-ratting--star{display:inline-block;color:#ffbf36;font-family:"Fontawesome"}.ha-review-ratting--star>span{position:relative;overflow:hidden;height:1em}.ha-review-ratting--star span>span{position:absolute;top:0;left:0;overflow:hidden;padding-top:1.5em}.ha-review-ratting--star span>span:before,span .ha-review-ratting--star:before{position:absolute;top:0;left:0}.ha-review-ratting--star span:before{content:"\f006\f006\f006\f006\f006"}.ha-review-ratting--star span>span:before{content:"\f005\f005\f005\f005\f005"}.ha-review-desc{margin-top:1.5rem;font-size:16px;line-height:1.6}.ha-review--top>.elementor-widget-container{padding:2rem}.ha-review--top .ha-review-figure{display:inline-block;max-width:70px;height:70px}.ha-review--left>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.ha-review--left>.elementor-widget-container,.ha-review--right>.elementor-widget-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;padding-left:2rem}.ha-review--left .ha-review-figure,.ha-review--right .ha-review-figure{-webkit-box-flex:0;-webkit-flex:0 0 150px;-ms-flex:0 0 150px;flex:0 0 150px;max-width:150px;height:150px}.ha-review--left .ha-review-body,.ha-review--right .ha-review-body{-webkit-box-flex:0;-webkit-flex:0 0 calc(100% - 150px);-ms-flex:0 0 calc(100% - 150px);flex:0 0 calc(100% - 150px);padding:2rem;max-width:calc(100% - 150px)}.ha-review--left .ha-review-body>:first-child,.ha-review--right .ha-review-body>:first-child{margin-top:0}.ha-review--right>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;padding-right:2rem;padding-left:0;text-align:right}.ha-image-compare .twentytwenty-container,.ha-image-compare .twentytwenty-wrapper{border-radius:inherit}.ha-gallery-filter{margin:0 10px 2rem;padding:0;list-style:none}.ha-gallery-filter>li{display:inline-block;margin-bottom:10px}.ha-gallery-filter>li:not(:last-child){margin-right:10px}.ha-gallery-filter>li>button{display:block;padding:10px 25px;border:2px solid #562dd4;border-radius:.25rem;background-color:transparent;color:#562dd4;text-transform:uppercase;font-size:14px;cursor:pointer;-webkit-transition:all .3s;transition:all .3s}.ha-gallery-filter>li>button:focus,.ha-gallery-filter>li>button:hover{outline:0;background-color:#562dd4;color:#fff}.ha-gallery-filter>.ha-filter-active>button{background-color:#562dd4;color:#fff}.ha-justified-gallery-item,.ha-justified-gallery-item>img{border-radius:6px}.ha-justified-gallery .justified-gallery>.ha-justified-gallery-item>.caption{bottom:-100px!important;padding:10px;-webkit-transition:all .25s!important;transition:all .25s!important;-webkit-animation:haSmoothReveal .3s forwards;animation:haSmoothReveal .3s forwards}.ha-justified-gallery .justified-gallery>.ha-justified-gallery-item>.caption.caption-visible{bottom:0!important}.ha-justified-gallery .justified-gallery>.entry-visible>a>img,.ha-justified-gallery .justified-gallery>.entry-visible>img{-webkit-transition:all 300ms,opacity 500ms ease-in;transition:all 300ms,opacity 500ms ease-in}@-webkit-keyframes haSmoothReveal{0%{-webkit-transform:translateY(100px);transform:translateY(100px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes haSmoothReveal{0%{-webkit-transform:translateY(100px);transform:translateY(100px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}.ha-carousel .slick-vertical .slick-slide,.ha-slider .slick-vertical .slick-slide{border:0}.ha-carousel .slick-next,.ha-carousel .slick-prev,.ha-slider .slick-next,.ha-slider .slick-prev{z-index:999;padding:0;border:1px solid rgba(255,255,255,.8);border-radius:50%;background-color:rgba(255,255,255,.8);color:#8c8c8c;text-align:center;font-size:12px;opacity:1}.ha-carousel .slick-next:focus,.ha-carousel .slick-next:hover,.ha-carousel .slick-prev:focus,.ha-carousel .slick-prev:hover,.ha-slider .slick-next:focus,.ha-slider .slick-next:hover,.ha-slider .slick-prev:focus,.ha-slider .slick-prev:hover{background-color:#fff}.ha-carousel .slick-next:before,.ha-carousel .slick-prev:before,.ha-slider .slick-next:before,.ha-slider .slick-prev:before{content:""}.ha-carousel .slick-disabled,.ha-slider .slick-disabled{opacity:.7}.ha-carousel .slick-prev,.ha-slider .slick-prev{left:25px}.ha-carousel .slick-next,.ha-slider .slick-next{right:25px}.ha-carousel .slick-dots,.ha-slider .slick-dots{bottom:-40px}.ha-carousel .slick-dots li,.ha-slider .slick-dots li{margin-right:2px;margin-left:2px}.ha-carousel .slick-dots li button:focus,.ha-carousel .slick-dots li button:hover,.ha-slider .slick-dots li button:focus,.ha-slider .slick-dots li button:hover{background-color:transparent}.ha-carousel .slick-dots li button:before,.ha-slider .slick-dots li button:before{color:#1b1b1b;opacity:1}.ha-carousel .slick-dots .slick-active button:before,.ha-carousel .slick-dots li button:hover:before,.ha-slider .slick-dots .slick-active button:before,.ha-slider .slick-dots li button:hover:before{-webkit-transform:scale(1.5);-ms-transform:scale(1.5);transform:scale(1.5)}.ha-carousel .slick-next,.ha-carousel .slick-prev{width:40px;height:40px;line-height:40px}.ha-slider .slick-next,.ha-slider .slick-prev{width:50px;height:50px;line-height:50px}.ha-carousel .slick-slider:not(.slick-vertical) .slick-slide{padding-right:5px;padding-left:5px}.ha-carousel .slick-slider.slick-vertical .slick-slide{padding-top:5px;padding-bottom:5px}.ha-slick-item{position:relative;overflow:hidden;vertical-align:bottom}.ha-slick-content{position:absolute;bottom:0;padding:1.5rem;width:100%;background:-webkit-linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.3));background:linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.3))}.ha-slick-title{margin-top:0;margin-bottom:.2rem;color:#fff;font-size:20px}.ha-slick-subtitle{margin:0;color:#fff}.ha-skills>.elementor-widget-container{padding-top:1px}.ha-skill{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;border-radius:15px;background-color:#e9ecef;font-size:.75rem}.ha-skill--inside .ha-skill-info,.ha-skill--outside .ha-skill-info{text-align:left;font-size:14px}.ha-skill--inside .ha-skill-level-text,.ha-skill--outside .ha-skill-level-text{float:right}.ha-skill--outside{height:2px}.ha-skill--outside .ha-skill-level{position:relative}.ha-skill--outside .ha-skill-info{position:absolute;top:-25px;width:100%;color:#242424}.ha-skill--inside{height:30px}.ha-skill--inside .ha-skill-info{padding-right:1rem;padding-left:1rem;color:#fff}.ha-skill-level{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;width:10%;border-radius:inherit;background-color:#562dd4;color:#fff;text-align:center;white-space:nowrap;-webkit-transition:width .6s ease;transition:width .6s ease}.ha-skill--outside{margin-top:40px}.ha-skill--inside:not(:first-child){margin-top:20px}.ha-gradient-heading{margin-top:0;margin-bottom:0}.ha-gradient-heading>a{color:inherit;text-decoration:none}.ha-logo-grid-item{float:left;overflow:hidden;height:180px;border-color:#e7e7e7}.ha-logo-grid-figure{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;margin:0;padding:30px;width:100%;height:100%}.ha-logo-grid-img{max-height:100%}@media (min-width:1025px){.ha-logo-grid--col-2 .ha-logo-grid-item{width:calc(100%/2)}.ha-logo-grid--col-3 .ha-logo-grid-item{width:calc(100%/3)}.ha-logo-grid--col-4 .ha-logo-grid-item{width:calc(100%/4)}.ha-logo-grid--col-5 .ha-logo-grid-item{width:calc(100%/5)}.ha-logo-grid--col-6 .ha-logo-grid-item{width:calc(100%/6)}}@media (max-width:1024px) and (min-width:768px){.ha-logo-grid--col--tablet2 .ha-logo-grid-item{width:calc(100%/2)}.ha-logo-grid--col--tablet3 .ha-logo-grid-item{width:calc(100%/3)}.ha-logo-grid--col--tablet4 .ha-logo-grid-item{width:calc(100%/4)}.ha-logo-grid--col--tablet5 .ha-logo-grid-item{width:calc(100%/5)}.ha-logo-grid--col--tablet6 .ha-logo-grid-item{width:calc(100%/6)}}@media (max-width:767px){.ha-logo-grid--col--mobile2 .ha-logo-grid-item{width:calc(100%/2)}.ha-logo-grid--col--mobile3 .ha-logo-grid-item{width:calc(100%/3)}.ha-logo-grid--col--mobile4 .ha-logo-grid-item{width:calc(100%/4)}.ha-logo-grid--col--mobile5 .ha-logo-grid-item{width:calc(100%/5)}.ha-logo-grid--col--mobile6 .ha-logo-grid-item{width:calc(100%/6)}}.ha-logo-grid--tictactoe .ha-logo-grid-item{border-width:2px 2px 0 0;border-style:solid}@media (min-width:1025px){.ha-logo-grid--tictactoe.ha-logo-grid--col-2 .ha-logo-grid-item:nth-child(2n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-3 .ha-logo-grid-item:nth-child(3n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-4 .ha-logo-grid-item:nth-child(4n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-5 .ha-logo-grid-item:nth-child(5n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-6 .ha-logo-grid-item:nth-child(6n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:0!important}}@media (max-width:1024px) and (min-width:768px){.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-child(2n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-child(3n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-child(4n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-child(5n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-child(6n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:0!important}}@media (max-width:767px){.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-child(2n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-child(3n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-child(4n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-child(5n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-child(6n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:0!important}}.ha-logo-grid--border .ha-logo-grid-item{border-width:0 2px 2px 0;border-style:solid}.ha-logo-grid--border .ha-logo-grid-item:first-child{border-top-left-radius:10px}.ha-logo-grid--border .ha-logo-grid-item:last-child{border-bottom-right-radius:10px}@media (min-width:1025px){.ha-logo-grid--border.ha-logo-grid--col-2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col-2 .ha-logo-grid-item:nth-child(2n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col-2 .ha-logo-grid-item:nth-child(2){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-2 .ha-logo-grid-item:nth-last-child(2){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col-3 .ha-logo-grid-item:nth-child(3n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col-3 .ha-logo-grid-item:nth-child(3){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-3 .ha-logo-grid-item:nth-last-child(3){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col-4 .ha-logo-grid-item:nth-child(4n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col-4 .ha-logo-grid-item:nth-child(4){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-4 .ha-logo-grid-item:nth-last-child(4){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col-5 .ha-logo-grid-item:nth-child(5n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col-5 .ha-logo-grid-item:nth-child(5){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-5 .ha-logo-grid-item:nth-last-child(5){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col-6 .ha-logo-grid-item:nth-child(6n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col-6 .ha-logo-grid-item:nth-child(6){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-6 .ha-logo-grid-item:nth-last-child(6){border-bottom-left-radius:10px}}@media (max-width:1024px) and (min-width:768px){.ha-logo-grid--border.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-child(2n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-child(2){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-last-child(2){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-child(3n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-child(3){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-last-child(3){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-child(4n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-child(4){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-last-child(4){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-child(5n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-child(5){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-last-child(5){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-child(6n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-child(6){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-last-child(6){border-bottom-left-radius:10px}}@media (max-width:767px){.ha-logo-grid--border.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-child(2n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-child(2){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-last-child(2){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-child(3n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-child(3){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-last-child(3){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-child(4n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-child(4){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-last-child(4){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-child(5n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-child(5){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-last-child(5){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-child(6n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-child(6){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-last-child(6){border-bottom-left-radius:10px}}.ha-logo-grid--box .ha-logo-grid-wrapper{margin:-.5rem}.ha-logo-grid--box .ha-logo-grid-item{margin:.5rem;border-width:2px;border-style:solid;border-radius:.5rem}@media (min-width:1025px){.ha-logo-grid--box.ha-logo-grid--col-2 .ha-logo-grid-item{width:calc((100%/2) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col-3 .ha-logo-grid-item{width:calc((100%/3) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col-4 .ha-logo-grid-item{width:calc((100%/4) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col-5 .ha-logo-grid-item{width:calc((100%/5) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col-6 .ha-logo-grid-item{width:calc((100%/6) - 1rem)}}@media (max-width:1024px) and (min-width:768px){.ha-logo-grid--box.ha-logo-grid--col--tablet2 .ha-logo-grid-item{width:calc((100%/2) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--tablet3 .ha-logo-grid-item{width:calc((100%/3) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--tablet4 .ha-logo-grid-item{width:calc((100%/4) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--tablet5 .ha-logo-grid-item{width:calc((100%/5) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--tablet6 .ha-logo-grid-item{width:calc((100%/6) - 1rem)}}@media (max-width:767px){.ha-logo-grid--box.ha-logo-grid--col--mobile2 .ha-logo-grid-item{width:calc((100%/2) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--mobile3 .ha-logo-grid-item{width:calc((100%/3) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--mobile4 .ha-logo-grid-item{width:calc((100%/4) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--mobile5 .ha-logo-grid-item{width:calc((100%/5) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--mobile6 .ha-logo-grid-item{width:calc((100%/6) - 1rem)}}.ha-dual-button>.elementor-widget-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.ha-dual-btn,.ha-dual-btn-connector{display:inline-block}.ha-dual-btn-wrapper{position:relative;text-align:center;font-weight:400}.ha-dual-btn{padding:1.2rem 3rem;color:#fff;text-decoration:none;font-size:14px}.ha-dual-btn--left{border-top-left-radius:50px;border-bottom-left-radius:50px;background-color:#562dd4}.ha-dual-btn--left:focus,.ha-dual-btn--left:hover{background-color:#4423ab}.ha-dual-btn--right{border-top-right-radius:50px;border-bottom-right-radius:50px;background-color:#e2498a}.ha-dual-btn--right:focus,.ha-dual-btn--right:hover{background-color:#d6226e}.ha-dual-btn-connector{position:absolute!important;top:50%;right:0;z-index:9;width:30px;height:30px;border-radius:100%;background-color:#fff;box-shadow:0 0 0 5px rgba(255,255,255,.3);color:#27374c;text-transform:uppercase;font-size:12px;line-height:30px;-webkit-transform:translate(50%,-50%);-ms-transform:translate(50%,-50%);transform:translate(50%,-50%)}.ha-dual-btn-icon--before{margin-right:5px}.ha-dual-btn-icon--after{margin-left:5px}.ha-testimonial--basic>.elementor-widget-container{padding:2rem;border:1px solid #ececec;border-radius:.5rem}.ha-testimonial--basic .ha-testimonial__content{margin-bottom:2.5em}.ha-testimonial--bubble .ha-testimonial__content{position:relative;margin-bottom:1.5rem;padding:2rem;border-radius:6px;background-color:#fff;box-shadow:0 .2rem 2.8rem rgba(36,36,36,.1);line-height:1.6rem}.ha-testimonial--bubble .ha-testimonial__content:after{position:absolute;bottom:-14px;color:#fff;content:"\e911";font-style:normal;font-size:36px;font-family:"Happy Icons";-webkit-transform:rotate(-180deg);-ms-transform:rotate(-180deg);transform:rotate(-180deg)}.ha-testimonial--left.ha-testimonial--bubble .ha-testimonial__content:after{left:15px}.ha-testimonial--center.ha-testimonial--bubble .ha-testimonial__content:after{left:50%;-webkit-transform:translateX(-50%) rotate(-180deg);-ms-transform:translateX(-50%) rotate(-180deg);transform:translateX(-50%) rotate(-180deg)}.ha-testimonial--right.ha-testimonial--bubble .ha-testimonial__content:after{right:15px}.ha-testimonial__reviewer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.ha-testimonial__reviewer-thumb{width:65px;height:65px}.ha-testimonial__reviewer-thumb>img{width:100%;height:100%;border-radius:50%;-o-object-fit:cover;object-fit:cover}.ha-testimonial__reviewer-name{margin-bottom:.3rem;color:#562dd4;font-weight:700;font-size:18px}.ha-testimonial__reviewer-title{color:#8c8c8c;font-size:16px}.ha-testimonial--left .ha-testimonial__reviewer-meta{padding-left:1em}.ha-testimonial--center .ha-testimonial__reviewer{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.ha-testimonial--center .ha-testimonial__reviewer-meta{padding-top:1em}.ha-testimonial--right .ha-testimonial__reviewer{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.ha-testimonial--right .ha-testimonial__reviewer-meta{padding-right:1em}.ha-testimonial--left{text-align:left}.ha-testimonial--right{text-align:right}.ha-number-body,.ha-testimonial--center{text-align:center}.ha-number-body{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;overflow:hidden;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;padding:6px;width:50px;height:50px;border-radius:100%;background-color:#562dd4;color:#fff;font-size:20px}.ha-hover-box-wrapper:before,.ha-number-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ha-number-text{position:relative;z-index:1;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.ha-hover-box{overflow:hidden}.ha-hover-box .ha-hover-box-main{position:relative;overflow:hidden}.ha-hover-box-wrapper,.ha-hover-box-wrapper .ha-hover-box-content{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%}.ha-hover-box-wrapper{overflow:hidden;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;padding:50px;max-height:100%;height:400px;-webkit-transition-duration:.4s;transition-duration:.4s}.ha-hover-box-wrapper:before{z-index:1;content:""}.ha-hover-box-wrapper:hover{-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transform:scale(1.06);-ms-transform:scale(1.06);transform:scale(1.06)}.ha-hover-box-wrapper:hover .ha-hover-box-content{opacity:0;-webkit-transition-delay:0ms;transition-delay:0ms;-webkit-transition-timing-function:cubic-bezier(.57,.21,.69,1);transition-timing-function:cubic-bezier(.57,.21,.69,1);-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transform:translate(0,36px);-ms-transform:translate(0,36px);transform:translate(0,36px)}.ha-hover-box-wrapper .ha-hover-box-content{z-index:99;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;text-align:left;opacity:1;-webkit-transition:opacity .2s ease-in-out,-webkit-transform .2s ease-in-out;transition:opacity .2s ease-in-out,transform .2s ease-in-out;transition:opacity .2s ease-in-out,transform .2s ease-in-out,-webkit-transform .2s ease-in-out;-webkit-transition-delay:.1s;transition-delay:.1s;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.ha-hover-box-wrapper .ha-hover-sub-title{display:inline-block;margin-bottom:20px;color:#222}.ha-hover-box-wrapper .ha-hover-title{margin-top:0;margin-bottom:10px;color:#222}.ha-hover-box-wrapper .ha-hover-description{margin:0;color:#222}.ha-hover-box-wrapper.reverse:hover .ha-hover-box-content{opacity:1;-webkit-transition-delay:.1s;transition-delay:.1s;-webkit-transform:translate(0,-16px);-ms-transform:translate(0,-16px);transform:translate(0,-16px)}.ha-hover-box-wrapper.reverse .ha-hover-box-content{opacity:0;-webkit-transition-delay:0s;transition-delay:0s}.ha-pre--column .ha-hover-sub-title{margin-bottom:20px}.ha-pre--column-reverse p.ha-hover-sub-title{margin-top:20px;margin-bottom:0}.ha-flip-box-container:after{display:block;visibility:hidden;clear:both;height:0;content:" ";font-size:0}.ha-flip-box-container .ha-flip-box-inner{position:relative;z-index:1;margin:0;padding:0;-webkit-backface-visibility:hidden;backface-visibility:hidden}.ha-flip-box-container .ha-flip-box-inner:hover .ha-flip-box-back{z-index:1}.ha-flip-box-container .ha-flip-box-inner:hover .ha-flip-box-front{z-index:-1}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-inner-wrapper{position:relative;-webkit-transform:translateZ(0);-webkit-perspective:1000px;perspective:1000px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front{top:0;right:0;left:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;height:250px;background-position:center;background-clip:padding-box;background-size:cover;background-repeat:no-repeat;text-align:center;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front{background-color:transparent;position:relative;bottom:0;z-index:10;padding:30px;border:1px solid #ddd;border-radius:.3rem}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back:before,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front:before{position:absolute;top:0;left:0;z-index:-9;width:100%;height:100%;background-color:transparent;content:""}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back{position:absolute;z-index:-1;padding:46px;border-radius:.3rem;background-color:#562dd4;color:#fff}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-text,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-text{text-align:center}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-text p,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-text p{margin-top:10px;margin-bottom:0}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-icon.icon{padding:20px;border-radius:50%;background-color:#f1f4f8;color:#242424}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-icon{display:inline-block;margin-bottom:20px;text-align:center}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-icon i{position:relative;display:block;width:1em;height:1em;font-size:28px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-flip-icon img,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-icon img{width:60px;height:60px;vertical-align:middle}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-box-heading{margin:0;font-weight:700;font-size:20px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner p{margin-bottom:0;font-size:16px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-flip-box-heading-back{margin:0;color:#fff;font-size:18px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-flip-icon{display:inline-block;margin-bottom:20px;text-align:center}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-flip-icon i{position:relative;display:block;width:1em;height:1em;color:#fff;font-size:20px}.ha-flip-box-container .ha-flip-box-back-inner .button-wrap{margin-top:12px}.ha-flip-box-container .ha-flip-box-back-inner .ha-flip-btn{display:inline-block;padding:.8rem 2.5rem;border-radius:4px;background-color:#fff;color:#562dd4;text-decoration:none;text-transform:uppercase;font-size:12px;-webkit-transition:all .3s;transition:all .3s}.ha-flip-box-container .ha-flip-box-back-inner .ha-flip-btn:hover{background-color:#fff;color:#562dd4}.ha-flip-box-container .ha-flip-box-inner.ha-flip-right .ha-flip-box-front,.ha-flip-box-container .ha-flip-box-inner.ha-flip-right:hover .ha-flip-box-back{-webkit-transform:rotateY(0);transform:rotateY(0)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-right .ha-flip-box-back{-webkit-transform:rotateY(-180deg);transform:rotateY(-180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-right:hover .ha-flip-box-front{-webkit-transform:rotateY(180deg);transform:rotateY(180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-left .ha-flip-box-front,.ha-flip-box-container .ha-flip-box-inner.ha-flip-left:hover .ha-flip-box-back{-webkit-transform:rotateY(0);transform:rotateY(0)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-left .ha-flip-box-back{-webkit-transform:rotateY(180deg);transform:rotateY(180deg)}.ha-flip-box-container .ha-flip-box.ha-flip-left:hover .ha-flip-box-front{-webkit-transform:rotateY(-180deg);transform:rotateY(-180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-up .ha-flip-box-front,.ha-flip-box-container .ha-flip-box-inner.ha-flip-up:hover .ha-flip-box-back{-webkit-transform:rotateX(0);transform:rotateX(0)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-up .ha-flip-box-back{-webkit-transform:rotateX(-180deg);transform:rotateX(-180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-up:hover .ha-flip-box-front{-webkit-transform:rotateX(180deg);transform:rotateX(180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-down .ha-flip-box-front,.ha-flip-box-container .ha-flip-box-inner.ha-flip-down:hover .ha-flip-box-back{-webkit-transform:rotateX(0);transform:rotateX(0)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-down .ha-flip-box-back{-webkit-transform:rotateX(180deg);transform:rotateX(180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-down:hover .ha-flip-box-front{-webkit-transform:rotateX(-180deg);transform:rotateX(-180deg)}.ha-flip-box-container.ha-flip-effect-classic .ha-flip-box-back,.ha-flip-box-container.ha-flip-effect-classic .ha-flip-box-front{-webkit-transition:-webkit-transform .6s cubic-bezier(.2,.85,.4,1.275);transition:transform .6s cubic-bezier(.2,.85,.4,1.275);transition:transform .6s cubic-bezier(.2,.85,.4,1.275),-webkit-transform .6s cubic-bezier(.2,.85,.4,1.275)}.ha-pricing-table>.elementor-widget-container{position:relative;overflow:hidden;padding:3em 4em}.ha-pricing-table-badge{position:absolute;top:0;padding:.8rem 1rem;background-color:#e2498a;color:#fff;line-height:1}.ha-pricing-table-badge--left{left:0;-webkit-transform:rotate(-90deg) translateX(-100%);-ms-transform:rotate(-90deg) translateX(-100%);transform:rotate(-90deg) translateX(-100%);-webkit-transform-origin:left top;-ms-transform-origin:left top;transform-origin:left top}.ha-pricing-table-badge--right{right:0;-webkit-transform:rotate(-90deg) translateY(-100%);-ms-transform:rotate(-90deg) translateY(-100%);transform:rotate(-90deg) translateY(-100%);-webkit-transform-origin:right top;-ms-transform-origin:right top;transform-origin:right top}.ha-pricing-table-title{margin-top:0;margin-bottom:.5rem;color:#242424;font-weight:400;font-size:24px}.ha-pricing-table-price{margin-bottom:3rem}.ha-pricing-table-price-tag{margin-bottom:.5rem;color:#242424;font-weight:700;font-size:60px;line-height:normal}.ha-pricing-table-currency{font-size:24px}.ha-pricing-table-period{color:#8c8c8c;font-size:16px}.ha-pricing-table-body{margin-bottom:3rem}.ha-pricing-table-features-title{margin-top:0;margin-bottom:1rem;font-weight:700;font-size:16px}.ha-pricing-table-features-list{margin:0;padding:0;list-style:none}.ha-pricing-table-features-list li{margin-bottom:1rem;font-size:16px}.ha-pricing-table-features-list i{margin-right:.5rem;min-width:15px;font-size:.8em}.ha-pricing-table-btn{display:inline-block;padding:.8rem 2rem;border-radius:40px;background-color:#e2498a;color:#fff;text-decoration:none;text-transform:uppercase;font-size:12px;-webkit-transition:all .3s;transition:all .3s}.ha-pricing-table-btn:hover{background-color:#562dd4;color:#fff}.ha-card>.elementor-widget-container,.ha-icon-box>.elementor-widget-container,.ha-image-compare>.elementor-widget-container,.ha-infobox>.elementor-widget-container,.ha-member>.elementor-widget-container,.ha-pricing-table>.elementor-widget-container,.ha-review>.elementor-widget-container{border-radius:.5rem;background-color:#fff;box-shadow:0 .2rem 2.8rem rgba(36,36,36,.1);word-wrap:break-word;overflow-wrap:break-word}.ha-logo-grid-wrapper:after,.ha-logo-grid-wrapper:before{display:table;content:" "}.ha-logo-grid-wrapper:after{clear:both}.ha-step-flow>.elementor-widget-container{padding:30px;text-align:center}.ha-step-arrow{position:absolute;top:49%;left:calc(100% + 50px);display:inline-block;width:100px;border-top:1px dashed #ddd}.ha-step-arrow:after{position:absolute;right:-6px;height:1.5em;color:#ddd;content:"\e90b";font-size:18px;font-family:"Happy Icons"!important;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.ha-steps-icon{position:relative;display:inline-block;margin-bottom:2rem;padding:40px;border-radius:50%;background-color:#f1f4f8;color:#242424;text-align:center;font-size:46px}.ha-steps-icon i{position:relative;display:block;width:1em;height:1em}.ha-steps-icon i:before{position:absolute;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-steps-icon .ha-steps-label{position:absolute;top:5px;right:0;padding:10px 12px;border:3px solid #fff;border-radius:20px;background-color:#e2498a;color:#fff;font-size:12px;line-height:0}.ha-steps-title{margin-top:0;margin-bottom:30px;font-weight:700;font-size:16px}.ha-steps-title a{display:block;color:#562dd4}.ha-steps-title a:hover{color:#242424}.ha-step-description{margin:0;color:#616161;font-weight:400;font-size:16px;line-height:1.5}
1
+ .happy-addon,.happy-addon *{box-sizing:border-box}.happy-addon img{max-width:100%;height:auto;-o-object-fit:cover;object-fit:cover}.happy-addon p:empty{display:none}.ha-screen-reader-text{position:absolute;overflow:hidden;clip:rect(1px,1px,1px,1px);margin:-1px;padding:0;width:1px;height:1px;border:0;word-wrap:normal!important;-webkit-clip-path:inset(50%);clip-path:inset(50%)}.ha-has-background-overlay>.elementor-widget-container{position:relative;z-index:1}.ha-has-background-overlay>.elementor-widget-container:before{position:absolute;top:0;left:0;z-index:-1;width:100%;height:100%;content:""}.ha-btn{display:inline-block;vertical-align:middle;text-align:center;text-decoration:none;font-size:14px;line-height:1;-webkit-transition:all .3s;transition:all .3s}.ha-btn:not(.ha-btn--link){padding:15px 25px;border-radius:.25rem;background-color:#562dd4;color:#fff}.ha-btn:not(.ha-btn--link):focus,.ha-btn:not(.ha-btn--link):hover{background-color:#e2498a}.ha-btn.ha-btn--link{color:#562dd4}.ha-btn.ha-btn--link:focus,.ha-btn.ha-btn--link:hover{color:#e2498a}.ha-btn-icon{-webkit-transition:all .3s;transition:all .3s}.ha-btn-icon+.ha-btn-text,.ha-btn-text+.ha-btn-icon{margin-left:5px}.ha-badge{padding:.475rem 1.1rem;border-radius:50px;background-color:#fff;font-size:12px}.ha-badge--top-left{top:1rem;left:1rem}.ha-badge--top-center{top:1rem;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-badge--top-right{top:1rem;right:1rem}.ha-badge--middle-left{top:50%;left:1rem;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.ha-badge--middle-center{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.ha-badge--middle-right{top:50%;right:1rem;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.ha-badge--bottom-left{bottom:1rem;left:1rem}.ha-badge--bottom-center{bottom:1rem;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-badge--bottom-right{right:1rem;bottom:1rem}.ha-card-figure{position:relative;height:250px}.ha-card-figure>img{border-top-left-radius:calc(.5rem - 1px);border-top-right-radius:calc(.5rem - 1px)}.ha-card-body{padding:1.5rem}.ha-card-title{margin-top:0;margin-bottom:.75rem;color:#151515;font-weight:700;font-size:22px}.ha-card-text{margin-bottom:2rem;color:#616161;font-size:16px;line-height:1.7}.ha-card-text>p,.ha-infobox-text>p{margin-top:0;margin-bottom:0}.ha-card--top .ha-card-figure{display:inline-block;width:100%}.ha-card--left>.elementor-widget-container,.ha-card--right>.elementor-widget-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center}.ha-card--left>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.ha-card--left .ha-card-body,.ha-card--left .ha-card-figure,.ha-card--right .ha-card-body,.ha-card--right .ha-card-figure{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.ha-card--left .ha-card-body,.ha-card--right .ha-card-body{padding:2.5rem}.ha-card--left .ha-card-figure>img{border-radius:calc(.5rem - 1px) 0 0 calc(.5rem - 1px)}.ha-card--right>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;text-align:right}.ha-card--right .ha-card-figure>img{border-radius:0 calc(.5rem - 1px) calc(.5rem - 1px) 0}.ha-card .ha-badge{position:absolute}.ha-infobox>.elementor-widget-container{padding:1.5rem}.ha-infobox-title{margin-top:0;margin-bottom:1rem;color:#151515;font-size:24px}.ha-infobox-figure{display:inline-block;margin:0 0 1.5rem!important}.ha-infobox-figure--icon{text-align:center;font-size:3rem}.ha-icon-box-icon>i,.ha-infobox-figure>i{position:relative;display:block;width:1em;height:1em}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-flip-icon i:before,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-icon i:before,.ha-icon-box-icon>i:before,.ha-infobox-figure>i:before{position:absolute;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-card-figure>img,.ha-infobox-figure>img,.ha-member-figure img{width:100%;height:100%;vertical-align:bottom}.ha-infobox-text+.ha-btn--link{margin-top:1rem}.ha-icon-box>.elementor-widget-container{position:relative;padding:1.25rem}.ha-icon-box-title{margin-top:0;margin-bottom:0;color:#151515;font-size:24px;-webkit-transition:color .3s;transition:color .3s}.ha-icon-box-icon{display:inline-block;margin-bottom:1rem;color:#151515;text-align:center;font-size:3rem;-webkit-transition:border .3s,background .3s,color .3s,-webkit-transform .3s;transition:transform .3s,border .3s,background .3s,color .3s;transition:transform .3s,border .3s,background .3s,color .3s,-webkit-transform .3s}.ha-icon-box-icon>i{-webkit-transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.ha-icon-box-link{display:block;color:transparent;text-decoration:none}.ha-icon-box .ha-badge{position:absolute;z-index:9999;background-color:#e2498a;color:#fff}.ha-member>.elementor-widget-container{padding:1.25rem}.ha-member-figure{display:inline-block;margin:0 0 1.5rem!important}.ha-member-name{margin-top:0;margin-bottom:.5rem;color:#151515;font-size:18px}.ha-member-position{margin-bottom:1.5rem;color:#7f7f7f;font-size:14px}.ha-member-bio{margin-bottom:1.5rem;font-size:14px;line-height:1.6}.ha-member-links>a{display:inline-block;color:#9895ad;text-align:center;line-height:1;-webkit-transition:all .2s;transition:all .2s}.ha-member-links>a:focus,.ha-member-links>a:hover{color:#222}.ha-member-links>a>i{width:1em;height:1em}.ha-member-links>a:not(:last-child){margin-right:.3rem}.ha-review-header{margin-top:1.5rem}.ha-review-desc p,.ha-review-figure{margin:0}.ha-review-figure>img{width:100%;height:100%;border-radius:50%;vertical-align:bottom}.ha-review-reviewer{margin-top:0;margin-bottom:.3rem;color:#151515;font-size:18px}.ha-review-position{margin-bottom:.5rem;color:#7f7f7f;font-size:15px}.ha-review-ratting{display:inline-block;font-size:12px;line-height:1}.ha-review-ratting--num{padding:.25em .66em;border-radius:2.5em;background-color:#562dd4;color:#fff}.ha-review-ratting--star{color:#ffbf36}.ha-review-desc{margin-top:1.5rem;font-size:16px;line-height:1.6}.ha-review--top>.elementor-widget-container{padding:2rem}.ha-review--top .ha-review-figure{display:inline-block;max-width:70px;height:70px}.ha-review--left>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.ha-review--left>.elementor-widget-container,.ha-review--right>.elementor-widget-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;padding-left:2rem}.ha-review--left .ha-review-figure,.ha-review--right .ha-review-figure{-webkit-box-flex:0;-webkit-flex:0 0 150px;-ms-flex:0 0 150px;flex:0 0 150px;max-width:150px;height:150px}.ha-review--left .ha-review-body,.ha-review--right .ha-review-body{-webkit-box-flex:0;-webkit-flex:0 0 calc(100% - 150px);-ms-flex:0 0 calc(100% - 150px);flex:0 0 calc(100% - 150px);padding:2rem;max-width:calc(100% - 150px)}.ha-review--left .ha-review-body>:first-child,.ha-review--right .ha-review-body>:first-child{margin-top:0}.ha-review--right>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;padding-right:2rem;padding-left:0;text-align:right}.ha-image-compare .twentytwenty-container,.ha-image-compare .twentytwenty-wrapper{border-radius:inherit}.ha-gallery-filter{margin:0 10px 2rem;padding:0;list-style:none}.ha-gallery-filter>li{display:inline-block;margin-bottom:10px}.ha-gallery-filter>li:not(:last-child){margin-right:10px}.ha-gallery-filter>li>button{display:block;padding:10px 25px;border:2px solid #562dd4;border-radius:.25rem;background-color:transparent;color:#562dd4;text-transform:uppercase;font-size:14px;cursor:pointer;-webkit-transition:all .3s;transition:all .3s}.ha-gallery-filter>li>button:focus,.ha-gallery-filter>li>button:hover{outline:0;background-color:#562dd4;color:#fff}.ha-gallery-filter>.ha-filter-active>button{background-color:#562dd4;color:#fff}.ha-image-grid-item{float:left}.ha-image-grid-inner{position:relative;display:block;overflow:hidden;margin:10px;text-decoration:none}.ha-image-grid-inner img{display:block;width:100%;-webkit-transition:all .25s;transition:all .25s}.ha-image-grid--layout-even .ha-image-grid-inner{height:250px}.ha-image-grid--layout-even .ha-image-grid-inner>img{height:100%}.ha-justified-gallery-item,.ha-justified-gallery-item>img{border-radius:6px}.ha-justified-gallery .justified-gallery>.ha-justified-gallery-item>.caption{bottom:-100px!important;padding:10px;-webkit-transition:all .25s!important;transition:all .25s!important;-webkit-animation:haSmoothReveal .3s forwards;animation:haSmoothReveal .3s forwards}.ha-justified-gallery .justified-gallery>.ha-justified-gallery-item>.caption.caption-visible{bottom:0!important}.ha-justified-gallery .justified-gallery>.entry-visible>a>img,.ha-justified-gallery .justified-gallery>.entry-visible>img{-webkit-transition:all 300ms,opacity 500ms ease-in;transition:all 300ms,opacity 500ms ease-in}@-webkit-keyframes haSmoothReveal{0%{-webkit-transform:translateY(100px);transform:translateY(100px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes haSmoothReveal{0%{-webkit-transform:translateY(100px);transform:translateY(100px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}.ha-carousel .slick-vertical .slick-slide,.ha-slider .slick-vertical .slick-slide{border:0}.ha-carousel .slick-next,.ha-carousel .slick-prev,.ha-slider .slick-next,.ha-slider .slick-prev{z-index:999;padding:0;border:1px solid rgba(255,255,255,.8);border-radius:50%;background-color:rgba(255,255,255,.8);color:#8c8c8c;text-align:center;font-size:12px;opacity:1}.ha-carousel .slick-next:focus,.ha-carousel .slick-next:hover,.ha-carousel .slick-prev:focus,.ha-carousel .slick-prev:hover,.ha-slider .slick-next:focus,.ha-slider .slick-next:hover,.ha-slider .slick-prev:focus,.ha-slider .slick-prev:hover{background-color:#fff}.ha-carousel .slick-next:before,.ha-carousel .slick-prev:before,.ha-slider .slick-next:before,.ha-slider .slick-prev:before{content:""}.ha-carousel .slick-disabled,.ha-slider .slick-disabled{opacity:.7}.ha-carousel .slick-prev,.ha-slider .slick-prev{left:25px}.ha-carousel .slick-next,.ha-slider .slick-next{right:25px}.ha-carousel .slick-dots,.ha-slider .slick-dots{bottom:-40px}.ha-carousel .slick-dots li,.ha-slider .slick-dots li{margin-right:2px;margin-left:2px}.ha-carousel .slick-dots li button:focus,.ha-carousel .slick-dots li button:hover,.ha-slider .slick-dots li button:focus,.ha-slider .slick-dots li button:hover{background-color:transparent}.ha-carousel .slick-dots li button:before,.ha-slider .slick-dots li button:before{color:#1b1b1b;opacity:1}.ha-carousel .slick-dots .slick-active button:before,.ha-carousel .slick-dots li button:hover:before,.ha-slider .slick-dots .slick-active button:before,.ha-slider .slick-dots li button:hover:before{-webkit-transform:scale(1.5);-ms-transform:scale(1.5);transform:scale(1.5)}.ha-carousel .slick-next,.ha-carousel .slick-prev{width:40px;height:40px;line-height:40px}.ha-slider .slick-next,.ha-slider .slick-prev{width:50px;height:50px;line-height:50px}.ha-carousel .slick-slider:not(.slick-vertical) .slick-slide{padding-right:5px;padding-left:5px}.ha-carousel .slick-slider.slick-vertical .slick-slide{padding-top:5px;padding-bottom:5px}.ha-slick-item{position:relative;overflow:hidden;vertical-align:bottom}.ha-slick-content{position:absolute;bottom:0;padding:1.5rem;width:100%;background:-webkit-linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.3));background:linear-gradient(rgba(0,0,0,0),rgba(0,0,0,.3))}.ha-slick-title{margin-top:0;margin-bottom:.2rem;color:#fff;font-size:20px}.ha-slick-subtitle{margin:0;color:#fff}.ha-skills>.elementor-widget-container{padding-top:1px}.ha-skill{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;border-radius:15px;background-color:#e9ecef;font-size:.75rem}.ha-skill--inside .ha-skill-info,.ha-skill--outside .ha-skill-info{text-align:left;font-size:14px}.ha-skill--inside .ha-skill-level-text,.ha-skill--outside .ha-skill-level-text{float:right}.ha-skill--outside{height:2px}.ha-skill--outside .ha-skill-level{position:relative}.ha-skill--outside .ha-skill-info{position:absolute;top:-25px;width:100%;color:#242424}.ha-skill--inside{height:30px}.ha-skill--inside .ha-skill-info{padding-right:1rem;padding-left:1rem;color:#fff}.ha-skill-level{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;width:10%;border-radius:inherit;background-color:#562dd4;color:#fff;text-align:center;white-space:nowrap;-webkit-transition:width .6s ease;transition:width .6s ease}.ha-skill--outside{margin-top:40px}.ha-skill--inside:not(:first-child){margin-top:20px}.ha-gradient-heading{margin-top:0;margin-bottom:0}.ha-gradient-heading>a{color:inherit;text-decoration:none}.ha-logo-grid-item{float:left;overflow:hidden;height:180px;border-color:#e7e7e7}.ha-logo-grid-figure{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;margin:0;padding:30px;width:100%;height:100%}.ha-logo-grid-img{max-height:100%}@media (min-width:1025px){.ha-logo-grid--col-2 .ha-logo-grid-item{width:calc(100%/2)}.ha-logo-grid--col-3 .ha-logo-grid-item{width:calc(100%/3)}.ha-logo-grid--col-4 .ha-logo-grid-item{width:calc(100%/4)}.ha-logo-grid--col-5 .ha-logo-grid-item{width:calc(100%/5)}.ha-logo-grid--col-6 .ha-logo-grid-item{width:calc(100%/6)}}@media (max-width:1024px) and (min-width:768px){.ha-logo-grid--col--tablet2 .ha-logo-grid-item{width:calc(100%/2)}.ha-logo-grid--col--tablet3 .ha-logo-grid-item{width:calc(100%/3)}.ha-logo-grid--col--tablet4 .ha-logo-grid-item{width:calc(100%/4)}.ha-logo-grid--col--tablet5 .ha-logo-grid-item{width:calc(100%/5)}.ha-logo-grid--col--tablet6 .ha-logo-grid-item{width:calc(100%/6)}}@media (max-width:767px){.ha-logo-grid--col--mobile2 .ha-logo-grid-item{width:calc(100%/2)}.ha-logo-grid--col--mobile3 .ha-logo-grid-item{width:calc(100%/3)}.ha-logo-grid--col--mobile4 .ha-logo-grid-item{width:calc(100%/4)}.ha-logo-grid--col--mobile5 .ha-logo-grid-item{width:calc(100%/5)}.ha-logo-grid--col--mobile6 .ha-logo-grid-item{width:calc(100%/6)}}.ha-logo-grid--tictactoe .ha-logo-grid-item{border-width:2px 2px 0 0;border-style:solid}@media (min-width:1025px){.ha-logo-grid--tictactoe.ha-logo-grid--col-2 .ha-logo-grid-item:nth-child(2n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-3 .ha-logo-grid-item:nth-child(3n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-4 .ha-logo-grid-item:nth-child(4n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-5 .ha-logo-grid-item:nth-child(5n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-6 .ha-logo-grid-item:nth-child(6n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col-6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:0!important}}@media (max-width:1024px) and (min-width:768px){.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-child(2n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-child(3n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-child(4n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-child(5n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-child(6n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:0!important}}@media (max-width:767px){.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-child(2n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-child(3n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-child(4n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-child(5n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-child(6n){border-right-width:0!important}.ha-logo-grid--tictactoe.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:0!important}}.ha-logo-grid--border .ha-logo-grid-item{border-width:0 2px 2px 0;border-style:solid}.ha-logo-grid--border .ha-logo-grid-item:first-child{border-top-left-radius:10px}.ha-logo-grid--border .ha-logo-grid-item:last-child{border-bottom-right-radius:10px}@media (min-width:1025px){.ha-logo-grid--border.ha-logo-grid--col-2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col-2 .ha-logo-grid-item:nth-child(2n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col-2 .ha-logo-grid-item:nth-child(2){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-2 .ha-logo-grid-item:nth-last-child(2){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col-3 .ha-logo-grid-item:nth-child(3n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col-3 .ha-logo-grid-item:nth-child(3){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-3 .ha-logo-grid-item:nth-last-child(3){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col-4 .ha-logo-grid-item:nth-child(4n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col-4 .ha-logo-grid-item:nth-child(4){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-4 .ha-logo-grid-item:nth-last-child(4){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col-5 .ha-logo-grid-item:nth-child(5n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col-5 .ha-logo-grid-item:nth-child(5){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-5 .ha-logo-grid-item:nth-last-child(5){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col-6 .ha-logo-grid-item:nth-child(6n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col-6 .ha-logo-grid-item:nth-child(6){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col-6 .ha-logo-grid-item:nth-last-child(6){border-bottom-left-radius:10px}}@media (max-width:1024px) and (min-width:768px){.ha-logo-grid--border.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-child(2n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-child(2){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet2 .ha-logo-grid-item:nth-last-child(2){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-child(3n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-child(3){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet3 .ha-logo-grid-item:nth-last-child(3){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-child(4n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-child(4){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet4 .ha-logo-grid-item:nth-last-child(4){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-child(5n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-child(5){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet5 .ha-logo-grid-item:nth-last-child(5){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-child(6n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-child(6){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--tablet6 .ha-logo-grid-item:nth-last-child(6){border-bottom-left-radius:10px}}@media (max-width:767px){.ha-logo-grid--border.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-child(-n+2){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-child(2n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-child(2){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile2 .ha-logo-grid-item:nth-last-child(2){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-child(-n+3){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-child(3n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-child(3){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile3 .ha-logo-grid-item:nth-last-child(3){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-child(-n+4){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-child(4n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-child(4){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile4 .ha-logo-grid-item:nth-last-child(4){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-child(-n+5){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-child(5n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-child(5){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile5 .ha-logo-grid-item:nth-last-child(5){border-bottom-left-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-child(-n+6){border-top-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-child(6n+1){border-left-width:2px}.ha-logo-grid--border.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-child(6){border-top-right-radius:10px}.ha-logo-grid--border.ha-logo-grid--col--mobile6 .ha-logo-grid-item:nth-last-child(6){border-bottom-left-radius:10px}}.ha-logo-grid--box .ha-logo-grid-wrapper{margin:-.5rem}.ha-logo-grid--box .ha-logo-grid-item{margin:.5rem;border-width:2px;border-style:solid;border-radius:.5rem}@media (min-width:1025px){.ha-logo-grid--box.ha-logo-grid--col-2 .ha-logo-grid-item{width:calc((100%/2) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col-3 .ha-logo-grid-item{width:calc((100%/3) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col-4 .ha-logo-grid-item{width:calc((100%/4) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col-5 .ha-logo-grid-item{width:calc((100%/5) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col-6 .ha-logo-grid-item{width:calc((100%/6) - 1rem)}}@media (max-width:1024px) and (min-width:768px){.ha-logo-grid--box.ha-logo-grid--col--tablet2 .ha-logo-grid-item{width:calc((100%/2) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--tablet3 .ha-logo-grid-item{width:calc((100%/3) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--tablet4 .ha-logo-grid-item{width:calc((100%/4) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--tablet5 .ha-logo-grid-item{width:calc((100%/5) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--tablet6 .ha-logo-grid-item{width:calc((100%/6) - 1rem)}}@media (max-width:767px){.ha-logo-grid--box.ha-logo-grid--col--mobile2 .ha-logo-grid-item{width:calc((100%/2) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--mobile3 .ha-logo-grid-item{width:calc((100%/3) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--mobile4 .ha-logo-grid-item{width:calc((100%/4) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--mobile5 .ha-logo-grid-item{width:calc((100%/5) - 1rem)}.ha-logo-grid--box.ha-logo-grid--col--mobile6 .ha-logo-grid-item{width:calc((100%/6) - 1rem)}}.ha-dual-button>.elementor-widget-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.ha-dual-btn,.ha-dual-btn-connector{display:inline-block}.ha-dual-btn-wrapper{position:relative;text-align:center;font-weight:400}.ha-dual-btn{padding:1.2rem 3rem;color:#fff;text-decoration:none;font-size:14px}.ha-dual-btn--left{border-top-left-radius:50px;border-bottom-left-radius:50px;background-color:#562dd4}.ha-dual-btn--left:focus,.ha-dual-btn--left:hover{background-color:#4423ab}.ha-dual-btn--right{border-top-right-radius:50px;border-bottom-right-radius:50px;background-color:#e2498a}.ha-dual-btn--right:focus,.ha-dual-btn--right:hover{background-color:#d6226e}.ha-dual-btn-connector{position:absolute!important;top:50%;right:0;z-index:9;width:30px;height:30px;border-radius:100%;background-color:#fff;box-shadow:0 0 0 5px rgba(255,255,255,.3);color:#27374c;text-transform:uppercase;font-size:12px;line-height:30px;-webkit-transform:translate(50%,-50%);-ms-transform:translate(50%,-50%);transform:translate(50%,-50%)}.ha-dual-btn-icon--before{margin-right:5px}.ha-dual-btn-icon--after{margin-left:5px}.ha-testimonial--basic>.elementor-widget-container{padding:2rem;border:1px solid #ececec;border-radius:.5rem}.ha-testimonial--basic .ha-testimonial__content{margin-bottom:2.5em}.ha-testimonial--bubble .ha-testimonial__content{position:relative;margin-bottom:1.5rem;padding:2rem;border-radius:6px;background-color:#fff;box-shadow:0 .2rem 2.8rem rgba(36,36,36,.1);line-height:1.6rem}.ha-testimonial--bubble .ha-testimonial__content:after{position:absolute;bottom:-14px;color:#fff;content:"\e911";font-style:normal;font-size:36px;font-family:"Happy Icons";-webkit-transform:rotate(-180deg);-ms-transform:rotate(-180deg);transform:rotate(-180deg)}.ha-testimonial--left.ha-testimonial--bubble .ha-testimonial__content:after{left:15px}.ha-testimonial--center.ha-testimonial--bubble .ha-testimonial__content:after{left:50%;-webkit-transform:translateX(-50%) rotate(-180deg);-ms-transform:translateX(-50%) rotate(-180deg);transform:translateX(-50%) rotate(-180deg)}.ha-testimonial--right.ha-testimonial--bubble .ha-testimonial__content:after{right:15px}.ha-testimonial__reviewer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.ha-testimonial__reviewer-thumb{width:65px;height:65px}.ha-testimonial__reviewer-thumb>img{width:100%;height:100%;border-radius:50%;-o-object-fit:cover;object-fit:cover}.ha-testimonial__reviewer-name{margin-bottom:.3rem;color:#562dd4;font-weight:700;font-size:18px}.ha-testimonial__reviewer-title{color:#8c8c8c;font-size:16px}.ha-testimonial--left .ha-testimonial__reviewer-meta{padding-left:1em}.ha-testimonial--center .ha-testimonial__reviewer{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.ha-testimonial--center .ha-testimonial__reviewer-meta{padding-top:1em}.ha-testimonial--right .ha-testimonial__reviewer{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.ha-testimonial--right .ha-testimonial__reviewer-meta{padding-right:1em}.ha-testimonial--left{text-align:left}.ha-testimonial--right{text-align:right}.ha-number-body,.ha-testimonial--center{text-align:center}.ha-number-body{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;overflow:hidden;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;padding:6px;width:50px;height:50px;border-radius:100%;background-color:#562dd4;color:#fff;font-size:20px}.ha-number-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ha-number-text{position:relative;z-index:1;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.ha-flip-box-container:after{display:block;visibility:hidden;clear:both;height:0;content:" ";font-size:0}.ha-flip-box-container .ha-flip-box-inner{position:relative;z-index:1;margin:0;padding:0;-webkit-backface-visibility:hidden;backface-visibility:hidden}.ha-flip-box-container .ha-flip-box-inner:hover .ha-flip-box-back{z-index:1}.ha-flip-box-container .ha-flip-box-inner:hover .ha-flip-box-front{z-index:-1}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-inner-wrapper{position:relative;-webkit-transform:translateZ(0);-webkit-perspective:1000px;perspective:1000px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front{top:0;right:0;left:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;height:250px;background-position:center;background-clip:padding-box;background-size:cover;background-repeat:no-repeat;text-align:center;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front{background-color:transparent;position:relative;bottom:0;z-index:10;padding:30px;border:1px solid #ddd;border-radius:.3rem}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back:before,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front:before{position:absolute;top:0;left:0;z-index:-9;width:100%;height:100%;background-color:transparent;content:""}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back{position:absolute;z-index:-1;padding:46px;border-radius:.3rem;background-color:#562dd4;color:#fff}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-text,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-text{text-align:center}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-text p,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-text p{margin-top:10px;margin-bottom:0}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-icon.icon{padding:20px;border-radius:50%;background-color:#f1f4f8;color:#242424}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-icon{display:inline-block;margin-bottom:20px;text-align:center}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-icon i{position:relative;display:block;width:1em;height:1em;font-size:28px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-flip-icon img,.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-icon img{width:60px;height:60px;vertical-align:middle}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner .ha-flip-box-heading{margin:0;font-weight:700;font-size:20px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-front-inner p{margin-bottom:0;font-size:16px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-flip-box-heading-back{margin:0;color:#fff;font-size:18px}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-flip-icon{display:inline-block;margin-bottom:20px;text-align:center}.ha-flip-box-container .ha-flip-box-inner .ha-flip-box-back-inner .ha-flip-icon i{position:relative;display:block;width:1em;height:1em;color:#fff;font-size:20px}.ha-flip-box-container .ha-flip-box-back-inner .button-wrap{margin-top:12px}.ha-flip-box-container .ha-flip-box-back-inner .ha-flip-btn{display:inline-block;padding:.8rem 2.5rem;border-radius:4px;background-color:#fff;color:#562dd4;text-decoration:none;text-transform:uppercase;font-size:12px;-webkit-transition:all .3s;transition:all .3s}.ha-flip-box-container .ha-flip-box-back-inner .ha-flip-btn:hover{background-color:#fff;color:#562dd4}.ha-flip-box-container .ha-flip-box-inner.ha-flip-right .ha-flip-box-front,.ha-flip-box-container .ha-flip-box-inner.ha-flip-right:hover .ha-flip-box-back{-webkit-transform:rotateY(0);transform:rotateY(0)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-right .ha-flip-box-back{-webkit-transform:rotateY(-180deg);transform:rotateY(-180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-right:hover .ha-flip-box-front{-webkit-transform:rotateY(180deg);transform:rotateY(180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-left .ha-flip-box-front,.ha-flip-box-container .ha-flip-box-inner.ha-flip-left:hover .ha-flip-box-back{-webkit-transform:rotateY(0);transform:rotateY(0)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-left .ha-flip-box-back{-webkit-transform:rotateY(180deg);transform:rotateY(180deg)}.ha-flip-box-container .ha-flip-box.ha-flip-left:hover .ha-flip-box-front{-webkit-transform:rotateY(-180deg);transform:rotateY(-180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-up .ha-flip-box-front,.ha-flip-box-container .ha-flip-box-inner.ha-flip-up:hover .ha-flip-box-back{-webkit-transform:rotateX(0);transform:rotateX(0)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-up .ha-flip-box-back{-webkit-transform:rotateX(-180deg);transform:rotateX(-180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-up:hover .ha-flip-box-front{-webkit-transform:rotateX(180deg);transform:rotateX(180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-down .ha-flip-box-front,.ha-flip-box-container .ha-flip-box-inner.ha-flip-down:hover .ha-flip-box-back{-webkit-transform:rotateX(0);transform:rotateX(0)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-down .ha-flip-box-back{-webkit-transform:rotateX(180deg);transform:rotateX(180deg)}.ha-flip-box-container .ha-flip-box-inner.ha-flip-down:hover .ha-flip-box-front{-webkit-transform:rotateX(-180deg);transform:rotateX(-180deg)}.ha-flip-box-container.ha-flip-effect-classic .ha-flip-box-back,.ha-flip-box-container.ha-flip-effect-classic .ha-flip-box-front{-webkit-transition:-webkit-transform .6s cubic-bezier(.2,.85,.4,1.275);transition:transform .6s cubic-bezier(.2,.85,.4,1.275);transition:transform .6s cubic-bezier(.2,.85,.4,1.275),-webkit-transform .6s cubic-bezier(.2,.85,.4,1.275)}.ha-pricing-table>.elementor-widget-container{position:relative;overflow:hidden;padding:3em 4em}.ha-pricing-table-badge{position:absolute;top:-1px;padding:.8rem 1rem;background-color:#e2498a;color:#fff;line-height:1}.ha-pricing-table-badge--left{left:0;-webkit-transform:rotate(-90deg) translateX(-100%);-ms-transform:rotate(-90deg) translateX(-100%);transform:rotate(-90deg) translateX(-100%);-webkit-transform-origin:left top;-ms-transform-origin:left top;transform-origin:left top}.ha-pricing-table-badge--right{right:0;-webkit-transform:rotate(-90deg) translateY(-100%);-ms-transform:rotate(-90deg) translateY(-100%);transform:rotate(-90deg) translateY(-100%);-webkit-transform-origin:right top;-ms-transform-origin:right top;transform-origin:right top}.ha-pricing-table-title{margin-top:0;margin-bottom:.5rem;color:#242424;font-weight:400;font-size:24px}.ha-pricing-table-price{margin-bottom:3rem}.ha-pricing-table-price-tag{margin-bottom:.5rem;color:#242424;font-weight:700;font-size:60px;line-height:normal}.ha-pricing-table-currency{font-size:24px}.ha-pricing-table-period{color:#8c8c8c;font-size:16px}.ha-pricing-table-body{margin-bottom:3rem}.ha-pricing-table-features-title{margin-top:0;margin-bottom:1rem;font-weight:700;font-size:16px}.ha-pricing-table-features-list{margin:0;padding:0;list-style:none}.ha-pricing-table-features-list li{margin-bottom:1rem;font-size:16px}.ha-pricing-table-features-list i{margin-right:.5rem;min-width:15px;font-size:.8em}.ha-pricing-table-btn{display:inline-block;padding:.8rem 2rem;border-radius:40px;background-color:#e2498a;color:#fff;text-decoration:none;text-transform:uppercase;font-size:12px;-webkit-transition:all .3s;transition:all .3s}.ha-pricing-table-btn:hover{background-color:#562dd4;color:#fff}.ha-card>.elementor-widget-container,.ha-icon-box>.elementor-widget-container,.ha-image-compare>.elementor-widget-container,.ha-infobox>.elementor-widget-container,.ha-member>.elementor-widget-container,.ha-pricing-table>.elementor-widget-container,.ha-review>.elementor-widget-container{border-radius:.5rem;background-color:#fff;box-shadow:0 .2rem 2.8rem rgba(36,36,36,.1);word-wrap:break-word;overflow-wrap:break-word}.ha-logo-grid-wrapper:after,.ha-logo-grid-wrapper:before{display:table;content:" "}.ha-logo-grid-wrapper:after{clear:both}.ha-step-flow>.elementor-widget-container{padding:30px;text-align:center}.ha-step-arrow,.ha-step-arrow:after{position:absolute;display:inline-block;border-top:1px solid #ddd}.ha-step-arrow{left:calc(100% + 20px);top:49%;width:100px}.ha-step-arrow:after{top:-2px;right:5px;width:12px;height:12px;border-right:1px solid #ddd;color:#ddd;content:"";-webkit-transform:rotate(45deg) translateY(-50%);-ms-transform:rotate(45deg) translateY(-50%);transform:rotate(45deg) translateY(-50%)}.ha-steps-icon{position:relative;display:inline-block;margin-bottom:2rem;padding:40px;border-radius:50%;background-color:#e9ecf0;box-shadow:0 2px 6px -2px #989898;color:#8056ee;text-align:center;font-size:46px}.ha-steps-icon i{position:relative;display:block;width:1em;height:1em}.ha-steps-icon i:before{position:absolute;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-steps-icon .ha-steps-label{position:absolute;top:5px;right:0;padding:12px 8px;border:3px solid #fff;border-radius:20px;background-color:#8056ee;color:#fff;font-size:12px;line-height:0}.ha-steps-title{margin-top:0;margin-bottom:30px;font-weight:700;font-size:16px}.ha-steps-title a{display:block;color:#562dd4}.ha-steps-title a:hover{color:#242424}.ha-step-description{margin:0;color:#616161;font-weight:400;font-size:16px;line-height:1.5}
assets/css/widgets/badge.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .ha-badge{padding:.475rem 1.1rem;border-radius:50px;background-color:#fff;font-size:12px}.ha-badge--top-left{top:1rem;left:1rem}.ha-badge--top-center{top:1rem;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-badge--top-right{top:1rem;right:1rem}.ha-badge--middle-left{top:50%;left:1rem;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.ha-badge--middle-center{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.ha-badge--middle-right{top:50%;right:1rem;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.ha-badge--bottom-left{bottom:1rem;left:1rem}.ha-badge--bottom-center{bottom:1rem;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-badge--bottom-right{right:1rem;bottom:1rem}
assets/css/widgets/card.min.css CHANGED
@@ -1 +1 @@
1
- .ha-card>.elementor-widget-container{border-radius:.5rem;background-color:#fff;box-shadow:0 .2rem 2.8rem rgba(36,36,36,.1);word-wrap:break-word;overflow-wrap:break-word}.ha-card-figure{position:relative;height:250px}.ha-card-figure>img{width:100%;height:100%;border-top-left-radius:calc(.5rem - 1px);border-top-right-radius:calc(.5rem - 1px);vertical-align:bottom}.ha-card-body{padding:1.5rem}.ha-card-title{margin-top:0;margin-bottom:.75rem;color:#151515;font-weight:700;font-size:22px}.ha-card-text{margin-bottom:2rem;color:#616161;font-size:16px;line-height:1.7}.ha-card-text>p{margin-top:0;margin-bottom:0}.ha-card--top .ha-card-figure{display:inline-block;width:100%}.ha-card--left>.elementor-widget-container,.ha-card--right>.elementor-widget-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center}.ha-card--left>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.ha-card--left .ha-card-body,.ha-card--left .ha-card-figure,.ha-card--right .ha-card-body,.ha-card--right .ha-card-figure{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.ha-card--left .ha-card-body,.ha-card--right .ha-card-body{padding:2.5rem}.ha-card--left .ha-card-figure>img{border-radius:calc(.5rem - 1px) 0 0 calc(.5rem - 1px)}.ha-card--right>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;text-align:right}.ha-card--right .ha-card-figure>img{border-radius:0 calc(.5rem - 1px) calc(.5rem - 1px) 0}.ha-card .ha-badge{position:absolute}.ha-badge{padding:.475rem 1.1rem;border-radius:50px;background-color:#fff;font-size:12px}.ha-badge--top-left{top:1rem;left:1rem}.ha-badge--top-center{top:1rem;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-badge--top-right{top:1rem;right:1rem}.ha-badge--middle-left{top:50%;left:1rem;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.ha-badge--middle-center{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.ha-badge--middle-right{top:50%;right:1rem;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.ha-badge--bottom-left{bottom:1rem;left:1rem}.ha-badge--bottom-center{bottom:1rem;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-badge--bottom-right{right:1rem;bottom:1rem}
1
+ .ha-card>.elementor-widget-container{border-radius:.5rem;background-color:#fff;box-shadow:0 .2rem 2.8rem rgba(36,36,36,.1);word-wrap:break-word;overflow-wrap:break-word}.ha-card-figure{position:relative;height:250px}.ha-card-figure>img{width:100%;height:100%;border-top-left-radius:calc(.5rem - 1px);border-top-right-radius:calc(.5rem - 1px);vertical-align:bottom}.ha-card-body{padding:1.5rem}.ha-card-title{margin-top:0;margin-bottom:.75rem;color:#151515;font-weight:700;font-size:22px}.ha-card-text{margin-bottom:2rem;color:#616161;font-size:16px;line-height:1.7}.ha-card-text>p{margin-top:0;margin-bottom:0}.ha-card--top .ha-card-figure{display:inline-block;width:100%}.ha-card--left>.elementor-widget-container,.ha-card--right>.elementor-widget-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center}.ha-card--left>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.ha-card--left .ha-card-body,.ha-card--left .ha-card-figure,.ha-card--right .ha-card-body,.ha-card--right .ha-card-figure{-webkit-box-flex:0;-webkit-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.ha-card--left .ha-card-body,.ha-card--right .ha-card-body{padding:2.5rem}.ha-card--left .ha-card-figure>img{border-radius:calc(.5rem - 1px) 0 0 calc(.5rem - 1px)}.ha-card--right>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;text-align:right}.ha-card--right .ha-card-figure>img{border-radius:0 calc(.5rem - 1px) calc(.5rem - 1px) 0}.ha-card .ha-badge{position:absolute}
assets/css/widgets/common.min.css CHANGED
@@ -1 +1 @@
1
- .happy-addon,.happy-addon *{box-sizing:border-box}.happy-addon img{max-width:100%;height:auto;-o-object-fit:cover;object-fit:cover}.happy-addon p:empty{display:none}
1
+ .happy-addon,.happy-addon *{box-sizing:border-box}.happy-addon img{max-width:100%;height:auto;-o-object-fit:cover;object-fit:cover}.happy-addon p:empty{display:none}.ha-screen-reader-text{position:absolute;overflow:hidden;clip:rect(1px,1px,1px,1px);margin:-1px;padding:0;width:1px;height:1px;border:0;word-wrap:normal!important;-webkit-clip-path:inset(50%);clip-path:inset(50%)}.ha-has-background-overlay>.elementor-widget-container{position:relative;z-index:1}.ha-has-background-overlay>.elementor-widget-container:before{position:absolute;top:0;left:0;z-index:-1;width:100%;height:100%;content:""}
assets/css/widgets/hover-box.min.css DELETED
@@ -1 +0,0 @@
1
- .ha-hover-box{overflow:hidden}.ha-hover-box .ha-hover-box-main{position:relative;overflow:hidden}.ha-hover-box-wrapper,.ha-hover-box-wrapper .ha-hover-box-content{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%}.ha-hover-box-wrapper{overflow:hidden;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;padding:50px;max-height:100%;height:400px;-webkit-transition-duration:.4s;transition-duration:.4s}.ha-hover-box-wrapper:before{position:absolute;top:0;left:0;z-index:1;width:100%;height:100%;content:""}.ha-hover-box-wrapper:hover{-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transform:scale(1.06);-ms-transform:scale(1.06);transform:scale(1.06)}.ha-hover-box-wrapper:hover .ha-hover-box-content{opacity:0;-webkit-transition-delay:0ms;transition-delay:0ms;-webkit-transition-timing-function:cubic-bezier(.57,.21,.69,1);transition-timing-function:cubic-bezier(.57,.21,.69,1);-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transform:translate(0,36px);-ms-transform:translate(0,36px);transform:translate(0,36px)}.ha-hover-box-wrapper .ha-hover-box-content{z-index:99;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;text-align:left;opacity:1;-webkit-transition:opacity .2s ease-in-out,-webkit-transform .2s ease-in-out;transition:opacity .2s ease-in-out,transform .2s ease-in-out;transition:opacity .2s ease-in-out,transform .2s ease-in-out,-webkit-transform .2s ease-in-out;-webkit-transition-delay:.1s;transition-delay:.1s;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.ha-hover-box-wrapper .ha-hover-sub-title{display:inline-block;margin-bottom:20px;color:#222}.ha-hover-box-wrapper .ha-hover-title{margin-top:0;margin-bottom:10px;color:#222}.ha-hover-box-wrapper .ha-hover-description{margin:0;color:#222}.ha-hover-box-wrapper.reverse:hover .ha-hover-box-content{opacity:1;-webkit-transition-delay:.1s;transition-delay:.1s;-webkit-transform:translate(0,-16px);-ms-transform:translate(0,-16px);transform:translate(0,-16px)}.ha-hover-box-wrapper.reverse .ha-hover-box-content{opacity:0;-webkit-transition-delay:0s;transition-delay:0s}.ha-pre--column .ha-hover-sub-title{margin-bottom:20px}.ha-pre--column-reverse p.ha-hover-sub-title{margin-top:20px;margin-bottom:0}
 
assets/css/widgets/image-grid.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .ha-image-grid-item{float:left}.ha-image-grid-inner{position:relative;display:block;overflow:hidden;margin:10px;text-decoration:none}.ha-image-grid-inner img{display:block;width:100%;-webkit-transition:all .25s;transition:all .25s}.ha-image-grid--layout-even .ha-image-grid-inner{height:250px}.ha-image-grid--layout-even .ha-image-grid-inner>img{height:100%}
assets/css/widgets/pricing-table.min.css CHANGED
@@ -1 +1 @@
1
- .ha-pricing-table>.elementor-widget-container{border-radius:.5rem;background-color:#fff;box-shadow:0 .2rem 2.8rem rgba(36,36,36,.1);word-wrap:break-word;overflow-wrap:break-word;position:relative;overflow:hidden;padding:3em 4em}.ha-pricing-table-badge{position:absolute;top:0;padding:.8rem 1rem;background-color:#e2498a;color:#fff;line-height:1}.ha-pricing-table-badge--left{left:0;-webkit-transform:rotate(-90deg) translateX(-100%);-ms-transform:rotate(-90deg) translateX(-100%);transform:rotate(-90deg) translateX(-100%);-webkit-transform-origin:left top;-ms-transform-origin:left top;transform-origin:left top}.ha-pricing-table-badge--right{right:0;-webkit-transform:rotate(-90deg) translateY(-100%);-ms-transform:rotate(-90deg) translateY(-100%);transform:rotate(-90deg) translateY(-100%);-webkit-transform-origin:right top;-ms-transform-origin:right top;transform-origin:right top}.ha-pricing-table-title{margin-top:0;margin-bottom:.5rem;color:#242424;font-weight:400;font-size:24px}.ha-pricing-table-price{margin-bottom:3rem}.ha-pricing-table-price-tag{margin-bottom:.5rem;color:#242424;font-weight:700;font-size:60px;line-height:normal}.ha-pricing-table-currency{font-size:24px}.ha-pricing-table-period{color:#8c8c8c;font-size:16px}.ha-pricing-table-body{margin-bottom:3rem}.ha-pricing-table-features-title{margin-top:0;margin-bottom:1rem;font-weight:700;font-size:16px}.ha-pricing-table-features-list{margin:0;padding:0;list-style:none}.ha-pricing-table-features-list li{margin-bottom:1rem;font-size:16px}.ha-pricing-table-features-list i{margin-right:.5rem;min-width:15px;font-size:.8em}.ha-pricing-table-btn{display:inline-block;padding:.8rem 2rem;border-radius:40px;background-color:#e2498a;color:#fff;text-decoration:none;text-transform:uppercase;font-size:12px;-webkit-transition:all .3s;transition:all .3s}.ha-pricing-table-btn:hover{background-color:#562dd4;color:#fff}
1
+ .ha-pricing-table>.elementor-widget-container{border-radius:.5rem;background-color:#fff;box-shadow:0 .2rem 2.8rem rgba(36,36,36,.1);word-wrap:break-word;overflow-wrap:break-word;position:relative;overflow:hidden;padding:3em 4em}.ha-pricing-table-badge{position:absolute;top:-1px;padding:.8rem 1rem;background-color:#e2498a;color:#fff;line-height:1}.ha-pricing-table-badge--left{left:0;-webkit-transform:rotate(-90deg) translateX(-100%);-ms-transform:rotate(-90deg) translateX(-100%);transform:rotate(-90deg) translateX(-100%);-webkit-transform-origin:left top;-ms-transform-origin:left top;transform-origin:left top}.ha-pricing-table-badge--right{right:0;-webkit-transform:rotate(-90deg) translateY(-100%);-ms-transform:rotate(-90deg) translateY(-100%);transform:rotate(-90deg) translateY(-100%);-webkit-transform-origin:right top;-ms-transform-origin:right top;transform-origin:right top}.ha-pricing-table-title{margin-top:0;margin-bottom:.5rem;color:#242424;font-weight:400;font-size:24px}.ha-pricing-table-price{margin-bottom:3rem}.ha-pricing-table-price-tag{margin-bottom:.5rem;color:#242424;font-weight:700;font-size:60px;line-height:normal}.ha-pricing-table-currency{font-size:24px}.ha-pricing-table-period{color:#8c8c8c;font-size:16px}.ha-pricing-table-body{margin-bottom:3rem}.ha-pricing-table-features-title{margin-top:0;margin-bottom:1rem;font-weight:700;font-size:16px}.ha-pricing-table-features-list{margin:0;padding:0;list-style:none}.ha-pricing-table-features-list li{margin-bottom:1rem;font-size:16px}.ha-pricing-table-features-list i{margin-right:.5rem;min-width:15px;font-size:.8em}.ha-pricing-table-btn{display:inline-block;padding:.8rem 2rem;border-radius:40px;background-color:#e2498a;color:#fff;text-decoration:none;text-transform:uppercase;font-size:12px;-webkit-transition:all .3s;transition:all .3s}.ha-pricing-table-btn:hover{background-color:#562dd4;color:#fff}
assets/css/widgets/review.min.css CHANGED
@@ -1 +1 @@
1
- .ha-review>.elementor-widget-container{border-radius:.5rem;background-color:#fff;box-shadow:0 .2rem 2.8rem rgba(36,36,36,.1);word-wrap:break-word;overflow-wrap:break-word}.ha-review-header{margin-top:1.5rem}.ha-review-desc p,.ha-review-figure{margin:0}.ha-review-figure>img{width:100%;height:100%;border-radius:50%;vertical-align:bottom}.ha-review-reviewer{margin-top:0;margin-bottom:.3rem;color:#151515;font-size:18px}.ha-review-position{margin-bottom:.5rem;color:#7f7f7f;font-size:15px}.ha-review-ratting{display:inline-block;font-size:12px;line-height:1}.ha-review-ratting--num{padding:.25em .66em;border-radius:2.5em;background-color:#287dfe;color:#fff}.ha-review-ratting--star{display:inline-block;color:#ffbf36;font-family:"Fontawesome"}.ha-review-ratting--star>span{position:relative;overflow:hidden;height:1em}.ha-review-ratting--star span>span{position:absolute;top:0;left:0;overflow:hidden;padding-top:1.5em}.ha-review-ratting--star span>span:before,span .ha-review-ratting--star:before{position:absolute;top:0;left:0}.ha-review-ratting--star span:before{content:"\f006\f006\f006\f006\f006"}.ha-review-ratting--star span>span:before{content:"\f005\f005\f005\f005\f005"}.ha-review-desc{margin-top:1.5rem;font-size:16px;line-height:1.6}.ha-review--top>.elementor-widget-container{padding:2rem}.ha-review--top .ha-review-figure{display:inline-block;max-width:70px;height:70px}.ha-review--left>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.ha-review--left>.elementor-widget-container,.ha-review--right>.elementor-widget-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;padding-left:2rem}.ha-review--left .ha-review-figure,.ha-review--right .ha-review-figure{-webkit-box-flex:0;-webkit-flex:0 0 150px;-ms-flex:0 0 150px;flex:0 0 150px;max-width:150px;height:150px}.ha-review--left .ha-review-body,.ha-review--right .ha-review-body{-webkit-box-flex:0;-webkit-flex:0 0 calc(100% - 150px);-ms-flex:0 0 calc(100% - 150px);flex:0 0 calc(100% - 150px);padding:2rem;max-width:calc(100% - 150px)}.ha-review--left .ha-review-body>:first-child,.ha-review--right .ha-review-body>:first-child{margin-top:0}.ha-review--right>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;padding-right:2rem;padding-left:0;text-align:right}
1
+ .ha-review>.elementor-widget-container{border-radius:.5rem;background-color:#fff;box-shadow:0 .2rem 2.8rem rgba(36,36,36,.1);word-wrap:break-word;overflow-wrap:break-word}.ha-review-header{margin-top:1.5rem}.ha-review-desc p,.ha-review-figure{margin:0}.ha-review-figure>img{width:100%;height:100%;border-radius:50%;vertical-align:bottom}.ha-review-reviewer{margin-top:0;margin-bottom:.3rem;color:#151515;font-size:18px}.ha-review-position{margin-bottom:.5rem;color:#7f7f7f;font-size:15px}.ha-review-ratting{display:inline-block;font-size:12px;line-height:1}.ha-review-ratting--num{padding:.25em .66em;border-radius:2.5em;background-color:#562dd4;color:#fff}.ha-review-ratting--star{color:#ffbf36}.ha-review-desc{margin-top:1.5rem;font-size:16px;line-height:1.6}.ha-review--top>.elementor-widget-container{padding:2rem}.ha-review--top .ha-review-figure{display:inline-block;max-width:70px;height:70px}.ha-review--left>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}.ha-review--left>.elementor-widget-container,.ha-review--right>.elementor-widget-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-ms-flex-align:center;padding-left:2rem}.ha-review--left .ha-review-figure,.ha-review--right .ha-review-figure{-webkit-box-flex:0;-webkit-flex:0 0 150px;-ms-flex:0 0 150px;flex:0 0 150px;max-width:150px;height:150px}.ha-review--left .ha-review-body,.ha-review--right .ha-review-body{-webkit-box-flex:0;-webkit-flex:0 0 calc(100% - 150px);-ms-flex:0 0 calc(100% - 150px);flex:0 0 calc(100% - 150px);padding:2rem;max-width:calc(100% - 150px)}.ha-review--left .ha-review-body>:first-child,.ha-review--right .ha-review-body>:first-child{margin-top:0}.ha-review--right>.elementor-widget-container{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-webkit-flex-direction:row-reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;padding-right:2rem;padding-left:0;text-align:right}
assets/css/widgets/steps-flow.min.css CHANGED
@@ -1 +1 @@
1
- .ha-step-flow>.elementor-widget-container{padding:30px;text-align:center}.ha-step-arrow{position:absolute;top:49%;left:calc(100% + 50px);display:inline-block;width:100px;border-top:1px dashed #ddd}.ha-step-arrow:after{position:absolute;right:-6px;height:1.5em;color:#ddd;content:"\e90b";font-size:18px;font-family:"Happy Icons"!important;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)}.ha-steps-icon{position:relative;display:inline-block;margin-bottom:2rem;padding:40px;border-radius:50%;background-color:#f1f4f8;color:#242424;text-align:center;font-size:46px}.ha-steps-icon i{position:relative;display:block;width:1em;height:1em}.ha-steps-icon i:before{position:absolute;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-steps-icon .ha-steps-label{position:absolute;top:5px;right:0;padding:10px 12px;border:3px solid #fff;border-radius:20px;background-color:#e2498a;color:#fff;font-size:12px;line-height:0}.ha-steps-title{margin-top:0;margin-bottom:30px;font-weight:700;font-size:16px}.ha-steps-title a{display:block;color:#562dd4}.ha-steps-title a:hover{color:#242424}.ha-step-description{margin:0;color:#616161;font-weight:400;font-size:16px;line-height:1.5}
1
+ .ha-step-flow>.elementor-widget-container{padding:30px;text-align:center}.ha-step-arrow,.ha-step-arrow:after{position:absolute;display:inline-block;border-top:1px solid #ddd}.ha-step-arrow{left:calc(100% + 20px);top:49%;width:100px}.ha-step-arrow:after{top:-2px;right:5px;width:12px;height:12px;border-right:1px solid #ddd;color:#ddd;content:"";-webkit-transform:rotate(45deg) translateY(-50%);-ms-transform:rotate(45deg) translateY(-50%);transform:rotate(45deg) translateY(-50%)}.ha-steps-icon{position:relative;display:inline-block;margin-bottom:2rem;padding:40px;border-radius:50%;background-color:#e9ecf0;box-shadow:0 2px 6px -2px #989898;color:#8056ee;text-align:center;font-size:46px}.ha-steps-icon i{position:relative;display:block;width:1em;height:1em}.ha-steps-icon i:before{position:absolute;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.ha-steps-icon .ha-steps-label{position:absolute;top:5px;right:0;padding:12px 8px;border:3px solid #fff;border-radius:20px;background-color:#8056ee;color:#fff;font-size:12px;line-height:0}.ha-steps-title{margin-top:0;margin-bottom:30px;font-weight:700;font-size:16px}.ha-steps-title a{display:block;color:#562dd4}.ha-steps-title a:hover{color:#242424}.ha-step-description{margin:0;color:#616161;font-weight:400;font-size:16px;line-height:1.5}
assets/fonts/happy-icons.js ADDED
@@ -0,0 +1,403 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "icons" : [
3
+ "3d-rotate",
4
+ "degree",
5
+ "accordion-horizontal",
6
+ "accordion-vertical",
7
+ "alarm-clock",
8
+ "alien-gun",
9
+ "alien",
10
+ "anchor",
11
+ "android",
12
+ "angle-down",
13
+ "angle-left",
14
+ "angle-right",
15
+ "angle-up",
16
+ "apple",
17
+ "arrow-left",
18
+ "arrow-right",
19
+ "arrow-zoom-out",
20
+ "arrow-corner",
21
+ "arrow-down",
22
+ "arrow-left1",
23
+ "arrow-right1",
24
+ "arrow-up",
25
+ "article",
26
+ "avatar-man",
27
+ "avatar-woman",
28
+ "badge1",
29
+ "badge2",
30
+ "badge3",
31
+ "bamboo",
32
+ "basketball",
33
+ "battery",
34
+ "beach-seat",
35
+ "bell",
36
+ "bicycle",
37
+ "blog-content",
38
+ "bluetooth",
39
+ "board",
40
+ "body",
41
+ "bomb",
42
+ "bond-hand",
43
+ "bond",
44
+ "bonsai",
45
+ "book",
46
+ "bowl",
47
+ "brick-wall",
48
+ "brush-paint",
49
+ "brush-roll",
50
+ "brush",
51
+ "bug",
52
+ "bulb",
53
+ "calculation",
54
+ "calendar",
55
+ "camera",
56
+ "candle",
57
+ "candles",
58
+ "car",
59
+ "card",
60
+ "caret-down",
61
+ "caret-fill-down",
62
+ "caret-fill-left",
63
+ "caret-fill-right",
64
+ "caret-fill-up",
65
+ "caret-left",
66
+ "caret-right",
67
+ "caret-up",
68
+ "carousal",
69
+ "cart-empty",
70
+ "cart-full",
71
+ "caution",
72
+ "chair",
73
+ "chair2",
74
+ "chat-bubble-single",
75
+ "chat-bubble",
76
+ "cheese",
77
+ "chef-cap",
78
+ "clip-board",
79
+ "clip",
80
+ "cloud-down",
81
+ "cloud-up",
82
+ "cloud",
83
+ "code-browser",
84
+ "code-clean",
85
+ "code",
86
+ "cog",
87
+ "color-card",
88
+ "color-plate",
89
+ "compass-math",
90
+ "compass",
91
+ "corner",
92
+ "crop",
93
+ "cross-circle",
94
+ "cross-game",
95
+ "cross-gap",
96
+ "cross",
97
+ "crown",
98
+ "cube",
99
+ "cup-coffee",
100
+ "cup",
101
+ "currency-paper",
102
+ "dashboard",
103
+ "delivery-van",
104
+ "diamond-ring",
105
+ "direction-both",
106
+ "direction-right",
107
+ "disable-person",
108
+ "disc",
109
+ "dislike",
110
+ "dollar-on-hand",
111
+ "door-path",
112
+ "Download-circle",
113
+ "download",
114
+ "drag-inside",
115
+ "drag-outside",
116
+ "drag",
117
+ "drawer",
118
+ "dribbble",
119
+ "dropper",
120
+ "egg-fry",
121
+ "ellipsis-fill-h",
122
+ "ellipsis-fill-v",
123
+ "ellipsis-horizontal",
124
+ "ellipsis-vertical",
125
+ "emo-normal",
126
+ "emo-sad",
127
+ "emo-smile",
128
+ "envelop",
129
+ "facebook",
130
+ "fancy-futton",
131
+ "feeder",
132
+ "file-cabinet",
133
+ "file-rotate",
134
+ "file",
135
+ "files",
136
+ "film-roll",
137
+ "film",
138
+ "finger-index",
139
+ "finger-print",
140
+ "fire-flame",
141
+ "flag",
142
+ "flip-card1",
143
+ "flip-card2",
144
+ "folder-network",
145
+ "folder",
146
+ "football",
147
+ "footer",
148
+ "form",
149
+ "forward",
150
+ "fountain-pen",
151
+ "gender-female",
152
+ "gender-male",
153
+ "gender-sign",
154
+ "gender",
155
+ "ghost",
156
+ "gift-box",
157
+ "globe1",
158
+ "globe2",
159
+ "globe3",
160
+ "globe4",
161
+ "google",
162
+ "graduate-cap",
163
+ "graph-bar",
164
+ "graph-pie",
165
+ "graph",
166
+ "grid-even",
167
+ "grid-masonry",
168
+ "grid-twist",
169
+ "grid",
170
+ "group",
171
+ "hand-mike",
172
+ "hand-watch",
173
+ "hand",
174
+ "header",
175
+ "headphone",
176
+ "headset",
177
+ "heart-beat",
178
+ "hexa",
179
+ "highlighter",
180
+ "home",
181
+ "hot-spot",
182
+ "hotdog",
183
+ "ice-cream",
184
+ "icon-box",
185
+ "imac",
186
+ "image-compare",
187
+ "image-slider",
188
+ "image",
189
+ "inbox",
190
+ "infinity",
191
+ "info",
192
+ "injection",
193
+ "instagram",
194
+ "jar-chemical",
195
+ "key",
196
+ "language-change",
197
+ "laptop",
198
+ "layer",
199
+ "lens",
200
+ "like",
201
+ "line-graph-pointed",
202
+ "link",
203
+ "linkedin",
204
+ "linux",
205
+ "list-2",
206
+ "list-group",
207
+ "list",
208
+ "location-pointer",
209
+ "lock",
210
+ "logo-carousel",
211
+ "logo-grid",
212
+ "lotus",
213
+ "love",
214
+ "madel",
215
+ "magic-wand",
216
+ "magnet",
217
+ "mail-open",
218
+ "man-range",
219
+ "map-marker",
220
+ "map-pointer",
221
+ "measurement",
222
+ "memory",
223
+ "menu-price",
224
+ "micro-chip",
225
+ "microphone1",
226
+ "microphone2",
227
+ "mobile",
228
+ "money-bag",
229
+ "money",
230
+ "monitor",
231
+ "mouse",
232
+ "muscle",
233
+ "net",
234
+ "network1",
235
+ "network2",
236
+ "newspaper",
237
+ "nuclear-circle",
238
+ "office-file",
239
+ "pacman",
240
+ "paper-fold",
241
+ "paper-plane-alt",
242
+ "paper-plane",
243
+ "pause",
244
+ "pen-head",
245
+ "pen-pencil",
246
+ "pen-scale",
247
+ "pen-paper",
248
+ "pen",
249
+ "pencil",
250
+ "pendrive",
251
+ "phone",
252
+ "pillar",
253
+ "pin-man-range",
254
+ "pin-man",
255
+ "pin",
256
+ "plane",
257
+ "play-end",
258
+ "play-next",
259
+ "play-previous",
260
+ "play-start",
261
+ "play-button",
262
+ "play-store",
263
+ "play",
264
+ "playing-card",
265
+ "plus-box",
266
+ "plus-circle",
267
+ "plus-gap",
268
+ "plus-open",
269
+ "popup",
270
+ "power",
271
+ "printer",
272
+ "progress-bar",
273
+ "promo",
274
+ "pulse",
275
+ "puzzle",
276
+ "question",
277
+ "quote",
278
+ "radar",
279
+ "radiation",
280
+ "reading-glass-alt",
281
+ "reading-glass",
282
+ "recycle-bin",
283
+ "recycle",
284
+ "refresh-time",
285
+ "reply",
286
+ "responsive-device",
287
+ "review",
288
+ "rocket1",
289
+ "rocket2",
290
+ "rss",
291
+ "safety-cap",
292
+ "safety-kit",
293
+ "sand-watch",
294
+ "scale",
295
+ "scanner",
296
+ "scissor",
297
+ "screen",
298
+ "search",
299
+ "seo",
300
+ "server-network",
301
+ "server",
302
+ "share",
303
+ "shield",
304
+ "ship",
305
+ "shirt",
306
+ "shopping-bag1",
307
+ "shopping-bag2",
308
+ "shopping-bag3",
309
+ "shopping-bag4",
310
+ "shuffle",
311
+ "shutter",
312
+ "sign-in",
313
+ "sign-out",
314
+ "sitemap1",
315
+ "sitemap2",
316
+ "skart",
317
+ "skull",
318
+ "skyscraper",
319
+ "slider-doc",
320
+ "slider-h-range",
321
+ "slider-image",
322
+ "slider-range-h",
323
+ "slider-v-open",
324
+ "slider-video",
325
+ "slider",
326
+ "smart-watch",
327
+ "snow",
328
+ "spa-face",
329
+ "spa-stone-flower",
330
+ "spa-stone",
331
+ "spark",
332
+ "speaker-off",
333
+ "speaker-on",
334
+ "spoon-fork",
335
+ "spoon",
336
+ "star",
337
+ "step-flow",
338
+ "steps",
339
+ "stop-watch",
340
+ "stop",
341
+ "support-call",
342
+ "tab",
343
+ "table-lamp",
344
+ "tablet",
345
+ "tag",
346
+ "target-arrow",
347
+ "target",
348
+ "target1",
349
+ "team-carousel",
350
+ "team-member",
351
+ "tennis-ball",
352
+ "terminal",
353
+ "testimonial-carousel",
354
+ "testimonial",
355
+ "text-animation",
356
+ "theatre",
357
+ "tick-circle",
358
+ "tick",
359
+ "tickets",
360
+ "tie-knot",
361
+ "tie",
362
+ "timeline",
363
+ "toggle",
364
+ "tools",
365
+ "tree-square",
366
+ "twitter-bird",
367
+ "twitter",
368
+ "ufo",
369
+ "umbralla",
370
+ "unlock",
371
+ "up-down",
372
+ "upload",
373
+ "upward-top-right",
374
+ "user-female",
375
+ "user-id",
376
+ "user-male",
377
+ "video-camera",
378
+ "water-drop",
379
+ "weather-cloud-day",
380
+ "weather-cloud",
381
+ "weather-day-rain",
382
+ "weather-day-snow",
383
+ "weather-day-windy-rain",
384
+ "weather-flood",
385
+ "weather-night-cloud",
386
+ "weather-rain-alt",
387
+ "weather-rain",
388
+ "weather-snow",
389
+ "weather-sun-rain",
390
+ "weather-sun",
391
+ "weather-sunny-day",
392
+ "weather-thunder",
393
+ "weather-windy-rain",
394
+ "webcam1",
395
+ "webcam2",
396
+ "weight-scale",
397
+ "windows",
398
+ "wine-glass2",
399
+ "wine-glass",
400
+ "worker-cap",
401
+ "youtube"
402
+ ]
403
+ }
assets/fonts/style.css CHANGED
@@ -9,7 +9,8 @@
9
  font-style: normal;
10
  }
11
 
12
- .hm {
 
13
  /* use !important to prevent issues with browser extensions that change fonts */
14
  font-family: 'Happy Icons' !important;
15
  speak: none;
9
  font-style: normal;
10
  }
11
 
12
+ .hm,
13
+ .fashm {
14
  /* use !important to prevent issues with browser extensions that change fonts */
15
  font-family: 'Happy Icons' !important;
16
  speak: none;
assets/fonts/style.min.css CHANGED
@@ -1 +1 @@
1
- @font-face{font-family:'Happy Icons';src:url(Happy-Addons-Icon.eot?vf4zr6);src:url(Happy-Addons-Icon.eot?vf4zr6#iefix) format('embedded-opentype'),url(Happy-Addons-Icon.ttf?vf4zr6) format('truetype'),url(Happy-Addons-Icon.woff?vf4zr6) format('woff'),url(Happy-Addons-Icon.svg?vf4zr6#Happy-Addons-Icon) format('svg');font-weight:400;font-style:normal}.hm{font-family:'Happy Icons'!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.hm-3d-rotate:before{content:"\e900"}.hm-degree:before{content:"\e901"}.hm-accordion-horizontal:before{content:"\e902"}.hm-accordion-vertical:before{content:"\e903"}.hm-alarm-clock:before{content:"\e904"}.hm-alien-gun:before{content:"\e905"}.hm-alien:before{content:"\e906"}.hm-anchor:before{content:"\e907"}.hm-android:before{content:"\e908"}.hm-angle-down:before{content:"\e909"}.hm-angle-left:before{content:"\e90a"}.hm-angle-right:before{content:"\e90b"}.hm-angle-up:before{content:"\e90c"}.hm-apple:before{content:"\e90d"}.hm-arrow-left:before{content:"\e90e"}.hm-arrow-right:before{content:"\e90f"}.hm-arrow-zoom-out:before{content:"\e910"}.hm-arrow-corner:before{content:"\e911"}.hm-arrow-down:before{content:"\e912"}.hm-arrow-left1:before{content:"\e913"}.hm-arrow-right1:before{content:"\e914"}.hm-arrow-up:before{content:"\e915"}.hm-article:before{content:"\e916"}.hm-avatar-man:before{content:"\e917"}.hm-avatar-woman:before{content:"\e918"}.hm-badge1:before{content:"\e919"}.hm-badge2:before{content:"\e91a"}.hm-badge3:before{content:"\e91b"}.hm-bamboo:before{content:"\e91c"}.hm-basketball:before{content:"\e91d"}.hm-battery:before{content:"\e91e"}.hm-beach-seat:before{content:"\e91f"}.hm-bell:before{content:"\e920"}.hm-bicycle:before{content:"\e921"}.hm-blog-content:before{content:"\e922"}.hm-bluetooth:before{content:"\e923"}.hm-board:before{content:"\e924"}.hm-body:before{content:"\e925"}.hm-bomb:before{content:"\e926"}.hm-bond-hand:before{content:"\e927"}.hm-bond:before{content:"\e928"}.hm-bonsai:before{content:"\e929"}.hm-book:before{content:"\e92a"}.hm-bowl:before{content:"\e92b"}.hm-brick-wall:before{content:"\e92c"}.hm-brush-paint:before{content:"\e92d"}.hm-brush-roll:before{content:"\e92e"}.hm-brush:before{content:"\e92f"}.hm-bug:before{content:"\e930"}.hm-bulb:before{content:"\e931"}.hm-calculation:before{content:"\e932"}.hm-calendar:before{content:"\e933"}.hm-camera:before{content:"\e934"}.hm-candle:before{content:"\e935"}.hm-candles:before{content:"\e936"}.hm-car:before{content:"\e937"}.hm-card:before{content:"\e938"}.hm-caret-down:before{content:"\e939"}.hm-caret-fill-down:before{content:"\e93a"}.hm-caret-fill-left:before{content:"\e93b"}.hm-caret-fill-right:before{content:"\e93c"}.hm-caret-fill-up:before{content:"\e93d"}.hm-caret-left:before{content:"\e93e"}.hm-caret-right:before{content:"\e93f"}.hm-caret-up:before{content:"\e940"}.hm-carousal:before{content:"\e941"}.hm-cart-empty:before{content:"\e942"}.hm-cart-full:before{content:"\e943"}.hm-caution:before{content:"\e944"}.hm-chair:before{content:"\e945"}.hm-chair2:before{content:"\e946"}.hm-chat-bubble-single:before{content:"\e947"}.hm-chat-bubble:before{content:"\e948"}.hm-cheese:before{content:"\e949"}.hm-chef-cap:before{content:"\e94a"}.hm-clip-board:before{content:"\e94b"}.hm-clip:before{content:"\e94c"}.hm-cloud-down:before{content:"\e94d"}.hm-cloud-up:before{content:"\e94e"}.hm-cloud:before{content:"\e94f"}.hm-code-browser:before{content:"\e950"}.hm-code-clean:before{content:"\e951"}.hm-code:before{content:"\e952"}.hm-cog:before{content:"\e953"}.hm-color-card:before{content:"\e954"}.hm-color-plate:before{content:"\e955"}.hm-compass-math:before{content:"\e956"}.hm-compass:before{content:"\e957"}.hm-corner:before{content:"\e958"}.hm-crop:before{content:"\e959"}.hm-cross-circle:before{content:"\e95a"}.hm-cross-game:before{content:"\e95b"}.hm-cross-gap:before{content:"\e95c"}.hm-cross:before{content:"\e95d"}.hm-crown:before{content:"\e95e"}.hm-cube:before{content:"\e95f"}.hm-cup-coffee:before{content:"\e960"}.hm-cup:before{content:"\e961"}.hm-currency-paper:before{content:"\e962"}.hm-dashboard:before{content:"\e963"}.hm-delivery-van:before{content:"\e964"}.hm-diamond-ring:before{content:"\e965"}.hm-direction-both:before{content:"\e966"}.hm-direction-right:before{content:"\e967"}.hm-disable-person:before{content:"\e968"}.hm-disc:before{content:"\e969"}.hm-dislike:before{content:"\e96a"}.hm-dollar-on-hand:before{content:"\e96b"}.hm-door-path:before{content:"\e96c"}.hm-Download-circle:before{content:"\e96d"}.hm-download:before{content:"\e96e"}.hm-drag-inside:before{content:"\e96f"}.hm-drag-outside:before{content:"\e970"}.hm-drag:before{content:"\e971"}.hm-drawer:before{content:"\e972"}.hm-dribbble:before{content:"\e973"}.hm-dropper:before{content:"\e974"}.hm-egg-fry:before{content:"\e975"}.hm-ellipsis-fill-h:before{content:"\e976"}.hm-ellipsis-fill-v:before{content:"\e977"}.hm-ellipsis-horizontal:before{content:"\e978"}.hm-ellipsis-vertical:before{content:"\e979"}.hm-emo-normal:before{content:"\e97a"}.hm-emo-sad:before{content:"\e97b"}.hm-emo-smile:before{content:"\e97c"}.hm-envelop:before{content:"\e97d"}.hm-facebook:before{content:"\e97e"}.hm-fancy-futton:before{content:"\e97f"}.hm-feeder:before{content:"\e980"}.hm-file-cabinet:before{content:"\e981"}.hm-file-rotate:before{content:"\e982"}.hm-file:before{content:"\e983"}.hm-files:before{content:"\e984"}.hm-film-roll:before{content:"\e985"}.hm-film:before{content:"\e986"}.hm-finger-index:before{content:"\e987"}.hm-finger-print:before{content:"\e988"}.hm-fire-flame:before{content:"\e989"}.hm-flag:before{content:"\e98a"}.hm-flip-card1:before{content:"\e98b"}.hm-flip-card2:before{content:"\e98c"}.hm-folder-network:before{content:"\e98d"}.hm-folder:before{content:"\e98e"}.hm-football:before{content:"\e98f"}.hm-footer:before{content:"\e990"}.hm-form:before{content:"\e991"}.hm-forward:before{content:"\e992"}.hm-fountain-pen:before{content:"\e993"}.hm-gender-female:before{content:"\e994"}.hm-gender-male:before{content:"\e995"}.hm-gender-sign:before{content:"\e996"}.hm-gender:before{content:"\e997"}.hm-ghost:before{content:"\e998"}.hm-gift-box:before{content:"\e999"}.hm-globe1:before{content:"\e99a"}.hm-globe2:before{content:"\e99b"}.hm-globe3:before{content:"\e99c"}.hm-globe4:before{content:"\e99d"}.hm-google:before{content:"\e99e"}.hm-graduate-cap:before{content:"\e99f"}.hm-graph-bar:before{content:"\e9a0"}.hm-graph-pie:before{content:"\e9a1"}.hm-graph:before{content:"\e9a2"}.hm-grid-even:before{content:"\e9a3"}.hm-grid-masonry:before{content:"\e9a4"}.hm-grid-twist:before{content:"\e9a5"}.hm-grid:before{content:"\e9a6"}.hm-group:before{content:"\e9a7"}.hm-hand-mike:before{content:"\e9a8"}.hm-hand-watch:before{content:"\e9a9"}.hm-hand:before{content:"\e9aa"}.hm-header:before{content:"\e9ab"}.hm-headphone:before{content:"\e9ac"}.hm-headset:before{content:"\e9ad"}.hm-heart-beat:before{content:"\e9ae"}.hm-hexa:before{content:"\e9af"}.hm-highlighter:before{content:"\e9b0"}.hm-home:before{content:"\e9b1"}.hm-hot-spot:before{content:"\e9b2"}.hm-hotdog:before{content:"\e9b3"}.hm-ice-cream:before{content:"\e9b4"}.hm-icon-box:before{content:"\e9b5"}.hm-imac:before{content:"\e9b6"}.hm-image-compare:before{content:"\e9b7"}.hm-image-slider:before{content:"\e9b8"}.hm-image:before{content:"\e9b9"}.hm-inbox:before{content:"\e9ba"}.hm-infinity:before{content:"\e9bb"}.hm-info:before{content:"\e9bc"}.hm-injection:before{content:"\e9bd"}.hm-instagram:before{content:"\e9be"}.hm-jar-chemical:before{content:"\e9bf"}.hm-key:before{content:"\e9c0"}.hm-language-change:before{content:"\e9c1"}.hm-laptop:before{content:"\e9c2"}.hm-layer:before{content:"\e9c3"}.hm-lens:before{content:"\e9c4"}.hm-like:before{content:"\e9c5"}.hm-line-graph-pointed:before{content:"\e9c6"}.hm-link:before{content:"\e9c7"}.hm-linkedin:before{content:"\e9c8"}.hm-linux:before{content:"\e9c9"}.hm-list-2:before{content:"\e9ca"}.hm-list-group:before{content:"\e9cb"}.hm-list:before{content:"\e9cc"}.hm-location-pointer:before{content:"\e9cd"}.hm-lock:before{content:"\e9ce"}.hm-logo-carousel:before{content:"\e9cf"}.hm-logo-grid:before{content:"\e9d0"}.hm-lotus:before{content:"\e9d1"}.hm-love:before{content:"\e9d2"}.hm-madel:before{content:"\e9d3"}.hm-magic-wand:before{content:"\e9d4"}.hm-magnet:before{content:"\e9d5"}.hm-mail-open:before{content:"\e9d6"}.hm-man-range:before{content:"\e9d7"}.hm-map-marker:before{content:"\e9d8"}.hm-map-pointer:before{content:"\e9d9"}.hm-measurement:before{content:"\e9da"}.hm-memory:before{content:"\e9db"}.hm-menu-price:before{content:"\e9dc"}.hm-micro-chip:before{content:"\e9dd"}.hm-microphone1:before{content:"\e9de"}.hm-microphone2:before{content:"\e9df"}.hm-mobile:before{content:"\e9e0"}.hm-money-bag:before{content:"\e9e1"}.hm-money:before{content:"\e9e2"}.hm-monitor:before{content:"\e9e3"}.hm-mouse:before{content:"\e9e4"}.hm-muscle:before{content:"\e9e5"}.hm-net:before{content:"\e9e6"}.hm-network1:before{content:"\e9e7"}.hm-network2:before{content:"\e9e8"}.hm-newspaper:before{content:"\e9e9"}.hm-nuclear-circle:before{content:"\e9ea"}.hm-office-file:before{content:"\e9eb"}.hm-pacman:before{content:"\e9ec"}.hm-paper-fold:before{content:"\e9ed"}.hm-paper-plane-alt:before{content:"\e9ee"}.hm-paper-plane:before{content:"\e9ef"}.hm-pause:before{content:"\e9f0"}.hm-pen-head:before{content:"\e9f1"}.hm-pen-pencil:before{content:"\e9f2"}.hm-pen-scale:before{content:"\e9f3"}.hm-pen-paper:before{content:"\e9f4"}.hm-pen:before{content:"\e9f5"}.hm-pencil:before{content:"\e9f6"}.hm-pendrive:before{content:"\e9f7"}.hm-phone:before{content:"\e9f8"}.hm-pillar:before{content:"\e9f9"}.hm-pin-man-range:before{content:"\e9fa"}.hm-pin-man:before{content:"\e9fb"}.hm-pin:before{content:"\e9fc"}.hm-plane:before{content:"\e9fd"}.hm-play-end:before{content:"\e9fe"}.hm-play-next:before{content:"\e9ff"}.hm-play-previous:before{content:"\ea00"}.hm-play-start:before{content:"\ea01"}.hm-play-button:before{content:"\ea02"}.hm-play-store:before{content:"\ea03"}.hm-play:before{content:"\ea04"}.hm-playing-card:before{content:"\ea05"}.hm-plus-box:before{content:"\ea06"}.hm-plus-circle:before{content:"\ea07"}.hm-plus-gap:before{content:"\ea08"}.hm-plus-open:before{content:"\ea09"}.hm-popup:before{content:"\ea0a"}.hm-power:before{content:"\ea0b"}.hm-printer:before{content:"\ea0c"}.hm-progress-bar:before{content:"\ea0d"}.hm-promo:before{content:"\ea0e"}.hm-pulse:before{content:"\ea0f"}.hm-puzzle:before{content:"\ea10"}.hm-question:before{content:"\ea11"}.hm-quote:before{content:"\ea12"}.hm-radar:before{content:"\ea13"}.hm-radiation:before{content:"\ea14"}.hm-reading-glass-alt:before{content:"\ea15"}.hm-reading-glass:before{content:"\ea16"}.hm-recycle-bin:before{content:"\ea17"}.hm-recycle:before{content:"\ea18"}.hm-refresh-time:before{content:"\ea19"}.hm-reply:before{content:"\ea1a"}.hm-responsive-device:before{content:"\ea1b"}.hm-review:before{content:"\ea1c"}.hm-rocket1:before{content:"\ea1d"}.hm-rocket2:before{content:"\ea1e"}.hm-rss:before{content:"\ea1f"}.hm-safety-cap:before{content:"\ea20"}.hm-safety-kit:before{content:"\ea21"}.hm-sand-watch:before{content:"\ea22"}.hm-scale:before{content:"\ea23"}.hm-scanner:before{content:"\ea24"}.hm-scissor:before{content:"\ea25"}.hm-screen:before{content:"\ea26"}.hm-search:before{content:"\ea27"}.hm-seo:before{content:"\ea28"}.hm-server-network:before{content:"\ea29"}.hm-server:before{content:"\ea2a"}.hm-share:before{content:"\ea2b"}.hm-shield:before{content:"\ea2c"}.hm-ship:before{content:"\ea2d"}.hm-shirt:before{content:"\ea2e"}.hm-shopping-bag1:before{content:"\ea2f"}.hm-shopping-bag2:before{content:"\ea30"}.hm-shopping-bag3:before{content:"\ea31"}.hm-shopping-bag4:before{content:"\ea32"}.hm-shuffle:before{content:"\ea33"}.hm-shutter:before{content:"\ea34"}.hm-sign-in:before{content:"\ea35"}.hm-sign-out:before{content:"\ea36"}.hm-sitemap1:before{content:"\ea37"}.hm-sitemap2:before{content:"\ea38"}.hm-skart:before{content:"\ea39"}.hm-skull:before{content:"\ea3a"}.hm-skyscraper:before{content:"\ea3b"}.hm-slider-doc:before{content:"\ea3c"}.hm-slider-h-range:before{content:"\ea3d"}.hm-slider-image:before{content:"\ea3e"}.hm-slider-range-h:before{content:"\ea3f"}.hm-slider-v-open:before{content:"\ea40"}.hm-slider-video:before{content:"\ea41"}.hm-slider:before{content:"\ea42"}.hm-smart-watch:before{content:"\ea43"}.hm-snow:before{content:"\ea44"}.hm-spa-face:before{content:"\ea45"}.hm-spa-stone-flower:before{content:"\ea46"}.hm-spa-stone:before{content:"\ea47"}.hm-spark:before{content:"\ea48"}.hm-speaker-off:before{content:"\ea49"}.hm-speaker-on:before{content:"\ea4a"}.hm-spoon-fork:before{content:"\ea4b"}.hm-spoon:before{content:"\ea4c"}.hm-star:before{content:"\ea4d"}.hm-step-flow:before{content:"\ea4e"}.hm-steps:before{content:"\ea4f"}.hm-stop-watch:before{content:"\ea50"}.hm-stop:before{content:"\ea51"}.hm-support-call:before{content:"\ea52"}.hm-tab:before{content:"\ea53"}.hm-table-lamp:before{content:"\ea54"}.hm-tablet:before{content:"\ea55"}.hm-tag:before{content:"\ea56"}.hm-target-arrow:before{content:"\ea57"}.hm-target:before{content:"\ea58"}.hm-target1:before{content:"\ea59"}.hm-team-carousel:before{content:"\ea5a"}.hm-team-member:before{content:"\ea5b"}.hm-tennis-ball:before{content:"\ea5c"}.hm-terminal:before{content:"\ea5d"}.hm-testimonial-carousel:before{content:"\ea5e"}.hm-testimonial:before{content:"\ea5f"}.hm-text-animation:before{content:"\ea60"}.hm-theatre:before{content:"\ea61"}.hm-tick-circle:before{content:"\ea62"}.hm-tick:before{content:"\ea63"}.hm-tickets:before{content:"\ea64"}.hm-tie-knot:before{content:"\ea65"}.hm-tie:before{content:"\ea66"}.hm-timeline:before{content:"\ea67"}.hm-toggle:before{content:"\ea68"}.hm-tools:before{content:"\ea69"}.hm-tree-square:before{content:"\ea6a"}.hm-twitter-bird:before{content:"\ea6b"}.hm-twitter:before{content:"\ea6c"}.hm-ufo:before{content:"\ea6d"}.hm-umbralla:before{content:"\ea6e"}.hm-unlock:before{content:"\ea6f"}.hm-up-down:before{content:"\ea70"}.hm-upload:before{content:"\ea71"}.hm-upward-top-right:before{content:"\ea72"}.hm-user-female:before{content:"\ea73"}.hm-user-id:before{content:"\ea74"}.hm-user-male:before{content:"\ea75"}.hm-video-camera:before{content:"\ea76"}.hm-water-drop:before{content:"\ea77"}.hm-weather-cloud-day:before{content:"\ea78"}.hm-weather-cloud:before{content:"\ea79"}.hm-weather-day-rain:before{content:"\ea7a"}.hm-weather-day-snow:before{content:"\ea7b"}.hm-weather-day-windy-rain:before{content:"\ea7c"}.hm-weather-flood:before{content:"\ea7d"}.hm-weather-night-cloud:before{content:"\ea7e"}.hm-weather-rain-alt:before{content:"\ea7f"}.hm-weather-rain:before{content:"\ea80"}.hm-weather-snow:before{content:"\ea81"}.hm-weather-sun-rain:before{content:"\ea82"}.hm-weather-sun:before{content:"\ea83"}.hm-weather-sunny-day:before{content:"\ea84"}.hm-weather-thunder:before{content:"\ea85"}.hm-weather-windy-rain:before{content:"\ea86"}.hm-webcam1:before{content:"\ea87"}.hm-webcam2:before{content:"\ea88"}.hm-weight-scale:before{content:"\ea89"}.hm-windows:before{content:"\ea8a"}.hm-wine-glass2:before{content:"\ea8b"}.hm-wine-glass:before{content:"\ea8c"}.hm-worker-cap:before{content:"\ea8d"}.hm-youtube:before{content:"\ea8e"}
1
+ @font-face{font-family:'Happy Icons';src:url(Happy-Addons-Icon.eot?vf4zr6);src:url(Happy-Addons-Icon.eot?vf4zr6#iefix) format('embedded-opentype'),url(Happy-Addons-Icon.ttf?vf4zr6) format('truetype'),url(Happy-Addons-Icon.woff?vf4zr6) format('woff'),url(Happy-Addons-Icon.svg?vf4zr6#Happy-Addons-Icon) format('svg');font-weight:400;font-style:normal}.fashm,.hm{font-family:'Happy Icons'!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.hm-3d-rotate:before{content:"\e900"}.hm-degree:before{content:"\e901"}.hm-accordion-horizontal:before{content:"\e902"}.hm-accordion-vertical:before{content:"\e903"}.hm-alarm-clock:before{content:"\e904"}.hm-alien-gun:before{content:"\e905"}.hm-alien:before{content:"\e906"}.hm-anchor:before{content:"\e907"}.hm-android:before{content:"\e908"}.hm-angle-down:before{content:"\e909"}.hm-angle-left:before{content:"\e90a"}.hm-angle-right:before{content:"\e90b"}.hm-angle-up:before{content:"\e90c"}.hm-apple:before{content:"\e90d"}.hm-arrow-left:before{content:"\e90e"}.hm-arrow-right:before{content:"\e90f"}.hm-arrow-zoom-out:before{content:"\e910"}.hm-arrow-corner:before{content:"\e911"}.hm-arrow-down:before{content:"\e912"}.hm-arrow-left1:before{content:"\e913"}.hm-arrow-right1:before{content:"\e914"}.hm-arrow-up:before{content:"\e915"}.hm-article:before{content:"\e916"}.hm-avatar-man:before{content:"\e917"}.hm-avatar-woman:before{content:"\e918"}.hm-badge1:before{content:"\e919"}.hm-badge2:before{content:"\e91a"}.hm-badge3:before{content:"\e91b"}.hm-bamboo:before{content:"\e91c"}.hm-basketball:before{content:"\e91d"}.hm-battery:before{content:"\e91e"}.hm-beach-seat:before{content:"\e91f"}.hm-bell:before{content:"\e920"}.hm-bicycle:before{content:"\e921"}.hm-blog-content:before{content:"\e922"}.hm-bluetooth:before{content:"\e923"}.hm-board:before{content:"\e924"}.hm-body:before{content:"\e925"}.hm-bomb:before{content:"\e926"}.hm-bond-hand:before{content:"\e927"}.hm-bond:before{content:"\e928"}.hm-bonsai:before{content:"\e929"}.hm-book:before{content:"\e92a"}.hm-bowl:before{content:"\e92b"}.hm-brick-wall:before{content:"\e92c"}.hm-brush-paint:before{content:"\e92d"}.hm-brush-roll:before{content:"\e92e"}.hm-brush:before{content:"\e92f"}.hm-bug:before{content:"\e930"}.hm-bulb:before{content:"\e931"}.hm-calculation:before{content:"\e932"}.hm-calendar:before{content:"\e933"}.hm-camera:before{content:"\e934"}.hm-candle:before{content:"\e935"}.hm-candles:before{content:"\e936"}.hm-car:before{content:"\e937"}.hm-card:before{content:"\e938"}.hm-caret-down:before{content:"\e939"}.hm-caret-fill-down:before{content:"\e93a"}.hm-caret-fill-left:before{content:"\e93b"}.hm-caret-fill-right:before{content:"\e93c"}.hm-caret-fill-up:before{content:"\e93d"}.hm-caret-left:before{content:"\e93e"}.hm-caret-right:before{content:"\e93f"}.hm-caret-up:before{content:"\e940"}.hm-carousal:before{content:"\e941"}.hm-cart-empty:before{content:"\e942"}.hm-cart-full:before{content:"\e943"}.hm-caution:before{content:"\e944"}.hm-chair:before{content:"\e945"}.hm-chair2:before{content:"\e946"}.hm-chat-bubble-single:before{content:"\e947"}.hm-chat-bubble:before{content:"\e948"}.hm-cheese:before{content:"\e949"}.hm-chef-cap:before{content:"\e94a"}.hm-clip-board:before{content:"\e94b"}.hm-clip:before{content:"\e94c"}.hm-cloud-down:before{content:"\e94d"}.hm-cloud-up:before{content:"\e94e"}.hm-cloud:before{content:"\e94f"}.hm-code-browser:before{content:"\e950"}.hm-code-clean:before{content:"\e951"}.hm-code:before{content:"\e952"}.hm-cog:before{content:"\e953"}.hm-color-card:before{content:"\e954"}.hm-color-plate:before{content:"\e955"}.hm-compass-math:before{content:"\e956"}.hm-compass:before{content:"\e957"}.hm-corner:before{content:"\e958"}.hm-crop:before{content:"\e959"}.hm-cross-circle:before{content:"\e95a"}.hm-cross-game:before{content:"\e95b"}.hm-cross-gap:before{content:"\e95c"}.hm-cross:before{content:"\e95d"}.hm-crown:before{content:"\e95e"}.hm-cube:before{content:"\e95f"}.hm-cup-coffee:before{content:"\e960"}.hm-cup:before{content:"\e961"}.hm-currency-paper:before{content:"\e962"}.hm-dashboard:before{content:"\e963"}.hm-delivery-van:before{content:"\e964"}.hm-diamond-ring:before{content:"\e965"}.hm-direction-both:before{content:"\e966"}.hm-direction-right:before{content:"\e967"}.hm-disable-person:before{content:"\e968"}.hm-disc:before{content:"\e969"}.hm-dislike:before{content:"\e96a"}.hm-dollar-on-hand:before{content:"\e96b"}.hm-door-path:before{content:"\e96c"}.hm-Download-circle:before{content:"\e96d"}.hm-download:before{content:"\e96e"}.hm-drag-inside:before{content:"\e96f"}.hm-drag-outside:before{content:"\e970"}.hm-drag:before{content:"\e971"}.hm-drawer:before{content:"\e972"}.hm-dribbble:before{content:"\e973"}.hm-dropper:before{content:"\e974"}.hm-egg-fry:before{content:"\e975"}.hm-ellipsis-fill-h:before{content:"\e976"}.hm-ellipsis-fill-v:before{content:"\e977"}.hm-ellipsis-horizontal:before{content:"\e978"}.hm-ellipsis-vertical:before{content:"\e979"}.hm-emo-normal:before{content:"\e97a"}.hm-emo-sad:before{content:"\e97b"}.hm-emo-smile:before{content:"\e97c"}.hm-envelop:before{content:"\e97d"}.hm-facebook:before{content:"\e97e"}.hm-fancy-futton:before{content:"\e97f"}.hm-feeder:before{content:"\e980"}.hm-file-cabinet:before{content:"\e981"}.hm-file-rotate:before{content:"\e982"}.hm-file:before{content:"\e983"}.hm-files:before{content:"\e984"}.hm-film-roll:before{content:"\e985"}.hm-film:before{content:"\e986"}.hm-finger-index:before{content:"\e987"}.hm-finger-print:before{content:"\e988"}.hm-fire-flame:before{content:"\e989"}.hm-flag:before{content:"\e98a"}.hm-flip-card1:before{content:"\e98b"}.hm-flip-card2:before{content:"\e98c"}.hm-folder-network:before{content:"\e98d"}.hm-folder:before{content:"\e98e"}.hm-football:before{content:"\e98f"}.hm-footer:before{content:"\e990"}.hm-form:before{content:"\e991"}.hm-forward:before{content:"\e992"}.hm-fountain-pen:before{content:"\e993"}.hm-gender-female:before{content:"\e994"}.hm-gender-male:before{content:"\e995"}.hm-gender-sign:before{content:"\e996"}.hm-gender:before{content:"\e997"}.hm-ghost:before{content:"\e998"}.hm-gift-box:before{content:"\e999"}.hm-globe1:before{content:"\e99a"}.hm-globe2:before{content:"\e99b"}.hm-globe3:before{content:"\e99c"}.hm-globe4:before{content:"\e99d"}.hm-google:before{content:"\e99e"}.hm-graduate-cap:before{content:"\e99f"}.hm-graph-bar:before{content:"\e9a0"}.hm-graph-pie:before{content:"\e9a1"}.hm-graph:before{content:"\e9a2"}.hm-grid-even:before{content:"\e9a3"}.hm-grid-masonry:before{content:"\e9a4"}.hm-grid-twist:before{content:"\e9a5"}.hm-grid:before{content:"\e9a6"}.hm-group:before{content:"\e9a7"}.hm-hand-mike:before{content:"\e9a8"}.hm-hand-watch:before{content:"\e9a9"}.hm-hand:before{content:"\e9aa"}.hm-header:before{content:"\e9ab"}.hm-headphone:before{content:"\e9ac"}.hm-headset:before{content:"\e9ad"}.hm-heart-beat:before{content:"\e9ae"}.hm-hexa:before{content:"\e9af"}.hm-highlighter:before{content:"\e9b0"}.hm-home:before{content:"\e9b1"}.hm-hot-spot:before{content:"\e9b2"}.hm-hotdog:before{content:"\e9b3"}.hm-ice-cream:before{content:"\e9b4"}.hm-icon-box:before{content:"\e9b5"}.hm-imac:before{content:"\e9b6"}.hm-image-compare:before{content:"\e9b7"}.hm-image-slider:before{content:"\e9b8"}.hm-image:before{content:"\e9b9"}.hm-inbox:before{content:"\e9ba"}.hm-infinity:before{content:"\e9bb"}.hm-info:before{content:"\e9bc"}.hm-injection:before{content:"\e9bd"}.hm-instagram:before{content:"\e9be"}.hm-jar-chemical:before{content:"\e9bf"}.hm-key:before{content:"\e9c0"}.hm-language-change:before{content:"\e9c1"}.hm-laptop:before{content:"\e9c2"}.hm-layer:before{content:"\e9c3"}.hm-lens:before{content:"\e9c4"}.hm-like:before{content:"\e9c5"}.hm-line-graph-pointed:before{content:"\e9c6"}.hm-link:before{content:"\e9c7"}.hm-linkedin:before{content:"\e9c8"}.hm-linux:before{content:"\e9c9"}.hm-list-2:before{content:"\e9ca"}.hm-list-group:before{content:"\e9cb"}.hm-list:before{content:"\e9cc"}.hm-location-pointer:before{content:"\e9cd"}.hm-lock:before{content:"\e9ce"}.hm-logo-carousel:before{content:"\e9cf"}.hm-logo-grid:before{content:"\e9d0"}.hm-lotus:before{content:"\e9d1"}.hm-love:before{content:"\e9d2"}.hm-madel:before{content:"\e9d3"}.hm-magic-wand:before{content:"\e9d4"}.hm-magnet:before{content:"\e9d5"}.hm-mail-open:before{content:"\e9d6"}.hm-man-range:before{content:"\e9d7"}.hm-map-marker:before{content:"\e9d8"}.hm-map-pointer:before{content:"\e9d9"}.hm-measurement:before{content:"\e9da"}.hm-memory:before{content:"\e9db"}.hm-menu-price:before{content:"\e9dc"}.hm-micro-chip:before{content:"\e9dd"}.hm-microphone1:before{content:"\e9de"}.hm-microphone2:before{content:"\e9df"}.hm-mobile:before{content:"\e9e0"}.hm-money-bag:before{content:"\e9e1"}.hm-money:before{content:"\e9e2"}.hm-monitor:before{content:"\e9e3"}.hm-mouse:before{content:"\e9e4"}.hm-muscle:before{content:"\e9e5"}.hm-net:before{content:"\e9e6"}.hm-network1:before{content:"\e9e7"}.hm-network2:before{content:"\e9e8"}.hm-newspaper:before{content:"\e9e9"}.hm-nuclear-circle:before{content:"\e9ea"}.hm-office-file:before{content:"\e9eb"}.hm-pacman:before{content:"\e9ec"}.hm-paper-fold:before{content:"\e9ed"}.hm-paper-plane-alt:before{content:"\e9ee"}.hm-paper-plane:before{content:"\e9ef"}.hm-pause:before{content:"\e9f0"}.hm-pen-head:before{content:"\e9f1"}.hm-pen-pencil:before{content:"\e9f2"}.hm-pen-scale:before{content:"\e9f3"}.hm-pen-paper:before{content:"\e9f4"}.hm-pen:before{content:"\e9f5"}.hm-pencil:before{content:"\e9f6"}.hm-pendrive:before{content:"\e9f7"}.hm-phone:before{content:"\e9f8"}.hm-pillar:before{content:"\e9f9"}.hm-pin-man-range:before{content:"\e9fa"}.hm-pin-man:before{content:"\e9fb"}.hm-pin:before{content:"\e9fc"}.hm-plane:before{content:"\e9fd"}.hm-play-end:before{content:"\e9fe"}.hm-play-next:before{content:"\e9ff"}.hm-play-previous:before{content:"\ea00"}.hm-play-start:before{content:"\ea01"}.hm-play-button:before{content:"\ea02"}.hm-play-store:before{content:"\ea03"}.hm-play:before{content:"\ea04"}.hm-playing-card:before{content:"\ea05"}.hm-plus-box:before{content:"\ea06"}.hm-plus-circle:before{content:"\ea07"}.hm-plus-gap:before{content:"\ea08"}.hm-plus-open:before{content:"\ea09"}.hm-popup:before{content:"\ea0a"}.hm-power:before{content:"\ea0b"}.hm-printer:before{content:"\ea0c"}.hm-progress-bar:before{content:"\ea0d"}.hm-promo:before{content:"\ea0e"}.hm-pulse:before{content:"\ea0f"}.hm-puzzle:before{content:"\ea10"}.hm-question:before{content:"\ea11"}.hm-quote:before{content:"\ea12"}.hm-radar:before{content:"\ea13"}.hm-radiation:before{content:"\ea14"}.hm-reading-glass-alt:before{content:"\ea15"}.hm-reading-glass:before{content:"\ea16"}.hm-recycle-bin:before{content:"\ea17"}.hm-recycle:before{content:"\ea18"}.hm-refresh-time:before{content:"\ea19"}.hm-reply:before{content:"\ea1a"}.hm-responsive-device:before{content:"\ea1b"}.hm-review:before{content:"\ea1c"}.hm-rocket1:before{content:"\ea1d"}.hm-rocket2:before{content:"\ea1e"}.hm-rss:before{content:"\ea1f"}.hm-safety-cap:before{content:"\ea20"}.hm-safety-kit:before{content:"\ea21"}.hm-sand-watch:before{content:"\ea22"}.hm-scale:before{content:"\ea23"}.hm-scanner:before{content:"\ea24"}.hm-scissor:before{content:"\ea25"}.hm-screen:before{content:"\ea26"}.hm-search:before{content:"\ea27"}.hm-seo:before{content:"\ea28"}.hm-server-network:before{content:"\ea29"}.hm-server:before{content:"\ea2a"}.hm-share:before{content:"\ea2b"}.hm-shield:before{content:"\ea2c"}.hm-ship:before{content:"\ea2d"}.hm-shirt:before{content:"\ea2e"}.hm-shopping-bag1:before{content:"\ea2f"}.hm-shopping-bag2:before{content:"\ea30"}.hm-shopping-bag3:before{content:"\ea31"}.hm-shopping-bag4:before{content:"\ea32"}.hm-shuffle:before{content:"\ea33"}.hm-shutter:before{content:"\ea34"}.hm-sign-in:before{content:"\ea35"}.hm-sign-out:before{content:"\ea36"}.hm-sitemap1:before{content:"\ea37"}.hm-sitemap2:before{content:"\ea38"}.hm-skart:before{content:"\ea39"}.hm-skull:before{content:"\ea3a"}.hm-skyscraper:before{content:"\ea3b"}.hm-slider-doc:before{content:"\ea3c"}.hm-slider-h-range:before{content:"\ea3d"}.hm-slider-image:before{content:"\ea3e"}.hm-slider-range-h:before{content:"\ea3f"}.hm-slider-v-open:before{content:"\ea40"}.hm-slider-video:before{content:"\ea41"}.hm-slider:before{content:"\ea42"}.hm-smart-watch:before{content:"\ea43"}.hm-snow:before{content:"\ea44"}.hm-spa-face:before{content:"\ea45"}.hm-spa-stone-flower:before{content:"\ea46"}.hm-spa-stone:before{content:"\ea47"}.hm-spark:before{content:"\ea48"}.hm-speaker-off:before{content:"\ea49"}.hm-speaker-on:before{content:"\ea4a"}.hm-spoon-fork:before{content:"\ea4b"}.hm-spoon:before{content:"\ea4c"}.hm-star:before{content:"\ea4d"}.hm-step-flow:before{content:"\ea4e"}.hm-steps:before{content:"\ea4f"}.hm-stop-watch:before{content:"\ea50"}.hm-stop:before{content:"\ea51"}.hm-support-call:before{content:"\ea52"}.hm-tab:before{content:"\ea53"}.hm-table-lamp:before{content:"\ea54"}.hm-tablet:before{content:"\ea55"}.hm-tag:before{content:"\ea56"}.hm-target-arrow:before{content:"\ea57"}.hm-target:before{content:"\ea58"}.hm-target1:before{content:"\ea59"}.hm-team-carousel:before{content:"\ea5a"}.hm-team-member:before{content:"\ea5b"}.hm-tennis-ball:before{content:"\ea5c"}.hm-terminal:before{content:"\ea5d"}.hm-testimonial-carousel:before{content:"\ea5e"}.hm-testimonial:before{content:"\ea5f"}.hm-text-animation:before{content:"\ea60"}.hm-theatre:before{content:"\ea61"}.hm-tick-circle:before{content:"\ea62"}.hm-tick:before{content:"\ea63"}.hm-tickets:before{content:"\ea64"}.hm-tie-knot:before{content:"\ea65"}.hm-tie:before{content:"\ea66"}.hm-timeline:before{content:"\ea67"}.hm-toggle:before{content:"\ea68"}.hm-tools:before{content:"\ea69"}.hm-tree-square:before{content:"\ea6a"}.hm-twitter-bird:before{content:"\ea6b"}.hm-twitter:before{content:"\ea6c"}.hm-ufo:before{content:"\ea6d"}.hm-umbralla:before{content:"\ea6e"}.hm-unlock:before{content:"\ea6f"}.hm-up-down:before{content:"\ea70"}.hm-upload:before{content:"\ea71"}.hm-upward-top-right:before{content:"\ea72"}.hm-user-female:before{content:"\ea73"}.hm-user-id:before{content:"\ea74"}.hm-user-male:before{content:"\ea75"}.hm-video-camera:before{content:"\ea76"}.hm-water-drop:before{content:"\ea77"}.hm-weather-cloud-day:before{content:"\ea78"}.hm-weather-cloud:before{content:"\ea79"}.hm-weather-day-rain:before{content:"\ea7a"}.hm-weather-day-snow:before{content:"\ea7b"}.hm-weather-day-windy-rain:before{content:"\ea7c"}.hm-weather-flood:before{content:"\ea7d"}.hm-weather-night-cloud:before{content:"\ea7e"}.hm-weather-rain-alt:before{content:"\ea7f"}.hm-weather-rain:before{content:"\ea80"}.hm-weather-snow:before{content:"\ea81"}.hm-weather-sun-rain:before{content:"\ea82"}.hm-weather-sun:before{content:"\ea83"}.hm-weather-sunny-day:before{content:"\ea84"}.hm-weather-thunder:before{content:"\ea85"}.hm-weather-windy-rain:before{content:"\ea86"}.hm-webcam1:before{content:"\ea87"}.hm-webcam2:before{content:"\ea88"}.hm-weight-scale:before{content:"\ea89"}.hm-windows:before{content:"\ea8a"}.hm-wine-glass2:before{content:"\ea8b"}.hm-wine-glass:before{content:"\ea8c"}.hm-worker-cap:before{content:"\ea8d"}.hm-youtube:before{content:"\ea8e"}
assets/js/happy-addons.js CHANGED
@@ -1,7 +1,6 @@
1
  'use strict';
2
- window.Happy = window.Happy || {};
3
 
4
- (function ($, Happy, w) {
5
  var $window = $(w);
6
 
7
  $.fn.getHappySettings = function() {
@@ -25,7 +24,7 @@ window.Happy = window.Happy || {};
25
  }
26
  }
27
 
28
- Happy.initImageComparison = function($scope) {
29
  var $item = $scope.find('.hajs-image-comparison'),
30
  settings = $item.getHappySettings(),
31
  fieldMap = {
@@ -41,7 +40,7 @@ window.Happy = window.Happy || {};
41
  });
42
  };
43
 
44
- Happy.initJustifiedGallery = function($scope) {
45
  var $item = $scope.find('.hajs-justified-gallery'),
46
  settings = $item.getHappySettings()
47
  $item.justifiedGallery($.extend({}, {
@@ -59,16 +58,28 @@ window.Happy = window.Happy || {};
59
  };
60
 
61
  $window.on('elementor/frontend/init', function() {
62
- var HappyEffects = elementorModules.frontend.handlers.Base.extend({
 
 
 
63
  onInit: function() {
64
- elementorModules.frontend.handlers.Base.prototype.onInit.apply(this, arguments);
65
- this.$container = this.$element.find('.elementor-widget-container')[0];
66
- this.run();
 
 
 
 
 
 
 
 
 
67
  },
68
 
69
  getDefaultSettings: function() {
70
  return {
71
- targets: this.$container,
72
  loop: true,
73
  direction: 'alternate',
74
  easing: 'easeInOutSine',
@@ -77,14 +88,14 @@ window.Happy = window.Happy || {};
77
 
78
  onElementChange: function() {
79
  this.animation && this.animation.restart();
80
- this.run();
81
  },
82
 
83
  getConfig: function(key) {
84
  return this.getElementSettings('ha_floating_fx_' + key);
85
  },
86
 
87
- run: function() {
88
  var config = this.getDefaultSettings();
89
 
90
  if (this.getConfig('translate_toggle')) {
@@ -146,15 +157,15 @@ window.Happy = window.Happy || {};
146
  }
147
 
148
  if (this.getConfig('translate_toggle') || this.getConfig('rotate_toggle') || this.getConfig('scale_toggle')) {
149
- this.$container.style.setProperty('will-change', 'transform');
150
  this.animation = anime(config);
151
  }
152
  }
153
  });
154
 
155
- var Slick = elementorModules.frontend.handlers.Base.extend({
156
  onInit: function () {
157
- elementorModules.frontend.handlers.Base.prototype.onInit.apply(this, arguments);
158
  this.$container = this.$element.find('.hajs-slick');
159
  this.run();
160
  },
@@ -209,13 +220,13 @@ window.Happy = window.Happy || {};
209
  settings.slidesToShow = this.getElementSettings('slides_to_show') || 3;
210
  settings.responsive = [
211
  {
212
- breakpoint: elementorFrontend.config.breakpoints.lg,
213
  settings: {
214
  slidesToShow: (this.getElementSettings('slides_to_show_tablet') || settings.slidesToShow),
215
  }
216
  },
217
  {
218
- breakpoint: elementorFrontend.config.breakpoints.md,
219
  settings: {
220
  slidesToShow: (this.getElementSettings('slides_to_show_mobile') || this.getElementSettings('slides_to_show_tablet')) || settings.slidesToShow,
221
  }
@@ -232,14 +243,14 @@ window.Happy = window.Happy || {};
232
  });
233
 
234
  var NumberHandler = function($scope) {
235
- elementorFrontend.waypoint($scope, function () {
236
  var $number = $scope.find('.ha-number-text');
237
  $number.numerator($number.data('animation'));
238
  });
239
  };
240
 
241
  var SkillHandler = function($scope) {
242
- elementorFrontend.waypoint($scope, function () {
243
  $scope.find('.ha-skill-level').each(function() {
244
  var $current = $(this),
245
  $lt = $current.find('.ha-skill-level-text'),
@@ -259,40 +270,75 @@ window.Happy = window.Happy || {};
259
  });
260
  };
261
 
262
- elementorFrontend.hooks.addAction(
263
- 'frontend/element_ready/ha-image-compare.default',
264
- Happy.initImageComparison
265
- );
266
- elementorFrontend.hooks.addAction(
267
- 'frontend/element_ready/ha-justified-gallery.default',
268
- Happy.initJustifiedGallery
269
- );
270
- elementorFrontend.hooks.addAction(
271
- 'frontend/element_ready/ha-slider.default',
272
- function($scope) {
273
- elementorFrontend.elementsHandler.addHandler(Slick, {$element: $scope});
274
- }
275
- );
276
- elementorFrontend.hooks.addAction(
277
- 'frontend/element_ready/ha-carousel.default',
278
- function($scope) {
279
- elementorFrontend.elementsHandler.addHandler(Slick, {$element: $scope});
280
- }
281
- );
282
- elementorFrontend.hooks.addAction(
283
- 'frontend/element_ready/ha-number.default',
284
- NumberHandler
285
- );
286
- elementorFrontend.hooks.addAction(
287
- 'frontend/element_ready/ha-skills.default',
288
- SkillHandler
289
- );
290
- elementorFrontend.hooks.addAction(
291
- 'frontend/element_ready/widget',
292
- function($scope) {
293
- elementorFrontend.elementsHandler.addHandler(HappyEffects, {$element: $scope});
 
 
 
 
 
 
 
 
 
 
 
294
  }
295
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  });
297
 
298
- } (jQuery, Happy, window));
1
  'use strict';
 
2
 
3
+ (function ($, w) {
4
  var $window = $(w);
5
 
6
  $.fn.getHappySettings = function() {
24
  }
25
  }
26
 
27
+ var HandleImageCompare = function($scope) {
28
  var $item = $scope.find('.hajs-image-comparison'),
29
  settings = $item.getHappySettings(),
30
  fieldMap = {
40
  });
41
  };
42
 
43
+ var HandleJustifiedGallery = function($scope) {
44
  var $item = $scope.find('.hajs-justified-gallery'),
45
  settings = $item.getHappySettings()
46
  $item.justifiedGallery($.extend({}, {
58
  };
59
 
60
  $window.on('elementor/frontend/init', function() {
61
+ var EF = elementorFrontend,
62
+ EM = elementorModules;
63
+
64
+ var ExtensionHandler = EM.frontend.handlers.Base.extend({
65
  onInit: function() {
66
+ EM.frontend.handlers.Base.prototype.onInit.apply(this, arguments);
67
+ this.widgetContainer = this.$element.find('.elementor-widget-container')[0];
68
+
69
+ this.initFloatingEffects();
70
+
71
+ this.initBackgroundOverlay();
72
+ },
73
+
74
+ initBackgroundOverlay: function() {
75
+ if (this.isEdit) {
76
+ this.$element.addClass('ha-has-background-overlay')
77
+ }
78
  },
79
 
80
  getDefaultSettings: function() {
81
  return {
82
+ targets: this.widgetContainer,
83
  loop: true,
84
  direction: 'alternate',
85
  easing: 'easeInOutSine',
88
 
89
  onElementChange: function() {
90
  this.animation && this.animation.restart();
91
+ this.initFloatingEffects();
92
  },
93
 
94
  getConfig: function(key) {
95
  return this.getElementSettings('ha_floating_fx_' + key);
96
  },
97
 
98
+ initFloatingEffects: function() {
99
  var config = this.getDefaultSettings();
100
 
101
  if (this.getConfig('translate_toggle')) {
157
  }
158
 
159
  if (this.getConfig('translate_toggle') || this.getConfig('rotate_toggle') || this.getConfig('scale_toggle')) {
160
+ this.widgetContainer.style.setProperty('will-change', 'transform');
161
  this.animation = anime(config);
162
  }
163
  }
164
  });
165
 
166
+ var Slick = EM.frontend.handlers.Base.extend({
167
  onInit: function () {
168
+ EM.frontend.handlers.Base.prototype.onInit.apply(this, arguments);
169
  this.$container = this.$element.find('.hajs-slick');
170
  this.run();
171
  },
220
  settings.slidesToShow = this.getElementSettings('slides_to_show') || 3;
221
  settings.responsive = [
222
  {
223
+ breakpoint: EF.config.breakpoints.lg,
224
  settings: {
225
  slidesToShow: (this.getElementSettings('slides_to_show_tablet') || settings.slidesToShow),
226
  }
227
  },
228
  {
229
+ breakpoint: EF.config.breakpoints.md,
230
  settings: {
231
  slidesToShow: (this.getElementSettings('slides_to_show_mobile') || this.getElementSettings('slides_to_show_tablet')) || settings.slidesToShow,
232
  }
243
  });
244
 
245
  var NumberHandler = function($scope) {
246
+ EF.waypoint($scope, function () {
247
  var $number = $scope.find('.ha-number-text');
248
  $number.numerator($number.data('animation'));
249
  });
250
  };
251
 
252
  var SkillHandler = function($scope) {
253
+ EF.waypoint($scope, function () {
254
  $scope.find('.ha-skill-level').each(function() {
255
  var $current = $(this),
256
  $lt = $current.find('.ha-skill-level-text'),
270
  });
271
  };
272
 
273
+ var Isotope = EM.frontend.handlers.Base.extend({
274
+ onInit: function () {
275
+ EM.frontend.handlers.Base.prototype.onInit.apply(this, arguments);
276
+ this.$container = this.$element.find('.hajs-isotope');
277
+ this.run();
278
+ this.runFilter();
279
+ },
280
+
281
+ getLayoutMode: function() {
282
+ var layout = this.getElementSettings('layout');
283
+ return ( layout === 'even' ? 'masonry' : layout );
284
+ },
285
+
286
+ getDefaultSettings: function() {
287
+ return {
288
+ itemSelector: '.ha-image-grid-item',
289
+ percentPosition: true,
290
+ layoutMode: this.getLayoutMode()
291
+ };
292
+ },
293
+
294
+ runFilter: function() {
295
+ var self = this;
296
+ initFilterable(this.$element, function(filter) {
297
+ self.$container.isotope({
298
+ filter: filter
299
+ });
300
+ });
301
+ },
302
+
303
+ onElementChange: function(changedProp) {
304
+ if (['layout', 'image_height', 'columns', 'image_margin'].indexOf(changedProp) !== -1) {
305
+ this.run()
306
+ }
307
+ },
308
+
309
+ run: function() {
310
+ var self = this;
311
+
312
+ this.$container.isotope(self.getDefaultSettings());
313
+ this.$container.imagesLoaded().progress(function() {
314
+ self.$container.isotope('layout');
315
+ });
316
  }
317
+ });
318
+
319
+ var handlersFnMap = {
320
+ 'ha-image-compare.default': HandleImageCompare,
321
+ 'ha-justified-gallery.default': HandleJustifiedGallery,
322
+ 'ha-number.default': NumberHandler,
323
+ 'ha-skills.default': SkillHandler
324
+ };
325
+
326
+ $.each( handlersFnMap, function( widgetName, handlerFn ) {
327
+ EF.hooks.addAction( 'frontend/element_ready/' + widgetName, handlerFn );
328
+ });
329
+
330
+ var handlersClassMap = {
331
+ 'ha-slider.default': Slick,
332
+ 'ha-carousel.default': Slick,
333
+ 'ha-image-grid.default': Isotope,
334
+ 'widget': ExtensionHandler
335
+ };
336
+
337
+ $.each( handlersClassMap, function( widgetName, handlerClass ) {
338
+ EF.hooks.addAction( 'frontend/element_ready/' + widgetName, function( $scope ) {
339
+ EF.elementsHandler.addHandler( handlerClass, { $element: $scope });
340
+ });
341
+ });
342
  });
343
 
344
+ } (jQuery, window));
assets/js/happy-addons.min.js CHANGED
@@ -1 +1 @@
1
- "use strict";window.Happy=window.Happy||{},function(t,e,n){function i(e,n){var i=e.find(".hajs-gallery-filter");i.length&&i.on("click","button",function(e){e.stopPropagation();var i=t(this);i.parent().addClass("ha-filter-active").siblings().removeClass("ha-filter-active"),n(i.data("filter"))})}var s=t(n);t.fn.getHappySettings=function(){return this.data("happy-settings")},e.initImageComparison=function(t){var e=t.find(".hajs-image-comparison"),n=e.getHappySettings();n[{on_hover:"move_slider_on_hover",on_swipe:"move_with_handle_only",on_click:"click_to_move"}[n.move_handle||"on_swipe"]]=!0,delete n.move_handle,e.imagesLoaded().done(function(){e.twentytwenty(n)})},e.initJustifiedGallery=function(e){var n=e.find(".hajs-justified-gallery"),s=n.getHappySettings();n.justifiedGallery(t.extend({},{rowHeight:150,lastRow:"justify",margins:10},s)),i(e,function(t){n.justifiedGallery({lastRow:"*"===t?s.lastRow:"nojustify",filter:t})})},s.on("elementor/frontend/init",function(){var n=elementorModules.frontend.handlers.Base.extend({onInit:function(){elementorModules.frontend.handlers.Base.prototype.onInit.apply(this,arguments),this.$container=this.$element.find(".elementor-widget-container")[0],this.run()},getDefaultSettings:function(){return{targets:this.$container,loop:!0,direction:"alternate",easing:"easeInOutSine"}},onElementChange:function(){this.animation&&this.animation.restart(),this.run()},getConfig:function(t){return this.getElementSettings("ha_floating_fx_"+t)},run:function(){var t=this.getDefaultSettings();this.getConfig("translate_toggle")&&((this.getConfig("translate_x.size")||this.getConfig("translate_x.sizes.to"))&&(t.translateX={value:[this.getConfig("translate_x.sizes.from")||0,this.getConfig("translate_x.size")||this.getConfig("translate_x.sizes.to")],duration:this.getConfig("translate_duration.size"),delay:this.getConfig("translate_delay.size")||0}),(this.getConfig("translate_y.size")||this.getConfig("translate_y.sizes.to"))&&(t.translateY={value:[this.getConfig("translate_y.sizes.from")||0,this.getConfig("translate_y.size")||this.getConfig("translate_y.sizes.to")],duration:this.getConfig("translate_duration.size"),delay:this.getConfig("translate_delay.size")||0})),this.getConfig("rotate_toggle")&&((this.getConfig("rotate_x.size")||this.getConfig("rotate_x.sizes.to"))&&(t.rotateX={value:[this.getConfig("rotate_x.sizes.from")||0,this.getConfig("rotate_x.size")||this.getConfig("rotate_x.sizes.to")],duration:this.getConfig("rotate_duration.size"),delay:this.getConfig("rotate_delay.size")||0}),(this.getConfig("rotate_y.size")||this.getConfig("rotate_y.sizes.to"))&&(t.rotateY={value:[this.getConfig("rotate_y.sizes.from")||0,this.getConfig("rotate_y.size")||this.getConfig("rotate_y.sizes.to")],duration:this.getConfig("rotate_duration.size"),delay:this.getConfig("rotate_delay.size")||0}),(this.getConfig("rotate_z.size")||this.getConfig("rotate_z.sizes.to"))&&(t.rotateZ={value:[this.getConfig("rotate_z.sizes.from")||0,this.getConfig("rotate_z.size")||this.getConfig("rotate_z.sizes.to")],duration:this.getConfig("rotate_duration.size"),delay:this.getConfig("rotate_delay.size")||0})),this.getConfig("scale_toggle")&&((this.getConfig("scale_x.size")||this.getConfig("scale_x.sizes.to"))&&(t.scaleX={value:[this.getConfig("scale_x.sizes.from")||0,this.getConfig("scale_x.size")||this.getConfig("scale_x.sizes.to")],duration:this.getConfig("scale_duration.size"),delay:this.getConfig("scale_delay.size")||0}),(this.getConfig("scale_y.size")||this.getConfig("scale_y.sizes.to"))&&(t.scaleY={value:[this.getConfig("scale_y.sizes.from")||0,this.getConfig("scale_y.size")||this.getConfig("scale_y.sizes.to")],duration:this.getConfig("scale_duration.size"),delay:this.getConfig("scale_delay.size")||0})),(this.getConfig("translate_toggle")||this.getConfig("rotate_toggle")||this.getConfig("scale_toggle"))&&(this.$container.style.setProperty("will-change","transform"),this.animation=anime(t))}}),i=elementorModules.frontend.handlers.Base.extend({onInit:function(){elementorModules.frontend.handlers.Base.prototype.onInit.apply(this,arguments),this.$container=this.$element.find(".hajs-slick"),this.run()},isCarousel:function(){return this.$element.hasClass("ha-carousel")},getDefaultSettings:function(){return{arrows:!1,dots:!1,checkVisible:!1,infinite:!0,slidesToShow:this.isCarousel()?3:1,rows:0,prevArrow:'<button type="button" class="slick-prev"><i class="fa fa-chevron-left"></i></button>',nextArrow:'<button type="button" class="slick-next"><i class="fa fa-chevron-right"></i></button>'}},onElementChange:function(){this.$container.slick("unslick"),this.run()},getReadySettings:function(){var e={infinite:!!this.getElementSettings("loop"),autoplay:!!this.getElementSettings("autoplay"),autoplaySpeed:this.getElementSettings("autoplay_speed"),speed:this.getElementSettings("animation_speed"),centerMode:!!this.getElementSettings("center"),vertical:!!this.getElementSettings("vertical"),slidesToScroll:1};switch(this.getElementSettings("navigation")){case"arrow":e.arrows=!0;break;case"dots":e.dots=!0;break;case"both":e.arrows=!0,e.dots=!0}return this.isCarousel()&&(e.slidesToShow=this.getElementSettings("slides_to_show")||3,e.responsive=[{breakpoint:elementorFrontend.config.breakpoints.lg,settings:{slidesToShow:this.getElementSettings("slides_to_show_tablet")||e.slidesToShow}},{breakpoint:elementorFrontend.config.breakpoints.md,settings:{slidesToShow:this.getElementSettings("slides_to_show_mobile")||this.getElementSettings("slides_to_show_tablet")||e.slidesToShow}}]),t.extend({},this.getDefaultSettings(),e)},run:function(){this.$container.slick(this.getReadySettings())}}),s=function(t){elementorFrontend.waypoint(t,function(){var e=t.find(".ha-number-text");e.numerator(e.data("animation"))})},o=function(e){elementorFrontend.waypoint(e,function(){e.find(".ha-skill-level").each(function(){var e=t(this),n=e.find(".ha-skill-level-text"),i=e.data("level");e.animate({width:i+"%"},500),n.numerator({toValue:i+"%",duration:1300,onComplete:function(){n.append("%")}})})})};elementorFrontend.hooks.addAction("frontend/element_ready/ha-image-compare.default",e.initImageComparison),elementorFrontend.hooks.addAction("frontend/element_ready/ha-justified-gallery.default",e.initJustifiedGallery),elementorFrontend.hooks.addAction("frontend/element_ready/ha-slider.default",function(t){elementorFrontend.elementsHandler.addHandler(i,{$element:t})}),elementorFrontend.hooks.addAction("frontend/element_ready/ha-carousel.default",function(t){elementorFrontend.elementsHandler.addHandler(i,{$element:t})}),elementorFrontend.hooks.addAction("frontend/element_ready/ha-number.default",s),elementorFrontend.hooks.addAction("frontend/element_ready/ha-skills.default",o),elementorFrontend.hooks.addAction("frontend/element_ready/widget",function(t){elementorFrontend.elementsHandler.addHandler(n,{$element:t})})})}(jQuery,Happy,window);
1
+ "use strict";!function(t,e){function i(e,i){var n=e.find(".hajs-gallery-filter");n.length&&n.on("click","button",function(e){e.stopPropagation();var n=t(this);n.parent().addClass("ha-filter-active").siblings().removeClass("ha-filter-active"),i(n.data("filter"))})}var n=t(e);t.fn.getHappySettings=function(){return this.data("happy-settings")};var s=function(t){var e=t.find(".hajs-image-comparison"),i=e.getHappySettings();i[{on_hover:"move_slider_on_hover",on_swipe:"move_with_handle_only",on_click:"click_to_move"}[i.move_handle||"on_swipe"]]=!0,delete i.move_handle,e.imagesLoaded().done(function(){e.twentytwenty(i)})},o=function(e){var n=e.find(".hajs-justified-gallery"),s=n.getHappySettings();n.justifiedGallery(t.extend({},{rowHeight:150,lastRow:"justify",margins:10},s)),i(e,function(t){n.justifiedGallery({lastRow:"*"===t?s.lastRow:"nojustify",filter:t})})};n.on("elementor/frontend/init",function(){var e=elementorFrontend,n=elementorModules,a=n.frontend.handlers.Base.extend({onInit:function(){n.frontend.handlers.Base.prototype.onInit.apply(this,arguments),this.widgetContainer=this.$element.find(".elementor-widget-container")[0],this.initFloatingEffects(),this.initBackgroundOverlay()},initBackgroundOverlay:function(){this.isEdit&&this.$element.addClass("ha-has-background-overlay")},getDefaultSettings:function(){return{targets:this.widgetContainer,loop:!0,direction:"alternate",easing:"easeInOutSine"}},onElementChange:function(){this.animation&&this.animation.restart(),this.initFloatingEffects()},getConfig:function(t){return this.getElementSettings("ha_floating_fx_"+t)},initFloatingEffects:function(){var t=this.getDefaultSettings();this.getConfig("translate_toggle")&&((this.getConfig("translate_x.size")||this.getConfig("translate_x.sizes.to"))&&(t.translateX={value:[this.getConfig("translate_x.sizes.from")||0,this.getConfig("translate_x.size")||this.getConfig("translate_x.sizes.to")],duration:this.getConfig("translate_duration.size"),delay:this.getConfig("translate_delay.size")||0}),(this.getConfig("translate_y.size")||this.getConfig("translate_y.sizes.to"))&&(t.translateY={value:[this.getConfig("translate_y.sizes.from")||0,this.getConfig("translate_y.size")||this.getConfig("translate_y.sizes.to")],duration:this.getConfig("translate_duration.size"),delay:this.getConfig("translate_delay.size")||0})),this.getConfig("rotate_toggle")&&((this.getConfig("rotate_x.size")||this.getConfig("rotate_x.sizes.to"))&&(t.rotateX={value:[this.getConfig("rotate_x.sizes.from")||0,this.getConfig("rotate_x.size")||this.getConfig("rotate_x.sizes.to")],duration:this.getConfig("rotate_duration.size"),delay:this.getConfig("rotate_delay.size")||0}),(this.getConfig("rotate_y.size")||this.getConfig("rotate_y.sizes.to"))&&(t.rotateY={value:[this.getConfig("rotate_y.sizes.from")||0,this.getConfig("rotate_y.size")||this.getConfig("rotate_y.sizes.to")],duration:this.getConfig("rotate_duration.size"),delay:this.getConfig("rotate_delay.size")||0}),(this.getConfig("rotate_z.size")||this.getConfig("rotate_z.sizes.to"))&&(t.rotateZ={value:[this.getConfig("rotate_z.sizes.from")||0,this.getConfig("rotate_z.size")||this.getConfig("rotate_z.sizes.to")],duration:this.getConfig("rotate_duration.size"),delay:this.getConfig("rotate_delay.size")||0})),this.getConfig("scale_toggle")&&((this.getConfig("scale_x.size")||this.getConfig("scale_x.sizes.to"))&&(t.scaleX={value:[this.getConfig("scale_x.sizes.from")||0,this.getConfig("scale_x.size")||this.getConfig("scale_x.sizes.to")],duration:this.getConfig("scale_duration.size"),delay:this.getConfig("scale_delay.size")||0}),(this.getConfig("scale_y.size")||this.getConfig("scale_y.sizes.to"))&&(t.scaleY={value:[this.getConfig("scale_y.sizes.from")||0,this.getConfig("scale_y.size")||this.getConfig("scale_y.sizes.to")],duration:this.getConfig("scale_duration.size"),delay:this.getConfig("scale_delay.size")||0})),(this.getConfig("translate_toggle")||this.getConfig("rotate_toggle")||this.getConfig("scale_toggle"))&&(this.widgetContainer.style.setProperty("will-change","transform"),this.animation=anime(t))}}),r=n.frontend.handlers.Base.extend({onInit:function(){n.frontend.handlers.Base.prototype.onInit.apply(this,arguments),this.$container=this.$element.find(".hajs-slick"),this.run()},isCarousel:function(){return this.$element.hasClass("ha-carousel")},getDefaultSettings:function(){return{arrows:!1,dots:!1,checkVisible:!1,infinite:!0,slidesToShow:this.isCarousel()?3:1,rows:0,prevArrow:'<button type="button" class="slick-prev"><i class="fa fa-chevron-left"></i></button>',nextArrow:'<button type="button" class="slick-next"><i class="fa fa-chevron-right"></i></button>'}},onElementChange:function(){this.$container.slick("unslick"),this.run()},getReadySettings:function(){var i={infinite:!!this.getElementSettings("loop"),autoplay:!!this.getElementSettings("autoplay"),autoplaySpeed:this.getElementSettings("autoplay_speed"),speed:this.getElementSettings("animation_speed"),centerMode:!!this.getElementSettings("center"),vertical:!!this.getElementSettings("vertical"),slidesToScroll:1};switch(this.getElementSettings("navigation")){case"arrow":i.arrows=!0;break;case"dots":i.dots=!0;break;case"both":i.arrows=!0,i.dots=!0}return this.isCarousel()&&(i.slidesToShow=this.getElementSettings("slides_to_show")||3,i.responsive=[{breakpoint:e.config.breakpoints.lg,settings:{slidesToShow:this.getElementSettings("slides_to_show_tablet")||i.slidesToShow}},{breakpoint:e.config.breakpoints.md,settings:{slidesToShow:this.getElementSettings("slides_to_show_mobile")||this.getElementSettings("slides_to_show_tablet")||i.slidesToShow}}]),t.extend({},this.getDefaultSettings(),i)},run:function(){this.$container.slick(this.getReadySettings())}}),l=function(t){e.waypoint(t,function(){var e=t.find(".ha-number-text");e.numerator(e.data("animation"))})},g=function(i){e.waypoint(i,function(){i.find(".ha-skill-level").each(function(){var e=t(this),i=e.find(".ha-skill-level-text"),n=e.data("level");e.animate({width:n+"%"},500),i.numerator({toValue:n+"%",duration:1300,onComplete:function(){i.append("%")}})})})},h=n.frontend.handlers.Base.extend({onInit:function(){n.frontend.handlers.Base.prototype.onInit.apply(this,arguments),this.$container=this.$element.find(".hajs-isotope"),this.run(),this.runFilter()},getLayoutMode:function(){var t=this.getElementSettings("layout");return"even"===t?"masonry":t},getDefaultSettings:function(){return{itemSelector:".ha-image-grid-item",percentPosition:!0,layoutMode:this.getLayoutMode()}},runFilter:function(){var t=this;i(this.$element,function(e){t.$container.isotope({filter:e})})},onElementChange:function(t){-1!==["layout","image_height","columns","image_margin"].indexOf(t)&&this.run()},run:function(){var t=this;this.$container.isotope(t.getDefaultSettings()),this.$container.imagesLoaded().progress(function(){t.$container.isotope("layout")})}}),f={"ha-image-compare.default":s,"ha-justified-gallery.default":o,"ha-number.default":l,"ha-skills.default":g};t.each(f,function(t,i){e.hooks.addAction("frontend/element_ready/"+t,i)});var d={"ha-slider.default":r,"ha-carousel.default":r,"ha-image-grid.default":h,widget:a};t.each(d,function(t,i){e.hooks.addAction("frontend/element_ready/"+t,function(t){e.elementsHandler.addHandler(i,{$element:t})})})})}(jQuery,window);
assets/vendor/jquery-numerator/jquery-numerator.js ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery Numerator Plugin 0.2.1
3
+ * https://github.com/garethdn/jquery-numerator
4
+ *
5
+ * Copyright 2015, Gareth Nolan
6
+ * http://ie.linkedin.com/in/garethnolan/
7
+
8
+ * Based on jQuery Boilerplate by Zeno Rocha with the help of Addy Osmani
9
+ * http://jqueryboilerplate.com
10
+ *
11
+ * Licensed under the MIT license:
12
+ * http://www.opensource.org/licenses/MIT
13
+ */
14
+
15
+ ;(function (factory) {
16
+ 'use strict';
17
+ if (typeof define === 'function' && define.amd) {
18
+ // AMD is used - Register as an anonymous module.
19
+ define(['jquery'], factory);
20
+ } else if (typeof exports === 'object') {
21
+ factory(require('jquery'));
22
+ } else {
23
+ // Neither AMD nor CommonJS used. Use global variables.
24
+ if (typeof jQuery === 'undefined') {
25
+ throw 'jquery-numerator requires jQuery to be loaded first';
26
+ }
27
+ factory(jQuery);
28
+ }
29
+ }(function ($) {
30
+
31
+ var pluginName = "numerator",
32
+ defaults = {
33
+ easing: 'swing',
34
+ duration: 500,
35
+ delimiter: undefined,
36
+ rounding: 0,
37
+ toValue: undefined,
38
+ fromValue: undefined,
39
+ queue: false,
40
+ onStart: function(){},
41
+ onStep: function(){},
42
+ onProgress: function(){},
43
+ onComplete: function(){}
44
+ };
45
+
46
+ function Plugin ( element, options ) {
47
+ this.element = element;
48
+ this.settings = $.extend( {}, defaults, options );
49
+ this._defaults = defaults;
50
+ this._name = pluginName;
51
+ this.init();
52
+ }
53
+
54
+ Plugin.prototype = {
55
+
56
+ init: function () {
57
+ this.parseElement();
58
+ this.setValue();
59
+ },
60
+
61
+ parseElement: function () {
62
+ var elText = $.trim($(this.element).text());
63
+
64
+ this.settings.fromValue = this.settings.fromValue || this.format(elText);
65
+ },
66
+
67
+ setValue: function() {
68
+ var self = this;
69
+
70
+ $({value: self.settings.fromValue}).animate({value: self.settings.toValue}, {
71
+
72
+ duration: parseInt(self.settings.duration, 10),
73
+
74
+ easing: self.settings.easing,
75
+
76
+ start: self.settings.onStart,
77
+
78
+ step: function(now, fx) {
79
+ $(self.element).text(self.format(now));
80
+ // accepts two params - (now, fx)
81
+ self.settings.onStep(now, fx);
82
+ },
83
+
84
+ // accepts three params - (animation object, progress ratio, time remaining(ms))
85
+ progress: self.settings.onProgress,
86
+
87
+ complete: self.settings.onComplete
88
+ });
89
+ },
90
+
91
+ format: function(value){
92
+ var self = this;
93
+
94
+ if ( parseInt(this.settings.rounding ) < 1) {
95
+ value = parseInt(value, 10);
96
+ } else {
97
+ value = parseFloat(value).toFixed( parseInt(this.settings.rounding) );
98
+ }
99
+
100
+ if (self.settings.delimiter) {
101
+ return this.delimit(value)
102
+ } else {
103
+ return value;
104
+ }
105
+ },
106
+
107
+ // TODO: Add comments to this function
108
+ delimit: function(value){
109
+ var self = this;
110
+
111
+ value = value.toString();
112
+
113
+ if (self.settings.rounding && parseInt(self.settings.rounding, 10) > 0) {
114
+ var decimals = value.substring( (value.length - (self.settings.rounding + 1)), value.length ),
115
+ wholeValue = value.substring( 0, (value.length - (self.settings.rounding + 1)));
116
+
117
+ return self.addDelimiter(wholeValue) + decimals;
118
+ } else {
119
+ return self.addDelimiter(value);
120
+ }
121
+ },
122
+
123
+ addDelimiter: function(value){
124
+ return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, this.settings.delimiter);
125
+ }
126
+ };
127
+
128
+ $.fn[ pluginName ] = function ( options ) {
129
+ return this.each(function() {
130
+ if ( $.data( this, "plugin_" + pluginName ) ) {
131
+ $.data(this, 'plugin_' + pluginName, null);
132
+ }
133
+ $.data( this, "plugin_" + pluginName, new Plugin( this, options ) );
134
+ });
135
+ };
136
+
137
+ }));
assets/vendor/jquery-numerator/jquery-numerator.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t){"use strict";if("function"==typeof define&&define.amd)define(["jquery"],t);else if("object"==typeof exports)t(require("jquery"));else{if("undefined"==typeof jQuery)throw"jquery-numerator requires jQuery to be loaded first";t(jQuery)}}(function(t){function e(e,s){this.element=e,this.settings=t.extend({},i,s),this._defaults=i,this._name=n,this.init()}var n="numerator",i={easing:"swing",duration:500,delimiter:void 0,rounding:0,toValue:void 0,fromValue:void 0,queue:!1,onStart:function(){},onStep:function(){},onProgress:function(){},onComplete:function(){}};e.prototype={init:function(){this.parseElement(),this.setValue()},parseElement:function(){var e=t.trim(t(this.element).text());this.settings.fromValue=this.settings.fromValue||this.format(e)},setValue:function(){var e=this;t({value:e.settings.fromValue}).animate({value:e.settings.toValue},{duration:parseInt(e.settings.duration,10),easing:e.settings.easing,start:e.settings.onStart,step:function(n,i){t(e.element).text(e.format(n)),e.settings.onStep(n,i)},progress:e.settings.onProgress,complete:e.settings.onComplete})},format:function(t){var e=this;return t=parseInt(this.settings.rounding)<1?parseInt(t,10):parseFloat(t).toFixed(parseInt(this.settings.rounding)),e.settings.delimiter?this.delimit(t):t},delimit:function(t){var e=this;if(t=t.toString(),e.settings.rounding&&parseInt(e.settings.rounding,10)>0){var n=t.substring(t.length-(e.settings.rounding+1),t.length),i=t.substring(0,t.length-(e.settings.rounding+1));return e.addDelimiter(i)+n}return e.addDelimiter(t)},addDelimiter:function(t){return t.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.settings.delimiter)}},t.fn[n]=function(i){return this.each(function(){t.data(this,"plugin_"+n)&&t.data(this,"plugin_"+n,null),t.data(this,"plugin_"+n,new e(this,i))})}});
assets/vendor/jquery.isotope.js ADDED
@@ -0,0 +1,4016 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Isotope PACKAGED v2.2.0
3
+ *
4
+ * Licensed GPLv3 for open source use
5
+ * or Isotope Commercial License for commercial use
6
+ *
7
+ * http://isotope.metafizzy.co
8
+ * Copyright 2015 Metafizzy
9
+ */
10
+
11
+ /**
12
+ * Bridget makes jQuery widgets
13
+ * v1.1.0
14
+ * MIT license
15
+ */
16
+
17
+ (function(window) {
18
+
19
+
20
+
21
+ // -------------------------- utils -------------------------- //
22
+ var slice = Array.prototype.slice;
23
+
24
+ function noop() {}
25
+
26
+ // -------------------------- definition -------------------------- //
27
+
28
+ function defineBridget($) {
29
+
30
+ // bail if no jQuery
31
+ if (!$) {
32
+ return;
33
+ }
34
+
35
+ // -------------------------- addOptionMethod -------------------------- //
36
+ /**
37
+ * adds option method -> $().plugin('option', {...})
38
+ * @param {Function} PluginClass - constructor class
39
+ */
40
+
41
+ function addOptionMethod(PluginClass) {
42
+ // don't overwrite original option method
43
+ if (PluginClass.prototype.option) {
44
+ return;
45
+ }
46
+
47
+ // option setter
48
+ PluginClass.prototype.option = function(opts) {
49
+ // bail out if not an object
50
+ if (!$.isPlainObject(opts)) {
51
+ return;
52
+ }
53
+ this.options = $.extend(true, this.options, opts);
54
+ };
55
+ }
56
+
57
+ // -------------------------- plugin bridge -------------------------- //
58
+ // helper function for logging errors
59
+ // $.error breaks jQuery chaining
60
+ var logError = typeof console === 'undefined' ? noop : function(message) {
61
+ console.error(message);
62
+ };
63
+
64
+ /**
65
+ * jQuery plugin bridge, access methods like $elem.plugin('method')
66
+ * @param {String} namespace - plugin name
67
+ * @param {Function} PluginClass - constructor class
68
+ */
69
+
70
+ function bridge(namespace, PluginClass) {
71
+ // add to jQuery fn namespace
72
+ $.fn[namespace] = function(options) {
73
+ if (typeof options === 'string') {
74
+ // call plugin method when first argument is a string
75
+ // get arguments for method
76
+ var args = slice.call(arguments, 1);
77
+
78
+ for (var i = 0, len = this.length; i < len; i++) {
79
+ var elem = this[i];
80
+ var instance = $.data(elem, namespace);
81
+ if (!instance) {
82
+ logError("cannot call methods on " + namespace + " prior to initialization; " + "attempted to call '" + options + "'");
83
+ continue;
84
+ }
85
+ if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
86
+ logError("no such method '" + options + "' for " + namespace + " instance");
87
+ continue;
88
+ }
89
+
90
+ // trigger method with arguments
91
+ var returnValue = instance[options].apply(instance, args);
92
+
93
+ // break look and return first value if provided
94
+ if (returnValue !== undefined) {
95
+ return returnValue;
96
+ }
97
+ }
98
+ // return this if no return value
99
+ return this;
100
+ } else {
101
+ return this.each(function() {
102
+ var instance = $.data(this, namespace);
103
+ if (instance) {
104
+ // apply options & init
105
+ instance.option(options);
106
+ instance._init();
107
+ } else {
108
+ // initialize new instance
109
+ instance = new PluginClass(this, options);
110
+ $.data(this, namespace, instance);
111
+ }
112
+ });
113
+ }
114
+ };
115
+
116
+ }
117
+
118
+ // -------------------------- bridget -------------------------- //
119
+ /**
120
+ * converts a Prototypical class into a proper jQuery plugin
121
+ * the class must have a ._init method
122
+ * @param {String} namespace - plugin name, used in $().pluginName
123
+ * @param {Function} PluginClass - constructor class
124
+ */
125
+ $.bridget = function(namespace, PluginClass) {
126
+ addOptionMethod(PluginClass);
127
+ bridge(namespace, PluginClass);
128
+ };
129
+
130
+ return $.bridget;
131
+
132
+ }
133
+
134
+ // transport
135
+ if (typeof define === 'function' && define.amd) {
136
+ // AMD
137
+ define('jquery-bridget/jquery.bridget', ['jquery'], defineBridget);
138
+ } else if (typeof exports === 'object') {
139
+ defineBridget(require('jquery'));
140
+ } else {
141
+ // get jquery from browser global
142
+ defineBridget(window.jQuery);
143
+ }
144
+
145
+ })(window);
146
+
147
+ /*!
148
+ * eventie v1.0.6
149
+ * event binding helper
150
+ * eventie.bind( elem, 'click', myFn )
151
+ * eventie.unbind( elem, 'click', myFn )
152
+ * MIT license
153
+ */
154
+
155
+ /*jshint browser: true, undef: true, unused: true */
156
+ /*global define: false, module: false */
157
+
158
+ (function(window) {
159
+
160
+
161
+
162
+ var docElem = document.documentElement;
163
+
164
+ var bind = function() {};
165
+
166
+ function getIEEvent(obj) {
167
+ var event = window.event;
168
+ // add event.target
169
+ event.target = event.target || event.srcElement || obj;
170
+ return event;
171
+ }
172
+
173
+ if (docElem.addEventListener) {
174
+ bind = function(obj, type, fn) {
175
+ obj.addEventListener(type, fn, false);
176
+ };
177
+ } else if (docElem.attachEvent) {
178
+ bind = function(obj, type, fn) {
179
+ obj[type + fn] = fn.handleEvent ?
180
+ function() {
181
+ var event = getIEEvent(obj);
182
+ fn.handleEvent.call(fn, event);
183
+ } : function() {
184
+ var event = getIEEvent(obj);
185
+ fn.call(obj, event);
186
+ };
187
+ obj.attachEvent("on" + type, obj[type + fn]);
188
+ };
189
+ }
190
+
191
+ var unbind = function() {};
192
+
193
+ if (docElem.removeEventListener) {
194
+ unbind = function(obj, type, fn) {
195
+ obj.removeEventListener(type, fn, false);
196
+ };
197
+ } else if (docElem.detachEvent) {
198
+ unbind = function(obj, type, fn) {
199
+ obj.detachEvent("on" + type, obj[type + fn]);
200
+ try {
201
+ delete obj[type + fn];
202
+ } catch (err) {
203
+ // can't delete window object properties
204
+ obj[type + fn] = undefined;
205
+ }
206
+ };
207
+ }
208
+
209
+ var eventie = {
210
+ bind: bind,
211
+ unbind: unbind
212
+ };
213
+
214
+ // ----- module definition ----- //
215
+ if (typeof define === 'function' && define.amd) {
216
+ // AMD
217
+ define('eventie/eventie', eventie);
218
+ } else if (typeof exports === 'object') {
219
+ // CommonJS
220
+ module.exports = eventie;
221
+ } else {
222
+ // browser global
223
+ window.eventie = eventie;
224
+ }
225
+
226
+ })(window);
227
+
228
+ /*!
229
+ * EventEmitter v4.2.11 - git.io/ee
230
+ * Unlicense - http://unlicense.org/
231
+ * Oliver Caldwell - http://oli.me.uk/
232
+ * @preserve
233
+ */
234
+
235
+ ;
236
+ (function() {
237
+
238
+
239
+ /**
240
+ * Class for managing events.
241
+ * Can be extended to provide event functionality in other classes.
242
+ *
243
+ * @class EventEmitter Manages event registering and emitting.
244
+ */
245
+
246
+ function EventEmitter() {}
247
+
248
+ // Shortcuts to improve speed and size
249
+ var proto = EventEmitter.prototype;
250
+ var exports = this;
251
+ var originalGlobalValue = exports.EventEmitter;
252
+
253
+ /**
254
+ * Finds the index of the listener for the event in its storage array.
255
+ *
256
+ * @param {Function[]} listeners Array of listeners to search through.
257
+ * @param {Function} listener Method to look for.
258
+ * @return {Number} Index of the specified listener, -1 if not found
259
+ * @api private
260
+ */
261
+
262
+ function indexOfListener(listeners, listener) {
263
+ var i = listeners.length;
264
+ while (i--) {
265
+ if (listeners[i].listener === listener) {
266
+ return i;
267
+ }
268
+ }
269
+
270
+ return -1;
271
+ }
272
+
273
+ /**
274
+ * Alias a method while keeping the context correct, to allow for overwriting of target method.
275
+ *
276
+ * @param {String} name The name of the target method.
277
+ * @return {Function} The aliased method
278
+ * @api private
279
+ */
280
+
281
+ function alias(name) {
282
+ return function aliasClosure() {
283
+ return this[name].apply(this, arguments);
284
+ };
285
+ }
286
+
287
+ /**
288
+ * Returns the listener array for the specified event.
289
+ * Will initialise the event object and listener arrays if required.
290
+ * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
291
+ * Each property in the object response is an array of listener functions.
292
+ *
293
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
294
+ * @return {Function[]|Object} All listener functions for the event.
295
+ */
296
+ proto.getListeners = function getListeners(evt) {
297
+ var events = this._getEvents();
298
+ var response;
299
+ var key;
300
+
301
+ // Return a concatenated array of all matching events if
302
+ // the selector is a regular expression.
303
+ if (evt instanceof RegExp) {
304
+ response = {};
305
+ for (key in events) {
306
+ if (events.hasOwnProperty(key) && evt.test(key)) {
307
+ response[key] = events[key];
308
+ }
309
+ }
310
+ } else {
311
+ response = events[evt] || (events[evt] = []);
312
+ }
313
+
314
+ return response;
315
+ };
316
+
317
+ /**
318
+ * Takes a list of listener objects and flattens it into a list of listener functions.
319
+ *
320
+ * @param {Object[]} listeners Raw listener objects.
321
+ * @return {Function[]} Just the listener functions.
322
+ */
323
+ proto.flattenListeners = function flattenListeners(listeners) {
324
+ var flatListeners = [];
325
+ var i;
326
+
327
+ for (i = 0; i < listeners.length; i += 1) {
328
+ flatListeners.push(listeners[i].listener);
329
+ }
330
+
331
+ return flatListeners;
332
+ };
333
+
334
+ /**
335
+ * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
336
+ *
337
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
338
+ * @return {Object} All listener functions for an event in an object.
339
+ */
340
+ proto.getListenersAsObject = function getListenersAsObject(evt) {
341
+ var listeners = this.getListeners(evt);
342
+ var response;
343
+
344
+ if (listeners instanceof Array) {
345
+ response = {};
346
+ response[evt] = listeners;
347
+ }
348
+
349
+ return response || listeners;
350
+ };
351
+
352
+ /**
353
+ * Adds a listener function to the specified event.
354
+ * The listener will not be added if it is a duplicate.
355
+ * If the listener returns true then it will be removed after it is called.
356
+ * If you pass a regular expression as the event name then the listener will be added to all events that match it.
357
+ *
358
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
359
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
360
+ * @return {Object} Current instance of EventEmitter for chaining.
361
+ */
362
+ proto.addListener = function addListener(evt, listener) {
363
+ var listeners = this.getListenersAsObject(evt);
364
+ var listenerIsWrapped = typeof listener === 'object';
365
+ var key;
366
+
367
+ for (key in listeners) {
368
+ if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
369
+ listeners[key].push(listenerIsWrapped ? listener : {
370
+ listener: listener,
371
+ once: false
372
+ });
373
+ }
374
+ }
375
+
376
+ return this;
377
+ };
378
+
379
+ /**
380
+ * Alias of addListener
381
+ */
382
+ proto.on = alias('addListener');
383
+
384
+ /**
385
+ * Semi-alias of addListener. It will add a listener that will be
386
+ * automatically removed after its first execution.
387
+ *
388
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
389
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
390
+ * @return {Object} Current instance of EventEmitter for chaining.
391
+ */
392
+ proto.addOnceListener = function addOnceListener(evt, listener) {
393
+ return this.addListener(evt, {
394
+ listener: listener,
395
+ once: true
396
+ });
397
+ };
398
+
399
+ /**
400
+ * Alias of addOnceListener.
401
+ */
402
+ proto.once = alias('addOnceListener');
403
+
404
+ /**
405
+ * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
406
+ * You need to tell it what event names should be matched by a regex.
407
+ *
408
+ * @param {String} evt Name of the event to create.
409
+ * @return {Object} Current instance of EventEmitter for chaining.
410
+ */
411
+ proto.defineEvent = function defineEvent(evt) {
412
+ this.getListeners(evt);
413
+ return this;
414
+ };
415
+
416
+ /**
417
+ * Uses defineEvent to define multiple events.
418
+ *
419
+ * @param {String[]} evts An array of event names to define.
420
+ * @return {Object} Current instance of EventEmitter for chaining.
421
+ */
422
+ proto.defineEvents = function defineEvents(evts) {
423
+ for (var i = 0; i < evts.length; i += 1) {
424
+ this.defineEvent(evts[i]);
425
+ }
426
+ return this;
427
+ };
428
+
429
+ /**
430
+ * Removes a listener function from the specified event.
431
+ * When passed a regular expression as the event name, it will remove the listener from all events that match it.
432
+ *
433
+ * @param {String|RegExp} evt Name of the event to remove the listener from.
434
+ * @param {Function} listener Method to remove from the event.
435
+ * @return {Object} Current instance of EventEmitter for chaining.
436
+ */
437
+ proto.removeListener = function removeListener(evt, listener) {
438
+ var listeners = this.getListenersAsObject(evt);
439
+ var index;
440
+ var key;
441
+
442
+ for (key in listeners) {
443
+ if (listeners.hasOwnProperty(key)) {
444
+ index = indexOfListener(listeners[key], listener);
445
+
446
+ if (index !== -1) {
447
+ listeners[key].splice(index, 1);
448
+ }
449
+ }
450
+ }
451
+
452
+ return this;
453
+ };
454
+
455
+ /**
456
+ * Alias of removeListener
457
+ */
458
+ proto.off = alias('removeListener');
459
+
460
+ /**
461
+ * Adds listeners in bulk using the manipulateListeners method.
462
+ * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
463
+ * You can also pass it a regular expression to add the array of listeners to all events that match it.
464
+ * Yeah, this function does quite a bit. That's probably a bad thing.
465
+ *
466
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
467
+ * @param {Function[]} [listeners] An optional array of listener functions to add.
468
+ * @return {Object} Current instance of EventEmitter for chaining.
469
+ */
470
+ proto.addListeners = function addListeners(evt, listeners) {
471
+ // Pass through to manipulateListeners
472
+ return this.manipulateListeners(false, evt, listeners);
473
+ };
474
+
475
+ /**
476
+ * Removes listeners in bulk using the manipulateListeners method.
477
+ * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
478
+ * You can also pass it an event name and an array of listeners to be removed.
479
+ * You can also pass it a regular expression to remove the listeners from all events that match it.
480
+ *
481
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
482
+ * @param {Function[]} [listeners] An optional array of listener functions to remove.
483
+ * @return {Object} Current instance of EventEmitter for chaining.
484
+ */
485
+ proto.removeListeners = function removeListeners(evt, listeners) {
486
+ // Pass through to manipulateListeners
487
+ return this.manipulateListeners(true, evt, listeners);
488
+ };
489
+
490
+ /**
491
+ * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
492
+ * The first argument will determine if the listeners are removed (true) or added (false).
493
+ * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
494
+ * You can also pass it an event name and an array of listeners to be added/removed.
495
+ * You can also pass it a regular expression to manipulate the listeners of all events that match it.
496
+ *
497
+ * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
498
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
499
+ * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
500
+ * @return {Object} Current instance of EventEmitter for chaining.
501
+ */
502
+ proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
503
+ var i;
504
+ var value;
505
+ var single = remove ? this.removeListener : this.addListener;
506
+ var multiple = remove ? this.removeListeners : this.addListeners;
507
+
508
+ // If evt is an object then pass each of its properties to this method
509
+ if (typeof evt === 'object' && !(evt instanceof RegExp)) {
510
+ for (i in evt) {
511
+ if (evt.hasOwnProperty(i) && (value = evt[i])) {
512
+ // Pass the single listener straight through to the singular method
513
+ if (typeof value === 'function') {
514
+ single.call(this, i, value);
515
+ } else {
516
+ // Otherwise pass back to the multiple function
517
+ multiple.call(this, i, value);
518
+ }
519
+ }
520
+ }
521
+ } else {
522
+ // So evt must be a string
523
+ // And listeners must be an array of listeners
524
+ // Loop over it and pass each one to the multiple method
525
+ i = listeners.length;
526
+ while (i--) {
527
+ single.call(this, evt, listeners[i]);
528
+ }
529
+ }
530
+
531
+ return this;
532
+ };
533
+
534
+ /**
535
+ * Removes all listeners from a specified event.
536
+ * If you do not specify an event then all listeners will be removed.
537
+ * That means every event will be emptied.
538
+ * You can also pass a regex to remove all events that match it.
539
+ *
540
+ * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
541
+ * @return {Object} Current instance of EventEmitter for chaining.
542
+ */
543
+ proto.removeEvent = function removeEvent(evt) {
544
+ var type = typeof evt;
545
+ var events = this._getEvents();
546
+ var key;
547
+
548
+ // Remove different things depending on the state of evt
549
+ if (type === 'string') {
550
+ // Remove all listeners for the specified event
551
+ delete events[evt];
552
+ } else if (evt instanceof RegExp) {
553
+ // Remove all events matching the regex.
554
+ for (key in events) {
555
+ if (events.hasOwnProperty(key) && evt.test(key)) {
556
+ delete events[key];
557
+ }
558
+ }
559
+ } else {
560
+ // Remove all listeners in all events
561
+ delete this._events;
562
+ }
563
+
564
+ return this;
565
+ };
566
+
567
+ /**
568
+ * Alias of removeEvent.
569
+ *
570
+ * Added to mirror the node API.
571
+ */
572
+ proto.removeAllListeners = alias('removeEvent');
573
+
574
+ /**
575
+ * Emits an event of your choice.
576
+ * When emitted, every listener attached to that event will be executed.
577
+ * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
578
+ * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
579
+ * So they will not arrive within the array on the other side, they will be separate.
580
+ * You can also pass a regular expression to emit to all events that match it.
581
+ *
582
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
583
+ * @param {Array} [args] Optional array of arguments to be passed to each listener.
584
+ * @return {Object} Current instance of EventEmitter for chaining.
585
+ */
586
+ proto.emitEvent = function emitEvent(evt, args) {
587
+ var listeners = this.getListenersAsObject(evt);
588
+ var listener;
589
+ var i;
590
+ var key;
591
+ var response;
592
+
593
+ for (key in listeners) {
594
+ if (listeners.hasOwnProperty(key)) {
595
+ i = listeners[key].length;
596
+
597
+ while (i--) {
598
+ // If the listener returns true then it shall be removed from the event
599
+ // The function is executed either with a basic call or an apply if there is an args array
600
+ listener = listeners[key][i];
601
+
602
+ if (listener.once === true) {
603
+ this.removeListener(evt, listener.listener);
604
+ }
605
+
606
+ response = listener.listener.apply(this, args || []);
607
+
608
+ if (response === this._getOnceReturnValue()) {
609
+ this.removeListener(evt, listener.listener);
610
+ }
611
+ }
612
+ }
613
+ }
614
+
615
+ return this;
616
+ };
617
+
618
+ /**
619
+ * Alias of emitEvent
620
+ */
621
+ proto.trigger = alias('emitEvent');
622
+
623
+ /**
624
+ * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
625
+ * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
626
+ *
627
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
628
+ * @param {...*} Optional additional arguments to be passed to each listener.
629
+ * @return {Object} Current instance of EventEmitter for chaining.
630
+ */
631
+ proto.emit = function emit(evt) {
632
+ var args = Array.prototype.slice.call(arguments, 1);
633
+ return this.emitEvent(evt, args);
634
+ };
635
+
636
+ /**
637
+ * Sets the current value to check against when executing listeners. If a
638
+ * listeners return value matches the one set here then it will be removed
639
+ * after execution. This value defaults to true.
640
+ *
641
+ * @param {*} value The new value to check for when executing listeners.
642
+ * @return {Object} Current instance of EventEmitter for chaining.
643
+ */
644
+ proto.setOnceReturnValue = function setOnceReturnValue(value) {
645
+ this._onceReturnValue = value;
646
+ return this;
647
+ };
648
+
649
+ /**
650
+ * Fetches the current value to check against when executing listeners. If
651
+ * the listeners return value matches this one then it should be removed
652
+ * automatically. It will return true by default.
653
+ *
654
+ * @return {*|Boolean} The current value to check for or the default, true.
655
+ * @api private
656
+ */
657
+ proto._getOnceReturnValue = function _getOnceReturnValue() {
658
+ if (this.hasOwnProperty('_onceReturnValue')) {
659
+ return this._onceReturnValue;
660
+ } else {
661
+ return true;
662
+ }
663
+ };
664
+
665
+ /**
666
+ * Fetches the events object and creates one if required.
667
+ *
668
+ * @return {Object} The events storage object.
669
+ * @api private
670
+ */
671
+ proto._getEvents = function _getEvents() {
672
+ return this._events || (this._events = {});
673
+ };
674
+
675
+ /**
676
+ * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
677
+ *
678
+ * @return {Function} Non conflicting EventEmitter class.
679
+ */
680
+ EventEmitter.noConflict = function noConflict() {
681
+ exports.EventEmitter = originalGlobalValue;
682
+ return EventEmitter;
683
+ };
684
+
685
+ // Expose the class either via AMD, CommonJS or the global object
686
+ if (typeof define === 'function' && define.amd) {
687
+ define('eventEmitter/EventEmitter', [], function() {
688
+ return EventEmitter;
689
+ });
690
+ } else if (typeof module === 'object' && module.exports) {
691
+ module.exports = EventEmitter;
692
+ } else {
693
+ exports.EventEmitter = EventEmitter;
694
+ }
695
+ }.call(this));
696
+
697
+ /*!
698
+ * getStyleProperty v1.0.4
699
+ * original by kangax
700
+ * http://perfectionkills.com/feature-testing-css-properties/
701
+ * MIT license
702
+ */
703
+
704
+ /*jshint browser: true, strict: true, undef: true */
705
+ /*global define: false, exports: false, module: false */
706
+
707
+ (function(window) {
708
+
709
+
710
+
711
+ var prefixes = 'Webkit Moz ms Ms O'.split(' ');
712
+ var docElemStyle = document.documentElement.style;
713
+
714
+ function getStyleProperty(propName) {
715
+ if (!propName) {
716
+ return;
717
+ }
718
+
719
+ // test standard property first
720
+ if (typeof docElemStyle[propName] === 'string') {
721
+ return propName;
722
+ }
723
+
724
+ // capitalize
725
+ propName = propName.charAt(0).toUpperCase() + propName.slice(1);
726
+
727
+ // test vendor specific properties
728
+ var prefixed;
729
+ for (var i = 0, len = prefixes.length; i < len; i++) {
730
+ prefixed = prefixes[i] + propName;
731
+ if (typeof docElemStyle[prefixed] === 'string') {
732
+ return prefixed;
733
+ }
734
+ }
735
+ }
736
+
737
+ // transport
738
+ if (typeof define === 'function' && define.amd) {
739
+ // AMD
740
+ define('get-style-property/get-style-property', [], function() {
741
+ return getStyleProperty;
742
+ });
743
+ } else if (typeof exports === 'object') {
744
+ // CommonJS for Component
745
+ module.exports = getStyleProperty;
746
+ } else {
747
+ // browser global
748
+ window.getStyleProperty = getStyleProperty;
749
+ }
750
+
751
+ })(window);
752
+
753
+ /*!
754
+ * getSize v1.2.2
755
+ * measure size of elements
756
+ * MIT license
757
+ */
758
+
759
+ /*jshint browser: true, strict: true, undef: true, unused: true */
760
+ /*global define: false, exports: false, require: false, module: false, console: false */
761
+
762
+ (function(window, undefined) {
763
+
764
+
765
+
766
+ // -------------------------- helpers -------------------------- //
767
+ // get a number from a string, not a percentage
768
+
769
+
770
+ function getStyleSize(value) {
771
+ var num = parseFloat(value);
772
+ // not a percent like '100%', and a number
773
+ var isValid = value.indexOf('%') === -1 && !isNaN(num);
774
+ return isValid && num;
775
+ }
776
+
777
+ function noop() {}
778
+
779
+ var logError = typeof console === 'undefined' ? noop : function(message) {
780
+ console.error(message);
781
+ };
782
+
783
+ // -------------------------- measurements -------------------------- //
784
+ var measurements = ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom', 'marginLeft', 'marginRight', 'marginTop', 'marginBottom', 'borderLeftWidth', 'borderRightWidth', 'borderTopWidth', 'borderBottomWidth'];
785
+
786
+ function getZeroSize() {
787
+ var size = {
788
+ width: 0,
789
+ height: 0,
790
+ innerWidth: 0,
791
+ innerHeight: 0,
792
+ outerWidth: 0,
793
+ outerHeight: 0
794
+ };
795
+ for (var i = 0, len = measurements.length; i < len; i++) {
796
+ var measurement = measurements[i];
797
+ size[measurement] = 0;
798
+ }
799
+ return size;
800
+ }
801
+
802
+
803
+
804
+ function defineGetSize(getStyleProperty) {
805
+
806
+ // -------------------------- setup -------------------------- //
807
+ var isSetup = false;
808
+
809
+ var getStyle, boxSizingProp, isBoxSizeOuter;
810
+
811
+ /**
812
+ * setup vars and functions
813
+ * do it on initial getSize(), rather than on script load
814
+ * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397
815
+ */
816
+
817
+ function setup() {
818
+ // setup once
819
+ if (isSetup) {
820
+ return;
821
+ }
822
+ isSetup = true;
823
+
824
+ var getComputedStyle = window.getComputedStyle;
825
+ getStyle = (function() {
826
+ var getStyleFn = getComputedStyle ?
827
+ function(elem) {
828
+ return getComputedStyle(elem, null);
829
+ } : function(elem) {
830
+ return elem.currentStyle;
831
+ };
832
+
833
+ return function getStyle(elem) {
834
+ var style = getStyleFn(elem);
835
+ if (!style) {
836
+ logError('Style returned ' + style + '. Are you running this code in a hidden iframe on Firefox? ' + 'See http://bit.ly/getsizebug1');
837
+ }
838
+ return style;
839
+ };
840
+ })();
841
+
842
+ // -------------------------- box sizing -------------------------- //
843
+ boxSizingProp = getStyleProperty('boxSizing');
844
+
845
+ /**
846
+ * WebKit measures the outer-width on style.width on border-box elems
847
+ * IE & Firefox measures the inner-width
848
+ */
849
+ if (boxSizingProp) {
850
+ var div = document.createElement('div');
851
+ div.style.width = '200px';
852
+ div.style.padding = '1px 2px 3px 4px';
853
+ div.style.borderStyle = 'solid';
854
+ div.style.borderWidth = '1px 2px 3px 4px';
855
+ div.style[boxSizingProp] = 'border-box';
856
+
857
+ var body = document.body || document.documentElement;
858
+ body.appendChild(div);
859
+ var style = getStyle(div);
860
+
861
+ isBoxSizeOuter = getStyleSize(style.width) === 200;
862
+ body.removeChild(div);
863
+ }
864
+
865
+ }
866
+
867
+ // -------------------------- getSize -------------------------- //
868
+
869
+ function getSize(elem) {
870
+ setup();
871
+
872
+ // use querySeletor if elem is string
873
+ if (typeof elem === 'string') {
874
+ elem = document.querySelector(elem);
875
+ }
876
+
877
+ // do not proceed on non-objects
878
+ if (!elem || typeof elem !== 'object' || !elem.nodeType) {
879
+ return;
880
+ }
881
+
882
+ var style = getStyle(elem);
883
+
884
+ // if hidden, everything is 0
885
+ if (style.display === 'none') {
886
+ return getZeroSize();
887
+ }
888
+
889
+ var size = {};
890
+ size.width = elem.offsetWidth;
891
+ size.height = elem.offsetHeight;
892
+
893
+ var isBorderBox = size.isBorderBox = !! (boxSizingProp && style[boxSizingProp] && style[boxSizingProp] === 'border-box');
894
+
895
+ // get all measurements
896
+ for (var i = 0, len = measurements.length; i < len; i++) {
897
+ var measurement = measurements[i];
898
+ var value = style[measurement];
899
+ value = mungeNonPixel(elem, value);
900
+ var num = parseFloat(value);
901
+ // any 'auto', 'medium' value will be 0
902
+ size[measurement] = !isNaN(num) ? num : 0;
903
+ }
904
+
905
+ var paddingWidth = size.paddingLeft + size.paddingRight;
906
+ var paddingHeight = size.paddingTop + size.paddingBottom;
907
+ var marginWidth = size.marginLeft + size.marginRight;
908
+ var marginHeight = size.marginTop + size.marginBottom;
909
+ var borderWidth = size.borderLeftWidth + size.borderRightWidth;
910
+ var borderHeight = size.borderTopWidth + size.borderBottomWidth;
911
+
912
+ var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
913
+
914
+ // overwrite width and height if we can get it from style
915
+ var styleWidth = getStyleSize(style.width);
916
+ if (styleWidth !== false) {
917
+ size.width = styleWidth +
918
+ // add padding and border unless it's already including it
919
+ (isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth);
920
+ }
921
+
922
+ var styleHeight = getStyleSize(style.height);
923
+ if (styleHeight !== false) {
924
+ size.height = styleHeight +
925
+ // add padding and border unless it's already including it
926
+ (isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight);
927
+ }
928
+
929
+ size.innerWidth = size.width - (paddingWidth + borderWidth);
930
+ size.innerHeight = size.height - (paddingHeight + borderHeight);
931
+
932
+ size.outerWidth = size.width + marginWidth;
933
+ size.outerHeight = size.height + marginHeight;
934
+
935
+ return size;
936
+ }
937
+
938
+ // IE8 returns percent values, not pixels
939
+ // taken from jQuery's curCSS
940
+
941
+
942
+ function mungeNonPixel(elem, value) {
943
+ // IE8 and has percent value
944
+ if (window.getComputedStyle || value.indexOf('%') === -1) {
945
+ return value;
946
+ }
947
+ var style = elem.style;
948
+ // Remember the original values
949
+ var left = style.left;
950
+ var rs = elem.runtimeStyle;
951
+ var rsLeft = rs && rs.left;
952
+
953
+ // Put in the new values to get a computed value out
954
+ if (rsLeft) {
955
+ rs.left = elem.currentStyle.left;
956
+ }
957
+ style.left = value;
958
+ value = style.pixelLeft;
959
+
960
+ // Revert the changed values
961
+ style.left = left;
962
+ if (rsLeft) {
963
+ rs.left = rsLeft;
964
+ }
965
+
966
+ return value;
967
+ }
968
+
969
+ return getSize;
970
+
971
+ }
972
+
973
+ // transport
974
+ if (typeof define === 'function' && define.amd) {
975
+ // AMD for RequireJS
976
+ define('get-size/get-size', ['get-style-property/get-style-property'], defineGetSize);
977
+ } else if (typeof exports === 'object') {
978
+ // CommonJS for Component
979
+ module.exports = defineGetSize(require('desandro-get-style-property'));
980
+ } else {
981
+ // browser global
982
+ window.getSize = defineGetSize(window.getStyleProperty);
983
+ }
984
+
985
+ })(window);
986
+
987
+ /*!
988
+ * docReady v1.0.4
989
+ * Cross browser DOMContentLoaded event emitter
990
+ * MIT license
991
+ */
992
+
993
+ /*jshint browser: true, strict: true, undef: true, unused: true*/
994
+ /*global define: false, require: false, module: false */
995
+
996
+ (function(window) {
997
+
998
+
999
+
1000
+ var document = window.document;
1001
+ // collection of functions to be triggered on ready
1002
+ var queue = [];
1003
+
1004
+ function docReady(fn) {
1005
+ // throw out non-functions
1006
+ if (typeof fn !== 'function') {
1007
+ return;
1008
+ }
1009
+
1010
+ if (docReady.isReady) {
1011
+ // ready now, hit it
1012
+ fn();
1013
+ } else {
1014
+ // queue function when ready
1015
+ queue.push(fn);
1016
+ }
1017
+ }
1018
+
1019
+ docReady.isReady = false;
1020
+
1021
+ // triggered on various doc ready events
1022
+
1023
+
1024
+ function onReady(event) {
1025
+ // bail if already triggered or IE8 document is not ready just yet
1026
+ var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete';
1027
+ if (docReady.isReady || isIE8NotReady) {
1028
+ return;
1029
+ }
1030
+
1031
+ trigger();
1032
+ }
1033
+
1034
+ function trigger() {
1035
+ docReady.isReady = true;
1036
+ // process queue
1037
+ for (var i = 0, len = queue.length; i < len; i++) {
1038
+ var fn = queue[i];
1039
+ fn();
1040
+ }
1041
+ }
1042
+
1043
+ function defineDocReady(eventie) {
1044
+ // trigger ready if page is ready
1045
+ if (document.readyState === 'complete') {
1046
+ trigger();
1047
+ } else {
1048
+ // listen for events
1049
+ eventie.bind(document, 'DOMContentLoaded', onReady);
1050
+ eventie.bind(document, 'readystatechange', onReady);
1051
+ eventie.bind(window, 'load', onReady);
1052
+ }
1053
+
1054
+ return docReady;
1055
+ }
1056
+
1057
+ // transport
1058
+ if (typeof define === 'function' && define.amd) {
1059
+ // AMD
1060
+ define('doc-ready/doc-ready', ['eventie/eventie'], defineDocReady);
1061
+ } else if (typeof exports === 'object') {
1062
+ module.exports = defineDocReady(require('eventie'));
1063
+ } else {
1064
+ // browser global
1065
+ window.docReady = defineDocReady(window.eventie);
1066
+ }
1067
+
1068
+ })(window);
1069
+
1070
+ /**
1071
+ * matchesSelector v1.0.3
1072
+ * matchesSelector( element, '.selector' )
1073
+ * MIT license
1074
+ */
1075
+
1076
+ /*jshint browser: true, strict: true, undef: true, unused: true */
1077
+ /*global define: false, module: false */
1078
+
1079
+ (function(ElemProto) {
1080
+
1081
+
1082
+
1083
+ var matchesMethod = (function() {
1084
+ // check for the standard method name first
1085
+ if (ElemProto.matches) {
1086
+ return 'matches';
1087
+ }
1088
+ // check un-prefixed
1089
+ if (ElemProto.matchesSelector) {
1090
+ return 'matchesSelector';
1091
+ }
1092
+ // check vendor prefixes
1093
+ var prefixes = ['webkit', 'moz', 'ms', 'o'];
1094
+
1095
+ for (var i = 0, len = prefixes.length; i < len; i++) {
1096
+ var prefix = prefixes[i];
1097
+ var method = prefix + 'MatchesSelector';
1098
+ if (ElemProto[method]) {
1099
+ return method;
1100
+ }
1101
+ }
1102
+ })();
1103
+
1104
+ // ----- match ----- //
1105
+
1106
+ function match(elem, selector) {
1107
+ return elem[matchesMethod](selector);
1108
+ }
1109
+
1110
+ // ----- appendToFragment ----- //
1111
+
1112
+ function checkParent(elem) {
1113
+ // not needed if already has parent
1114
+ if (elem.parentNode) {
1115
+ return;
1116
+ }
1117
+ var fragment = document.createDocumentFragment();
1118
+ fragment.appendChild(elem);
1119
+ }
1120
+
1121
+ // ----- query ----- //
1122
+ // fall back to using QSA
1123
+ // thx @jonathantneal https://gist.github.com/3062955
1124
+
1125
+
1126
+ function query(elem, selector) {
1127
+ // append to fragment if no parent
1128
+ checkParent(elem);
1129
+
1130
+ // match elem with all selected elems of parent
1131
+ var elems = elem.parentNode.querySelectorAll(selector);
1132
+ for (var i = 0, len = elems.length; i < len; i++) {
1133
+ // return true if match
1134
+ if (elems[i] === elem) {
1135
+ return true;
1136
+ }
1137
+ }
1138
+ // otherwise return false
1139
+ return false;
1140
+ }
1141
+
1142
+ // ----- matchChild ----- //
1143
+
1144
+ function matchChild(elem, selector) {
1145
+ checkParent(elem);
1146
+ return match(elem, selector);
1147
+ }
1148
+
1149
+ // ----- matchesSelector ----- //
1150
+ var matchesSelector;
1151
+
1152
+ if (matchesMethod) {
1153
+ // IE9 supports matchesSelector, but doesn't work on orphaned elems
1154
+ // check for that
1155
+ var div = document.createElement('div');
1156
+ var supportsOrphans = match(div, 'div');
1157
+ matchesSelector = supportsOrphans ? match : matchChild;
1158
+ } else {
1159
+ matchesSelector = query;
1160
+ }
1161
+
1162
+ // transport
1163
+ if (typeof define === 'function' && define.amd) {
1164
+ // AMD
1165
+ define('matches-selector/matches-selector', [], function() {
1166
+ return matchesSelector;
1167
+ });
1168
+ } else if (typeof exports === 'object') {
1169
+ module.exports = matchesSelector;
1170
+ } else {
1171
+ // browser global
1172
+ window.matchesSelector = matchesSelector;
1173
+ }
1174
+
1175
+ })(Element.prototype);
1176
+
1177
+ /**
1178
+ * Fizzy UI utils v1.0.1
1179
+ * MIT license
1180
+ */
1181
+
1182
+ /*jshint browser: true, undef: true, unused: true, strict: true */
1183
+
1184
+ (function(window, factory) { /*global define: false, module: false, require: false */
1185
+
1186
+ // universal module definition
1187
+ if (typeof define == 'function' && define.amd) {
1188
+ // AMD
1189
+ define('fizzy-ui-utils/utils', ['doc-ready/doc-ready', 'matches-selector/matches-selector'], function(docReady, matchesSelector) {
1190
+ return factory(window, docReady, matchesSelector);
1191
+ });
1192
+ } else if (typeof exports == 'object') {
1193
+ // CommonJS
1194
+ module.exports = factory(
1195
+ window, require('doc-ready'), require('desandro-matches-selector'));
1196
+ } else {
1197
+ // browser global
1198
+ window.fizzyUIUtils = factory(
1199
+ window, window.docReady, window.matchesSelector);
1200
+ }
1201
+
1202
+ }(window, function factory(window, docReady, matchesSelector) {
1203
+
1204
+
1205
+
1206
+ var utils = {};
1207
+
1208
+ // ----- extend ----- //
1209
+ // extends objects
1210
+ utils.extend = function(a, b) {
1211
+ for (var prop in b) {
1212
+ a[prop] = b[prop];
1213
+ }
1214
+ return a;
1215
+ };
1216
+
1217
+ // ----- modulo ----- //
1218
+ utils.modulo = function(num, div) {
1219
+ return ((num % div) + div) % div;
1220
+ };
1221
+
1222
+ // ----- isArray ----- //
1223
+ var objToString = Object.prototype.toString;
1224
+ utils.isArray = function(obj) {
1225
+ return objToString.call(obj) == '[object Array]';
1226
+ };
1227
+
1228
+ // ----- makeArray ----- //
1229
+ // turn element or nodeList into an array
1230
+ utils.makeArray = function(obj) {
1231
+ var ary = [];
1232
+ if (utils.isArray(obj)) {
1233
+ // use object if already an array
1234
+ ary = obj;
1235
+ } else if (obj && typeof obj.length == 'number') {
1236
+ // convert nodeList to array
1237
+ for (var i = 0, len = obj.length; i < len; i++) {
1238
+ ary.push(obj[i]);
1239
+ }
1240
+ } else {
1241
+ // array of single index
1242
+ ary.push(obj);
1243
+ }
1244
+ return ary;
1245
+ };
1246
+
1247
+ // ----- indexOf ----- //
1248
+ // index of helper cause IE8
1249
+ utils.indexOf = Array.prototype.indexOf ?
1250
+ function(ary, obj) {
1251
+ return ary.indexOf(obj);
1252
+ } : function(ary, obj) {
1253
+ for (var i = 0, len = ary.length; i < len; i++) {
1254
+ if (ary[i] === obj) {
1255
+ return i;
1256
+ }
1257
+ }
1258
+ return -1;
1259
+ };
1260
+
1261
+ // ----- removeFrom ----- //
1262
+ utils.removeFrom = function(ary, obj) {
1263
+ var index = utils.indexOf(ary, obj);
1264
+ if (index != -1) {
1265
+ ary.splice(index, 1);
1266
+ }
1267
+ };
1268
+
1269
+ // ----- isElement ----- //
1270
+ // http://stackoverflow.com/a/384380/182183
1271
+ utils.isElement = (typeof HTMLElement == 'function' || typeof HTMLElement == 'object') ?
1272
+ function isElementDOM2(obj) {
1273
+ return obj instanceof HTMLElement;
1274
+ } : function isElementQuirky(obj) {
1275
+ return obj && typeof obj == 'object' && obj.nodeType == 1 && typeof obj.nodeName == 'string';
1276
+ };
1277
+
1278
+ // ----- setText ----- //
1279
+ utils.setText = (function() {
1280
+ var setTextProperty;
1281
+
1282
+ function setText(elem, text) {
1283
+ // only check setTextProperty once
1284
+ setTextProperty = setTextProperty || (document.documentElement.textContent !== undefined ? 'textContent' : 'innerText');
1285
+ elem[setTextProperty] = text;
1286
+ }
1287
+ return setText;
1288
+ })();
1289
+
1290
+ // ----- getParent ----- //
1291
+ utils.getParent = function(elem, selector) {
1292
+ while (elem != document.body) {
1293
+ elem = elem.parentNode;
1294
+ if (matchesSelector(elem, selector)) {
1295
+ return elem;
1296
+ }
1297
+ }
1298
+ };
1299
+
1300
+ // ----- getQueryElement ----- //
1301
+ // use element as selector string
1302
+ utils.getQueryElement = function(elem) {
1303
+ if (typeof elem == 'string') {
1304
+ return document.querySelector(elem);
1305
+ }
1306
+ return elem;
1307
+ };
1308
+
1309
+ // ----- handleEvent ----- //
1310
+ // enable .ontype to trigger from .addEventListener( elem, 'type' )
1311
+ utils.handleEvent = function(event) {
1312
+ var method = 'on' + event.type;
1313
+ if (this[method]) {
1314
+ this[method](event);
1315
+ }
1316
+ };
1317
+
1318
+ // ----- filterFindElements ----- //
1319
+ utils.filterFindElements = function(elems, selector) {
1320
+ // make array of elems
1321
+ elems = utils.makeArray(elems);
1322
+ var ffElems = [];
1323
+
1324
+ for (var i = 0, len = elems.length; i < len; i++) {
1325
+ var elem = elems[i];
1326
+ // check that elem is an actual element
1327
+ if (!utils.isElement(elem)) {
1328
+ continue;
1329
+ }
1330
+ // filter & find items if we have a selector
1331
+ if (selector) {
1332
+ // filter siblings
1333
+ if (matchesSelector(elem, selector)) {
1334
+ ffElems.push(elem);
1335
+ }
1336
+ // find children
1337
+ var childElems = elem.querySelectorAll(selector);
1338
+ // concat childElems to filterFound array
1339
+ for (var j = 0, jLen = childElems.length; j < jLen; j++) {
1340
+ ffElems.push(childElems[j]);
1341
+ }
1342
+ } else {
1343
+ ffElems.push(elem);
1344
+ }
1345
+ }
1346
+
1347
+ return ffElems;
1348
+ };
1349
+
1350
+ // ----- debounceMethod ----- //
1351
+ utils.debounceMethod = function(_class, methodName, threshold) {
1352
+ // original method
1353
+ var method = _class.prototype[methodName];
1354
+ var timeoutName = methodName + 'Timeout';
1355
+
1356
+ _class.prototype[methodName] = function() {
1357
+ var timeout = this[timeoutName];
1358
+ if (timeout) {
1359
+ clearTimeout(timeout);
1360
+ }
1361
+ var args = arguments;
1362
+
1363
+ var _this = this;
1364
+ this[timeoutName] = setTimeout(function() {
1365
+ method.apply(_this, args);
1366
+ delete _this[timeoutName];
1367
+ }, threshold || 100);
1368
+ };
1369
+ };
1370
+
1371
+ // ----- htmlInit ----- //
1372
+ // http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
1373
+ utils.toDashed = function(str) {
1374
+ return str.replace(/(.)([A-Z])/g, function(match, $1, $2) {
1375
+ return $1 + '-' + $2;
1376
+ }).toLowerCase();
1377
+ };
1378
+
1379
+ var console = window.console;
1380
+ /**
1381
+ * allow user to initialize classes via .js-namespace class
1382
+ * htmlInit( Widget, 'widgetName' )
1383
+ * options are parsed from data-namespace-option attribute
1384
+ */
1385
+ utils.htmlInit = function(WidgetClass, namespace) {
1386
+ docReady(function() {
1387
+ var dashedNamespace = utils.toDashed(namespace);
1388
+ var elems = document.querySelectorAll('.js-' + dashedNamespace);
1389
+ var dataAttr = 'data-' + dashedNamespace + '-options';
1390
+
1391
+ for (var i = 0, len = elems.length; i < len; i++) {
1392
+ var elem = elems[i];
1393
+ var attr = elem.getAttribute(dataAttr);
1394
+ var options;
1395
+ try {
1396
+ options = attr && JSON.parse(attr);
1397
+ } catch (error) {
1398
+ // log error, do not initialize
1399
+ if (console) {
1400
+ console.error('Error parsing ' + dataAttr + ' on ' + elem.nodeName.toLowerCase() + (elem.id ? '#' + elem.id : '') + ': ' + error);
1401
+ }
1402
+ continue;
1403
+ }
1404
+ // initialize
1405
+ var instance = new WidgetClass(elem, options);
1406
+ // make available via $().data('layoutname')
1407
+ var jQuery = window.jQuery;
1408
+ if (jQuery) {
1409
+ jQuery.data(elem, namespace, instance);
1410
+ }
1411
+ }
1412
+ });
1413
+ };
1414
+
1415
+ // ----- ----- //
1416
+ return utils;
1417
+
1418
+ }));
1419
+
1420
+ /**
1421
+ * Outlayer Item
1422
+ */
1423
+
1424
+ (function(window, factory) {
1425
+
1426
+ // universal module definition
1427
+ if (typeof define === 'function' && define.amd) {
1428
+ // AMD
1429
+ define('outlayer/item', ['eventEmitter/EventEmitter', 'get-size/get-size', 'get-style-property/get-style-property', 'fizzy-ui-utils/utils'], function(EventEmitter, getSize, getStyleProperty, utils) {
1430
+ return factory(window, EventEmitter, getSize, getStyleProperty, utils);
1431
+ });
1432
+ } else if (typeof exports === 'object') {
1433
+ // CommonJS
1434
+ module.exports = factory(
1435
+ window, require('wolfy87-eventemitter'), require('get-size'), require('desandro-get-style-property'), require('fizzy-ui-utils'));
1436
+ } else {
1437
+ // browser global
1438
+ window.Outlayer = {};
1439
+ window.Outlayer.Item = factory(
1440
+ window, window.EventEmitter, window.getSize, window.getStyleProperty, window.fizzyUIUtils);
1441
+ }
1442
+
1443
+ }(window, function factory(window, EventEmitter, getSize, getStyleProperty, utils) {
1444
+
1445
+
1446
+ // ----- helpers ----- //
1447
+ var getComputedStyle = window.getComputedStyle;
1448
+ var getStyle = getComputedStyle ?
1449
+ function(elem) {
1450
+ return getComputedStyle(elem, null);
1451
+ } : function(elem) {
1452
+ return elem.currentStyle;
1453
+ };
1454
+
1455
+
1456
+ function isEmptyObj(obj) {
1457
+ for (var prop in obj) {
1458
+ return false;
1459
+ }
1460
+ prop = null;
1461
+ return true;
1462
+ }
1463
+
1464
+ // -------------------------- CSS3 support -------------------------- //
1465
+ var transitionProperty = getStyleProperty('transition');
1466
+ var transformProperty = getStyleProperty('transform');
1467
+ var supportsCSS3 = transitionProperty && transformProperty;
1468
+ var is3d = !! getStyleProperty('perspective');
1469
+
1470
+ var transitionEndEvent = {
1471
+ WebkitTransition: 'webkitTransitionEnd',
1472
+ MozTransition: 'transitionend',
1473
+ OTransition: 'otransitionend',
1474
+ transition: 'transitionend'
1475
+ }[transitionProperty];
1476
+
1477
+ // properties that could have vendor prefix
1478
+ var prefixableProperties = ['transform', 'transition', 'transitionDuration', 'transitionProperty'];
1479
+
1480
+ // cache all vendor properties
1481
+ var vendorProperties = (function() {
1482
+ var cache = {};
1483
+ for (var i = 0, len = prefixableProperties.length; i < len; i++) {
1484
+ var prop = prefixableProperties[i];
1485
+ var supportedProp = getStyleProperty(prop);
1486
+ if (supportedProp && supportedProp !== prop) {
1487
+ cache[prop] = supportedProp;
1488
+ }
1489
+ }
1490
+ return cache;
1491
+ })();
1492
+
1493
+ // -------------------------- Item -------------------------- //
1494
+
1495
+ function Item(element, layout) {
1496
+ if (!element) {
1497
+ return;
1498
+ }
1499
+
1500
+ this.element = element;
1501
+ // parent layout class, i.e. Masonry, Isotope, or Packery
1502
+ this.layout = layout;
1503
+ this.position = {
1504
+ x: 0,
1505
+ y: 0
1506
+ };
1507
+
1508
+ this._create();
1509
+ }
1510
+
1511
+ // inherit EventEmitter
1512
+ utils.extend(Item.prototype, EventEmitter.prototype);
1513
+
1514
+ Item.prototype._create = function() {
1515
+ // transition objects
1516
+ this._transn = {
1517
+ ingProperties: {},
1518
+ clean: {},
1519
+ onEnd: {}
1520
+ };
1521
+
1522
+ this.css({
1523
+ position: 'absolute'
1524
+ });
1525
+ };
1526
+
1527
+ // trigger specified handler for event type
1528
+ Item.prototype.handleEvent = function(event) {
1529
+ var method = 'on' + event.type;
1530
+ if (this[method]) {
1531
+ this[method](event);
1532
+ }
1533
+ };
1534
+
1535
+ Item.prototype.getSize = function() {
1536
+ this.size = getSize(this.element);
1537
+ };
1538
+
1539
+ /**
1540
+ * apply CSS styles to element
1541
+ * @param {Object} style
1542
+ */
1543
+ Item.prototype.css = function(style) {
1544
+ var elemStyle = this.element.style;
1545
+
1546
+ for (var prop in style) {
1547
+ // use vendor property if available
1548
+ var supportedProp = vendorProperties[prop] || prop;
1549
+ elemStyle[supportedProp] = style[prop];
1550
+ }
1551
+ };
1552
+
1553
+ // measure position, and sets it
1554
+ Item.prototype.getPosition = function() {
1555
+ var style = getStyle(this.element);
1556
+ var layoutOptions = this.layout.options;
1557
+ var isOriginLeft = layoutOptions.isOriginLeft;
1558
+ var isOriginTop = layoutOptions.isOriginTop;
1559
+ var x = parseInt(style[isOriginLeft ? 'left' : 'right'], 10);
1560
+ var y = parseInt(style[isOriginTop ? 'top' : 'bottom'], 10);
1561
+
1562
+ // clean up 'auto' or other non-integer values
1563
+ x = isNaN(x) ? 0 : x;
1564
+ y = isNaN(y) ? 0 : y;
1565
+ // remove padding from measurement
1566
+ var layoutSize = this.layout.size;
1567
+ x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
1568
+ y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
1569
+
1570
+ this.position.x = x;
1571
+ this.position.y = y;
1572
+ };
1573
+
1574
+ // set settled position, apply padding
1575
+ Item.prototype.layoutPosition = function() {
1576
+ var layoutSize = this.layout.size;
1577
+ var layoutOptions = this.layout.options;
1578
+ var style = {};
1579
+
1580
+ // x
1581
+ var xPadding = layoutOptions.isOriginLeft ? 'paddingLeft' : 'paddingRight';
1582
+ var xProperty = layoutOptions.isOriginLeft ? 'left' : 'right';
1583
+ var xResetProperty = layoutOptions.isOriginLeft ? 'right' : 'left';
1584
+
1585
+ var x = this.position.x + layoutSize[xPadding];
1586
+ // set in percentage
1587
+ x = layoutOptions.percentPosition && !layoutOptions.isHorizontal ? ((x / layoutSize.width) * 100) + '%' : x + 'px';
1588
+ style[xProperty] = x;
1589
+ // reset other property
1590
+ style[xResetProperty] = '';
1591
+
1592
+ // y
1593
+ var yPadding = layoutOptions.isOriginTop ? 'paddingTop' : 'paddingBottom';
1594
+ var yProperty = layoutOptions.isOriginTop ? 'top' : 'bottom';
1595
+ var yResetProperty = layoutOptions.isOriginTop ? 'bottom' : 'top';
1596
+
1597
+ var y = this.position.y + layoutSize[yPadding];
1598
+ // set in percentage
1599
+ y = layoutOptions.percentPosition && layoutOptions.isHorizontal ? ((y / layoutSize.height) * 100) + '%' : y + 'px';
1600
+ style[yProperty] = y;
1601
+ // reset other property
1602
+ style[yResetProperty] = '';
1603
+
1604
+ this.css(style);
1605
+ this.emitEvent('layout', [this]);
1606
+ };
1607
+
1608
+
1609
+ // transform translate function
1610
+ var translate = is3d ?
1611
+ function(x, y) {
1612
+ return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
1613
+ } : function(x, y) {
1614
+ return 'translate(' + x + 'px, ' + y + 'px)';
1615
+ };
1616
+
1617
+
1618
+ Item.prototype._transitionTo = function(x, y) {
1619
+ this.getPosition();
1620
+ // get current x & y from top/left
1621
+ var curX = this.position.x;
1622
+ var curY = this.position.y;
1623
+
1624
+ var compareX = parseInt(x, 10);
1625
+ var compareY = parseInt(y, 10);
1626
+ var didNotMove = compareX === this.position.x && compareY === this.position.y;
1627
+
1628
+ // save end position
1629
+ this.setPosition(x, y);
1630
+
1631
+ // if did not move and not transitioning, just go to layout
1632
+ if (didNotMove && !this.isTransitioning) {
1633
+ this.layoutPosition();
1634
+ return;
1635
+ }
1636
+
1637
+ var transX = x - curX;
1638
+ var transY = y - curY;
1639
+ var transitionStyle = {};
1640
+ // flip cooridinates if origin on right or bottom
1641
+ var layoutOptions = this.layout.options;
1642
+ transX = layoutOptions.isOriginLeft ? transX : -transX;
1643
+ transY = layoutOptions.isOriginTop ? transY : -transY;
1644
+ transitionStyle.transform = translate(transX, transY);
1645
+
1646
+ this.transition({
1647
+ to: transitionStyle,
1648
+ onTransitionEnd: {
1649
+ transform: this.layoutPosition
1650
+ },
1651
+ isCleaning: true
1652
+ });
1653
+ };
1654
+
1655
+ // non transition + transform support
1656
+ Item.prototype.goTo = function(x, y) {
1657
+ this.setPosition(x, y);
1658
+ this.layoutPosition();
1659
+ };
1660
+
1661
+ // use transition and transforms if supported
1662
+ Item.prototype.moveTo = supportsCSS3 ? Item.prototype._transitionTo : Item.prototype.goTo;
1663
+
1664
+ Item.prototype.setPosition = function(x, y) {
1665
+ this.position.x = parseInt(x, 10);
1666
+ this.position.y = parseInt(y, 10);
1667
+ };
1668
+
1669
+ // ----- transition ----- //
1670
+ /**
1671
+ * @param {Object} style - CSS
1672
+ * @param {Function} onTransitionEnd
1673
+ */
1674
+
1675
+ // non transition, just trigger callback
1676
+ Item.prototype._nonTransition = function(args) {
1677
+ this.css(args.to);
1678
+ if (args.isCleaning) {
1679
+ this._removeStyles(args.to);
1680
+ }
1681
+ for (var prop in args.onTransitionEnd) {
1682
+ args.onTransitionEnd[prop].call(this);
1683
+ }
1684
+ };
1685
+
1686
+ /**
1687
+ * proper transition
1688
+ * @param {Object} args - arguments
1689
+ * @param {Object} to - style to transition to
1690
+ * @param {Object} from - style to start transition from
1691
+ * @param {Boolean} isCleaning - removes transition styles after transition
1692
+ * @param {Function} onTransitionEnd - callback
1693
+ */
1694
+ Item.prototype._transition = function(args) {
1695
+ // redirect to nonTransition if no transition duration
1696
+ if (!parseFloat(this.layout.options.transitionDuration)) {
1697
+ this._nonTransition(args);
1698
+ return;
1699
+ }
1700
+
1701
+ var _transition = this._transn;
1702
+ // keep track of onTransitionEnd callback by css property
1703
+ for (var prop in args.onTransitionEnd) {
1704
+ _transition.onEnd[prop] = args.onTransitionEnd[prop];
1705
+ }
1706
+ // keep track of properties that are transitioning
1707
+ for (prop in args.to) {
1708
+ _transition.ingProperties[prop] = true;
1709
+ // keep track of properties to clean up when transition is done
1710
+ if (args.isCleaning) {
1711
+ _transition.clean[prop] = true;
1712
+ }
1713
+ }
1714
+
1715
+ // set from styles
1716
+ if (args.from) {
1717
+ this.css(args.from);
1718
+ // force redraw. http://blog.alexmaccaw.com/css-transitions
1719
+ var h = this.element.offsetHeight;
1720
+ // hack for JSHint to hush about unused var
1721
+ h = null;
1722
+ }
1723
+ // enable transition
1724
+ this.enableTransition(args.to);
1725
+ // set styles that are transitioning
1726
+ this.css(args.to);
1727
+
1728
+ this.isTransitioning = true;
1729
+
1730
+ };
1731
+
1732
+ var itemTransitionProperties = transformProperty && (utils.toDashed(transformProperty) + ',opacity');
1733
+
1734
+ Item.prototype.enableTransition = function( /* style */ ) {
1735
+ // only enable if not already transitioning
1736
+ // bug in IE10 were re-setting transition style will prevent
1737
+ // transitionend event from triggering
1738
+ if (this.isTransitioning) {
1739
+ return;
1740
+ }
1741
+
1742
+ // make transition: foo, bar, baz from style object
1743
+ // TODO uncomment this bit when IE10 bug is resolved
1744
+ // var transitionValue = [];
1745
+ // for ( var prop in style ) {
1746
+ // // dash-ify camelCased properties like WebkitTransition
1747
+ // transitionValue.push( toDash( prop ) );
1748
+ // }
1749
+ // enable transition styles
1750
+ // HACK always enable transform,opacity for IE10
1751
+ this.css({
1752
+ transitionProperty: itemTransitionProperties,
1753
+ transitionDuration: this.layout.options.transitionDuration
1754
+ });
1755
+ // listen for transition end event
1756
+ this.element.addEventListener(transitionEndEvent, this, false);
1757
+ };
1758
+
1759
+ Item.prototype.transition = Item.prototype[transitionProperty ? '_transition' : '_nonTransition'];
1760
+
1761
+ // ----- events ----- //
1762
+ Item.prototype.onwebkitTransitionEnd = function(event) {
1763
+ this.ontransitionend(event);
1764
+ };
1765
+
1766
+ Item.prototype.onotransitionend = function(event) {
1767
+ this.ontransitionend(event);
1768
+ };
1769
+
1770
+ // properties that I munge to make my life easier
1771
+ var dashedVendorProperties = {
1772
+ '-webkit-transform': 'transform',
1773
+ '-moz-transform': 'transform',
1774
+ '-o-transform': 'transform'
1775
+ };
1776
+
1777
+ Item.prototype.ontransitionend = function(event) {
1778
+ // disregard bubbled events from children
1779
+ if (event.target !== this.element) {
1780
+ return;
1781
+ }
1782
+ var _transition = this._transn;
1783
+ // get property name of transitioned property, convert to prefix-free
1784
+ var propertyName = dashedVendorProperties[event.propertyName] || event.propertyName;
1785
+
1786
+ // remove property that has completed transitioning
1787
+ delete _transition.ingProperties[propertyName];
1788
+ // check if any properties are still transitioning
1789
+ if (isEmptyObj(_transition.ingProperties)) {
1790
+ // all properties have completed transitioning
1791
+ this.disableTransition();
1792
+ }
1793
+ // clean style
1794
+ if (propertyName in _transition.clean) {
1795
+ // clean up style
1796
+ this.element.style[event.propertyName] = '';
1797
+ delete _transition.clean[propertyName];
1798
+ }
1799
+ // trigger onTransitionEnd callback
1800
+ if (propertyName in _transition.onEnd) {
1801
+ var onTransitionEnd = _transition.onEnd[propertyName];
1802
+ onTransitionEnd.call(this);
1803
+ delete _transition.onEnd[propertyName];
1804
+ }
1805
+
1806
+ this.emitEvent('transitionEnd', [this]);
1807
+ };
1808
+
1809
+ Item.prototype.disableTransition = function() {
1810
+ this.removeTransitionStyles();
1811
+ this.element.removeEventListener(transitionEndEvent, this, false);
1812
+ this.isTransitioning = false;
1813
+ };
1814
+
1815
+ /**
1816
+ * removes style property from element
1817
+ * @param {Object} style
1818
+ **/
1819
+ Item.prototype._removeStyles = function(style) {
1820
+ // clean up transition styles
1821
+ var cleanStyle = {};
1822
+ for (var prop in style) {
1823
+ cleanStyle[prop] = '';
1824
+ }
1825
+ this.css(cleanStyle);
1826
+ };
1827
+
1828
+ var cleanTransitionStyle = {
1829
+ transitionProperty: '',
1830
+ transitionDuration: ''
1831
+ };
1832
+
1833
+ Item.prototype.removeTransitionStyles = function() {
1834
+ // remove transition
1835
+ this.css(cleanTransitionStyle);
1836
+ };
1837
+
1838
+ // ----- show/hide/remove ----- //
1839
+ // remove element from DOM
1840
+ Item.prototype.removeElem = function() {
1841
+ this.element.parentNode.removeChild(this.element);
1842
+ // remove display: none
1843
+ this.css({
1844
+ display: ''
1845
+ });
1846
+ this.emitEvent('remove', [this]);
1847
+ };
1848
+
1849
+ Item.prototype.remove = function() {
1850
+ // just remove element if no transition support or no transition
1851
+ if (!transitionProperty || !parseFloat(this.layout.options.transitionDuration)) {
1852
+ this.removeElem();
1853
+ return;
1854
+ }
1855
+
1856
+ // start transition
1857
+ var _this = this;
1858
+ this.once('transitionEnd', function() {
1859
+ _this.removeElem();
1860
+ });
1861
+ this.hide();
1862
+ };
1863
+
1864
+ Item.prototype.reveal = function() {
1865
+ delete this.isHidden;
1866
+ // remove display: none
1867
+ this.css({
1868
+ display: ''
1869
+ });
1870
+
1871
+ var options = this.layout.options;
1872
+
1873
+ var onTransitionEnd = {};
1874
+ var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
1875
+ onTransitionEnd[transitionEndProperty] = this.onRevealTransitionEnd;
1876
+
1877
+ this.transition({
1878
+ from: options.hiddenStyle,
1879
+ to: options.visibleStyle,
1880
+ isCleaning: true,
1881
+ onTransitionEnd: onTransitionEnd
1882
+ });
1883
+ };
1884
+
1885
+ Item.prototype.onRevealTransitionEnd = function() {
1886
+ // check if still visible
1887
+ // during transition, item may have been hidden
1888
+ if (!this.isHidden) {
1889
+ this.emitEvent('reveal');
1890
+ }
1891
+ };
1892
+
1893
+ /**
1894
+ * get style property use for hide/reveal transition end
1895
+ * @param {String} styleProperty - hiddenStyle/visibleStyle
1896
+ * @returns {String}
1897
+ */
1898
+ Item.prototype.getHideRevealTransitionEndProperty = function(styleProperty) {
1899
+ var optionStyle = this.layout.options[styleProperty];
1900
+ // use opacity
1901
+ if (optionStyle.opacity) {
1902
+ return 'opacity';
1903
+ }
1904
+ // get first property
1905
+ for (var prop in optionStyle) {
1906
+ return prop;
1907
+ }
1908
+ };
1909
+
1910
+ Item.prototype.hide = function() {
1911
+ // set flag
1912
+ this.isHidden = true;
1913
+ // remove display: none
1914
+ this.css({
1915
+ display: ''
1916
+ });
1917
+
1918
+ var options = this.layout.options;
1919
+
1920
+ var onTransitionEnd = {};
1921
+ var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
1922
+ onTransitionEnd[transitionEndProperty] = this.onHideTransitionEnd;
1923
+
1924
+ this.transition({
1925
+ from: options.visibleStyle,
1926
+ to: options.hiddenStyle,
1927
+ // keep hidden stuff hidden
1928
+ isCleaning: true,
1929
+ onTransitionEnd: onTransitionEnd
1930
+ });
1931
+ };
1932
+
1933
+ Item.prototype.onHideTransitionEnd = function() {
1934
+ // check if still hidden
1935
+ // during transition, item may have been un-hidden
1936
+ if (this.isHidden) {
1937
+ this.css({
1938
+ display: 'none'
1939
+ });
1940
+ this.emitEvent('hide');
1941
+ }
1942
+ };
1943
+
1944
+ Item.prototype.destroy = function() {
1945
+ this.css({
1946
+ position: '',
1947
+ left: '',
1948
+ right: '',
1949
+ top: '',
1950
+ bottom: '',
1951
+ transition: '',
1952
+ transform: ''
1953
+ });
1954
+ };
1955
+
1956
+ return Item;
1957
+
1958
+ }));
1959
+
1960
+ /*!
1961
+ * Outlayer v1.4.0
1962
+ * the brains and guts of a layout library
1963
+ * MIT license
1964
+ */
1965
+
1966
+ (function(window, factory) {
1967
+
1968
+ // universal module definition
1969
+ if (typeof define == 'function' && define.amd) {
1970
+ // AMD
1971
+ define('outlayer/outlayer', ['eventie/eventie', 'eventEmitter/EventEmitter', 'get-size/get-size', 'fizzy-ui-utils/utils', './item'], function(eventie, EventEmitter, getSize, utils, Item) {
1972
+ return factory(window, eventie, EventEmitter, getSize, utils, Item);
1973
+ });
1974
+ } else if (typeof exports == 'object') {
1975
+ // CommonJS
1976
+ module.exports = factory(
1977
+ window, require('eventie'), require('wolfy87-eventemitter'), require('get-size'), require('fizzy-ui-utils'), require('./item'));
1978
+ } else {
1979
+ // browser global
1980
+ window.Outlayer = factory(
1981
+ window, window.eventie, window.EventEmitter, window.getSize, window.fizzyUIUtils, window.Outlayer.Item);
1982
+ }
1983
+
1984
+ }(window, function factory(window, eventie, EventEmitter, getSize, utils, Item) {
1985
+
1986
+
1987
+ // ----- vars ----- //
1988
+ var console = window.console;
1989
+ var jQuery = window.jQuery;
1990
+ var noop = function() {};
1991
+
1992
+ // -------------------------- Outlayer -------------------------- //
1993
+ // globally unique identifiers
1994
+ var GUID = 0;
1995
+ // internal store of all Outlayer intances
1996
+ var instances = {};
1997
+
1998
+
1999
+ /**
2000
+ * @param {Element, String} element
2001
+ * @param {Object} options
2002
+ * @constructor
2003
+ */
2004
+
2005
+ function Outlayer(element, options) {
2006
+ var queryElement = utils.getQueryElement(element);
2007
+ if (!queryElement) {
2008
+ if (console) {
2009
+ console.error('Bad element for ' + this.constructor.namespace + ': ' + (queryElement || element));
2010
+ }
2011
+ return;
2012
+ }
2013
+ this.element = queryElement;
2014
+ // add jQuery
2015
+ if (jQuery) {
2016
+ this.$element = jQuery(this.element);
2017
+ }
2018
+
2019
+ // options
2020
+ this.options = utils.extend({}, this.constructor.defaults);
2021
+ this.option(options);
2022
+
2023
+ // add id for Outlayer.getFromElement
2024
+ var id = ++GUID;
2025
+ this.element.outlayerGUID = id; // expando
2026
+ instances[id] = this; // associate via id
2027
+ // kick it off
2028
+ this._create();
2029
+
2030
+ if (this.options.isInitLayout) {
2031
+ this.layout();
2032
+ }
2033
+ }
2034
+
2035
+ // settings are for internal use only
2036
+ Outlayer.namespace = 'outlayer';
2037
+ Outlayer.Item = Item;
2038
+
2039
+ // default options
2040
+ Outlayer.defaults = {
2041
+ containerStyle: {
2042
+ position: 'relative'
2043
+ },
2044
+ isInitLayout: true,
2045
+ isOriginLeft: true,
2046
+ isOriginTop: true,
2047
+ isResizeBound: true,
2048
+ isResizingContainer: true,
2049
+ // item options
2050
+ transitionDuration: '0.4s',
2051
+ hiddenStyle: {
2052
+ opacity: 0,
2053
+ transform: 'scale(0.001)'
2054
+ },
2055
+ visibleStyle: {
2056
+ opacity: 1,
2057
+ transform: 'scale(1)'
2058
+ }
2059
+ };
2060
+
2061
+ // inherit EventEmitter
2062
+ utils.extend(Outlayer.prototype, EventEmitter.prototype);
2063
+
2064
+ /**
2065
+ * set options
2066
+ * @param {Object} opts
2067
+ */
2068
+ Outlayer.prototype.option = function(opts) {
2069
+ utils.extend(this.options, opts);
2070
+ };
2071
+
2072
+ Outlayer.prototype._create = function() {
2073
+ // get items from children
2074
+ this.reloadItems();
2075
+ // elements that affect layout, but are not laid out
2076
+ this.stamps = [];
2077
+ this.stamp(this.options.stamp);
2078
+ // set container style
2079
+ utils.extend(this.element.style, this.options.containerStyle);
2080
+
2081
+ // bind resize method
2082
+ if (this.options.isResizeBound) {
2083
+ this.bindResize();
2084
+ }
2085
+ };
2086
+
2087
+ // goes through all children again and gets bricks in proper order
2088
+ Outlayer.prototype.reloadItems = function() {
2089
+ // collection of item elements
2090
+ this.items = this._itemize(this.element.children);
2091
+ };
2092
+
2093
+
2094
+ /**
2095
+ * turn elements into Outlayer.Items to be used in layout
2096
+ * @param {Array or NodeList or HTMLElement} elems
2097
+ * @returns {Array} items - collection of new Outlayer Items
2098
+ */
2099
+ Outlayer.prototype._itemize = function(elems) {
2100
+
2101
+ var itemElems = this._filterFindItemElements(elems);
2102
+ var Item = this.constructor.Item;
2103
+
2104
+ // create new Outlayer Items for collection
2105
+ var items = [];
2106
+ for (var i = 0, len = itemElems.length; i < len; i++) {
2107
+ var elem = itemElems[i];
2108
+ var item = new Item(elem, this);
2109
+ items.push(item);
2110
+ }
2111
+
2112
+ return items;
2113
+ };
2114
+
2115
+ /**
2116
+ * get item elements to be used in layout
2117
+ * @param {Array or NodeList or HTMLElement} elems
2118
+ * @returns {Array} items - item elements
2119
+ */
2120
+ Outlayer.prototype._filterFindItemElements = function(elems) {
2121
+ return utils.filterFindElements(elems, this.options.itemSelector);
2122
+ };
2123
+
2124
+ /**
2125
+ * getter method for getting item elements
2126
+ * @returns {Array} elems - collection of item elements
2127
+ */
2128
+ Outlayer.prototype.getItemElements = function() {
2129
+ var elems = [];
2130
+ for (var i = 0, len = this.items.length; i < len; i++) {
2131
+ elems.push(this.items[i].element);
2132
+ }
2133
+ return elems;
2134
+ };
2135
+
2136
+ // ----- init & layout ----- //
2137
+ /**
2138
+ * lays out all items
2139
+ */
2140
+ Outlayer.prototype.layout = function() {
2141
+ this._resetLayout();
2142
+ this._manageStamps();
2143
+
2144
+ // don't animate first layout
2145
+ var isInstant = this.options.isLayoutInstant !== undefined ? this.options.isLayoutInstant : !this._isLayoutInited;
2146
+ this.layoutItems(this.items, isInstant);
2147
+
2148
+ // flag for initalized
2149
+ this._isLayoutInited = true;
2150
+ };
2151
+
2152
+ // _init is alias for layout
2153
+ Outlayer.prototype._init = Outlayer.prototype.layout;
2154
+
2155
+ /**
2156
+ * logic before any new layout
2157
+ */
2158
+ Outlayer.prototype._resetLayout = function() {
2159
+ this.getSize();
2160
+ };
2161
+
2162
+
2163
+ Outlayer.prototype.getSize = function() {
2164
+ this.size = getSize(this.element);
2165
+ };
2166
+
2167
+ /**
2168
+ * get measurement from option, for columnWidth, rowHeight, gutter
2169
+ * if option is String -> get element from selector string, & get size of element
2170
+ * if option is Element -> get size of element
2171
+ * else use option as a number
2172
+ *
2173
+ * @param {String} measurement
2174
+ * @param {String} size - width or height
2175
+ * @private
2176
+ */
2177
+ Outlayer.prototype._getMeasurement = function(measurement, size) {
2178
+ var option = this.options[measurement];
2179
+ var elem;
2180
+ if (!option) {
2181
+ // default to 0
2182
+ this[measurement] = 0;
2183
+ } else {
2184
+ // use option as an element
2185
+ if (typeof option === 'string') {
2186
+ elem = this.element.querySelector(option);
2187
+ } else if (utils.isElement(option)) {
2188
+ elem = option;
2189
+ }
2190
+ // use size of element, if element
2191
+ this[measurement] = elem ? getSize(elem)[size] : option;
2192
+ }
2193
+ };
2194
+
2195
+ /**
2196
+ * layout a collection of item elements
2197
+ * @api public
2198
+ */
2199
+ Outlayer.prototype.layoutItems = function(items, isInstant) {
2200
+ items = this._getItemsForLayout(items);
2201
+
2202
+ this._layoutItems(items, isInstant);
2203
+
2204
+ this._postLayout();
2205
+ };
2206
+
2207
+ /**
2208
+ * get the items to be laid out
2209
+ * you may want to skip over some items
2210
+ * @param {Array} items
2211
+ * @returns {Array} items
2212
+ */
2213
+ Outlayer.prototype._getItemsForLayout = function(items) {
2214
+ var layoutItems = [];
2215
+ for (var i = 0, len = items.length; i < len; i++) {
2216
+ var item = items[i];
2217
+ if (!item.isIgnored) {
2218
+ layoutItems.push(item);
2219
+ }
2220
+ }
2221
+ return layoutItems;
2222
+ };
2223
+
2224
+ /**
2225
+ * layout items
2226
+ * @param {Array} items
2227
+ * @param {Boolean} isInstant
2228
+ */
2229
+ Outlayer.prototype._layoutItems = function(items, isInstant) {
2230
+ this._emitCompleteOnItems('layout', items);
2231
+
2232
+ if (!items || !items.length) {
2233
+ // no items, emit event with empty array
2234
+ return;
2235
+ }
2236
+
2237
+ var queue = [];
2238
+
2239
+ for (var i = 0, len = items.length; i < len; i++) {
2240
+ var item = items[i];
2241
+ // get x/y object from method
2242
+ var position = this._getItemLayoutPosition(item);
2243
+ // enqueue
2244
+ position.item = item;
2245
+ position.isInstant = isInstant || item.isLayoutInstant;
2246
+ queue.push(position);
2247
+ }
2248
+
2249
+ this._processLayoutQueue(queue);
2250
+ };
2251
+
2252
+ /**
2253
+ * get item layout position
2254
+ * @param {Outlayer.Item} item
2255
+ * @returns {Object} x and y position
2256
+ */
2257
+ Outlayer.prototype._getItemLayoutPosition = function( /* item */ ) {
2258
+ return {
2259
+ x: 0,
2260
+ y: 0
2261
+ };
2262
+ };
2263
+
2264
+ /**
2265
+ * iterate over array and position each item
2266
+ * Reason being - separating this logic prevents 'layout invalidation'
2267
+ * thx @paul_irish
2268
+ * @param {Array} queue
2269
+ */
2270
+ Outlayer.prototype._processLayoutQueue = function(queue) {
2271
+ for (var i = 0, len = queue.length; i < len; i++) {
2272
+ var obj = queue[i];
2273
+ this._positionItem(obj.item, obj.x, obj.y, obj.isInstant);
2274
+ }
2275
+ };
2276
+
2277
+ /**
2278
+ * Sets position of item in DOM
2279
+ * @param {Outlayer.Item} item
2280
+ * @param {Number} x - horizontal position
2281
+ * @param {Number} y - vertical position
2282
+ * @param {Boolean} isInstant - disables transitions
2283
+ */
2284
+ Outlayer.prototype._positionItem = function(item, x, y, isInstant) {
2285
+ if (isInstant) {
2286
+ // if not transition, just set CSS
2287
+ item.goTo(x, y);
2288
+ } else {
2289
+ item.moveTo(x, y);
2290
+ }
2291
+ };
2292
+
2293
+ /**
2294
+ * Any logic you want to do after each layout,
2295
+ * i.e. size the container
2296
+ */
2297
+ Outlayer.prototype._postLayout = function() {
2298
+ this.resizeContainer();
2299
+ };
2300
+
2301
+ Outlayer.prototype.resizeContainer = function() {
2302
+ if (!this.options.isResizingContainer) {
2303
+ return;
2304
+ }
2305
+ var size = this._getContainerSize();
2306
+ if (size) {
2307
+ this._setContainerMeasure(size.width, true);
2308
+ this._setContainerMeasure(size.height, false);
2309
+ }
2310
+ };
2311
+
2312
+ /**
2313
+ * Sets width or height of container if returned
2314
+ * @returns {Object} size
2315
+ * @param {Number} width
2316
+ * @param {Number} height
2317
+ */
2318
+ Outlayer.prototype._getContainerSize = noop;
2319
+
2320
+ /**
2321
+ * @param {Number} measure - size of width or height
2322
+ * @param {Boolean} isWidth
2323
+ */
2324
+ Outlayer.prototype._setContainerMeasure = function(measure, isWidth) {
2325
+ if (measure === undefined) {
2326
+ return;
2327
+ }
2328
+
2329
+ var elemSize = this.size;
2330
+ // add padding and border width if border box
2331
+ if (elemSize.isBorderBox) {
2332
+ measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + elemSize.borderLeftWidth + elemSize.borderRightWidth : elemSize.paddingBottom + elemSize.paddingTop + elemSize.borderTopWidth + elemSize.borderBottomWidth;
2333
+ }
2334
+
2335
+ measure = Math.max(measure, 0);
2336
+ this.element.style[isWidth ? 'width' : 'height'] = measure + 'px';
2337
+ };
2338
+
2339
+ /**
2340
+ * emit eventComplete on a collection of items events
2341
+ * @param {String} eventName
2342
+ * @param {Array} items - Outlayer.Items
2343
+ */
2344
+ Outlayer.prototype._emitCompleteOnItems = function(eventName, items) {
2345
+ var _this = this;
2346
+
2347
+ function onComplete() {
2348
+ _this.emitEvent(eventName + 'Complete', [items]);
2349
+ }
2350
+
2351
+ var count = items.length;
2352
+ if (!items || !count) {
2353
+ onComplete();
2354
+ return;
2355
+ }
2356
+
2357
+ var doneCount = 0;
2358
+
2359
+ function tick() {
2360
+ doneCount++;
2361
+ if (doneCount === count) {
2362
+ onComplete();
2363
+ }
2364
+ }
2365
+
2366
+ // bind callback
2367
+ for (var i = 0, len = items.length; i < len; i++) {
2368
+ var item = items[i];
2369
+ item.once(eventName, tick);
2370
+ }
2371
+ };
2372
+
2373
+ // -------------------------- ignore & stamps -------------------------- //
2374
+
2375
+ /**
2376
+ * keep item in collection, but do not lay it out
2377
+ * ignored items do not get skipped in layout
2378
+ * @param {Element} elem
2379
+ */
2380
+ Outlayer.prototype.ignore = function(elem) {
2381
+ var item = this.getItem(elem);
2382
+ if (item) {
2383
+ item.isIgnored = true;
2384
+ }
2385
+ };
2386
+
2387
+ /**
2388
+ * return item to layout collection
2389
+ * @param {Element} elem
2390
+ */
2391
+ Outlayer.prototype.unignore = function(elem) {
2392
+ var item = this.getItem(elem);
2393
+ if (item) {
2394
+ delete item.isIgnored;
2395
+ }
2396
+ };
2397
+
2398
+ /**
2399
+ * adds elements to stamps
2400
+ * @param {NodeList, Array, Element, or String} elems
2401
+ */
2402
+ Outlayer.prototype.stamp = function(elems) {
2403
+ elems = this._find(elems);
2404
+ if (!elems) {
2405
+ return;
2406
+ }
2407
+
2408
+ this.stamps = this.stamps.concat(elems);
2409
+ // ignore
2410
+ for (var i = 0, len = elems.length; i < len; i++) {
2411
+ var elem = elems[i];
2412
+ this.ignore(elem);
2413
+ }
2414
+ };
2415
+
2416
+ /**
2417
+ * removes elements to stamps
2418
+ * @param {NodeList, Array, or Element} elems
2419
+ */
2420
+ Outlayer.prototype.unstamp = function(elems) {
2421
+ elems = this._find(elems);
2422
+ if (!elems) {
2423
+ return;
2424
+ }
2425
+
2426
+ for (var i = 0, len = elems.length; i < len; i++) {
2427
+ var elem = elems[i];
2428
+ // filter out removed stamp elements
2429
+ utils.removeFrom(this.stamps, elem);
2430
+ this.unignore(elem);
2431
+ }
2432
+
2433
+ };
2434
+
2435
+ /**
2436
+ * finds child elements
2437
+ * @param {NodeList, Array, Element, or String} elems
2438
+ * @returns {Array} elems
2439
+ */
2440
+ Outlayer.prototype._find = function(elems) {
2441
+ if (!elems) {
2442
+ return;
2443
+ }
2444
+ // if string, use argument as selector string
2445
+ if (typeof elems === 'string') {
2446
+ elems = this.element.querySelectorAll(elems);
2447
+ }
2448
+ elems = utils.makeArray(elems);
2449
+ return elems;
2450
+ };
2451
+
2452
+ Outlayer.prototype._manageStamps = function() {
2453
+ if (!this.stamps || !this.stamps.length) {
2454
+ return;
2455
+ }
2456
+
2457
+ this._getBoundingRect();
2458
+
2459
+ for (var i = 0, len = this.stamps.length; i < len; i++) {
2460
+ var stamp = this.stamps[i];
2461
+ this._manageStamp(stamp);
2462
+ }
2463
+ };
2464
+
2465
+ // update boundingLeft / Top
2466
+ Outlayer.prototype._getBoundingRect = function() {
2467
+ // get bounding rect for container element
2468
+ var boundingRect = this.element.getBoundingClientRect();
2469
+ var size = this.size;
2470
+ this._boundingRect = {
2471
+ left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
2472
+ top: boundingRect.top + size.paddingTop + size.borderTopWidth,
2473
+ right: boundingRect.right - (size.paddingRight + size.borderRightWidth),
2474
+ bottom: boundingRect.bottom - (size.paddingBottom + size.borderBottomWidth)
2475
+ };
2476
+ };
2477
+
2478
+ /**
2479
+ * @param {Element} stamp
2480
+ **/
2481
+ Outlayer.prototype._manageStamp = noop;
2482
+
2483
+ /**
2484
+ * get x/y position of element relative to container element
2485
+ * @param {Element} elem
2486
+ * @returns {Object} offset - has left, top, right, bottom
2487
+ */
2488
+ Outlayer.prototype._getElementOffset = function(elem) {
2489
+ var boundingRect = elem.getBoundingClientRect();
2490
+ var thisRect = this._boundingRect;
2491
+ var size = getSize(elem);
2492
+ var offset = {
2493
+ left: boundingRect.left - thisRect.left - size.marginLeft,
2494
+ top: boundingRect.top - thisRect.top - size.marginTop,
2495
+ right: thisRect.right - boundingRect.right - size.marginRight,
2496
+ bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
2497
+ };
2498
+ return offset;
2499
+ };
2500
+
2501
+ // -------------------------- resize -------------------------- //
2502
+ // enable event handlers for listeners
2503
+ // i.e. resize -> onresize
2504
+ Outlayer.prototype.handleEvent = function(event) {
2505
+ var method = 'on' + event.type;
2506
+ if (this[method]) {
2507
+ this[method](event);
2508
+ }
2509
+ };
2510
+
2511
+ /**
2512
+ * Bind layout to window resizing
2513
+ */
2514
+ Outlayer.prototype.bindResize = function() {
2515
+ // bind just one listener
2516
+ if (this.isResizeBound) {
2517
+ return;
2518
+ }
2519
+ eventie.bind(window, 'resize', this);
2520
+ this.isResizeBound = true;
2521
+ };
2522
+
2523
+ /**
2524
+ * Unbind layout to window resizing
2525
+ */
2526
+ Outlayer.prototype.unbindResize = function() {
2527
+ if (this.isResizeBound) {
2528
+ eventie.unbind(window, 'resize', this);
2529
+ }
2530
+ this.isResizeBound = false;
2531
+ };
2532
+
2533
+ // original debounce by John Hann
2534
+ // http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
2535
+ // this fires every resize
2536
+ Outlayer.prototype.onresize = function() {
2537
+ if (this.resizeTimeout) {
2538
+ clearTimeout(this.resizeTimeout);
2539
+ }
2540
+
2541
+ var _this = this;
2542
+
2543
+ function delayed() {
2544
+ _this.resize();
2545
+ delete _this.resizeTimeout;
2546
+ }
2547
+
2548
+ this.resizeTimeout = setTimeout(delayed, 100);
2549
+ };
2550
+
2551
+ // debounced, layout on resize
2552
+ Outlayer.prototype.resize = function() {
2553
+ // don't trigger if size did not change
2554
+ // or if resize was unbound. See #9
2555
+ if (!this.isResizeBound || !this.needsResizeLayout()) {
2556
+ return;
2557
+ }
2558
+
2559
+ this.layout();
2560
+ };
2561
+
2562
+ /**
2563
+ * check if layout is needed post layout
2564
+ * @returns Boolean
2565
+ */
2566
+ Outlayer.prototype.needsResizeLayout = function() {
2567
+ var size = getSize(this.element);
2568
+ // check that this.size and size are there
2569
+ // IE8 triggers resize on body size change, so they might not be
2570
+ var hasSizes = this.size && size;
2571
+ return hasSizes && size.innerWidth !== this.size.innerWidth;
2572
+ };
2573
+
2574
+ // -------------------------- methods -------------------------- //
2575
+ /**
2576
+ * add items to Outlayer instance
2577
+ * @param {Array or NodeList or Element} elems
2578
+ * @returns {Array} items - Outlayer.Items
2579
+ **/
2580
+ Outlayer.prototype.addItems = function(elems) {
2581
+ var items = this._itemize(elems);
2582
+ // add items to collection
2583
+ if (items.length) {
2584
+ this.items = this.items.concat(items);
2585
+ }
2586
+ return items;
2587
+ };
2588
+
2589
+ /**
2590
+ * Layout newly-appended item elements
2591
+ * @param {Array or NodeList or Element} elems
2592
+ */
2593
+ Outlayer.prototype.appended = function(elems) {
2594
+ var items = this.addItems(elems);
2595
+ if (!items.length) {
2596
+ return;
2597
+ }
2598
+ // layout and reveal just the new items
2599
+ this.layoutItems(items, true);
2600
+ this.reveal(items);
2601
+ };
2602
+
2603
+ /**
2604
+ * Layout prepended elements
2605
+ * @param {Array or NodeList or Element} elems
2606
+ */
2607
+ Outlayer.prototype.prepended = function(elems) {
2608
+ var items = this._itemize(elems);
2609
+ if (!items.length) {
2610
+ return;
2611
+ }
2612
+ // add items to beginning of collection
2613
+ var previousItems = this.items.slice(0);
2614
+ this.items = items.concat(previousItems);
2615
+ // start new layout
2616
+ this._resetLayout();
2617
+ this._manageStamps();
2618
+ // layout new stuff without transition
2619
+ this.layoutItems(items, true);
2620
+ this.reveal(items);
2621
+ // layout previous items
2622
+ this.layoutItems(previousItems);
2623
+ };
2624
+
2625
+ /**
2626
+ * reveal a collection of items
2627
+ * @param {Array of Outlayer.Items} items
2628
+ */
2629
+ Outlayer.prototype.reveal = function(items) {
2630
+ this._emitCompleteOnItems('reveal', items);
2631
+
2632
+ var len = items && items.length;
2633
+ for (var i = 0; len && i < len; i++) {
2634
+ var item = items[i];
2635
+ item.reveal();
2636
+ }
2637
+ };
2638
+
2639
+ /**
2640
+ * hide a collection of items
2641
+ * @param {Array of Outlayer.Items} items
2642
+ */
2643
+ Outlayer.prototype.hide = function(items) {
2644
+ this._emitCompleteOnItems('hide', items);
2645
+
2646
+ var len = items && items.length;
2647
+ for (var i = 0; len && i < len; i++) {
2648
+ var item = items[i];
2649
+ item.hide();
2650
+ }
2651
+ };
2652
+
2653
+ /**
2654
+ * reveal item elements
2655
+ * @param {Array}, {Element}, {NodeList} items
2656
+ */
2657
+ Outlayer.prototype.revealItemElements = function(elems) {
2658
+ var items = this.getItems(elems);
2659
+ this.reveal(items);
2660
+ };
2661
+
2662
+ /**
2663
+ * hide item elements
2664
+ * @param {Array}, {Element}, {NodeList} items
2665
+ */
2666
+ Outlayer.prototype.hideItemElements = function(elems) {
2667
+ var items = this.getItems(elems);
2668
+ this.hide(items);
2669
+ };
2670
+
2671
+ /**
2672
+ * get Outlayer.Item, given an Element
2673
+ * @param {Element} elem
2674
+ * @param {Function} callback
2675
+ * @returns {Outlayer.Item} item
2676
+ */
2677
+ Outlayer.prototype.getItem = function(elem) {
2678
+ // loop through items to get the one that matches
2679
+ for (var i = 0, len = this.items.length; i < len; i++) {
2680
+ var item = this.items[i];
2681
+ if (item.element === elem) {
2682
+ // return item
2683
+ return item;
2684
+ }
2685
+ }
2686
+ };
2687
+
2688
+ /**
2689
+ * get collection of Outlayer.Items, given Elements
2690
+ * @param {Array} elems
2691
+ * @returns {Array} items - Outlayer.Items
2692
+ */
2693
+ Outlayer.prototype.getItems = function(elems) {
2694
+ elems = utils.makeArray(elems);
2695
+ var items = [];
2696
+ for (var i = 0, len = elems.length; i < len; i++) {
2697
+ var elem = elems[i];
2698
+ var item = this.getItem(elem);
2699
+ if (item) {
2700
+ items.push(item);
2701
+ }
2702
+ }
2703
+
2704
+ return items;
2705
+ };
2706
+
2707
+ /**
2708
+ * remove element(s) from instance and DOM
2709
+ * @param {Array or NodeList or Element} elems
2710
+ */
2711
+ Outlayer.prototype.remove = function(elems) {
2712
+ var removeItems = this.getItems(elems);
2713
+
2714
+ this._emitCompleteOnItems('remove', removeItems);
2715
+
2716
+ // bail if no items to remove
2717
+ if (!removeItems || !removeItems.length) {
2718
+ return;
2719
+ }
2720
+
2721
+ for (var i = 0, len = removeItems.length; i < len; i++) {
2722
+ var item = removeItems[i];
2723
+ item.remove();
2724
+ // remove item from collection
2725
+ utils.removeFrom(this.items, item);
2726
+ }
2727
+ };
2728
+
2729
+ // ----- destroy ----- //
2730
+ // remove and disable Outlayer instance
2731
+ Outlayer.prototype.destroy = function() {
2732
+ // clean up dynamic styles
2733
+ var style = this.element.style;
2734
+ style.height = '';
2735
+ style.position = '';
2736
+ style.width = '';
2737
+ // destroy items
2738
+ for (var i = 0, len = this.items.length; i < len; i++) {
2739
+ var item = this.items[i];
2740
+ item.destroy();
2741
+ }
2742
+
2743
+ this.unbindResize();
2744
+
2745
+ var id = this.element.outlayerGUID;
2746
+ delete instances[id]; // remove reference to instance by id
2747
+ delete this.element.outlayerGUID;
2748
+ // remove data for jQuery
2749
+ if (jQuery) {
2750
+ jQuery.removeData(this.element, this.constructor.namespace);
2751
+ }
2752
+
2753
+ };
2754
+
2755
+ // -------------------------- data -------------------------- //
2756
+ /**
2757
+ * get Outlayer instance from element
2758
+ * @param {Element} elem
2759
+ * @returns {Outlayer}
2760
+ */
2761
+ Outlayer.data = function(elem) {
2762
+ elem = utils.getQueryElement(elem);
2763
+ var id = elem && elem.outlayerGUID;
2764
+ return id && instances[id];
2765
+ };
2766
+
2767
+
2768
+ // -------------------------- create Outlayer class -------------------------- //
2769
+ /**
2770
+ * create a layout class
2771
+ * @param {String} namespace
2772
+ */
2773
+ Outlayer.create = function(namespace, options) {
2774
+ // sub-class Outlayer
2775
+
2776
+
2777
+ function Layout() {
2778
+ Outlayer.apply(this, arguments);
2779
+ }
2780
+ // inherit Outlayer prototype, use Object.create if there
2781
+ if (Object.create) {
2782
+ Layout.prototype = Object.create(Outlayer.prototype);
2783
+ } else {
2784
+ utils.extend(Layout.prototype, Outlayer.prototype);
2785
+ }
2786
+ // set contructor, used for namespace and Item
2787
+ Layout.prototype.constructor = Layout;
2788
+
2789
+ Layout.defaults = utils.extend({}, Outlayer.defaults);
2790
+ // apply new options
2791
+ utils.extend(Layout.defaults, options);
2792
+ // keep prototype.settings for backwards compatibility (Packery v1.2.0)
2793
+ Layout.prototype.settings = {};
2794
+
2795
+ Layout.namespace = namespace;
2796
+
2797
+ Layout.data = Outlayer.data;
2798
+
2799
+ // sub-class Item
2800
+ Layout.Item = function LayoutItem() {
2801
+ Item.apply(this, arguments);
2802
+ };
2803
+
2804
+ Layout.Item.prototype = new Item();
2805
+
2806
+ // -------------------------- declarative -------------------------- //
2807
+ utils.htmlInit(Layout, namespace);
2808
+
2809
+ // -------------------------- jQuery bridge -------------------------- //
2810
+ // make into jQuery plugin
2811
+ if (jQuery && jQuery.bridget) {
2812
+ jQuery.bridget(namespace, Layout);
2813
+ }
2814
+
2815
+ return Layout;
2816
+ };
2817
+
2818
+ // ----- fin ----- //
2819
+ // back in global
2820
+ Outlayer.Item = Item;
2821
+
2822
+ return Outlayer;
2823
+
2824
+ }));
2825
+
2826
+
2827
+ /**
2828
+ * Isotope Item
2829
+ **/
2830
+
2831
+ (function(window, factory) {
2832
+
2833
+ // universal module definition
2834
+ if (typeof define == 'function' && define.amd) {
2835
+ // AMD
2836
+ define('isotope/js/item', ['outlayer/outlayer'], factory);
2837
+ } else if (typeof exports == 'object') {
2838
+ // CommonJS
2839
+ module.exports = factory(
2840
+ require('outlayer'));
2841
+ } else {
2842
+ // browser global
2843
+ window.Isotope = window.Isotope || {};
2844
+ window.Isotope.Item = factory(
2845
+ window.Outlayer);
2846
+ }
2847
+
2848
+ }(window, function factory(Outlayer) {
2849
+
2850
+
2851
+ // -------------------------- Item -------------------------- //
2852
+ // sub-class Outlayer Item
2853
+
2854
+
2855
+ function Item() {
2856
+ Outlayer.Item.apply(this, arguments);
2857
+ }
2858
+
2859
+ Item.prototype = new Outlayer.Item();
2860
+
2861
+ Item.prototype._create = function() {
2862
+ // assign id, used for original-order sorting
2863
+ this.id = this.layout.itemGUID++;
2864
+ Outlayer.Item.prototype._create.call(this);
2865
+ this.sortData = {};
2866
+ };
2867
+
2868
+ Item.prototype.updateSortData = function() {
2869
+ if (this.isIgnored) {
2870
+ return;
2871
+ }
2872
+ // default sorters
2873
+ this.sortData.id = this.id;
2874
+ // for backward compatibility
2875
+ this.sortData['original-order'] = this.id;
2876
+ this.sortData.random = Math.random();
2877
+ // go thru getSortData obj and apply the sorters
2878
+ var getSortData = this.layout.options.getSortData;
2879
+ var sorters = this.layout._sorters;
2880
+ for (var key in getSortData) {
2881
+ var sorter = sorters[key];
2882
+ this.sortData[key] = sorter(this.element, this);
2883
+ }
2884
+ };
2885
+
2886
+ var _destroy = Item.prototype.destroy;
2887
+ Item.prototype.destroy = function() {
2888
+ // call super
2889
+ _destroy.apply(this, arguments);
2890
+ // reset display, #741
2891
+ this.css({
2892
+ display: ''
2893
+ });
2894
+ };
2895
+
2896
+ return Item;
2897
+
2898
+ }));
2899
+
2900
+ /**
2901
+ * Isotope LayoutMode
2902
+ */
2903
+
2904
+ (function(window, factory) {
2905
+
2906
+ // universal module definition
2907
+ if (typeof define == 'function' && define.amd) {
2908
+ // AMD
2909
+ define('isotope/js/layout-mode', ['get-size/get-size', 'outlayer/outlayer'], factory);
2910
+ } else if (typeof exports == 'object') {
2911
+ // CommonJS
2912
+ module.exports = factory(
2913
+ require('get-size'), require('outlayer'));
2914
+ } else {
2915
+ // browser global
2916
+ window.Isotope = window.Isotope || {};
2917
+ window.Isotope.LayoutMode = factory(
2918
+ window.getSize, window.Outlayer);
2919
+ }
2920
+
2921
+ }(window, function factory(getSize, Outlayer) {
2922
+
2923
+
2924
+ // layout mode class
2925
+
2926
+
2927
+ function LayoutMode(isotope) {
2928
+ this.isotope = isotope;
2929
+ // link properties
2930
+ if (isotope) {
2931
+ this.options = isotope.options[this.namespace];
2932
+ this.element = isotope.element;
2933
+ this.items = isotope.filteredItems;
2934
+ this.size = isotope.size;
2935
+ }
2936
+ }
2937
+
2938
+ /**
2939
+ * some methods should just defer to default Outlayer method
2940
+ * and reference the Isotope instance as `this`
2941
+ **/
2942
+ (function() {
2943
+ var facadeMethods = ['_resetLayout', '_getItemLayoutPosition', '_manageStamp', '_getContainerSize', '_getElementOffset', 'needsResizeLayout'];
2944
+
2945
+ for (var i = 0, len = facadeMethods.length; i < len; i++) {
2946
+ var methodName = facadeMethods[i];
2947
+ LayoutMode.prototype[methodName] = getOutlayerMethod(methodName);
2948
+ }
2949
+
2950
+ function getOutlayerMethod(methodName) {
2951
+ return function() {
2952
+ return Outlayer.prototype[methodName].apply(this.isotope, arguments);
2953
+ };
2954
+ }
2955
+ })();
2956
+
2957
+ // ----- ----- //
2958
+ // for horizontal layout modes, check vertical size
2959
+ LayoutMode.prototype.needsVerticalResizeLayout = function() {
2960
+ // don't trigger if size did not change
2961
+ var size = getSize(this.isotope.element);
2962
+ // check that this.size and size are there
2963
+ // IE8 triggers resize on body size change, so they might not be
2964
+ var hasSizes = this.isotope.size && size;
2965
+ return hasSizes && size.innerHeight != this.isotope.size.innerHeight;
2966
+ };
2967
+
2968
+ // ----- measurements ----- //
2969
+ LayoutMode.prototype._getMeasurement = function() {
2970
+ this.isotope._getMeasurement.apply(this, arguments);
2971
+ };
2972
+
2973
+ LayoutMode.prototype.getColumnWidth = function() {
2974
+ this.getSegmentSize('column', 'Width');
2975
+ };
2976
+
2977
+ LayoutMode.prototype.getRowHeight = function() {
2978
+ this.getSegmentSize('row', 'Height');
2979
+ };
2980
+
2981
+ /**
2982
+ * get columnWidth or rowHeight
2983
+ * segment: 'column' or 'row'
2984
+ * size 'Width' or 'Height'
2985
+ **/
2986
+ LayoutMode.prototype.getSegmentSize = function(segment, size) {
2987
+ var segmentName = segment + size;
2988
+ var outerSize = 'outer' + size;
2989
+ // columnWidth / outerWidth // rowHeight / outerHeight
2990
+ this._getMeasurement(segmentName, outerSize);
2991
+ // got rowHeight or columnWidth, we can chill
2992
+ if (this[segmentName]) {
2993
+ return;
2994
+ }
2995
+ // fall back to item of first element
2996
+ var firstItemSize = this.getFirstItemSize();
2997
+ this[segmentName] = firstItemSize && firstItemSize[outerSize] ||
2998
+ // or size of container
2999
+ this.isotope.size['inner' + size];
3000
+ };
3001
+
3002
+ LayoutMode.prototype.getFirstItemSize = function() {
3003
+ var firstItem = this.isotope.filteredItems[0];
3004
+ return firstItem && firstItem.element && getSize(firstItem.element);
3005
+ };
3006
+
3007
+ // ----- methods that should reference isotope ----- //
3008
+ LayoutMode.prototype.layout = function() {
3009
+ this.isotope.layout.apply(this.isotope, arguments);
3010
+ };
3011
+
3012
+ LayoutMode.prototype.getSize = function() {
3013
+ this.isotope.getSize();
3014
+ this.size = this.isotope.size;
3015
+ };
3016
+
3017
+ // -------------------------- create -------------------------- //
3018
+ LayoutMode.modes = {};
3019
+
3020
+ LayoutMode.create = function(namespace, options) {
3021
+
3022
+ function Mode() {
3023
+ LayoutMode.apply(this, arguments);
3024
+ }
3025
+
3026
+ Mode.prototype = new LayoutMode();
3027
+
3028
+ // default options
3029
+ if (options) {
3030
+ Mode.options = options;
3031
+ }
3032
+
3033
+ Mode.prototype.namespace = namespace;
3034
+ // register in Isotope
3035
+ LayoutMode.modes[namespace] = Mode;
3036
+
3037
+ return Mode;
3038
+ };
3039
+
3040
+ return LayoutMode;
3041
+
3042
+ }));
3043
+
3044
+ /*!
3045
+ * Masonry v3.3.0
3046
+ * Cascading grid layout library
3047
+ * http://masonry.desandro.com
3048
+ * MIT License
3049
+ * by David DeSandro
3050
+ */
3051
+
3052
+ (function(window, factory) {
3053
+
3054
+ // universal module definition
3055
+ if (typeof define === 'function' && define.amd) {
3056
+ // AMD
3057
+ define('masonry/masonry', ['outlayer/outlayer', 'get-size/get-size', 'fizzy-ui-utils/utils'], factory);
3058
+ } else if (typeof exports === 'object') {
3059
+ // CommonJS
3060
+ module.exports = factory(
3061
+ require('outlayer'), require('get-size'), require('fizzy-ui-utils'));
3062
+ } else {
3063
+ // browser global
3064
+ window.Masonry = factory(
3065
+ window.Outlayer, window.getSize, window.fizzyUIUtils);
3066
+ }
3067
+
3068
+ }(window, function factory(Outlayer, getSize, utils) {
3069
+
3070
+
3071
+
3072
+ // -------------------------- masonryDefinition -------------------------- //
3073
+ // create an Outlayer layout class
3074
+ var Masonry = Outlayer.create('masonry');
3075
+
3076
+ Masonry.prototype._resetLayout = function() {
3077
+ this.getSize();
3078
+ this._getMeasurement('columnWidth', 'outerWidth');
3079
+ this._getMeasurement('gutter', 'outerWidth');
3080
+ this.measureColumns();
3081
+
3082
+ // reset column Y
3083
+ var i = this.cols;
3084
+ this.colYs = [];
3085
+ while (i--) {
3086
+ this.colYs.push(0);
3087
+ }
3088
+
3089
+ this.maxY = 0;
3090
+ };
3091
+
3092
+ Masonry.prototype.measureColumns = function() {
3093
+ this.getContainerWidth();
3094
+ // if columnWidth is 0, default to outerWidth of first item
3095
+ if (!this.columnWidth) {
3096
+ var firstItem = this.items[0];
3097
+ var firstItemElem = firstItem && firstItem.element;
3098
+ // columnWidth fall back to item of first element
3099
+ this.columnWidth = firstItemElem && getSize(firstItemElem).outerWidth ||
3100
+ // if first elem has no width, default to size of container
3101
+ this.containerWidth;
3102
+ }
3103
+
3104
+ var columnWidth = this.columnWidth += this.gutter;
3105
+
3106
+ // calculate columns
3107
+ var containerWidth = this.containerWidth + this.gutter;
3108
+ var cols = containerWidth / columnWidth;
3109
+ // fix rounding errors, typically with gutters
3110
+ var excess = columnWidth - containerWidth % columnWidth;
3111
+ // if overshoot is less than a pixel, round up, otherwise floor it
3112
+ var mathMethod = excess && excess < 1 ? 'round' : 'floor';
3113
+ cols = Math[mathMethod](cols);
3114
+ this.cols = Math.max(cols, 1);
3115
+ };
3116
+
3117
+ Masonry.prototype.getContainerWidth = function() {
3118
+ // container is parent if fit width
3119
+ var container = this.options.isFitWidth ? this.element.parentNode : this.element;
3120
+ // check that this.size and size are there
3121
+ // IE8 triggers resize on body size change, so they might not be
3122
+ var size = getSize(container);
3123
+ this.containerWidth = size && size.innerWidth;
3124
+ };
3125
+
3126
+ Masonry.prototype._getItemLayoutPosition = function(item) {
3127
+ item.getSize();
3128
+ // how many columns does this brick span
3129
+ var remainder = item.size.outerWidth % this.columnWidth;
3130
+ var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
3131
+ // round if off by 1 pixel, otherwise use ceil
3132
+ var colSpan = Math[mathMethod](item.size.outerWidth / this.columnWidth);
3133
+ colSpan = Math.min(colSpan, this.cols);
3134
+
3135
+ var colGroup = this._getColGroup(colSpan);
3136
+ // get the minimum Y value from the columns
3137
+ var minimumY = Math.min.apply(Math, colGroup);
3138
+ var shortColIndex = utils.indexOf(colGroup, minimumY);
3139
+
3140
+ // position the brick
3141
+ var position = {
3142
+ x: this.columnWidth * shortColIndex,
3143
+ y: minimumY
3144
+ };
3145
+
3146
+ // apply setHeight to necessary columns
3147
+ var setHeight = minimumY + item.size.outerHeight;
3148
+ var setSpan = this.cols + 1 - colGroup.length;
3149
+ for (var i = 0; i < setSpan; i++) {
3150
+ this.colYs[shortColIndex + i] = setHeight;
3151
+ }
3152
+
3153
+ return position;
3154
+ };
3155
+
3156
+ /**
3157
+ * @param {Number} colSpan - number of columns the element spans
3158
+ * @returns {Array} colGroup
3159
+ */
3160
+ Masonry.prototype._getColGroup = function(colSpan) {
3161
+ if (colSpan < 2) {
3162
+ // if brick spans only one column, use all the column Ys
3163
+ return this.colYs;
3164
+ }
3165
+
3166
+ var colGroup = [];
3167
+ // how many different places could this brick fit horizontally
3168
+ var groupCount = this.cols + 1 - colSpan;
3169
+ // for each group potential horizontal position
3170
+ for (var i = 0; i < groupCount; i++) {
3171
+ // make an array of colY values for that one group
3172
+ var groupColYs = this.colYs.slice(i, i + colSpan);
3173
+ // and get the max value of the array
3174
+ colGroup[i] = Math.max.apply(Math, groupColYs);
3175
+ }
3176
+ return colGroup;
3177
+ };
3178
+
3179
+ Masonry.prototype._manageStamp = function(stamp) {
3180
+ var stampSize = getSize(stamp);
3181
+ var offset = this._getElementOffset(stamp);
3182
+ // get the columns that this stamp affects
3183
+ var firstX = this.options.isOriginLeft ? offset.left : offset.right;
3184
+ var lastX = firstX + stampSize.outerWidth;
3185
+ var firstCol = Math.floor(firstX / this.columnWidth);
3186
+ firstCol = Math.max(0, firstCol);
3187
+ var lastCol = Math.floor(lastX / this.columnWidth);
3188
+ // lastCol should not go over if multiple of columnWidth #425
3189
+ lastCol -= lastX % this.columnWidth ? 0 : 1;
3190
+ lastCol = Math.min(this.cols - 1, lastCol);
3191
+ // set colYs to bottom of the stamp
3192
+ var stampMaxY = (this.options.isOriginTop ? offset.top : offset.bottom) + stampSize.outerHeight;
3193
+ for (var i = firstCol; i <= lastCol; i++) {
3194
+ this.colYs[i] = Math.max(stampMaxY, this.colYs[i]);
3195
+ }
3196
+ };
3197
+
3198
+ Masonry.prototype._getContainerSize = function() {
3199
+ this.maxY = Math.max.apply(Math, this.colYs);
3200
+ var size = {
3201
+ height: this.maxY
3202
+ };
3203
+
3204
+ if (this.options.isFitWidth) {
3205
+ size.width = this._getContainerFitWidth();
3206
+ }
3207
+
3208
+ return size;
3209
+ };
3210
+
3211
+ Masonry.prototype._getContainerFitWidth = function() {
3212
+ var unusedCols = 0;
3213
+ // count unused columns
3214
+ var i = this.cols;
3215
+ while (--i) {
3216
+ if (this.colYs[i] !== 0) {
3217
+ break;
3218
+ }
3219
+ unusedCols++;
3220
+ }
3221
+ // fit container to columns that have been used
3222
+ return (this.cols - unusedCols) * this.columnWidth - this.gutter;
3223
+ };
3224
+
3225
+ Masonry.prototype.needsResizeLayout = function() {
3226
+ var previousWidth = this.containerWidth;
3227
+ this.getContainerWidth();
3228
+ return previousWidth !== this.containerWidth;
3229
+ };
3230
+
3231
+ return Masonry;
3232
+
3233
+ }));
3234
+
3235
+ /*!
3236
+ * Masonry layout mode
3237
+ * sub-classes Masonry
3238
+ * http://masonry.desandro.com
3239
+ */
3240
+
3241
+ (function(window, factory) {
3242
+
3243
+ // universal module definition
3244
+ if (typeof define == 'function' && define.amd) {
3245
+ // AMD
3246
+ define('isotope/js/layout-modes/masonry', ['../layout-mode', 'masonry/masonry'], factory);
3247
+ } else if (typeof exports == 'object') {
3248
+ // CommonJS
3249
+ module.exports = factory(
3250
+ require('../layout-mode'), require('masonry-layout'));
3251
+ } else {
3252
+ // browser global
3253
+ factory(
3254
+ window.Isotope.LayoutMode, window.Masonry);
3255
+ }
3256
+
3257
+ }(window, function factory(LayoutMode, Masonry) {
3258
+
3259
+
3260
+ // -------------------------- helpers -------------------------- //
3261
+ // extend objects
3262
+
3263
+
3264
+ function extend(a, b) {
3265
+ for (var prop in b) {
3266
+ a[prop] = b[prop];
3267
+ }
3268
+ return a;
3269
+ }
3270
+
3271
+ // -------------------------- masonryDefinition -------------------------- //
3272
+ // create an Outlayer layout class
3273
+ var MasonryMode = LayoutMode.create('masonry');
3274
+
3275
+ // save on to these methods
3276
+ var _getElementOffset = MasonryMode.prototype._getElementOffset;
3277
+ var layout = MasonryMode.prototype.layout;
3278
+ var _getMeasurement = MasonryMode.prototype._getMeasurement;
3279
+
3280
+ // sub-class Masonry
3281
+ extend(MasonryMode.prototype, Masonry.prototype);
3282
+
3283
+ // set back, as it was overwritten by Masonry
3284
+ MasonryMode.prototype._getElementOffset = _getElementOffset;
3285
+ MasonryMode.prototype.layout = layout;
3286
+ MasonryMode.prototype._getMeasurement = _getMeasurement;
3287
+
3288
+ var measureColumns = MasonryMode.prototype.measureColumns;
3289
+ MasonryMode.prototype.measureColumns = function() {
3290
+ // set items, used if measuring first item
3291
+ this.items = this.isotope.filteredItems;
3292
+ measureColumns.call(this);
3293
+ };
3294
+
3295
+ // HACK copy over isOriginLeft/Top options
3296
+ var _manageStamp = MasonryMode.prototype._manageStamp;
3297
+ MasonryMode.prototype._manageStamp = function() {
3298
+ this.options.isOriginLeft = this.isotope.options.isOriginLeft;
3299
+ this.options.isOriginTop = this.isotope.options.isOriginTop;
3300
+ _manageStamp.apply(this, arguments);
3301
+ };
3302
+
3303
+ return MasonryMode;
3304
+
3305
+ }));
3306
+
3307
+ /**
3308
+ * fitRows layout mode
3309
+ */
3310
+
3311
+ (function(window, factory) {
3312
+
3313
+ // universal module definition
3314
+ if (typeof define == 'function' && define.amd) {
3315
+ // AMD
3316
+ define('isotope/js/layout-modes/fit-rows', ['../layout-mode'], factory);
3317
+ } else if (typeof exports == 'object') {
3318
+ // CommonJS
3319
+ module.exports = factory(
3320
+ require('../layout-mode'));
3321
+ } else {
3322
+ // browser global
3323
+ factory(
3324
+ window.Isotope.LayoutMode);
3325
+ }
3326
+
3327
+ }(window, function factory(LayoutMode) {
3328
+
3329
+
3330
+ var FitRows = LayoutMode.create('fitRows');
3331
+
3332
+ FitRows.prototype._resetLayout = function() {
3333
+ this.x = 0;
3334
+ this.y = 0;
3335
+ this.maxY = 0;
3336
+ this._getMeasurement('gutter', 'outerWidth');
3337
+ };
3338
+
3339
+ FitRows.prototype._getItemLayoutPosition = function(item) {
3340
+ item.getSize();
3341
+
3342
+ var itemWidth = item.size.outerWidth + this.gutter;
3343
+ // if this element cannot fit in the current row
3344
+ var containerWidth = this.isotope.size.innerWidth + this.gutter;
3345
+ if (this.x !== 0 && itemWidth + this.x > containerWidth) {
3346
+ this.x = 0;
3347
+ this.y = this.maxY;
3348
+ }
3349
+
3350
+ var position = {
3351
+ x: this.x,
3352
+ y: this.y
3353
+ };
3354
+
3355
+ this.maxY = Math.max(this.maxY, this.y + item.size.outerHeight);
3356
+ this.x += itemWidth;
3357
+
3358
+ return position;
3359
+ };
3360
+
3361
+ FitRows.prototype._getContainerSize = function() {
3362
+ return {
3363
+ height: this.maxY
3364
+ };
3365
+ };
3366
+
3367
+ return FitRows;
3368
+
3369
+ }));
3370
+
3371
+ /**
3372
+ * vertical layout mode
3373
+ */
3374
+
3375
+ (function(window, factory) {
3376
+
3377
+ // universal module definition
3378
+ if (typeof define == 'function' && define.amd) {
3379
+ // AMD
3380
+ define('isotope/js/layout-modes/vertical', ['../layout-mode'], factory);
3381
+ } else if (typeof exports == 'object') {
3382
+ // CommonJS
3383
+ module.exports = factory(
3384
+ require('../layout-mode'));
3385
+ } else {
3386
+ // browser global
3387
+ factory(
3388
+ window.Isotope.LayoutMode);
3389
+ }
3390
+
3391
+ }(window, function factory(LayoutMode) {
3392
+
3393
+
3394
+ var Vertical = LayoutMode.create('vertical', {
3395
+ horizontalAlignment: 0
3396
+ });
3397
+
3398
+ Vertical.prototype._resetLayout = function() {
3399
+ this.y = 0;
3400
+ };
3401
+
3402
+ Vertical.prototype._getItemLayoutPosition = function(item) {
3403
+ item.getSize();
3404
+ var x = (this.isotope.size.innerWidth - item.size.outerWidth) * this.options.horizontalAlignment;
3405
+ var y = this.y;
3406
+ this.y += item.size.outerHeight;
3407
+ return {
3408
+ x: x,
3409
+ y: y
3410
+ };
3411
+ };
3412
+
3413
+ Vertical.prototype._getContainerSize = function() {
3414
+ return {
3415
+ height: this.y
3416
+ };
3417
+ };
3418
+
3419
+ return Vertical;
3420
+
3421
+ }));
3422
+
3423
+ /*!
3424
+ * Isotope v2.2.0
3425
+ *
3426
+ * Licensed GPLv3 for open source use
3427
+ * or Isotope Commercial License for commercial use
3428
+ *
3429
+ * http://isotope.metafizzy.co
3430
+ * Copyright 2015 Metafizzy
3431
+ */
3432
+
3433
+ (function(window, factory) {
3434
+
3435
+ // universal module definition
3436
+ if (typeof define == 'function' && define.amd) {
3437
+ // AMD
3438
+ define(['outlayer/outlayer', 'get-size/get-size', 'matches-selector/matches-selector', 'fizzy-ui-utils/utils', 'isotope/js/item', 'isotope/js/layout-mode',
3439
+ // include default layout modes
3440
+ 'isotope/js/layout-modes/masonry', 'isotope/js/layout-modes/fit-rows', 'isotope/js/layout-modes/vertical'], function(Outlayer, getSize, matchesSelector, utils, Item, LayoutMode) {
3441
+ return factory(window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode);
3442
+ });
3443
+ } else if (typeof exports == 'object') {
3444
+ // CommonJS
3445
+ module.exports = factory(
3446
+ window, require('outlayer'), require('get-size'), require('desandro-matches-selector'), require('fizzy-ui-utils'), require('./item'), require('./layout-mode'),
3447
+ // include default layout modes
3448
+ require('./layout-modes/masonry'), require('./layout-modes/fit-rows'), require('./layout-modes/vertical'));
3449
+ } else {
3450
+ // browser global
3451
+ window.Isotope = factory(
3452
+ window, window.Outlayer, window.getSize, window.matchesSelector, window.fizzyUIUtils, window.Isotope.Item, window.Isotope.LayoutMode);
3453
+ }
3454
+
3455
+ }(window, function factory(window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode) {
3456
+
3457
+
3458
+
3459
+ // -------------------------- vars -------------------------- //
3460
+ var jQuery = window.jQuery;
3461
+
3462
+ // -------------------------- helpers -------------------------- //
3463
+ var trim = String.prototype.trim ?
3464
+ function(str) {
3465
+ return str.trim();
3466
+ } : function(str) {
3467
+ return str.replace(/^\s+|\s+$/g, '');
3468
+ };
3469
+
3470
+ var docElem = document.documentElement;
3471
+
3472
+ var getText = docElem.textContent ?
3473
+ function(elem) {
3474
+ return elem.textContent;
3475
+ } : function(elem) {
3476
+ return elem.innerText;
3477
+ };
3478
+
3479
+ // -------------------------- isotopeDefinition -------------------------- //
3480
+ // create an Outlayer layout class
3481
+ var Isotope = Outlayer.create('isotope', {
3482
+ layoutMode: "masonry",
3483
+ isJQueryFiltering: true,
3484
+ sortAscending: true
3485
+ });
3486
+
3487
+ Isotope.Item = Item;
3488
+ Isotope.LayoutMode = LayoutMode;
3489
+
3490
+ Isotope.prototype._create = function() {
3491
+ this.itemGUID = 0;
3492
+ // functions that sort items
3493
+ this._sorters = {};
3494
+ this._getSorters();
3495
+ // call super
3496
+ Outlayer.prototype._create.call(this);
3497
+
3498
+ // create layout modes
3499
+ this.modes = {};
3500
+ // start filteredItems with all items
3501
+ this.filteredItems = this.items;
3502
+ // keep of track of sortBys
3503
+ this.sortHistory = ['original-order'];
3504
+ // create from registered layout modes
3505
+ for (var name in LayoutMode.modes) {
3506
+ this._initLayoutMode(name);
3507
+ }
3508
+ };
3509
+
3510
+ Isotope.prototype.reloadItems = function() {
3511
+ // reset item ID counter
3512
+ this.itemGUID = 0;
3513
+ // call super
3514
+ Outlayer.prototype.reloadItems.call(this);
3515
+ };
3516
+
3517
+ Isotope.prototype._itemize = function() {
3518
+ var items = Outlayer.prototype._itemize.apply(this, arguments);
3519
+ // assign ID for original-order
3520
+ for (var i = 0, len = items.length; i < len; i++) {
3521
+ var item = items[i];
3522
+ item.id = this.itemGUID++;
3523
+ }
3524
+ this._updateItemsSortData(items);
3525
+ return items;
3526
+ };
3527
+
3528
+
3529
+ // -------------------------- layout -------------------------- //
3530
+ Isotope.prototype._initLayoutMode = function(name) {
3531
+ var Mode = LayoutMode.modes[name];
3532
+ // set mode options
3533
+ // HACK extend initial options, back-fill in default options
3534
+ var initialOpts = this.options[name] || {};
3535
+ this.options[name] = Mode.options ? utils.extend(Mode.options, initialOpts) : initialOpts;
3536
+ // init layout mode instance
3537
+ this.modes[name] = new Mode(this);
3538
+ };
3539
+
3540
+
3541
+ Isotope.prototype.layout = function() {
3542
+ // if first time doing layout, do all magic
3543
+ if (!this._isLayoutInited && this.options.isInitLayout) {
3544
+ this.arrange();
3545
+ return;
3546
+ }
3547
+ this._layout();
3548
+ };
3549
+
3550
+ // private method to be used in layout() & magic()
3551
+ Isotope.prototype._layout = function() {
3552
+ // don't animate first layout
3553
+ var isInstant = this._getIsInstant();
3554
+ // layout flow
3555
+ this._resetLayout();
3556
+ this._manageStamps();
3557
+ this.layoutItems(this.filteredItems, isInstant);
3558
+
3559
+ // flag for initalized
3560
+ this._isLayoutInited = true;
3561
+ };
3562
+
3563
+ // filter + sort + layout
3564
+ Isotope.prototype.arrange = function(opts) {
3565
+ // set any options pass
3566
+ this.option(opts);
3567
+ this._getIsInstant();
3568
+ // filter, sort, and layout
3569
+ // filter
3570
+ var filtered = this._filter(this.items);
3571
+ this.filteredItems = filtered.matches;
3572
+
3573
+ var _this = this;
3574
+
3575
+ function hideReveal() {
3576
+ _this.reveal(filtered.needReveal);
3577
+ _this.hide(filtered.needHide);
3578
+ }
3579
+
3580
+ this._bindArrangeComplete();
3581
+
3582
+ if (this._isInstant) {
3583
+ this._noTransition(hideReveal);
3584
+ } else {
3585
+ hideReveal();
3586
+ }
3587
+
3588
+ this._sort();
3589
+ this._layout();
3590
+ };
3591
+ // alias to _init for main plugin method
3592
+ Isotope.prototype._init = Isotope.prototype.arrange;
3593
+
3594
+ // HACK
3595
+ // Don't animate/transition first layout
3596
+ // Or don't animate/transition other layouts
3597
+ Isotope.prototype._getIsInstant = function() {
3598
+ var isInstant = this.options.isLayoutInstant !== undefined ? this.options.isLayoutInstant : !this._isLayoutInited;
3599
+ this._isInstant = isInstant;
3600
+ return isInstant;
3601
+ };
3602
+
3603
+ // listen for layoutComplete, hideComplete and revealComplete
3604
+ // to trigger arrangeComplete
3605
+ Isotope.prototype._bindArrangeComplete = function() {
3606
+ // listen for 3 events to trigger arrangeComplete
3607
+ var isLayoutComplete, isHideComplete, isRevealComplete;
3608
+ var _this = this;
3609
+
3610
+ function arrangeParallelCallback() {
3611
+ if (isLayoutComplete && isHideComplete && isRevealComplete) {
3612
+ _this.emitEvent('arrangeComplete', [_this.filteredItems]);
3613
+ }
3614
+ }
3615
+ this.once('layoutComplete', function() {
3616
+ isLayoutComplete = true;
3617
+ arrangeParallelCallback();
3618
+ });
3619
+ this.once('hideComplete', function() {
3620
+ isHideComplete = true;
3621
+ arrangeParallelCallback();
3622
+ });
3623
+ this.once('revealComplete', function() {
3624
+ isRevealComplete = true;
3625
+ arrangeParallelCallback();
3626
+ });
3627
+ };
3628
+
3629
+ // -------------------------- filter -------------------------- //
3630
+ Isotope.prototype._filter = function(items) {
3631
+ var filter = this.options.filter;
3632
+ filter = filter || '*';
3633
+ var matches = [];
3634
+ var hiddenMatched = [];
3635
+ var visibleUnmatched = [];
3636
+
3637
+ var test = this._getFilterTest(filter);
3638
+
3639
+ // test each item
3640
+ for (var i = 0, len = items.length; i < len; i++) {
3641
+ var item = items[i];
3642
+ if (item.isIgnored) {
3643
+ continue;
3644
+ }
3645
+ // add item to either matched or unmatched group
3646
+ var isMatched = test(item);
3647
+ // item.isFilterMatched = isMatched;
3648
+ // add to matches if its a match
3649
+ if (isMatched) {
3650
+ matches.push(item);
3651
+ }
3652
+ // add to additional group if item needs to be hidden or revealed
3653
+ if (isMatched && item.isHidden) {
3654
+ hiddenMatched.push(item);
3655
+ } else if (!isMatched && !item.isHidden) {
3656
+ visibleUnmatched.push(item);
3657
+ }
3658
+ }
3659
+
3660
+ // return collections of items to be manipulated
3661
+ return {
3662
+ matches: matches,
3663
+ needReveal: hiddenMatched,
3664
+ needHide: visibleUnmatched
3665
+ };
3666
+ };
3667
+
3668
+ // get a jQuery, function, or a matchesSelector test given the filter
3669
+ Isotope.prototype._getFilterTest = function(filter) {
3670
+ if (jQuery && this.options.isJQueryFiltering) {
3671
+ // use jQuery
3672
+ return function(item) {
3673
+ return jQuery(item.element).is(filter);
3674
+ };
3675
+ }
3676
+ if (typeof filter == 'function') {
3677
+ // use filter as function
3678
+ return function(item) {
3679
+ return filter(item.element);
3680
+ };
3681
+ }
3682
+ // default, use filter as selector string
3683
+ return function(item) {
3684
+ return matchesSelector(item.element, filter);
3685
+ };
3686
+ };
3687
+
3688
+ // -------------------------- sorting -------------------------- //
3689
+ /**
3690
+ * @params {Array} elems
3691
+ * @public
3692
+ */
3693
+ Isotope.prototype.updateSortData = function(elems) {
3694
+ // get items
3695
+ var items;
3696
+ if (elems) {
3697
+ elems = utils.makeArray(elems);
3698
+ items = this.getItems(elems);
3699
+ } else {
3700
+ // update all items if no elems provided
3701
+ items = this.items;
3702
+ }
3703
+
3704
+ this._getSorters();
3705
+ this._updateItemsSortData(items);
3706
+ };
3707
+
3708
+ Isotope.prototype._getSorters = function() {
3709
+ var getSortData = this.options.getSortData;
3710
+ for (var key in getSortData) {
3711
+ var sorter = getSortData[key];
3712
+ this._sorters[key] = mungeSorter(sorter);
3713
+ }
3714
+ };
3715
+
3716
+ /**
3717
+ * @params {Array} items - of Isotope.Items
3718
+ * @private
3719
+ */
3720
+ Isotope.prototype._updateItemsSortData = function(items) {
3721
+ // do not update if no items
3722
+ var len = items && items.length;
3723
+
3724
+ for (var i = 0; len && i < len; i++) {
3725
+ var item = items[i];
3726
+ item.updateSortData();
3727
+ }
3728
+ };
3729
+
3730
+ // ----- munge sorter ----- //
3731
+ // encapsulate this, as we just need mungeSorter
3732
+ // other functions in here are just for munging
3733
+ var mungeSorter = (function() {
3734
+ // add a magic layer to sorters for convienent shorthands
3735
+ // `.foo-bar` will use the text of .foo-bar querySelector
3736
+ // `[foo-bar]` will use attribute
3737
+ // you can also add parser
3738
+ // `.foo-bar parseInt` will parse that as a number
3739
+
3740
+
3741
+ function mungeSorter(sorter) {
3742
+ // if not a string, return function or whatever it is
3743
+ if (typeof sorter != 'string') {
3744
+ return sorter;
3745
+ }
3746
+ // parse the sorter string
3747
+ var args = trim(sorter).split(' ');
3748
+ var query = args[0];
3749
+ // check if query looks like [an-attribute]
3750
+ var attrMatch = query.match(/^\[(.+)\]$/);
3751
+ var attr = attrMatch && attrMatch[1];
3752
+ var getValue = getValueGetter(attr, query);
3753
+ // use second argument as a parser
3754
+ var parser = Isotope.sortDataParsers[args[1]];
3755
+ // parse the value, if there was a parser
3756
+ sorter = parser ?
3757
+ function(elem) {
3758
+ return elem && parser(getValue(elem));
3759
+ } :
3760
+ // otherwise just return value
3761
+
3762
+
3763
+ function(elem) {
3764
+ return elem && getValue(elem);
3765
+ };
3766
+
3767
+ return sorter;
3768
+ }
3769
+
3770
+ // get an attribute getter, or get text of the querySelector
3771
+
3772
+
3773
+ function getValueGetter(attr, query) {
3774
+ var getValue;
3775
+ // if query looks like [foo-bar], get attribute
3776
+ if (attr) {
3777
+ getValue = function(elem) {
3778
+ return elem.getAttribute(attr);
3779
+ };
3780
+ } else {
3781
+ // otherwise, assume its a querySelector, and get its text
3782
+ getValue = function(elem) {
3783
+ var child = elem.querySelector(query);
3784
+ return child && getText(child);
3785
+ };
3786
+ }
3787
+ return getValue;
3788
+ }
3789
+
3790
+ return mungeSorter;
3791
+ })();
3792
+
3793
+ // parsers used in getSortData shortcut strings
3794
+ Isotope.sortDataParsers = {
3795
+ 'parseInt': function(val) {
3796
+ return parseInt(val, 10);
3797
+ },
3798
+ 'parseFloat': function(val) {
3799
+ return parseFloat(val);
3800
+ }
3801
+ };
3802
+
3803
+ // ----- sort method ----- //
3804
+ // sort filteredItem order
3805
+ Isotope.prototype._sort = function() {
3806
+ var sortByOpt = this.options.sortBy;
3807
+ if (!sortByOpt) {
3808
+ return;
3809
+ }
3810
+ // concat all sortBy and sortHistory
3811
+ var sortBys = [].concat.apply(sortByOpt, this.sortHistory);
3812
+ // sort magic
3813
+ var itemSorter = getItemSorter(sortBys, this.options.sortAscending);
3814
+ this.filteredItems.sort(itemSorter);
3815
+ // keep track of sortBy History
3816
+ if (sortByOpt != this.sortHistory[0]) {
3817
+ // add to front, oldest goes in last
3818
+ this.sortHistory.unshift(sortByOpt);
3819
+ }
3820
+ };
3821
+
3822
+ // returns a function used for sorting
3823
+
3824
+
3825
+ function getItemSorter(sortBys, sortAsc) {
3826
+ return function sorter(itemA, itemB) {
3827
+ // cycle through all sortKeys
3828
+ for (var i = 0, len = sortBys.length; i < len; i++) {
3829
+ var sortBy = sortBys[i];
3830
+ var a = itemA.sortData[sortBy];
3831
+ var b = itemB.sortData[sortBy];
3832
+ if (a > b || a < b) {
3833
+ // if sortAsc is an object, use the value given the sortBy key
3834
+ var isAscending = sortAsc[sortBy] !== undefined ? sortAsc[sortBy] : sortAsc;
3835
+ var direction = isAscending ? 1 : -1;
3836
+ return (a > b ? 1 : -1) * direction;
3837
+ }
3838
+ }
3839
+ return 0;
3840
+ };
3841
+ }
3842
+
3843
+ // -------------------------- methods -------------------------- //
3844
+ // get layout mode
3845
+ Isotope.prototype._mode = function() {
3846
+ var layoutMode = this.options.layoutMode;
3847
+ var mode = this.modes[layoutMode];
3848
+ if (!mode) {
3849
+ // TODO console.error
3850
+ throw new Error('No layout mode: ' + layoutMode);
3851
+ }
3852
+ // HACK sync mode's options
3853
+ // any options set after init for layout mode need to be synced
3854
+ mode.options = this.options[layoutMode];
3855
+ return mode;
3856
+ };
3857
+
3858
+ Isotope.prototype._resetLayout = function() {
3859
+ // trigger original reset layout
3860
+ Outlayer.prototype._resetLayout.call(this);
3861
+ this._mode()._resetLayout();
3862
+ };
3863
+
3864
+ Isotope.prototype._getItemLayoutPosition = function(item) {
3865
+ return this._mode()._getItemLayoutPosition(item);
3866
+ };
3867
+
3868
+ Isotope.prototype._manageStamp = function(stamp) {
3869
+ this._mode()._manageStamp(stamp);
3870
+ };
3871
+
3872
+ Isotope.prototype._getContainerSize = function() {
3873
+ return this._mode()._getContainerSize();
3874
+ };
3875
+
3876
+ Isotope.prototype.needsResizeLayout = function() {
3877
+ return this._mode().needsResizeLayout();
3878
+ };
3879
+
3880
+ // -------------------------- adding & removing -------------------------- //
3881
+ // HEADS UP overwrites default Outlayer appended
3882
+ Isotope.prototype.appended = function(elems) {
3883
+ var items = this.addItems(elems);
3884
+ if (!items.length) {
3885
+ return;
3886
+ }
3887
+ // filter, layout, reveal new items
3888
+ var filteredItems = this._filterRevealAdded(items);
3889
+ // add to filteredItems
3890
+ this.filteredItems = this.filteredItems.concat(filteredItems);
3891
+ };
3892
+
3893
+ // HEADS UP overwrites default Outlayer prepended
3894
+ Isotope.prototype.prepended = function(elems) {
3895
+ var items = this._itemize(elems);
3896
+ if (!items.length) {
3897
+ return;
3898
+ }
3899
+ // start new layout
3900
+ this._resetLayout();
3901
+ this._manageStamps();
3902
+ // filter, layout, reveal new items
3903
+ var filteredItems = this._filterRevealAdded(items);
3904
+ // layout previous items
3905
+ this.layoutItems(this.filteredItems);
3906
+ // add to items and filteredItems
3907
+ this.filteredItems = filteredItems.concat(this.filteredItems);
3908
+ this.items = items.concat(this.items);
3909
+ };
3910
+
3911
+ Isotope.prototype._filterRevealAdded = function(items) {
3912
+ var filtered = this._filter(items);
3913
+ this.hide(filtered.needHide);
3914
+ // reveal all new items
3915
+ this.reveal(filtered.matches);
3916
+ // layout new items, no transition
3917
+ this.layoutItems(filtered.matches, true);
3918
+ return filtered.matches;
3919
+ };
3920
+
3921
+ /**
3922
+ * Filter, sort, and layout newly-appended item elements
3923
+ * @param {Array or NodeList or Element} elems
3924
+ */
3925
+ Isotope.prototype.insert = function(elems) {
3926
+ var items = this.addItems(elems);
3927
+ if (!items.length) {
3928
+ return;
3929
+ }
3930
+ // append item elements
3931
+ var i, item;
3932
+ var len = items.length;
3933
+ for (i = 0; i < len; i++) {
3934
+ item = items[i];
3935
+ this.element.appendChild(item.element);
3936
+ }
3937
+ // filter new stuff
3938
+ var filteredInsertItems = this._filter(items).matches;
3939
+ // set flag
3940
+ for (i = 0; i < len; i++) {
3941
+ items[i].isLayoutInstant = true;
3942
+ }
3943
+ this.arrange();
3944
+ // reset flag
3945
+ for (i = 0; i < len; i++) {
3946
+ delete items[i].isLayoutInstant;
3947
+ }
3948
+ this.reveal(filteredInsertItems);
3949
+ };
3950
+
3951
+ var _remove = Isotope.prototype.remove;
3952
+ Isotope.prototype.remove = function(elems) {
3953
+ elems = utils.makeArray(elems);
3954
+ var removeItems = this.getItems(elems);
3955
+ // do regular thing
3956
+ _remove.call(this, elems);
3957
+ // bail if no items to remove
3958
+ var len = removeItems && removeItems.length;
3959
+ if (!len) {
3960
+ return;
3961
+ }
3962
+ // remove elems from filteredItems
3963
+ for (var i = 0; i < len; i++) {
3964
+ var item = removeItems[i];
3965
+ // remove item from collection
3966
+ utils.removeFrom(this.filteredItems, item);
3967
+ }
3968
+ };
3969
+
3970
+ Isotope.prototype.shuffle = function() {
3971
+ // update random sortData
3972
+ for (var i = 0, len = this.items.length; i < len; i++) {
3973
+ var item = this.items[i];
3974
+ item.sortData.random = Math.random();
3975
+ }
3976
+ this.options.sortBy = 'random';
3977
+ this._sort();
3978
+ this._layout();
3979
+ };
3980
+
3981
+ /**
3982
+ * trigger fn without transition
3983
+ * kind of hacky to have this in the first place
3984
+ * @param {Function} fn
3985
+ * @returns ret
3986
+ * @private
3987
+ */
3988
+ Isotope.prototype._noTransition = function(fn) {
3989
+ // save transitionDuration before disabling
3990
+ var transitionDuration = this.options.transitionDuration;
3991
+ // disable transition
3992
+ this.options.transitionDuration = 0;
3993
+ // do it
3994
+ var returnValue = fn.call(this);
3995
+ // re-enable transition for reveal
3996
+ this.options.transitionDuration = transitionDuration;
3997
+ return returnValue;
3998
+ };
3999
+
4000
+ // ----- helper methods ----- //
4001
+ /**
4002
+ * getter method for getting filtered item elements
4003
+ * @returns {Array} elems - collection of item elements
4004
+ */
4005
+ Isotope.prototype.getFilteredItemElements = function() {
4006
+ var elems = [];
4007
+ for (var i = 0, len = this.filteredItems.length; i < len; i++) {
4008
+ elems.push(this.filteredItems[i].element);
4009
+ }
4010
+ return elems;
4011
+ };
4012
+
4013
+ // ----- ----- //
4014
+ return Isotope;
4015
+
4016
+ }));
base.php CHANGED
@@ -6,17 +6,10 @@
6
  */
7
  namespace Happy_Addons\Elementor;
8
 
9
- use Happy_Addons\Elementor\Assets\OnDemand_Loader;
10
- use Happy_Addons\Elementor\Manager\Assets;
11
- use Happy_Addons\Elementor\Manager\Widgets;
12
- use Happy_Addons\Elementor\Extension\Happy_Effects;
13
-
14
  defined( 'ABSPATH' ) || die();
15
 
16
  class Base {
17
 
18
- const VERSION = '1.4.1';
19
-
20
  const MINIMUM_ELEMENTOR_VERSION = '2.5.0';
21
 
22
  const MINIMUM_PHP_VERSION = '5.4';
@@ -66,16 +59,23 @@ class Base {
66
  // Register custom controls
67
  add_action( 'elementor/controls/controls_registered', [$this, 'register_controls'] );
68
 
69
- Widgets::init();
70
- Assets::init();
71
- Happy_Effects::init();
72
- OnDemand_Loader::init();
 
73
 
74
  $this->init_appsero_tracking();
75
 
76
  if ( is_user_logged_in() ) {
77
  Admin_Bar::init();
78
  }
 
 
 
 
 
 
79
  }
80
 
81
  /**
@@ -85,13 +85,13 @@ class Base {
85
  */
86
  protected function init_appsero_tracking() {
87
  if ( ! class_exists( 'Appsero\Client' ) ) {
88
- require_once __DIR__ . '/vendor/appsero/src/Client.php';
89
  }
90
 
91
  $client = new \Appsero\Client(
92
  '70b96801-94cc-4501-a005-8f9a4e20e152',
93
  'Happy Elementor Addons',
94
- HAPPY__FILE__
95
  );
96
 
97
  // Active insights
@@ -99,19 +99,24 @@ class Base {
99
  }
100
 
101
  public function include_files() {
102
- require( __DIR__ . '/inc/functions.php' );
103
- require( __DIR__ . '/inc/happy-icons.php' );
104
- require( __DIR__ . '/classes/widget-manager.php' );
105
- require( __DIR__ . '/classes/asset-manager.php' );
106
- require( __DIR__ . '/classes/happy-effects.php' );
107
- require( __DIR__ . '/classes/class.ondemand-loader.php' );
 
 
 
 
108
 
109
  if ( is_admin() ) {
110
- require( __DIR__ . '/classes/class.communicator.php' );
 
111
  }
112
 
113
  if ( is_user_logged_in() ) {
114
- require( __DIR__ . '/classes/admin-bar.php' );
115
  }
116
  }
117
 
@@ -211,7 +216,7 @@ class Base {
211
  * @access public
212
  */
213
  public function register_controls() {
214
- require( __DIR__ . '/controls/foreground.php' );
215
  $foreground = __NAMESPACE__ . '\Controls\Group_Control_Foreground';
216
 
217
  \Elementor\Plugin::instance()->controls_manager->add_group_control( $foreground::get_type(), new $foreground() );
6
  */
7
  namespace Happy_Addons\Elementor;
8
 
 
 
 
 
 
9
  defined( 'ABSPATH' ) || die();
10
 
11
  class Base {
12
 
 
 
13
  const MINIMUM_ELEMENTOR_VERSION = '2.5.0';
14
 
15
  const MINIMUM_PHP_VERSION = '5.4';
59
  // Register custom controls
60
  add_action( 'elementor/controls/controls_registered', [$this, 'register_controls'] );
61
 
62
+ Widgets_Manager::init();
63
+ Assets_Manager::init();
64
+ Extensions_Manager::init();
65
+ Cache_Manager::init();
66
+ Icons_Manager::init();
67
 
68
  $this->init_appsero_tracking();
69
 
70
  if ( is_user_logged_in() ) {
71
  Admin_Bar::init();
72
  }
73
+
74
+ if ( is_admin() ) {
75
+ Updater::init();
76
+ }
77
+
78
+ do_action( 'happyaddons_loaded' );
79
  }
80
 
81
  /**
85
  */
86
  protected function init_appsero_tracking() {
87
  if ( ! class_exists( 'Appsero\Client' ) ) {
88
+ require_once HAPPY_ADDONS_DIR_PATH . 'vendor/appsero/src/Client.php';
89
  }
90
 
91
  $client = new \Appsero\Client(
92
  '70b96801-94cc-4501-a005-8f9a4e20e152',
93
  'Happy Elementor Addons',
94
+ HAPPY_ADDONS__FILE__
95
  );
96
 
97
  // Active insights
99
  }
100
 
101
  public function include_files() {
102
+ require( HAPPY_ADDONS_DIR_PATH . 'inc/functions.php' );
103
+
104
+ require( HAPPY_ADDONS_DIR_PATH . 'classes/icons-manager.php' );
105
+ require( HAPPY_ADDONS_DIR_PATH . 'classes/widgets-manager.php' );
106
+ require( HAPPY_ADDONS_DIR_PATH . 'classes/assets-manager.php' );
107
+ require( HAPPY_ADDONS_DIR_PATH . 'classes/extensions-manager.php' );
108
+ require( HAPPY_ADDONS_DIR_PATH . 'classes/cache-manager.php' );
109
+
110
+ require( HAPPY_ADDONS_DIR_PATH . 'classes/widgets-cache.php' );
111
+ require( HAPPY_ADDONS_DIR_PATH . 'classes/assets-cache.php' );
112
 
113
  if ( is_admin() ) {
114
+ require( HAPPY_ADDONS_DIR_PATH . 'classes/class.communicator.php' );
115
+ require( HAPPY_ADDONS_DIR_PATH . 'classes/updater.php' );
116
  }
117
 
118
  if ( is_user_logged_in() ) {
119
+ require( HAPPY_ADDONS_DIR_PATH . 'classes/admin-bar.php' );
120
  }
121
  }
122
 
216
  * @access public
217
  */
218
  public function register_controls() {
219
+ require( HAPPY_ADDONS_DIR_PATH . 'controls/foreground.php' );
220
  $foreground = __NAMESPACE__ . '\Controls\Group_Control_Foreground';
221
 
222
  \Elementor\Plugin::instance()->controls_manager->add_group_control( $foreground::get_type(), new $foreground() );
base/widget-base.php CHANGED
@@ -121,7 +121,7 @@ abstract class Base extends Widget_Base {
121
  * In 2.6.0 Elementor removed render_edit_tools method.
122
  */
123
  protected function render_edit_tools() {
124
- if ( version_compare( ELEMENTOR_VERSION, '2.5.16', '<=' ) ) {
125
  parent::render_edit_tools();
126
  }
127
  }
121
  * In 2.6.0 Elementor removed render_edit_tools method.
122
  */
123
  protected function render_edit_tools() {
124
+ if ( ha_is_elementor_version( '<=', '2.5.16' ) ) {
125
  parent::render_edit_tools();
126
  }
127
  }
classes/admin-bar.php CHANGED
@@ -1,8 +1,6 @@
1
  <?php
2
  namespace Happy_Addons\Elementor;
3
 
4
- use Happy_Addons\Elementor\Assets\OnDemand_Loader;
5
-
6
  defined( 'ABSPATH' ) || die();
7
 
8
  class Admin_Bar {
@@ -22,13 +20,14 @@ class Admin_Bar {
22
  if ( ! check_ajax_referer( 'ha_clear_cache', 'nonce' ) ) {
23
  wp_send_json_error();
24
  }
25
- $type = isset( $_POST['type'] ) ? $_POST['type'] : '';
26
 
 
 
 
27
  if ( $type === 'page' ) {
28
- $post_id = isset( $_POST['post_id'] ) ? $_POST['post_id'] : 0;
29
- OnDemand_Loader::clean_only_cache( $post_id );
30
  } elseif ( $type === 'all' ) {
31
- OnDemand_Loader::clean_all_cache();
32
  }
33
  wp_send_json_success();
34
  }
@@ -40,16 +39,16 @@ class Admin_Bar {
40
 
41
  wp_enqueue_style(
42
  'happy-admin-bar',
43
- HAPPY_ASSETS . 'admin/css/admin-bar.css',
44
  null,
45
- Base::VERSION
46
  );
47
 
48
  wp_enqueue_script(
49
  'happy-admin-bar',
50
- HAPPY_ASSETS . 'admin/js/admin-bar.js',
51
  ['jquery'],
52
- Base::VERSION,
53
  true
54
  );
55
 
@@ -64,7 +63,7 @@ class Admin_Bar {
64
  );
65
  }
66
 
67
- public static function add_toolbar_items( $admin_bar ) {
68
  if ( ! current_user_can( 'manage_options' ) ) {
69
  return;
70
  }
@@ -77,10 +76,10 @@ class Admin_Bar {
77
 
78
  if ( is_singular() ) {
79
  $admin_bar->add_menu( array(
80
- 'id' => 'ha-clear-page-cache',
81
  'parent' => 'happy-addons',
82
- 'title' => '<i class="dashicons dashicons-update-alt"></i> ' . __( 'Clear Page Cache', 'happy-elementor-addons' ),
83
- 'href' => '#',
84
  'meta' => [
85
  'class' => 'hajs-clear-cache ha-clear-page-cache',
86
  ]
@@ -88,10 +87,10 @@ class Admin_Bar {
88
  }
89
 
90
  $admin_bar->add_menu( array(
91
- 'id' => 'ha-clear-all-cache',
92
  'parent' => 'happy-addons',
93
- 'title' => '<i class="dashicons dashicons-update-alt"></i> ' . __( 'Clear All Cache', 'happy-elementor-addons' ),
94
- 'href' => '#',
95
  'meta' => [
96
  'class' => 'hajs-clear-cache ha-clear-all-cache',
97
  ]
1
  <?php
2
  namespace Happy_Addons\Elementor;
3
 
 
 
4
  defined( 'ABSPATH' ) || die();
5
 
6
  class Admin_Bar {
20
  if ( ! check_ajax_referer( 'ha_clear_cache', 'nonce' ) ) {
21
  wp_send_json_error();
22
  }
 
23
 
24
+ $type = isset( $_POST['type'] ) ? $_POST['type'] : '';
25
+ $post_id = isset( $_POST['post_id'] ) ? $_POST['post_id'] : 0;
26
+ $assets_cache = new Assets_Cache( $post_id );
27
  if ( $type === 'page' ) {
28
+ $assets_cache->delete();
 
29
  } elseif ( $type === 'all' ) {
30
+ $assets_cache->delete_all();
31
  }
32
  wp_send_json_success();
33
  }
39
 
40
  wp_enqueue_style(
41
  'happy-admin-bar',
42
+ HAPPY_ADDONS_ASSETS . 'admin/css/admin-bar.css',
43
  null,
44
+ HAPPY_ADDONS_VERSION
45
  );
46
 
47
  wp_enqueue_script(
48
  'happy-admin-bar',
49
+ HAPPY_ADDONS_ASSETS . 'admin/js/admin-bar.js',
50
  ['jquery'],
51
+ HAPPY_ADDONS_VERSION,
52
  true
53
  );
54
 
63
  );
64
  }
65
 
66
+ public static function add_toolbar_items( \WP_Admin_Bar $admin_bar ) {
67
  if ( ! current_user_can( 'manage_options' ) ) {
68
  return;
69
  }
76
 
77
  if ( is_singular() ) {
78
  $admin_bar->add_menu( array(
79
+ 'id' => 'ha-clear-page-cache',
80
  'parent' => 'happy-addons',
81
+ 'title' => '<i class="dashicons dashicons-update-alt"></i> ' . __( 'Purge Page Cache', 'happy-elementor-addons' ),
82
+ 'href' => '#',
83
  'meta' => [
84
  'class' => 'hajs-clear-cache ha-clear-page-cache',
85
  ]
87
  }
88
 
89
  $admin_bar->add_menu( array(
90
+ 'id' => 'ha-clear-all-cache',
91
  'parent' => 'happy-addons',
92
+ 'title' => '<i class="dashicons dashicons-update-alt"></i> ' . __( 'Purge All Cache', 'happy-elementor-addons' ),
93
+ 'href' => '#',
94
  'meta' => [
95
  'class' => 'hajs-clear-cache ha-clear-all-cache',
96
  ]
classes/asset-manager.php DELETED
@@ -1,237 +0,0 @@
1
- <?php
2
-
3
- namespace Happy_Addons\Elementor\Manager;
4
-
5
- use Happy_Addons\Elementor\Assets\OnDemand_Loader;
6
- use Happy_Addons\Elementor\Base;
7
-
8
- defined( 'ABSPATH' ) || die();
9
-
10
- class Assets {
11
-
12
- /**
13
- * Bind hook and run internal methods here
14
- */
15
- public static function init() {
16
- // Frontend scripts
17
- add_action( 'wp_enqueue_scripts', [ __CLASS__, 'enqueue_3rd_party_dependencies' ] );
18
- add_action( 'wp_enqueue_scripts', [ __CLASS__, 'enqueue_self_dependencies' ], 99 );
19
-
20
- // Edit and preview enqueue
21
- add_action( 'elementor/preview/enqueue_styles', [ __CLASS__, 'enqueue_preview_style' ] );
22
-
23
- add_action( 'elementor/editor/before_enqueue_scripts', [ __CLASS__, 'enqueue_editor_scripts' ] );
24
-
25
- // Placeholder image replacement
26
- add_filter( 'elementor/utils/get_placeholder_image_src', [ __CLASS__, 'set_placeholder_image' ] );
27
- }
28
-
29
- public static function set_placeholder_image() {
30
- return HAPPY_ASSETS . 'imgs/placeholder.jpg';
31
- }
32
-
33
- public static function enqueue_3rd_party_dependencies() {
34
- $suffix = ha_is_script_debug_enabled() ? '.' : '.min.';
35
-
36
- wp_enqueue_style(
37
- 'happy-icon',
38
- HAPPY_ASSETS . 'fonts/style.min.css',
39
- null,
40
- Base::VERSION
41
- );
42
-
43
- /**
44
- * Image comparasion
45
- */
46
- wp_register_style(
47
- 'twentytwenty',
48
- HAPPY_ASSETS . 'vendor/twentytwenty/css/twentytwenty.css',
49
- null,
50
- Base::VERSION
51
- );
52
-
53
- wp_register_script(
54
- 'jquery-event-move',
55
- HAPPY_ASSETS . 'vendor/twentytwenty/js/jquery.event.move.js',
56
- [ 'jquery' ],
57
- Base::VERSION,
58
- true
59
- );
60
-
61
- wp_register_script(
62
- 'jquery-twentytwenty',
63
- HAPPY_ASSETS . 'vendor/twentytwenty/js/jquery.twentytwenty.js',
64
- [ 'jquery-event-move' ],
65
- Base::VERSION,
66
- true
67
- );
68
-
69
- /**
70
- * Justified Grid
71
- */
72
- wp_register_style(
73
- 'justifiedGallery',
74
- HAPPY_ASSETS . 'vendor/justifiedGallery/css/justifiedGallery.min.css',
75
- null,
76
- Base::VERSION
77
- );
78
-
79
- wp_register_script(
80
- 'jquery-justifiedGallery',
81
- HAPPY_ASSETS . 'vendor/justifiedGallery/js/jquery.justifiedGallery.min.js',
82
- [ 'jquery' ],
83
- Base::VERSION,
84
- true
85
- );
86
-
87
- /**
88
- * Carousel and Slider
89
- */
90
- wp_register_style(
91
- 'slick',
92
- HAPPY_ASSETS . 'vendor/slick/slick.css',
93
- null,
94
- Base::VERSION
95
- );
96
-
97
- wp_register_style(
98
- 'slick-theme',
99
- HAPPY_ASSETS . 'vendor/slick/slick-theme.css',
100
- null,
101
- Base::VERSION
102
- );
103
-
104
- wp_register_script(
105
- 'jquery-slick',
106
- HAPPY_ASSETS . 'vendor/slick/slick' . $suffix . 'js',
107
- [ 'jquery' ],
108
- Base::VERSION,
109
- true
110
- );
111
-
112
- /**
113
- * Floating effects
114
- */
115
- wp_register_script(
116
- 'anime',
117
- HAPPY_ASSETS . 'vendor/anime/lib/anime.min.js',
118
- null,
119
- Base::VERSION,
120
- true
121
- );
122
-
123
- // Load used libraries only on frontend
124
- if ( ha_should_load_used_library_only() ) {
125
- OnDemand_Loader::load_used_libraries();
126
- } else {
127
- wp_enqueue_style( 'twentytwenty' );
128
- wp_enqueue_script( 'jquery-event-move' );
129
- wp_enqueue_script( 'jquery-twentytwenty' );
130
-
131
- wp_enqueue_style( 'justifiedGallery' );
132
- wp_enqueue_script( 'jquery-justifiedGallery' );
133
-
134
- wp_enqueue_style( 'slick' );
135
- wp_enqueue_style( 'slick-theme' );
136
- wp_enqueue_script( 'jquery-slick' );
137
-
138
- wp_enqueue_script( 'elementor-waypoints' );
139
- wp_enqueue_script( 'jquery-numerator' );
140
-
141
- wp_enqueue_script( 'anime' );
142
- }
143
- }
144
-
145
- public static function enqueue_self_dependencies() {
146
- $suffix = ha_is_script_debug_enabled() ? '.' : '.min.';
147
-
148
- if ( ha_should_load_complied_assets() ) {
149
- $compiled_asset = OnDemand_Loader::get_compiled_asset();
150
-
151
- if ( $compiled_asset && $compiled_asset['url'] ) {
152
- wp_enqueue_style(
153
- 'happy-elementor-addons',
154
- $compiled_asset['url'],
155
- [ 'elementor-frontend' ],
156
- $compiled_asset['version']
157
- );
158
- } else {
159
- wp_enqueue_style(
160
- 'happy-elementor-addons',
161
- HAPPY_ASSETS . 'css/main' . $suffix . 'css',
162
- [ 'elementor-frontend' ],
163
- Base::VERSION
164
- );
165
- }
166
- } else {
167
- wp_enqueue_style(
168
- 'happy-elementor-addons',
169
- HAPPY_ASSETS . 'css/main' . $suffix . 'css',
170
- [ 'elementor-frontend' ],
171
- Base::VERSION
172
- );
173
- }
174
-
175
- // Happy addons script
176
- wp_enqueue_script(
177
- 'happy-elementor-addons',
178
- HAPPY_ASSETS . 'js/happy-addons' . $suffix . 'js',
179
- [ 'imagesloaded', 'jquery' ],
180
- Base::VERSION,
181
- true
182
- );
183
- }
184
-
185
- public static function enqueue_editor_scripts() {
186
- wp_enqueue_style(
187
- 'happy-icon',
188
- HAPPY_ASSETS . 'fonts/style.min.css',
189
- null,
190
- Base::VERSION
191
- );
192
-
193
- wp_enqueue_style(
194
- 'happy-elementor-addons-admin',
195
- HAPPY_ASSETS . 'admin/css/main.min.css',
196
- null,
197
- Base::VERSION
198
- );
199
-
200
- wp_enqueue_script(
201
- 'happy-elementor-addons-admin',
202
- HAPPY_ASSETS . 'admin/js/happy-addons.min.js',
203
- [ 'elementor-editor' ],
204
- Base::VERSION,
205
- true
206
- );
207
- }
208
-
209
- public static function enqueue_preview_style() {
210
- if ( class_exists( 'WeForms' ) ) {
211
- wp_enqueue_style(
212
- 'happy-elementor-weform-preview',
213
- plugins_url( '/weforms/assets/wpuf/css/frontend-forms.css', 'weforms' ),
214
- null,
215
- Base::VERSION
216
- );
217
- }
218
-
219
- if ( class_exists( 'WPForms_Lite' ) ) {
220
- wp_enqueue_style(
221
- 'happy-elementor-wpform-preview',
222
- plugins_url( '/wpforms-lite/assets/css/wpforms-full.css', 'wpforms-lite' ),
223
- null,
224
- Base::VERSION
225
- );
226
- }
227
-
228
- if ( class_exists( 'Caldera_Forms' ) ) {
229
- wp_enqueue_style(
230
- 'happy-elementor-caldera-preview',
231
- plugins_url( '/caldera-forms/assets/css/caldera-forms-front.css', 'caldera-forms' ),
232
- null,
233
- Base::VERSION
234
- );
235
- }
236
- }
237
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/assets-cache.php ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Happy_Addons\Elementor;
3
+
4
+ defined( 'ABSPATH' ) || die();
5
+
6
+ class Assets_Cache {
7
+
8
+ const FILE_PREFIX = 'happy-';
9
+
10
+ /**
11
+ * @var int
12
+ */
13
+ protected $post_id = 0;
14
+
15
+ /**
16
+ * @var Widgets_Cache
17
+ */
18
+ protected $widgets_cache = null;
19
+
20
+ protected $upload_path;
21
+
22
+ protected $upload_url;
23
+
24
+ public function __construct( $post_id = 0, Widgets_Cache $widget_cache_instance = null ) {
25
+ $this->post_id = $post_id;
26
+ $this->widgets_cache = $widget_cache_instance;
27
+
28
+ $upload_dir = wp_upload_dir();
29
+ $this->upload_path = trailingslashit( $upload_dir['basedir'] );
30
+ $this->upload_url = trailingslashit( $upload_dir['baseurl'] );
31
+ }
32
+
33
+ public function get_widgets_cache() {
34
+ if ( is_null( $this->widgets_cache ) ) {
35
+ $this->widgets_cache = new Widgets_Cache( $this->get_post_id() );
36
+ }
37
+ return $this->widgets_cache;
38
+ }
39
+
40
+ public function get_cache_dir_name() {
41
+ return trailingslashit( 'happyaddons' . DIRECTORY_SEPARATOR . 'cache' );
42
+ }
43
+
44
+ public function get_post_id() {
45
+ return $this->post_id;
46
+ }
47
+
48
+ public function get_cache_dir() {
49
+ return $this->upload_path . $this->get_cache_dir_name();
50
+ }
51
+
52
+ public function get_cache_url() {
53
+ return $this->upload_url . $this->get_cache_dir_name();
54
+ }
55
+
56
+ public function get_file_name() {
57
+ return $this->get_cache_dir() . self::FILE_PREFIX . "{$this->get_post_id()}.css";
58
+ }
59
+
60
+ public function get_file_url() {
61
+ return $this->get_cache_url() . self::FILE_PREFIX . "{$this->get_post_id()}.css";
62
+ }
63
+
64
+ public function cache_exists() {
65
+ return file_exists( $this->get_file_name() );
66
+ }
67
+
68
+ public function has() {
69
+ if ( ! $this->cache_exists() ) {
70
+ $this->save();
71
+ }
72
+ return $this->cache_exists();
73
+ }
74
+
75
+ public function delete() {
76
+ if ( $this->cache_exists() ) {
77
+ unlink( $this->get_file_name() );
78
+ }
79
+ }
80
+
81
+ public function delete_all() {
82
+ $files = glob( $this->get_cache_dir() . '/*' );
83
+ foreach ( $files as $file ) {
84
+ if ( is_file( $file ) ) {
85
+ unlink( $file );
86
+ }
87
+ }
88
+ }
89
+
90
+ public function enqueue() {
91
+ if ( $this->has() ) {
92
+ wp_enqueue_style(
93
+ 'happy-elementor-addons-' . $this->get_post_id(),
94
+ $this->get_file_url(),
95
+ [ 'elementor-frontend' ],
96
+ HAPPY_ADDONS_VERSION . '.' . get_post_modified_time()
97
+ );
98
+ }
99
+ }
100
+
101
+ public function enqueue_libraries() {
102
+ $widgets = $this->get_widgets_cache()->get();
103
+
104
+ if ( empty( $widgets ) || ! is_array( $widgets ) ) {
105
+ return;
106
+ }
107
+
108
+ $widgets_map = Widgets_Manager::get_widgets_map();
109
+ $base_widget = isset( $widgets_map[ Widgets_Manager::get_base_widget_key() ] ) ? $widgets_map[ Widgets_Manager::get_base_widget_key() ] : [];
110
+
111
+ if ( isset( $base_widget['vendor'], $base_widget['vendor']['css'] ) && is_array( $base_widget['vendor']['css'] ) ) {
112
+ foreach ( $base_widget['vendor']['css'] as $vendor_css_handle ) {
113
+ wp_enqueue_style( $vendor_css_handle );
114
+ }
115
+ }
116
+
117
+ if ( isset( $base_widget['vendor'], $base_widget['vendor']['js'] ) && is_array( $base_widget['vendor']['js'] ) ) {
118
+ foreach ( $base_widget['vendor']['js'] as $vendor_js_handle ) {
119
+ wp_enqueue_script( $vendor_js_handle );
120
+ }
121
+ }
122
+
123
+ foreach ( $widgets as $widget_key ) {
124
+ if ( ! isset( $widgets_map[ $widget_key ], $widgets_map[ $widget_key ]['vendor'] ) ) {
125
+ continue;
126
+ }
127
+
128
+ $vendor = $widgets_map[ $widget_key ]['vendor'];
129
+
130
+ if ( isset( $vendor['css'] ) && is_array( $vendor['css'] ) ) {
131
+ foreach ( $vendor['css'] as $vendor_css_handle ) {
132
+ wp_enqueue_style( $vendor_css_handle );
133
+ }
134
+ }
135
+
136
+ if ( isset( $vendor['js'] ) && is_array( $vendor['js'] ) ) {
137
+ foreach ( $vendor['js'] as $vendor_js_handle ) {
138
+ wp_enqueue_script( $vendor_js_handle );
139
+ }
140
+ }
141
+ }
142
+ }
143
+
144
+ public function save() {
145
+ $widgets = $this->get_widgets_cache()->get();
146
+
147
+ if ( empty( $widgets ) ) {
148
+ return;
149
+ }
150
+
151
+ $widgets_map = Widgets_Manager::get_widgets_map();
152
+ $base_widget = isset( $widgets_map[ Widgets_Manager::get_base_widget_key() ] ) ? $widgets_map[ Widgets_Manager::get_base_widget_key() ] : [];
153
+ $styles = '';
154
+
155
+ // Get common css styles
156
+ if ( isset( $base_widget['css'] ) && is_array( $base_widget['css'] ) ) {
157
+ $styles = $this->get_styles( $base_widget['css'] );
158
+ }
159
+
160
+ $cached_widgets = [];
161
+ foreach ( $widgets as $widget_key ) {
162
+ if ( isset( $cached_widgets[ $widget_key ] ) ||
163
+ ! isset( $widgets_map[ $widget_key ], $widgets_map[ $widget_key ]['css'] )
164
+ ) {
165
+ continue;
166
+ }
167
+ $styles .= $this->get_styles( $widgets_map[ $widget_key ]['css'], isset( $widgets_map['is_pro'] ) );
168
+ $cached_widgets[ $widget_key ] = true;
169
+ }
170
+ $styles .= sprintf( '/** Compiled CSS for: %s **/', implode(', ', array_keys( $cached_widgets ) ) );
171
+
172
+ if ( ! is_dir( $this->get_cache_dir() ) ) {
173
+ @mkdir( $this->get_cache_dir(), 0777, true );
174
+ }
175
+ file_put_contents( $this->get_file_name(), $styles );
176
+ }
177
+
178
+ protected function get_styles( $files_name, $is_pro = false ) {
179
+ $styles = '';
180
+ foreach ( $files_name as $file_name ) {
181
+ $file_path = HAPPY_ADDONS_DIR_PATH . "assets/css/widgets/{$file_name}.min.css";
182
+ $file_path = apply_filters( 'happyaddons_cached_widget_css_file_path', $file_path, $file_name, $is_pro );
183
+ if ( file_exists( $file_path ) ) {
184
+ $styles .= file_get_contents( $file_path );
185
+ };
186
+ }
187
+ return $styles;
188
+ }
189
+ }
classes/assets-manager.php ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Happy_Addons\Elementor;
3
+
4
+ use Elementor\Core\Files\CSS\Post as Post_CSS;
5
+
6
+ defined( 'ABSPATH' ) || die();
7
+
8
+ class Assets_Manager {
9
+
10
+ /**
11
+ * Bind hook and run internal methods here
12
+ */
13
+ public static function init() {
14
+ // Frontend scripts
15
+ add_action( 'wp_enqueue_scripts', [ __CLASS__, 'frontend_register' ] );
16
+ add_action( 'wp_enqueue_scripts', [ __CLASS__, 'frontend_enqueue' ], 99 );
17
+ add_action( 'elementor/css-file/post/enqueue', [ __CLASS__, 'frontend_elementor_enqueue' ] );
18
+
19
+ // Edit and preview enqueue
20
+ add_action( 'elementor/preview/enqueue_styles', [ __CLASS__, 'enqueue_preview_style' ] );
21
+
22
+ add_action( 'elementor/editor/before_enqueue_scripts', [ __CLASS__, 'enqueue_editor_scripts' ] );
23
+
24
+ // Placeholder image replacement
25
+ add_filter( 'elementor/utils/get_placeholder_image_src', [ __CLASS__, 'set_placeholder_image' ] );
26
+ }
27
+
28
+ public static function set_placeholder_image() {
29
+ return HAPPY_ADDONS_ASSETS . 'imgs/placeholder.jpg';
30
+ }
31
+
32
+ public static function frontend_register() {
33
+ $suffix = ha_is_script_debug_enabled() ? '.' : '.min.';
34
+
35
+ wp_register_style(
36
+ 'happy-icons',
37
+ HAPPY_ADDONS_ASSETS . 'fonts/style.min.css',
38
+ null,
39
+ HAPPY_ADDONS_VERSION
40
+ );
41
+
42
+ /**
43
+ * Image comparasion
44
+ */
45
+ wp_register_style(
46
+ 'twentytwenty',
47
+ HAPPY_ADDONS_ASSETS . 'vendor/twentytwenty/css/twentytwenty.css',
48
+ null,
49
+ HAPPY_ADDONS_VERSION
50
+ );
51
+
52
+ wp_register_script(
53
+ 'jquery-event-move',
54
+ HAPPY_ADDONS_ASSETS . 'vendor/twentytwenty/js/jquery.event.move.js',
55
+ [ 'jquery' ],
56
+ HAPPY_ADDONS_VERSION,
57
+ true
58
+ );
59
+
60
+ wp_register_script(
61
+ 'jquery-twentytwenty',
62
+ HAPPY_ADDONS_ASSETS . 'vendor/twentytwenty/js/jquery.twentytwenty.js',
63
+ [ 'jquery-event-move' ],
64
+ HAPPY_ADDONS_VERSION,
65
+ true
66
+ );
67
+
68
+ /**
69
+ * Justified Grid
70
+ */
71
+ wp_register_style(
72
+ 'justifiedGallery',
73
+ HAPPY_ADDONS_ASSETS . 'vendor/justifiedGallery/css/justifiedGallery.min.css',
74
+ null,
75
+ HAPPY_ADDONS_VERSION
76
+ );
77
+
78
+ wp_register_script(
79
+ 'jquery-justifiedGallery',
80
+ HAPPY_ADDONS_ASSETS . 'vendor/justifiedGallery/js/jquery.justifiedGallery.min.js',
81
+ [ 'jquery' ],
82
+ HAPPY_ADDONS_VERSION,
83
+ true
84
+ );
85
+
86
+ /**
87
+ * Carousel and Slider
88
+ */
89
+ wp_register_style(
90
+ 'slick',
91
+ HAPPY_ADDONS_ASSETS . 'vendor/slick/slick.css',
92
+ null,
93
+ HAPPY_ADDONS_VERSION
94
+ );
95
+
96
+ wp_register_style(
97
+ 'slick-theme',
98
+ HAPPY_ADDONS_ASSETS . 'vendor/slick/slick-theme.css',
99
+ null,
100
+ HAPPY_ADDONS_VERSION
101
+ );
102
+
103
+ wp_register_script(
104
+ 'jquery-slick',
105
+ HAPPY_ADDONS_ASSETS . 'vendor/slick/slick' . $suffix . 'js',
106
+ [ 'jquery' ],
107
+ HAPPY_ADDONS_VERSION,
108
+ true
109
+ );
110
+
111
+ /**
112
+ * Masonry grid
113
+ */
114
+ wp_register_script(
115
+ 'jquery-isotope',
116
+ HAPPY_ADDONS_ASSETS . 'vendor/jquery.isotope.js',
117
+ [ 'jquery' ],
118
+ HAPPY_ADDONS_VERSION,
119
+ true
120
+ );
121
+
122
+ /**
123
+ * Number animation
124
+ */
125
+ wp_register_script(
126
+ 'jquery-numerator',
127
+ HAPPY_ADDONS_ASSETS . 'vendor/jquery-numerator/jquery-numerator' . $suffix . 'js',
128
+ [ 'jquery' ],
129
+ HAPPY_ADDONS_VERSION,
130
+ true
131
+ );
132
+
133
+ /**
134
+ * Floating effects
135
+ */
136
+ wp_register_script(
137
+ 'anime',
138
+ HAPPY_ADDONS_ASSETS . 'vendor/anime/lib/anime.min.js',
139
+ null,
140
+ HAPPY_ADDONS_VERSION,
141
+ true
142
+ );
143
+
144
+ wp_register_style(
145
+ 'happy-elementor-addons',
146
+ HAPPY_ADDONS_ASSETS . 'css/main' . $suffix . 'css',
147
+ [ 'elementor-frontend' ],
148
+ HAPPY_ADDONS_VERSION
149
+ );
150
+
151
+ // Happy addons script
152
+ wp_register_script(
153
+ 'happy-elementor-addons',
154
+ HAPPY_ADDONS_ASSETS . 'js/happy-addons' . $suffix . 'js',
155
+ [ 'imagesloaded', 'jquery' ],
156
+ HAPPY_ADDONS_VERSION,
157
+ true
158
+ );
159
+ }
160
+
161
+ private static function enqueue() {
162
+ wp_enqueue_style( 'happy-icons' );
163
+ wp_enqueue_style( 'font-awesome' );
164
+
165
+ wp_enqueue_style( 'twentytwenty' );
166
+ wp_enqueue_script( 'jquery-event-move' );
167
+ wp_enqueue_script( 'jquery-twentytwenty' );
168
+
169
+ wp_enqueue_style( 'justifiedGallery' );
170
+ wp_enqueue_script( 'jquery-justifiedGallery' );
171
+
172
+ wp_enqueue_style( 'slick' );
173
+ wp_enqueue_style( 'slick-theme' );
174
+ wp_enqueue_script( 'jquery-slick' );
175
+
176
+ wp_enqueue_script( 'jquery-isotope' );
177
+
178
+ wp_enqueue_script( 'elementor-waypoints' );
179
+ wp_enqueue_script( 'jquery-numerator' );
180
+
181
+ wp_enqueue_script( 'anime' );
182
+
183
+ // Self assets
184
+ wp_enqueue_style( 'happy-elementor-addons' );
185
+ wp_enqueue_script( 'happy-elementor-addons' );
186
+ }
187
+
188
+ public static function frontend_elementor_enqueue( Post_CSS $file ) {
189
+ if ( get_post_type( $file->get_post_id() ) === 'elementor_library' ) {
190
+ if ( Cache_Manager::should_enqueue( $file->get_post_id() ) ) {
191
+ Cache_Manager::enqueue( $file->get_post_id() );
192
+ } else {
193
+ self::enqueue();
194
+ }
195
+ }
196
+ }
197
+
198
+ public static function frontend_enqueue() {
199
+ if ( Cache_Manager::should_enqueue( get_the_ID() ) ) {
200
+ Cache_Manager::enqueue( get_the_ID() );
201
+ } else {
202
+ self::enqueue();
203
+ }
204
+ }
205
+
206
+ public static function enqueue_editor_scripts() {
207
+ wp_enqueue_style(
208
+ 'happy-icons',
209
+ HAPPY_ADDONS_ASSETS . 'fonts/style.min.css',
210
+ null,
211
+ HAPPY_ADDONS_VERSION
212
+ );
213
+
214
+ wp_enqueue_style(
215
+ 'happy-elementor-addons-admin',
216
+ HAPPY_ADDONS_ASSETS . 'admin/css/main.min.css',
217
+ null,
218
+ HAPPY_ADDONS_VERSION
219
+ );
220
+
221
+ wp_enqueue_script(
222
+ 'happy-elementor-addons-admin',
223
+ HAPPY_ADDONS_ASSETS . 'admin/js/happy-addons.min.js',
224
+ [ 'elementor-editor' ],
225
+ HAPPY_ADDONS_VERSION,
226
+ true
227
+ );
228
+ }
229
+
230
+ public static function enqueue_preview_style() {
231
+ if ( class_exists( 'WeForms' ) ) {
232
+ wp_enqueue_style(
233
+ 'happy-elementor-weform-preview',
234
+ plugins_url( '/weforms/assets/wpuf/css/frontend-forms.css', 'weforms' ),
235
+ null,
236
+ HAPPY_ADDONS_VERSION
237
+ );
238
+ }
239
+
240
+ if ( class_exists( 'WPForms_Lite' ) ) {
241
+ wp_enqueue_style(
242
+ 'happy-elementor-wpform-preview',
243
+ plugins_url( '/wpforms-lite/assets/css/wpforms-full.css', 'wpforms-lite' ),
244
+ null,
245
+ HAPPY_ADDONS_VERSION
246
+ );
247
+ }
248
+
249
+ if ( class_exists( 'Caldera_Forms' ) ) {
250
+ wp_enqueue_style(
251
+ 'happy-elementor-caldera-preview',
252
+ plugins_url( '/caldera-forms/assets/css/caldera-forms-front.css', 'caldera-forms' ),
253
+ null,
254
+ HAPPY_ADDONS_VERSION
255
+ );
256
+ }
257
+ }
258
+ }
classes/cache-manager.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Happy_Addons\Elementor;
3
+
4
+ use Elementor\Core\Files\CSS\Post as Post_CSS;
5
+
6
+ defined( 'ABSPATH' ) || die();
7
+
8
+ class Cache_Manager {
9
+
10
+ private static $widgets_cache;
11
+
12
+ public static function init() {
13
+ add_action( 'elementor/editor/after_save', [ __CLASS__, 'cache_widgets' ], 10, 2 );
14
+ }
15
+
16
+ public static function cache_widgets( $post_id, $data ) {
17
+ if ( ! self::is_published( $post_id ) ) {
18
+ return;
19
+ }
20
+
21
+ self::$widgets_cache = new Widgets_Cache( $post_id, $data );
22
+ self::$widgets_cache->save();
23
+
24
+ // Delete to regenerate cache file
25
+ $assets_cache = new Assets_Cache( $post_id, self::$widgets_cache );
26
+ $assets_cache->delete();
27
+ }
28
+
29
+ public static function is_published( $post_id ) {
30
+ return get_post_status( $post_id ) === 'publish';
31
+ }
32
+
33
+ public static function is_editing_mode() {
34
+ return (
35
+ ha_elementor()->editor->is_edit_mode() ||
36
+ ha_elementor()->preview->is_preview_mode() ||
37
+ is_preview()
38
+ );
39
+ }
40
+
41
+ public static function is_built_with_elementor( $post_id ) {
42
+ return ha_elementor()->db->is_built_with_elementor( $post_id );
43
+ }
44
+
45
+ public static function should_enqueue( $post_id ) {
46
+ if ( ! ha_is_happy_mode_enabled() ||
47
+ ! self::is_built_with_elementor( $post_id ) ||
48
+ ! self::is_published( $post_id ) ||
49
+ self::is_editing_mode() ) {
50
+ return false;
51
+ }
52
+
53
+ self::$widgets_cache = new Widgets_Cache( $post_id );
54
+ if ( ! self::$widgets_cache->has() ) {
55
+ return false;
56
+ }
57
+
58
+ return true;
59
+ }
60
+
61
+ public static function enqueue_fa5_fonts( $post_id ) {
62
+ $post_css = new Post_CSS( $post_id );
63
+ $meta = $post_css->get_meta();
64
+ if ( ! empty( $meta['icons'] ) ) {
65
+ $icons_types = \Elementor\Icons_Manager::get_icon_manager_tabs();
66
+ foreach ( $meta['icons'] as $icon_font ) {
67
+ if ( ! isset( $icons_types[ $icon_font ] ) ) {
68
+ continue;
69
+ }
70
+ ha_elementor()->frontend->enqueue_font( $icon_font );
71
+ }
72
+ }
73
+ }
74
+
75
+ public static function enqueue( $post_id ) {
76
+ $assets_cache = new Assets_Cache( $post_id, self::$widgets_cache );
77
+ $assets_cache->enqueue_libraries();
78
+ $assets_cache->enqueue();
79
+ self::enqueue_fa5_fonts( $post_id );
80
+ wp_enqueue_script( 'happy-elementor-addons' );
81
+ }
82
+ }
classes/class.ondemand-loader.php DELETED
@@ -1,246 +0,0 @@
1
- <?php
2
-
3
- namespace Happy_Addons\Elementor\Assets;
4
-
5
- use Happy_Addons\Elementor\Base;
6
- use Happy_Addons\Elementor\Manager\Widgets;
7
-
8
- defined( 'ABSPATH' ) || die();
9
-
10
- class OnDemand_Loader {
11
-
12
- const DB_KEY = '_elementor_elements_usage';
13
-
14
- private static $upload_path;
15
-
16
- private static $upload_url;
17
-
18
- private static $cache_dir;
19
-
20
- private static $cache_dir_name;
21
-
22
- private static $cache_url;
23
-
24
- public static function init() {
25
- $upload_dir = wp_upload_dir();
26
- self::$upload_path = trailingslashit( $upload_dir['basedir'] );
27
- self::$upload_url = trailingslashit( $upload_dir['baseurl'] );;
28
-
29
- self::$cache_dir_name = trailingslashit( 'happyaddons/cache' );
30
-
31
- self::$cache_dir = self::$upload_path . self::$cache_dir_name;
32
- self::$cache_url = self::$upload_url . self::$cache_dir_name;
33
-
34
- add_action( 'save_post', [__CLASS__, 'save_elements_usage'] );
35
- }
36
-
37
- /**
38
- * Get used elements in a post
39
- *
40
- * @param $post_id
41
- * @return array
42
- */
43
- public static function get_elements_usage( $post_id ) {
44
- $usage = self::get_only_elements_usage( $post_id );
45
- if ( ! $usage ) {
46
- self::save_elements_usage( $post_id );
47
- $usage = self::get_only_elements_usage( $post_id );
48
- }
49
- return $usage;
50
- }
51
-
52
- public static function get_only_elements_usage( $post_id ) {
53
- $usage = get_post_meta( $post_id, self::DB_KEY, true );
54
- return ( is_array( $usage ) ? $usage : [] );
55
- }
56
-
57
- /**
58
- * Save used elements
59
- *
60
- * @param $post_id
61
- * @return void
62
- */
63
- public static function save_elements_usage( $post_id ) {
64
- /**
65
- * Before version 2.6.5 elementor didn't store elements usage data
66
- */
67
- if ( version_compare( ELEMENTOR_VERSION, '2.6.5', '<=' ) || ! self::get_only_elements_usage( $post_id ) ) {
68
- $usage = [];
69
- //we need to populate _elementor_elements_usage;
70
- $document = \Elementor\Plugin::$instance->documents->get( $post_id );
71
- $data = $document ? $document->get_elements_data() : [];
72
-
73
- \Elementor\Plugin::$instance->db->iterate_data( $data, function ( $element ) use ( & $usage ) {
74
- if ( empty( $element['widgetType'] ) ) {
75
- $type = $element['elType'];
76
- } else {
77
- $type = $element['widgetType'];
78
- }
79
-
80
- if ( ! isset( $usage[ $type ] ) ) {
81
- $usage[ $type ] = 0;
82
- }
83
-
84
- $usage[ $type ] ++;
85
-
86
- return $element;
87
- } );
88
-
89
- update_post_meta( $post_id, self::DB_KEY, $usage );
90
- self::clean_only_cache( $post_id );
91
- }
92
- }
93
-
94
- public static function get_supported_types() {
95
- return get_option( 'elementor_cpt_support', ['post', 'page'] );
96
- }
97
-
98
- public static function get_compiled_asset() {
99
- global $post;
100
- if ( ! isset( $post ) || empty( $post ) ) {
101
- return;
102
- }
103
-
104
- $filename = self::$cache_dir . "post-{$post->ID}.css";
105
-
106
- if ( ! file_exists( $filename ) ) {
107
- self::compile_assets( $post->ID );
108
- }
109
-
110
- if ( file_exists( $filename ) ) {
111
- return [
112
- 'url' => self::$cache_url . "post-{$post->ID}.css",
113
- 'version' => Base::VERSION . '.' . get_post_modified_time( 'U', false, $post ),
114
- ];
115
- }
116
-
117
- return [];
118
- }
119
-
120
- public static function get_self_elements_usage( $post_id ) {
121
- return array_keys( array_filter( self::get_elements_usage( $post_id ), function( $widget_name ) {
122
- return strpos( $widget_name, 'ha-' ) !== false;
123
- }, ARRAY_FILTER_USE_KEY ) );
124
- }
125
-
126
- public static function compile_assets( $post_id ) {
127
- if ( ! apply_filters( 'happyaddons_ondemand_asset_compiling', true ) ) {
128
- return;
129
- }
130
-
131
- if ( ! in_array( get_post_type( $post_id ), self::get_supported_types() ) ) {
132
- return;
133
- }
134
-
135
- $filename = self::$cache_dir . "post-{$post_id}.css";
136
- $widgets = self::get_self_elements_usage( $post_id );
137
-
138
- if ( $widgets && is_array( $widgets ) ) {
139
- $widgets_map = Widgets::get_widgets_map();
140
- $base_widget = isset( $widgets_map[ Widgets::get_base_widget_key() ] ) ? $widgets_map[ Widgets::get_base_widget_key() ] : [];
141
- $data = '';
142
-
143
- if ( isset( $base_widget['css'] ) && is_array( $base_widget['css'] ) ) {
144
- foreach ( $base_widget['css'] as $_file_name_prefix ) {
145
- if ( file_exists( HAPPY_DIR_PATH . "assets/css/widgets/{$_file_name_prefix}.min.css" ) ) {
146
- $data .= file_get_contents( HAPPY_DIR_PATH . "assets/css/widgets/{$_file_name_prefix}.min.css" );
147
- };
148
- }
149
- }
150
-
151
- foreach ( $widgets as $_widget ) {
152
- $map_key = substr( $_widget, 3 );
153
-
154
- if ( ! isset( $widgets_map[ $map_key ] ) ) {
155
- continue;
156
- }
157
-
158
- if ( ! isset( $widgets_map[ $map_key ]['css'] ) ) {
159
- continue;
160
- }
161
-
162
- foreach ( $widgets_map[ $map_key ]['css'] as $_file_name_prefix ) {
163
- if ( file_exists( HAPPY_DIR_PATH . "assets/css/widgets/{$_file_name_prefix}.min.css" ) ) {
164
- $data .= file_get_contents( HAPPY_DIR_PATH . "assets/css/widgets/{$_file_name_prefix}.min.css" );
165
- };
166
- }
167
- }
168
-
169
- if ( ! is_dir( self::$cache_dir ) ) {
170
- @mkdir( self::$cache_dir, 0777, true );
171
- }
172
-
173
- file_put_contents( $filename, $data );
174
- }
175
- }
176
-
177
- public static function load_used_libraries() {
178
- global $post;
179
- if ( ! isset( $post ) || empty( $post ) ) {
180
- return;
181
- }
182
-
183
- $widgets_used = self::get_elements_usage( $post->ID );
184
-
185
- if ( is_array( $widgets_used ) ) {
186
- $widgets = Widgets::get_widgets_map();
187
-
188
- foreach( $widgets as $widget => $data ) {
189
- if ( ! isset( $data['vendor'] ) || ! is_array( $data['vendor'] ) ) {
190
- continue;
191
- }
192
-
193
- // Handle common assets only
194
- if ( Widgets::get_base_widget_key() === $widget ) {
195
- if ( isset( $data['vendor']['css'] ) && is_array( $data['vendor']['css'] ) ) {
196
- foreach ( $data['vendor']['css'] as $vendor_css_handle ) {
197
- wp_enqueue_style( $vendor_css_handle );
198
- }
199
- }
200
-
201
- if ( isset( $data['vendor']['js'] ) && is_array( $data['vendor']['js'] ) ) {
202
- foreach ( $data['vendor']['js'] as $vendor_css_handle ) {
203
- wp_enqueue_script( $vendor_css_handle );
204
- }
205
- }
206
- continue;
207
- }
208
-
209
- // Handle widgets assets only
210
- $widget_id = 'ha-' . $widget;
211
-
212
- if ( ! array_key_exists( $widget_id, $widgets_used ) ) {
213
- continue;
214
- }
215
-
216
- if ( is_array( $data['vendor']['css'] ) ) {
217
- foreach ( $data['vendor']['css'] as $vendor_css_handle ) {
218
- wp_enqueue_style( $vendor_css_handle );
219
- }
220
- }
221
-
222
- if ( is_array( $data['vendor']['js'] ) ) {
223
- foreach ( $data['vendor']['js'] as $vendor_css_handle ) {
224
- wp_enqueue_script( $vendor_css_handle );
225
- }
226
- }
227
- }
228
- }
229
- }
230
-
231
- public static function clean_all_cache() {
232
- $files = glob( self::$cache_dir . '/*' );
233
- foreach( $files as $file ) {
234
- if ( is_file( $file ) ) {
235
- unlink( $file );
236
- }
237
- }
238
- }
239
-
240
- public static function clean_only_cache( $post_id ) {
241
- $filename = self::$cache_dir . "post-{$post_id}.css";
242
- if ( file_exists( $filename ) ) {
243
- unlink( $filename );
244
- }
245
- }
246
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/extensions-manager.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Happy_Addons\Elementor;
3
+
4
+ use Happy_Addons\Elementor\Extension\Background_Overlay;
5
+ use Happy_Addons\Elementor\Extension\Happy_Effects;
6
+
7
+ defined( 'ABSPATH' ) || die();
8
+
9
+ class Extensions_Manager {
10
+
11
+ /**
12
+ * Initialize
13
+ */
14
+ public static function init() {
15
+ include HAPPY_ADDONS_DIR_PATH . 'extensions/background-overlay.php';
16
+ include HAPPY_ADDONS_DIR_PATH . 'extensions/happy-effects.php';
17
+
18
+ Background_Overlay::init();
19
+ Happy_Effects::init();
20
+ }
21
+ }
classes/icons-manager.php ADDED
@@ -0,0 +1,438 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Happy_Addons\Elementor;
3
+
4
+ defined( 'ABSPATH' ) || die();
5
+
6
+ class Icons_Manager {
7
+
8
+ public static function init() {
9
+ if ( ha_is_elementor_version( '>=', '2.6.0' ) ) {
10
+ add_filter( 'elementor/icons_manager/additional_tabs', [ __CLASS__, 'add_happy_icons_tab' ] );
11
+ }
12
+ }
13
+
14
+ public static function add_happy_icons_tab( $tabs ) {
15
+ $tabs['happy-icons'] = [
16
+ 'name' => 'happy-icons',
17
+ 'label' => __( 'Happy Icons', 'happy-elementor-addons' ),
18
+ 'url' => HAPPY_ADDONS_ASSETS . 'fonts/style.min.css',
19
+ 'enqueue' => [ HAPPY_ADDONS_ASSETS . 'fonts/style.min.css' ],
20
+ 'prefix' => 'hm-',
21
+ 'displayPrefix' => 'hm',
22
+ 'labelIcon' => 'fas fa-grin-wink',
23
+ 'ver' => HAPPY_ADDONS_VERSION,
24
+ 'fetchJson' => HAPPY_ADDONS_ASSETS . 'fonts/happy-icons.js',
25
+ 'native' => false,
26
+ ];
27
+ return $tabs;
28
+ }
29
+
30
+ /**
31
+ * Get a list of happy icons
32
+ *
33
+ * @return array
34
+ */
35
+ public static function get_happy_icons() {
36
+ return [
37
+ 'hm hm-3d-rotate' => '3d-rotate',
38
+ 'hm hm-degree' => 'degree',
39
+ 'hm hm-accordion-horizontal' => 'accordion-horizontal',
40
+ 'hm hm-accordion-vertical' => 'accordion-vertical',
41
+ 'hm hm-alarm-clock' => 'alarm-clock',
42
+ 'hm hm-alien-gun' => 'alien-gun',
43
+ 'hm hm-alien' => 'alien',
44
+ 'hm hm-anchor' => 'anchor',
45
+ 'hm hm-android' => 'android',
46
+ 'hm hm-angle-down' => 'angle-down',
47
+ 'hm hm-angle-left' => 'angle-left',
48
+ 'hm hm-angle-right' => 'angle-right',
49
+ 'hm hm-angle-up' => 'angle-up',
50
+ 'hm hm-apple' => 'apple',
51
+ 'hm hm-arrow-left' => 'arrow-left',
52
+ 'hm hm-arrow-right' => 'arrow-right',
53
+ 'hm hm-arrow-zoom-out' => 'arrow-zoom-out',
54
+ 'hm hm-arrow-corner' => 'arrow-corner',
55
+ 'hm hm-arrow-down' => 'arrow-down',
56
+ 'hm hm-arrow-left1' => 'arrow-left1',
57
+ 'hm hm-arrow-right1' => 'arrow-right1',
58
+ 'hm hm-arrow-up' => 'arrow-up',
59
+ 'hm hm-article' => 'article',
60
+ 'hm hm-avatar-man' => 'avatar-man',
61
+ 'hm hm-avatar-woman' => 'avatar-woman',
62
+ 'hm hm-badge1' => 'badge1',
63
+ 'hm hm-badge2' => 'badge2',
64
+ 'hm hm-badge3' => 'badge3',
65
+ 'hm hm-bamboo' => 'bamboo',
66
+ 'hm hm-basketball' => 'basketball',
67
+ 'hm hm-battery' => 'battery',
68
+ 'hm hm-beach-seat' => 'beach-seat',
69
+ 'hm hm-bell' => 'bell',
70
+ 'hm hm-bicycle' => 'bicycle',
71
+ 'hm hm-blog-content' => 'blog-content',
72
+ 'hm hm-bluetooth' => 'bluetooth',
73
+ 'hm hm-board' => 'board',
74
+ 'hm hm-body' => 'body',
75
+ 'hm hm-bomb' => 'bomb',
76
+ 'hm hm-bond-hand' => 'bond-hand',
77
+ 'hm hm-bond' => 'bond',
78
+ 'hm hm-bonsai' => 'bonsai',
79
+ 'hm hm-book' => 'book',
80
+ 'hm hm-bowl' => 'bowl',
81
+ 'hm hm-brick-wall' => 'brick-wall',
82
+ 'hm hm-brush-paint' => 'brush-paint',
83
+ 'hm hm-brush-roll' => 'brush-roll',
84
+ 'hm hm-brush' => 'brush',
85
+ 'hm hm-bug' => 'bug',
86
+ 'hm hm-bulb' => 'bulb',
87
+ 'hm hm-calculation' => 'calculation',
88
+ 'hm hm-calendar' => 'calendar',
89
+ 'hm hm-camera' => 'camera',
90
+ 'hm hm-candle' => 'candle',
91
+ 'hm hm-candles' => 'candles',
92
+ 'hm hm-car' => 'car',
93
+ 'hm hm-card' => 'card',
94
+ 'hm hm-caret-down' => 'caret-down',
95
+ 'hm hm-caret-fill-down' => 'caret-fill-down',
96
+ 'hm hm-caret-fill-left' => 'caret-fill-left',
97
+ 'hm hm-caret-fill-right' => 'caret-fill-right',
98
+ 'hm hm-caret-fill-up' => 'caret-fill-up',
99
+ 'hm hm-caret-left' => 'caret-left',
100
+ 'hm hm-caret-right' => 'caret-right',
101
+ 'hm hm-caret-up' => 'caret-up',
102
+ 'hm hm-carousal' => 'carousal',
103
+ 'hm hm-cart-empty' => 'cart-empty',
104
+ 'hm hm-cart-full' => 'cart-full',
105
+ 'hm hm-caution' => 'caution',
106
+ 'hm hm-chair' => 'chair',
107
+ 'hm hm-chair2' => 'chair2',
108
+ 'hm hm-chat-bubble-single' => 'chat-bubble-single',
109
+ 'hm hm-chat-bubble' => 'chat-bubble',
110
+ 'hm hm-cheese' => 'cheese',
111
+ 'hm hm-chef-cap' => 'chef-cap',
112
+ 'hm hm-clip-board' => 'clip-board',
113
+ 'hm hm-clip' => 'clip',
114
+ 'hm hm-cloud-down' => 'cloud-down',
115
+ 'hm hm-cloud-up' => 'cloud-up',
116
+ 'hm hm-cloud' => 'cloud',
117
+ 'hm hm-code-browser' => 'code-browser',
118
+ 'hm hm-code-clean' => 'code-clean',
119
+ 'hm hm-code' => 'code',
120
+ 'hm hm-cog' => 'cog',
121
+ 'hm hm-color-card' => 'color-card',
122
+ 'hm hm-color-plate' => 'color-plate',
123
+ 'hm hm-compass-math' => 'compass-math',
124
+ 'hm hm-compass' => 'compass',
125
+ 'hm hm-corner' => 'corner',
126
+ 'hm hm-crop' => 'crop',
127
+ 'hm hm-cross-circle' => 'cross-circle',
128
+ 'hm hm-cross-game' => 'cross-game',
129
+ 'hm hm-cross-gap' => 'cross-gap',
130
+ 'hm hm-cross' => 'cross',
131
+ 'hm hm-crown' => 'crown',
132
+ 'hm hm-cube' => 'cube',
133
+ 'hm hm-cup-coffee' => 'cup-coffee',
134
+ 'hm hm-cup' => 'cup',
135
+ 'hm hm-currency-paper' => 'currency-paper',
136
+ 'hm hm-dashboard' => 'dashboard',
137
+ 'hm hm-delivery-van' => 'delivery-van',
138
+ 'hm hm-diamond-ring' => 'diamond-ring',
139
+ 'hm hm-direction-both' => 'direction-both',
140
+ 'hm hm-direction-right' => 'direction-right',
141
+ 'hm hm-disable-person' => 'disable-person',
142
+ 'hm hm-disc' => 'disc',
143
+ 'hm hm-dislike' => 'dislike',
144
+ 'hm hm-dollar-on-hand' => 'dollar-on-hand',
145
+ 'hm hm-door-path' => 'door-path',
146
+ 'hm hm-Download-circle' => 'Download-circle',
147
+ 'hm hm-download' => 'download',
148
+ 'hm hm-drag-inside' => 'drag-inside',
149
+ 'hm hm-drag-outside' => 'drag-outside',
150
+ 'hm hm-drag' => 'drag',
151
+ 'hm hm-drawer' => 'drawer',
152
+ 'hm hm-dribbble' => 'dribbble',
153
+ 'hm hm-dropper' => 'dropper',
154
+ 'hm hm-egg-fry' => 'egg-fry',
155
+ 'hm hm-ellipsis-fill-h' => 'ellipsis-fill-h',
156
+ 'hm hm-ellipsis-fill-v' => 'ellipsis-fill-v',
157
+ 'hm hm-ellipsis-horizontal' => 'ellipsis-horizontal',
158
+ 'hm hm-ellipsis-vertical' => 'ellipsis-vertical',
159
+ 'hm hm-emo-normal' => 'emo-normal',
160
+ 'hm hm-emo-sad' => 'emo-sad',
161
+ 'hm hm-emo-smile' => 'emo-smile',
162
+ 'hm hm-envelop' => 'envelop',
163
+ 'hm hm-facebook' => 'facebook',
164
+ 'hm hm-fancy-futton' => 'fancy-futton',
165
+ 'hm hm-feeder' => 'feeder',
166
+ 'hm hm-file-cabinet' => 'file-cabinet',
167
+ 'hm hm-file-rotate' => 'file-rotate',
168
+ 'hm hm-file' => 'file',
169
+ 'hm hm-files' => 'files',
170
+ 'hm hm-film-roll' => 'film-roll',
171
+ 'hm hm-film' => 'film',
172
+ 'hm hm-finger-index' => 'finger-index',
173
+ 'hm hm-finger-print' => 'finger-print',
174
+ 'hm hm-fire-flame' => 'fire-flame',
175
+ 'hm hm-flag' => 'flag',
176
+ 'hm hm-flip-card1' => 'flip-card1',
177
+ 'hm hm-flip-card2' => 'flip-card2',
178
+ 'hm hm-folder-network' => 'folder-network',
179
+ 'hm hm-folder' => 'folder',
180
+ 'hm hm-football' => 'football',
181
+ 'hm hm-footer' => 'footer',
182
+ 'hm hm-form' => 'form',
183
+ 'hm hm-forward' => 'forward',
184
+ 'hm hm-fountain-pen' => 'fountain-pen',
185
+ 'hm hm-gender-female' => 'gender-female',
186
+ 'hm hm-gender-male' => 'gender-male',
187
+ 'hm hm-gender-sign' => 'gender-sign',
188
+ 'hm hm-gender' => 'gender',
189
+ 'hm hm-ghost' => 'ghost',
190
+ 'hm hm-gift-box' => 'gift-box',
191
+ 'hm hm-globe1' => 'globe1',
192
+ 'hm hm-globe2' => 'globe2',
193
+ 'hm hm-globe3' => 'globe3',
194
+ 'hm hm-globe4' => 'globe4',
195
+ 'hm hm-google' => 'google',
196
+ 'hm hm-graduate-cap' => 'graduate-cap',
197
+ 'hm hm-graph-bar' => 'graph-bar',
198
+ 'hm hm-graph-pie' => 'graph-pie',
199
+ 'hm hm-graph' => 'graph',
200
+ 'hm hm-grid-even' => 'grid-even',
201
+ 'hm hm-grid-masonry' => 'grid-masonry',
202
+ 'hm hm-grid-twist' => 'grid-twist',
203
+ 'hm hm-grid' => 'grid',
204
+ 'hm hm-group' => 'group',
205
+ 'hm hm-hand-mike' => 'hand-mike',
206
+ 'hm hm-hand-watch' => 'hand-watch',
207
+ 'hm hm-hand' => 'hand',
208
+ 'hm hm-header' => 'header',
209
+ 'hm hm-headphone' => 'headphone',
210
+ 'hm hm-headset' => 'headset',
211
+ 'hm hm-heart-beat' => 'heart-beat',
212
+ 'hm hm-hexa' => 'hexa',
213
+ 'hm hm-highlighter' => 'highlighter',
214
+ 'hm hm-home' => 'home',
215
+ 'hm hm-hot-spot' => 'hot-spot',
216
+ 'hm hm-hotdog' => 'hotdog',
217
+ 'hm hm-ice-cream' => 'ice-cream',
218
+ 'hm hm-icon-box' => 'icon-box',
219
+ 'hm hm-imac' => 'imac',
220
+ 'hm hm-image-compare' => 'image-compare',
221
+ 'hm hm-image-slider' => 'image-slider',
222
+ 'hm hm-image' => 'image',
223
+ 'hm hm-inbox' => 'inbox',
224
+ 'hm hm-infinity' => 'infinity',
225
+ 'hm hm-info' => 'info',
226
+ 'hm hm-injection' => 'injection',
227
+ 'hm hm-instagram' => 'instagram',
228
+ 'hm hm-jar-chemical' => 'jar-chemical',
229
+ 'hm hm-key' => 'key',
230
+ 'hm hm-language-change' => 'language-change',
231
+ 'hm hm-laptop' => 'laptop',
232
+ 'hm hm-layer' => 'layer',
233
+ 'hm hm-lens' => 'lens',
234
+ 'hm hm-like' => 'like',
235
+ 'hm hm-line-graph-pointed' => 'line-graph-pointed',
236
+ 'hm hm-link' => 'link',
237
+ 'hm hm-linkedin' => 'linkedin',
238
+ 'hm hm-linux' => 'linux',
239
+ 'hm hm-list-2' => 'list-2',
240
+ 'hm hm-list-group' => 'list-group',
241
+ 'hm hm-list' => 'list',
242
+ 'hm hm-location-pointer' => 'location-pointer',
243
+ 'hm hm-lock' => 'lock',
244
+ 'hm hm-logo-carousel' => 'logo-carousel',
245
+ 'hm hm-logo-grid' => 'logo-grid',
246
+ 'hm hm-lotus' => 'lotus',
247
+ 'hm hm-love' => 'love',
248
+ 'hm hm-madel' => 'madel',
249
+ 'hm hm-magic-wand' => 'magic-wand',
250
+ 'hm hm-magnet' => 'magnet',
251
+ 'hm hm-mail-open' => 'mail-open',
252
+ 'hm hm-man-range' => 'man-range',
253
+ 'hm hm-map-marker' => 'map-marker',
254
+ 'hm hm-map-pointer' => 'map-pointer',
255
+ 'hm hm-measurement' => 'measurement',
256
+ 'hm hm-memory' => 'memory',
257
+ 'hm hm-menu-price' => 'menu-price',
258
+ 'hm hm-micro-chip' => 'micro-chip',
259
+ 'hm hm-microphone1' => 'microphone1',
260
+ 'hm hm-microphone2' => 'microphone2',
261
+ 'hm hm-mobile' => 'mobile',
262
+ 'hm hm-money-bag' => 'money-bag',
263
+ 'hm hm-money' => 'money',
264
+ 'hm hm-monitor' => 'monitor',
265
+ 'hm hm-mouse' => 'mouse',
266
+ 'hm hm-muscle' => 'muscle',
267
+ 'hm hm-net' => 'net',
268
+ 'hm hm-network1' => 'network1',
269
+ 'hm hm-network2' => 'network2',
270
+ 'hm hm-newspaper' => 'newspaper',
271
+ 'hm hm-nuclear-circle' => 'nuclear-circle',
272
+ 'hm hm-office-file' => 'office-file',
273
+ 'hm hm-pacman' => 'pacman',
274
+ 'hm hm-paper-fold' => 'paper-fold',
275
+ 'hm hm-paper-plane-alt' => 'paper-plane-alt',
276
+ 'hm hm-paper-plane' => 'paper-plane',
277
+ 'hm hm-pause' => 'pause',
278
+ 'hm hm-pen-head' => 'pen-head',
279
+ 'hm hm-pen-pencil' => 'pen-pencil',
280
+ 'hm hm-pen-scale' => 'pen-scale',
281
+ 'hm hm-pen-paper' => 'pen-paper',
282
+ 'hm hm-pen' => 'pen',
283
+ 'hm hm-pencil' => 'pencil',
284
+ 'hm hm-pendrive' => 'pendrive',
285
+ 'hm hm-phone' => 'phone',
286
+ 'hm hm-pillar' => 'pillar',
287
+ 'hm hm-pin-man-range' => 'pin-man-range',
288
+ 'hm hm-pin-man' => 'pin-man',
289
+ 'hm hm-pin' => 'pin',
290
+ 'hm hm-plane' => 'plane',
291
+ 'hm hm-play-end' => 'play-end',
292
+ 'hm hm-play-next' => 'play-next',
293
+ 'hm hm-play-previous' => 'play-previous',
294
+ 'hm hm-play-start' => 'play-start',
295
+ 'hm hm-play-button' => 'play-button',
296
+ 'hm hm-play-store' => 'play-store',
297
+ 'hm hm-play' => 'play',
298
+ 'hm hm-playing-card' => 'playing-card',
299
+ 'hm hm-plus-box' => 'plus-box',
300
+ 'hm hm-plus-circle' => 'plus-circle',
301
+ 'hm hm-plus-gap' => 'plus-gap',
302
+ 'hm hm-plus-open' => 'plus-open',
303
+ 'hm hm-popup' => 'popup',
304
+ 'hm hm-power' => 'power',
305
+ 'hm hm-printer' => 'printer',
306
+ 'hm hm-progress-bar' => 'progress-bar',
307
+ 'hm hm-promo' => 'promo',
308
+ 'hm hm-pulse' => 'pulse',
309
+ 'hm hm-puzzle' => 'puzzle',
310
+ 'hm hm-question' => 'question',
311
+ 'hm hm-quote' => 'quote',
312
+ 'hm hm-radar' => 'radar',
313
+ 'hm hm-radiation' => 'radiation',
314
+ 'hm hm-reading-glass-alt' => 'reading-glass-alt',
315
+ 'hm hm-reading-glass' => 'reading-glass',
316
+ 'hm hm-recycle-bin' => 'recycle-bin',
317
+ 'hm hm-recycle' => 'recycle',
318
+ 'hm hm-refresh-time' => 'refresh-time',
319
+ 'hm hm-reply' => 'reply',
320
+ 'hm hm-responsive-device' => 'responsive-device',
321
+ 'hm hm-review' => 'review',
322
+ 'hm hm-rocket1' => 'rocket1',
323
+ 'hm hm-rocket2' => 'rocket2',
324
+ 'hm hm-rss' => 'rss',
325
+ 'hm hm-safety-cap' => 'safety-cap',
326
+ 'hm hm-safety-kit' => 'safety-kit',
327
+ 'hm hm-sand-watch' => 'sand-watch',
328
+ 'hm hm-scale' => 'scale',
329
+ 'hm hm-scanner' => 'scanner',
330
+ 'hm hm-scissor' => 'scissor',
331
+ 'hm hm-screen' => 'screen',
332
+ 'hm hm-search' => 'search',
333
+ 'hm hm-seo' => 'seo',
334
+ 'hm hm-server-network' => 'server-network',
335
+ 'hm hm-server' => 'server',
336
+ 'hm hm-share' => 'share',
337
+ 'hm hm-shield' => 'shield',
338
+ 'hm hm-ship' => 'ship',
339
+ 'hm hm-shirt' => 'shirt',
340
+ 'hm hm-shopping-bag1' => 'shopping-bag1',
341
+ 'hm hm-shopping-bag2' => 'shopping-bag2',
342
+ 'hm hm-shopping-bag3' => 'shopping-bag3',
343
+ 'hm hm-shopping-bag4' => 'shopping-bag4',
344
+ 'hm hm-shuffle' => 'shuffle',
345
+ 'hm hm-shutter' => 'shutter',
346
+ 'hm hm-sign-in' => 'sign-in',
347
+ 'hm hm-sign-out' => 'sign-out',
348
+ 'hm hm-sitemap1' => 'sitemap1',
349
+ 'hm hm-sitemap2' => 'sitemap2',
350
+ 'hm hm-skart' => 'skart',
351
+ 'hm hm-skull' => 'skull',
352
+ 'hm hm-skyscraper' => 'skyscraper',
353
+ 'hm hm-slider-doc' => 'slider-doc',
354
+ 'hm hm-slider-h-range' => 'slider-h-range',
355
+ 'hm hm-slider-image' => 'slider-image',
356
+ 'hm hm-slider-range-h' => 'slider-range-h',
357
+ 'hm hm-slider-v-open' => 'slider-v-open',
358
+ 'hm hm-slider-video' => 'slider-video',
359
+ 'hm hm-slider' => 'slider',
360
+ 'hm hm-smart-watch' => 'smart-watch',
361
+ 'hm hm-snow' => 'snow',
362
+ 'hm hm-spa-face' => 'spa-face',
363
+ 'hm hm-spa-stone-flower' => 'spa-stone-flower',
364
+ 'hm hm-spa-stone' => 'spa-stone',
365
+ 'hm hm-spark' => 'spark',
366
+ 'hm hm-speaker-off' => 'speaker-off',
367
+ 'hm hm-speaker-on' => 'speaker-on',
368
+ 'hm hm-spoon-fork' => 'spoon-fork',
369
+ 'hm hm-spoon' => 'spoon',
370
+ 'hm hm-star' => 'star',
371
+ 'hm hm-step-flow' => 'step-flow',
372
+ 'hm hm-steps' => 'steps',
373
+ 'hm hm-stop-watch' => 'stop-watch',
374
+ 'hm hm-stop' => 'stop',
375
+ 'hm hm-support-call' => 'support-call',
376
+ 'hm hm-tab' => 'tab',
377
+ 'hm hm-table-lamp' => 'table-lamp',
378
+ 'hm hm-tablet' => 'tablet',
379
+ 'hm hm-tag' => 'tag',
380
+ 'hm hm-target-arrow' => 'target-arrow',
381
+ 'hm hm-target' => 'target',
382
+ 'hm hm-target1' => 'target1',
383
+ 'hm hm-team-carousel' => 'team-carousel',
384
+ 'hm hm-team-member' => 'team-member',
385
+ 'hm hm-tennis-ball' => 'tennis-ball',
386
+ 'hm hm-terminal' => 'terminal',
387
+ 'hm hm-testimonial-carousel' => 'testimonial-carousel',
388
+ 'hm hm-testimonial' => 'testimonial',
389
+ 'hm hm-text-animation' => 'text-animation',
390
+ 'hm hm-theatre' => 'theatre',
391
+ 'hm hm-tick-circle' => 'tick-circle',
392
+ 'hm hm-tick' => 'tick',
393
+ 'hm hm-tickets' => 'tickets',
394
+ 'hm hm-tie-knot' => 'tie-knot',
395
+ 'hm hm-tie' => 'tie',
396
+ 'hm hm-timeline' => 'timeline',
397
+ 'hm hm-toggle' => 'toggle',
398
+ 'hm hm-tools' => 'tools',
399
+ 'hm hm-tree-square' => 'tree-square',
400
+ 'hm hm-twitter-bird' => 'twitter-bird',
401
+ 'hm hm-twitter' => 'twitter',
402
+ 'hm hm-ufo' => 'ufo',
403
+ 'hm hm-umbralla' => 'umbralla',
404
+ 'hm hm-unlock' => 'unlock',
405
+ 'hm hm-up-down' => 'up-down',
406
+ 'hm hm-upload' => 'upload',
407
+ 'hm hm-upward-top-right' => 'upward-top-right',
408
+ 'hm hm-user-female' => 'user-female',
409
+ 'hm hm-user-id' => 'user-id',
410
+ 'hm hm-user-male' => 'user-male',
411
+ 'hm hm-video-camera' => 'video-camera',
412
+ 'hm hm-water-drop' => 'water-drop',
413
+ 'hm hm-weather-cloud-day' => 'weather-cloud-day',
414
+ 'hm hm-weather-cloud' => 'weather-cloud',
415
+ 'hm hm-weather-day-rain' => 'weather-day-rain',
416
+ 'hm hm-weather-day-snow' => 'weather-day-snow',
417
+ 'hm hm-weather-day-windy-rain' => 'weather-day-windy-rain',
418
+ 'hm hm-weather-flood' => 'weather-flood',
419
+ 'hm hm-weather-night-cloud' => 'weather-night-cloud',
420
+ 'hm hm-weather-rain-alt' => 'weather-rain-alt',
421
+ 'hm hm-weather-rain' => 'weather-rain',
422
+ 'hm hm-weather-snow' => 'weather-snow',
423
+ 'hm hm-weather-sun-rain' => 'weather-sun-rain',
424
+ 'hm hm-weather-sun' => 'weather-sun',
425
+ 'hm hm-weather-sunny-day' => 'weather-sunny-day',
426
+ 'hm hm-weather-thunder' => 'weather-thunder',
427
+ 'hm hm-weather-windy-rain' => 'weather-windy-rain',
428
+ 'hm hm-webcam1' => 'webcam1',
429
+ 'hm hm-webcam2' => 'webcam2',
430
+ 'hm hm-weight-scale' => 'weight-scale',
431
+ 'hm hm-windows' => 'windows',
432
+ 'hm hm-wine-glass2' => 'wine-glass2',
433
+ 'hm hm-wine-glass' => 'wine-glass',
434
+ 'hm hm-worker-cap' => 'worker-cap',
435
+ 'hm hm-youtube' => 'youtube',
436
+ ];
437
+ }
438
+ }
classes/updater.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Happy_Addons\Elementor;
3
+
4
+ defined( 'ABSPATH' ) || die();
5
+
6
+ /**
7
+ * Class Updater
8
+ *
9
+ * @package Happy_Addons\Elementor
10
+ * @since 1.5.0
11
+ */
12
+ class Updater {
13
+
14
+ const VERSION_DB_KEY = 'happyaddons_version';
15
+
16
+ public static function init() {
17
+ if ( self::should_update() ) {
18
+ self::update();
19
+ self::update_version();
20
+ }
21
+ }
22
+
23
+ protected static function v_1_5_0() {
24
+ add_option( 'elementor_icon_manager_needs_update', 'yes' );
25
+ add_option( 'elementor_load_fa4_shim', 'yes' );
26
+ }
27
+
28
+ protected static function update() {
29
+ self::v_1_5_0();
30
+
31
+ $assets_cache = new Assets_Cache();
32
+ $assets_cache->delete_all();
33
+ }
34
+
35
+ protected static function get_old_version() {
36
+ return get_option( self::VERSION_DB_KEY, '' );
37
+ }
38
+
39
+ protected static function get_new_version() {
40
+ return HAPPY_ADDONS_VERSION;
41
+ }
42
+
43
+ protected static function update_version() {
44
+ update_option( self::VERSION_DB_KEY, self::get_new_version() );
45
+ }
46
+
47
+ protected static function should_update() {
48
+ if ( ! self::get_old_version() ) {
49
+ return true;
50
+ }
51
+ return version_compare( self::get_new_version(), self::get_old_version(), '>' );
52
+ }
53
+ }
classes/widgets-cache.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Happy_Addons\Elementor;
3
+
4
+ defined( 'ABSPATH' ) || die();
5
+
6
+ class Widgets_Cache {
7
+
8
+ const OPTION_KEY = 'happyaddons_elements_cache';
9
+
10
+ const META_KEY = '_happyaddons_elements_cache';
11
+
12
+ protected $post_id = 0;
13
+
14
+ protected $elementor_data = null;
15
+
16
+ protected $is_built_with_elementor = false;
17
+
18
+ protected $is_published = false;
19
+
20
+ public function __construct( $post_id = 0, $data = null ) {
21
+ if ( ! $post_id || ! Cache_Manager::is_built_with_elementor( $post_id ) || ! Cache_Manager::is_published( $post_id ) ) {
22
+ return;
23
+ }
24
+
25
+ if ( ! is_null( $data ) ) {
26
+ $this->elementor_data = $data;
27
+ }
28
+
29
+ $this->post_id = $post_id;
30
+ $this->is_published = true;
31
+ $this->is_built_with_elementor = true;
32
+ }
33
+
34
+ public function get_post_id() {
35
+ return $this->post_id;
36
+ }
37
+
38
+ protected function get_global_widget_type( $template_id ) {
39
+ $template_data = ha_elementor()->templates_manager->get_template_data( [
40
+ 'source' => 'local',
41
+ 'template_id' => $template_id,
42
+ ] );
43
+
44
+ if ( is_wp_error( $template_data ) ) {
45
+ return '';
46
+ }
47
+
48
+ if ( empty( $template_data['content'] ) ) {
49
+ return '';
50
+ }
51
+
52
+ $original_widget_type = ha_elementor()->widgets_manager->get_widget_types( $template_data['content'][0]['widgetType'] );
53
+ return $original_widget_type ? $template_data['content'][0]['widgetType'] : '';
54
+ }
55
+
56
+ public function get_widget_type( $element ) {
57
+ if ( empty( $element['widgetType'] ) ) {
58
+ $type = $element['elType'];
59
+ } else {
60
+ $type = $element['widgetType'];
61
+ }
62
+
63
+ if ( $type === 'global' && ! empty( $element['templateID'] ) ) {
64
+ $type = $this->get_global_widget_type( $element['templateID'] );
65
+ }
66
+ return $type;
67
+ }
68
+
69
+ public function get_cache_data() {
70
+ $cache = get_post_meta( $this->get_post_id(), self::META_KEY, true );
71
+ if ( empty( $cache ) ) {
72
+ $cache = $this->save();
73
+ }
74
+ return $cache;
75
+ }
76
+
77
+ public function get() {
78
+ $cache = $this->get_cache_data();
79
+ return array_map( function( $widget_key ) {
80
+ return str_replace( 'ha-', '', $widget_key );
81
+ }, array_keys( $cache ) );
82
+ }
83
+
84
+ public function has() {
85
+ $cache = $this->get();
86
+ return ! empty( $cache );
87
+ }
88
+
89
+ public function delete() {
90
+ delete_post_meta( $this->get_post_id(), self::META_KEY );
91
+ }
92
+
93
+ public function get_post_type() {
94
+ return get_post_type( $this->get_post_id() );
95
+ }
96
+
97
+ public function get_elementor_data() {
98
+ if ( ! $this->is_built_with_elementor || ! $this->is_published ) {
99
+ return [];
100
+ }
101
+
102
+ if ( is_null( $this->elementor_data ) ) {
103
+ $document = ha_elementor()->documents->get( $this->get_post_id() );
104
+ $data = $document ? $document->get_elements_data() : [];
105
+ } else {
106
+ $data = $this->elementor_data;
107
+ }
108
+
109
+ return $data;
110
+ }
111
+
112
+ public function save() {
113
+ $data = $this->get_elementor_data();
114
+
115
+ if ( empty( $data ) ) {
116
+ return [];
117
+ }
118
+
119
+ $cache = [];
120
+ ha_elementor()->db->iterate_data( $data, function ( $element ) use ( &$cache ) {
121
+ $type = $this->get_widget_type( $element );
122
+
123
+ if ( strpos( $type, 'ha-' ) !== false ) {
124
+ if ( ! isset( $cache[ $type ] ) ) {
125
+ $cache[ $type ] = 0;
126
+ }
127
+ $cache[ $type ] ++;
128
+ }
129
+
130
+ return $element;
131
+ } );
132
+
133
+ // Handle global cache here
134
+ $doc_type = $this->get_post_type();
135
+ $prev_cache = get_post_meta( $this->get_post_id(), self::META_KEY, true );
136
+ $global_cache = get_option( self::OPTION_KEY, [] );
137
+
138
+ if ( is_array( $prev_cache ) ) {
139
+ foreach ( $prev_cache as $type => $count ) {
140
+ if ( isset( $global_cache[ $doc_type ][ $type ] ) ) {
141
+ $global_cache[ $doc_type ][ $type ] -= $prev_cache[ $type ];
142
+ if ( 0 === $global_cache[ $doc_type ][ $type ] ) {
143
+ unset( $global_cache[ $doc_type ][ $type ] );
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ foreach ( $cache as $type => $count ) {
150
+ if ( ! isset( $global_cache[ $doc_type ] ) ) {
151
+ $global_cache[ $doc_type ] = [];
152
+ }
153
+
154
+ if ( ! isset( $global_cache[ $doc_type ][ $type ] ) ) {
155
+ $global_cache[ $doc_type ][ $type ] = 0;
156
+ }
157
+
158
+ $global_cache[ $doc_type ][ $type ] += $cache[ $type ];
159
+ }
160
+
161
+ // Save cache
162
+ update_option( self::OPTION_KEY, $global_cache );
163
+ update_post_meta( $this->get_post_id(), self::META_KEY, $cache );
164
+ return $cache;
165
+ }
166
+ }
classes/{widget-manager.php → widgets-manager.php} RENAMED
@@ -1,19 +1,16 @@
1
  <?php
2
- namespace Happy_Addons\Elementor\Manager;
3
 
4
- use Elementor\Plugin as Elementor;
 
5
  use Happy_Addons\Elementor\Widget\Card;
6
- use Happy_Addons\Elementor\Widget\AdCard;
7
  use Happy_Addons\Elementor\Widget\CalderaForm;
8
  use Happy_Addons\Elementor\Widget\Calendly;
9
  use Happy_Addons\Elementor\Widget\Carousel;
10
  use Happy_Addons\Elementor\Widget\CF7;
11
  use Happy_Addons\Elementor\Widget\Dual_Button;
12
- use Happy_Addons\Elementor\Widget\Feature_List;
13
  use Happy_Addons\Elementor\Widget\Flip_Box;
14
- use Happy_Addons\Elementor\Widget\Google_Map;
15
  use Happy_Addons\Elementor\Widget\Gradient_Heading;
16
- use Happy_Addons\Elementor\Widget\Hover_Box;
17
  use Happy_Addons\Elementor\Widget\Icon_Box;
18
  use Happy_Addons\Elementor\Widget\Image_Compare;
19
  use Happy_Addons\Elementor\Widget\Image_Grid;
@@ -34,25 +31,46 @@ use Happy_Addons\Elementor\Widget\WPForm;
34
 
35
  defined( 'ABSPATH' ) || die();
36
 
37
- class Widgets {
 
38
  /**
39
  * Initialize
40
  */
41
  public static function init() {
42
- add_action( 'elementor/widgets/widgets_registered', [__CLASS__, 'register'] );
 
 
 
 
 
 
 
 
 
 
 
 
43
  }
44
 
45
  public static function get_widgets_map() {
46
  $widgets_map = [
47
- // This is base for happy addons
48
  self::get_base_widget_key() => [
49
  'css' => ['common', 'btn'],
50
  'js' => [],
51
  'vendor' => [
52
- 'js' => ['anime']
 
53
  ]
54
  ],
 
 
 
 
 
 
55
 
 
 
56
  // All the widgets are listed below with respective map
57
  'infobox' => [
58
  'class' => InfoBox::class,
@@ -65,7 +83,7 @@ class Widgets {
65
  ],
66
  'card' => [
67
  'class' => Card::class,
68
- 'css' => ['card'],
69
  'js' => [],
70
  'vendor' => [
71
  'css' => [],
@@ -83,7 +101,7 @@ class Widgets {
83
  ],
84
  'icon-box' => [
85
  'class' => Icon_Box::class,
86
- 'css' => ['icon-box'],
87
  'js' => [],
88
  'vendor' => [
89
  'css' => [],
@@ -119,13 +137,22 @@ class Widgets {
119
  ],
120
  'justified-gallery' => [
121
  'class' => Justified_Gallery::class,
122
- 'css' => ['justified-gallery'],
123
  'js' => [],
124
  'vendor' => [
125
  'css' => ['justifiedGallery'],
126
  'js' => ['jquery-justifiedGallery'],
127
  ],
128
  ],
 
 
 
 
 
 
 
 
 
129
  'slider' => [
130
  'class' => Slider::class,
131
  'css' => ['slider-carousel'],
@@ -271,23 +298,6 @@ class Widgets {
271
  ],
272
  ],
273
  ];
274
-
275
- return apply_filters( 'happyaddons_widgets_map', $widgets_map );
276
- }
277
-
278
- /**
279
- * Check widget file and include
280
- *
281
- * @param $widget
282
- * @return bool
283
- */
284
- private static function is_registrable( $widget ) {
285
- $widget_file = HAPPY_DIR_PATH . 'widgets/' . $widget . '/widget.php';
286
- if ( $widget !== self::get_base_widget_key() && is_readable( $widget_file ) ) {
287
- include( $widget_file );
288
- return true;
289
- }
290
- return false;
291
  }
292
 
293
  public static function get_base_widget_key() {
@@ -304,12 +314,20 @@ class Widgets {
304
  * @access public
305
  */
306
  public static function register() {
307
- require( HAPPY_DIR_PATH . 'base/widget-base.php' );
308
 
309
- foreach ( self::get_widgets_map() as $widget => $data ) {
310
- if ( self::is_registrable( $widget ) && class_exists( $data['class'] ) ) {
311
- Elementor::instance()->widgets_manager->register_widget_type( new $data['class'] );
312
  }
313
  }
314
  }
 
 
 
 
 
 
 
 
315
  }
1
  <?php
2
+ namespace Happy_Addons\Elementor;
3
 
4
+ use Elementor\Element_Base;
5
+ use Elementor\Widget_Base;
6
  use Happy_Addons\Elementor\Widget\Card;
 
7
  use Happy_Addons\Elementor\Widget\CalderaForm;
8
  use Happy_Addons\Elementor\Widget\Calendly;
9
  use Happy_Addons\Elementor\Widget\Carousel;
10
  use Happy_Addons\Elementor\Widget\CF7;
11
  use Happy_Addons\Elementor\Widget\Dual_Button;
 
12
  use Happy_Addons\Elementor\Widget\Flip_Box;
 
13
  use Happy_Addons\Elementor\Widget\Gradient_Heading;
 
14
  use Happy_Addons\Elementor\Widget\Icon_Box;
15
  use Happy_Addons\Elementor\Widget\Image_Compare;
16
  use Happy_Addons\Elementor\Widget\Image_Grid;
31
 
32
  defined( 'ABSPATH' ) || die();
33
 
34
+ class Widgets_Manager {
35
+
36
  /**
37
  * Initialize
38
  */
39
  public static function init() {
40
+ add_action( 'elementor/widgets/widgets_registered', [ __CLASS__, 'register' ] );
41
+ add_action( 'elementor/frontend/before_render', [ __CLASS__, 'add_global_widget_render_attributes' ] );
42
+ }
43
+
44
+ public static function add_global_widget_render_attributes( Element_Base $widget ) {
45
+ if ( $widget->get_data( 'widgetType' ) === 'global' && method_exists( $widget, 'get_original_element_instance' ) ) {
46
+ $original_instance = $widget->get_original_element_instance();
47
+ if ( method_exists( $original_instance, 'get_html_wrapper_class' ) && strpos( $original_instance->get_data( 'widgetType' ), 'ha-' ) !== false ) {
48
+ $widget->add_render_attribute( '_wrapper', [
49
+ 'class' => $original_instance->get_html_wrapper_class(),
50
+ ] );
51
+ }
52
+ }
53
  }
54
 
55
  public static function get_widgets_map() {
56
  $widgets_map = [
 
57
  self::get_base_widget_key() => [
58
  'css' => ['common', 'btn'],
59
  'js' => [],
60
  'vendor' => [
61
+ 'js' => ['anime'],
62
+ 'css' => ['happy-icons', 'font-awesome']
63
  ]
64
  ],
65
+ ];
66
+
67
+ $local_widgets_map = self::get_local_widgets_map();
68
+ $widgets_map = array_merge( $widgets_map, $local_widgets_map );
69
+ return apply_filters( 'happyaddons_widgets_map', $widgets_map );
70
+ }
71
 
72
+ public static function get_local_widgets_map() {
73
+ return [
74
  // All the widgets are listed below with respective map
75
  'infobox' => [
76
  'class' => InfoBox::class,
83
  ],
84
  'card' => [
85
  'class' => Card::class,
86
+ 'css' => ['card', 'badge'],
87
  'js' => [],
88
  'vendor' => [
89
  'css' => [],
101
  ],
102
  'icon-box' => [
103
  'class' => Icon_Box::class,
104
+ 'css' => ['icon-box', 'badge'],
105
  'js' => [],
106
  'vendor' => [
107
  'css' => [],
137
  ],
138
  'justified-gallery' => [
139
  'class' => Justified_Gallery::class,
140
+ 'css' => ['justified-gallery', 'gallery-filter'],
141
  'js' => [],
142
  'vendor' => [
143
  'css' => ['justifiedGallery'],
144
  'js' => ['jquery-justifiedGallery'],
145
  ],
146
  ],
147
+ 'image-grid' => [
148
+ 'class' => Image_Grid::class,
149
+ 'css' => ['image-grid', 'gallery-filter'],
150
+ 'js' => [],
151
+ 'vendor' => [
152
+ 'css' => [],
153
+ 'js' => ['jquery-isotope'],
154
+ ],
155
+ ],
156
  'slider' => [
157
  'class' => Slider::class,
158
  'css' => ['slider-carousel'],
298
  ],
299
  ],
300
  ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  }
302
 
303
  public static function get_base_widget_key() {
314
  * @access public
315
  */
316
  public static function register() {
317
+ require( HAPPY_ADDONS_DIR_PATH . 'base/widget-base.php' );
318
 
319
+ foreach ( self::get_local_widgets_map() as $widget_key => $data ) {
320
+ if ( ! empty( $data['class'] ) ) {
321
+ self::register_widget( $widget_key, $data['class'] );
322
  }
323
  }
324
  }
325
+
326
+ protected static function register_widget( $widget_key, $class ) {
327
+ $widget_file = HAPPY_ADDONS_DIR_PATH . 'widgets/' . $widget_key . '/widget.php';
328
+ if ( is_readable( $widget_file ) ) {
329
+ include( $widget_file );
330
+ \Elementor\Plugin::instance()->widgets_manager->register_widget_type( new $class );
331
+ }
332
+ }
333
  }
extensions/background-overlay.php ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Happy_Addons\Elementor\Extension;
3
+
4
+ use Elementor\Controls_Manager;
5
+ use Elementor\Element_Base;
6
+ use Elementor\Group_Control_Background;
7
+ use Elementor\Group_Control_Css_Filter;
8
+
9
+ defined( 'ABSPATH' ) || die();
10
+
11
+ class Background_Overlay {
12
+
13
+ public static function init() {
14
+ add_action( 'elementor/element/common/_section_background/after_section_end', [__CLASS__, 'add_section'] );
15
+ add_action( 'elementor/element/after_add_attributes', [__CLASS__, 'add_attributes'] );
16
+ }
17
+
18
+ public static function add_attributes( Element_Base $element ) {
19
+ if ( in_array( $element->get_name(), [ 'column', 'section' ] ) ) {
20
+ return;
21
+ }
22
+
23
+ if ( \Elementor\Plugin::instance()->editor->is_edit_mode() ) {
24
+ return;
25
+ }
26
+
27
+ $settings = $element->get_settings_for_display();
28
+
29
+ $overlay_bg = isset( $settings['_ha_background_overlay_background'] ) ? $settings['_ha_background_overlay_background'] : '';
30
+ $overlay_hover_bg = isset( $settings['_ha_background_overlay_hover_background'] ) ? $settings['_ha_background_overlay_hover_background'] : '';
31
+
32
+ $has_background_overlay = ( in_array( $overlay_bg, [ 'classic', 'gradient' ], true ) ||
33
+ in_array( $overlay_hover_bg, [ 'classic', 'gradient' ], true ) );
34
+
35
+ if ( $has_background_overlay ) {
36
+ $element->add_render_attribute( '_wrapper', 'class', 'ha-has-background-overlay' );
37
+ }
38
+ }
39
+
40
+ public static function add_section( Element_Base $element ) {
41
+ $element->start_controls_section(
42
+ '_ha_section_background_overlay',
43
+ [
44
+ 'label' => __( 'Background Overlay', 'elementor' ),
45
+ 'tab' => Controls_Manager::TAB_ADVANCED,
46
+ 'condition' => [
47
+ '_background_background' => [ 'classic', 'gradient' ],
48
+ ],
49
+ ]
50
+ );
51
+
52
+ $element->start_controls_tabs( '_ha_tabs_background_overlay' );
53
+
54
+ $element->start_controls_tab(
55
+ '_ha_tab_background_overlay_normal',
56
+ [
57
+ 'label' => __( 'Normal', 'elementor' ),
58
+ ]
59
+ );
60
+
61
+ $element->add_group_control(
62
+ Group_Control_Background::get_type(),
63
+ [
64
+ 'name' => '_ha_background_overlay',
65
+ 'selector' => '{{WRAPPER}}.ha-has-background-overlay > .elementor-widget-container:before',
66
+ ]
67
+ );
68
+
69
+ $element->add_control(
70
+ '_ha_background_overlay_opacity',
71
+ [
72
+ 'label' => __( 'Opacity', 'elementor' ),
73
+ 'type' => Controls_Manager::SLIDER,
74
+ 'default' => [
75
+ 'size' => .5,
76
+ ],
77
+ 'range' => [
78
+ 'px' => [
79
+ 'max' => 1,
80
+ 'step' => 0.01,
81
+ ],
82
+ ],
83
+ 'selectors' => [
84
+ '{{WRAPPER}}.ha-has-background-overlay > .elementor-widget-container:before' => 'opacity: {{SIZE}};',
85
+ ],
86
+ 'condition' => [
87
+ '_ha_background_overlay_background' => [ 'classic', 'gradient' ],
88
+ ],
89
+ ]
90
+ );
91
+
92
+ $element->add_group_control(
93
+ Group_Control_Css_Filter::get_type(),
94
+ [
95
+ 'name' => '_ha_css_filters',
96
+ 'selector' => '{{WRAPPER}}.ha-has-background-overlay > .elementor-widget-container:before',
97
+ ]
98
+ );
99
+
100
+ $element->add_control(
101
+ '_ha_overlay_blend_mode',
102
+ [
103
+ 'label' => __( 'Blend Mode', 'elementor' ),
104
+ 'type' => Controls_Manager::SELECT,
105
+ 'options' => [
106
+ '' => __( 'Normal', 'elementor' ),
107
+ 'multiply' => 'Multiply',
108
+ 'screen' => 'Screen',
109
+ 'overlay' => 'Overlay',
110
+ 'darken' => 'Darken',
111
+ 'lighten' => 'Lighten',
112
+ 'color-dodge' => 'Color Dodge',
113
+ 'saturation' => 'Saturation',
114
+ 'color' => 'Color',
115
+ 'luminosity' => 'Luminosity',
116
+ ],
117
+ 'selectors' => [
118
+ '{{WRAPPER}}.ha-has-background-overlay > .elementor-widget-container:before' => 'mix-blend-mode: {{VALUE}}',
119
+ ],
120
+ ]
121
+ );
122
+
123
+ $element->end_controls_tab();
124
+
125
+ $element->start_controls_tab(
126
+ '_ha_tab_background_overlay_hover',
127
+ [
128
+ 'label' => __( 'Hover', 'elementor' ),
129
+ ]
130
+ );
131
+
132
+ $element->add_group_control(
133
+ Group_Control_Background::get_type(),
134
+ [
135
+ 'name' => '_ha_background_overlay_hover',
136
+ 'selector' => '{{WRAPPER}}.ha-has-background-overlay:hover > .elementor-widget-container:before',
137
+ ]
138
+ );
139
+
140
+ $element->add_control(
141
+ '_ha_background_overlay_hover_opacity',
142
+ [
143
+ 'label' => __( 'Opacity', 'elementor' ),
144
+ 'type' => Controls_Manager::SLIDER,
145
+ 'default' => [
146
+ 'size' => .5,
147
+ ],
148
+ 'range' => [
149
+ 'px' => [
150
+ 'max' => 1,
151
+ 'step' => 0.01,
152
+ ],
153
+ ],
154
+ 'selectors' => [
155
+ '{{WRAPPER}}.ha-has-background-overlay:hover > .elementor-widget-container:before' => 'opacity: {{SIZE}};',
156
+ ],
157
+ 'condition' => [
158
+ '_ha_background_overlay_hover_background' => [ 'classic', 'gradient' ],
159
+ ],
160
+ ]
161
+ );
162
+
163
+ $element->add_group_control(
164
+ Group_Control_Css_Filter::get_type(),
165
+ [
166
+ 'name' => '_ha_css_filters_hover',
167
+ 'selector' => '{{WRAPPER}}.ha-has-background-overlay:hover > .elementor-widget-container:before',
168
+ ]
169
+ );
170
+
171
+ $element->add_control(
172
+ '_ha_background_overlay_hover_transition',
173
+ [
174
+ 'label' => __( 'Transition Duration', 'elementor' ),
175
+ 'type' => Controls_Manager::SLIDER,
176
+ 'default' => [
177
+ 'size' => 0.3,
178
+ ],
179
+ 'range' => [
180
+ 'px' => [
181
+ 'max' => 3,
182
+ 'step' => 0.1,
183
+ ],
184
+ ],
185
+ 'separator' => 'before',
186
+ 'selectors' => [
187
+ '{{WRAPPER}}.ha-has-background-overlay > .elementor-widget-container:before' => 'transition: background {{SIZE}}s;',
188
+ ]
189
+ ]
190
+ );
191
+
192
+ $element->end_controls_tab();
193
+
194
+ $element->end_controls_tabs();
195
+
196
+ $element->end_controls_section();
197
+ }
198
+ }
{classes → extensions}/happy-effects.php RENAMED
@@ -3,7 +3,6 @@ namespace Happy_Addons\Elementor\Extension;
3
 
4
  use Elementor\Controls_Manager;
5
  use Elementor\Element_Base;
6
- use Elementor\Core\Files\CSS\Post;
7
 
8
  defined( 'ABSPATH' ) || die();
9
 
3
 
4
  use Elementor\Controls_Manager;
5
  use Elementor\Element_Base;
 
6
 
7
  defined( 'ABSPATH' ) || die();
8
 
inc/functions.php CHANGED
@@ -342,19 +342,65 @@ function ha_get_css_blend_modes() {
342
  ];
343
  }
344
 
345
- function ha_should_load_complied_assets() {
346
- return (
347
- apply_filters( 'happyaddons_ondemand_asset_compiling', true ) &&
348
- ! \Elementor\Plugin::$instance->editor->is_edit_mode() &&
349
- ! \Elementor\Plugin::$instance->preview->is_preview_mode() &&
350
- ! is_preview()
351
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  }
353
 
354
- function ha_should_load_used_library_only() {
355
- return (
356
- ! \Elementor\Plugin::$instance->editor->is_edit_mode() &&
357
- ! \Elementor\Plugin::$instance->preview->is_preview_mode() &&
358
- ! is_preview()
359
- );
360
  }
342
  ];
343
  }
344
 
345
+ /**
346
+ * Check elementor version
347
+ *
348
+ * @param string $version
349
+ * @param string $operator
350
+ * @return bool
351
+ */
352
+ function ha_is_elementor_version( $operator = '<', $version = '2.6.0' ) {
353
+ return defined( 'ELEMENTOR_VERSION' ) && version_compare( ELEMENTOR_VERSION, $version, $operator );
354
+ }
355
+
356
+ /**
357
+ * Render icon html with backward compatibility
358
+ *
359
+ * @param array $settings
360
+ * @param string $old_icon_id
361
+ * @param string $new_icon_id
362
+ * @param array $attributes
363
+ */
364
+ function ha_render_icon( $settings = [], $old_icon_id = 'icon', $new_icon_id = 'selected_icon', $attributes = [] ) {
365
+ // Check if its already migrated
366
+ $migrated = isset( $settings['__fa4_migrated'][ $new_icon_id ] );
367
+ // Check if its a new widget without previously selected icon using the old Icon control
368
+ $is_new = empty( $settings[ $old_icon_id ] );
369
+
370
+ $attributes['aria-hidden'] = 'true';
371
+
372
+ if ( ha_is_elementor_version( '>=', '2.6.0' ) && ( $is_new || $migrated ) ) {
373
+ \Elementor\Icons_Manager::render_icon( $settings[ $new_icon_id ], $attributes );
374
+ } else {
375
+ if ( empty( $attributes['class'] ) ) {
376
+ $attributes['class'] = $settings[ $old_icon_id ];
377
+ } else {
378
+ if ( is_array( $attributes['class'] ) ) {
379
+ $attributes['class'][] = $settings[ $old_icon_id ];
380
+ } else {
381
+ $attributes['class'] .= ' ' . $settings[ $old_icon_id ];
382
+ }
383
+ }
384
+ printf( '<i %s></i>', \Elementor\Utils::render_html_attributes( $attributes ) );
385
+ }
386
+ }
387
+
388
+ /**
389
+ * List of happy icons
390
+ *
391
+ * @return array
392
+ */
393
+ function ha_get_happy_icons() {
394
+ return \Happy_Addons\Elementor\Icons_Manager::get_happy_icons();
395
+ }
396
+
397
+ /**
398
+ * @return bool
399
+ */
400
+ function ha_is_happy_mode_enabled() {
401
+ return apply_filters( 'happyaddons_is_happy_mode_enabled', true );
402
  }
403
 
404
+ function ha_elementor() {
405
+ return \Elementor\Plugin::instance();
 
 
 
 
406
  }
inc/happy-icons.php DELETED
@@ -1,409 +0,0 @@
1
- <?php
2
- /**
3
- * List of happy icons
4
- *
5
- * @return array
6
- */
7
- function ha_get_happy_icons() {
8
- return [
9
- 'hm hm-3d-rotate' => '3d-rotate',
10
- 'hm hm-degree' => 'degree',
11
- 'hm hm-accordion-horizontal' => 'accordion-horizontal',
12
- 'hm hm-accordion-vertical' => 'accordion-vertical',
13
- 'hm hm-alarm-clock' => 'alarm-clock',
14
- 'hm hm-alien-gun' => 'alien-gun',
15
- 'hm hm-alien' => 'alien',
16
- 'hm hm-anchor' => 'anchor',
17
- 'hm hm-android' => 'android',
18
- 'hm hm-angle-down' => 'angle-down',
19
- 'hm hm-angle-left' => 'angle-left',
20
- 'hm hm-angle-right' => 'angle-right',
21
- 'hm hm-angle-up' => 'angle-up',
22
- 'hm hm-apple' => 'apple',
23
- 'hm hm-arrow-left' => 'arrow-left',
24
- 'hm hm-arrow-right' => 'arrow-right',
25
- 'hm hm-arrow-zoom-out' => 'arrow-zoom-out',
26
- 'hm hm-arrow-corner' => 'arrow-corner',
27
- 'hm hm-arrow-down' => 'arrow-down',
28
- 'hm hm-arrow-left1' => 'arrow-left1',
29
- 'hm hm-arrow-right1' => 'arrow-right1',
30
- 'hm hm-arrow-up' => 'arrow-up',
31
- 'hm hm-article' => 'article',
32
- 'hm hm-avatar-man' => 'avatar-man',
33
- 'hm hm-avatar-woman' => 'avatar-woman',
34
- 'hm hm-badge1' => 'badge1',
35
- 'hm hm-badge2' => 'badge2',
36
- 'hm hm-badge3' => 'badge3',
37
- 'hm hm-bamboo' => 'bamboo',
38
- 'hm hm-basketball' => 'basketball',
39
- 'hm hm-battery' => 'battery',
40
- 'hm hm-beach-seat' => 'beach-seat',
41
- 'hm hm-bell' => 'bell',
42
- 'hm hm-bicycle' => 'bicycle',
43
- 'hm hm-blog-content' => 'blog-content',
44
- 'hm hm-bluetooth' => 'bluetooth',
45
- 'hm hm-board' => 'board',
46
- 'hm hm-body' => 'body',
47
- 'hm hm-bomb' => 'bomb',
48
- 'hm hm-bond-hand' => 'bond-hand',
49
- 'hm hm-bond' => 'bond',
50
- 'hm hm-bonsai' => 'bonsai',
51
- 'hm hm-book' => 'book',
52
- 'hm hm-bowl' => 'bowl',
53
- 'hm hm-brick-wall' => 'brick-wall',
54
- 'hm hm-brush-paint' => 'brush-paint',
55
- 'hm hm-brush-roll' => 'brush-roll',
56
- 'hm hm-brush' => 'brush',
57
- 'hm hm-bug' => 'bug',
58
- 'hm hm-bulb' => 'bulb',
59
- 'hm hm-calculation' => 'calculation',
60
- 'hm hm-calendar' => 'calendar',
61
- 'hm hm-camera' => 'camera',
62
- 'hm hm-candle' => 'candle',
63
- 'hm hm-candles' => 'candles',
64
- 'hm hm-car' => 'car',
65
- 'hm hm-card' => 'card',
66
- 'hm hm-caret-down' => 'caret-down',
67
- 'hm hm-caret-fill-down' => 'caret-fill-down',
68
- 'hm hm-caret-fill-left' => 'caret-fill-left',
69
- 'hm hm-caret-fill-right' => 'caret-fill-right',
70
- 'hm hm-caret-fill-up' => 'caret-fill-up',
71
- 'hm hm-caret-left' => 'caret-left',
72
- 'hm hm-caret-right' => 'caret-right',
73
- 'hm hm-caret-up' => 'caret-up',
74
- 'hm hm-carousal' => 'carousal',
75
- 'hm hm-cart-empty' => 'cart-empty',
76
- 'hm hm-cart-full' => 'cart-full',
77
- 'hm hm-caution' => 'caution',
78
- 'hm hm-chair' => 'chair',
79
- 'hm hm-chair2' => 'chair2',
80
- 'hm hm-chat-bubble-single' => 'chat-bubble-single',
81
- 'hm hm-chat-bubble' => 'chat-bubble',
82
- 'hm hm-cheese' => 'cheese',
83
- 'hm hm-chef-cap' => 'chef-cap',
84
- 'hm hm-clip-board' => 'clip-board',
85
- 'hm hm-clip' => 'clip',
86
- 'hm hm-cloud-down' => 'cloud-down',
87
- 'hm hm-cloud-up' => 'cloud-up',
88
- 'hm hm-cloud' => 'cloud',
89
- 'hm hm-code-browser' => 'code-browser',
90
- 'hm hm-code-clean' => 'code-clean',
91
- 'hm hm-code' => 'code',
92
- 'hm hm-cog' => 'cog',
93
- 'hm hm-color-card' => 'color-card',
94
- 'hm hm-color-plate' => 'color-plate',
95
- 'hm hm-compass-math' => 'compass-math',
96
- 'hm hm-compass' => 'compass',
97
- 'hm hm-corner' => 'corner',
98
- 'hm hm-crop' => 'crop',
99
- 'hm hm-cross-circle' => 'cross-circle',
100
- 'hm hm-cross-game' => 'cross-game',
101
- 'hm hm-cross-gap' => 'cross-gap',
102
- 'hm hm-cross' => 'cross',
103
- 'hm hm-crown' => 'crown',
104
- 'hm hm-cube' => 'cube',
105
- 'hm hm-cup-coffee' => 'cup-coffee',
106
- 'hm hm-cup' => 'cup',
107
- 'hm hm-currency-paper' => 'currency-paper',
108
- 'hm hm-dashboard' => 'dashboard',
109
- 'hm hm-delivery-van' => 'delivery-van',
110
- 'hm hm-diamond-ring' => 'diamond-ring',
111
- 'hm hm-direction-both' => 'direction-both',
112
- 'hm hm-direction-right' => 'direction-right',
113
- 'hm hm-disable-person' => 'disable-person',
114
- 'hm hm-disc' => 'disc',
115
- 'hm hm-dislike' => 'dislike',
116
- 'hm hm-dollar-on-hand' => 'dollar-on-hand',
117
- 'hm hm-door-path' => 'door-path',
118
- 'hm hm-Download-circle' => 'Download-circle',
119
- 'hm hm-download' => 'download',
120
- 'hm hm-drag-inside' => 'drag-inside',
121
- 'hm hm-drag-outside' => 'drag-outside',
122
- 'hm hm-drag' => 'drag',
123
- 'hm hm-drawer' => 'drawer',
124
- 'hm hm-dribbble' => 'dribbble',
125
- 'hm hm-dropper' => 'dropper',
126
- 'hm hm-egg-fry' => 'egg-fry',
127
- 'hm hm-ellipsis-fill-h' => 'ellipsis-fill-h',
128
- 'hm hm-ellipsis-fill-v' => 'ellipsis-fill-v',
129
- 'hm hm-ellipsis-horizontal' => 'ellipsis-horizontal',
130
- 'hm hm-ellipsis-vertical' => 'ellipsis-vertical',
131
- 'hm hm-emo-normal' => 'emo-normal',
132
- 'hm hm-emo-sad' => 'emo-sad',
133
- 'hm hm-emo-smile' => 'emo-smile',
134
- 'hm hm-envelop' => 'envelop',
135
- 'hm hm-facebook' => 'facebook',
136
- 'hm hm-fancy-futton' => 'fancy-futton',
137
- 'hm hm-feeder' => 'feeder',
138
- 'hm hm-file-cabinet' => 'file-cabinet',
139
- 'hm hm-file-rotate' => 'file-rotate',
140
- 'hm hm-file' => 'file',
141
- 'hm hm-files' => 'files',
142
- 'hm hm-film-roll' => 'film-roll',
143
- 'hm hm-film' => 'film',
144
- 'hm hm-finger-index' => 'finger-index',
145
- 'hm hm-finger-print' => 'finger-print',
146
- 'hm hm-fire-flame' => 'fire-flame',
147
- 'hm hm-flag' => 'flag',
148
- 'hm hm-flip-card1' => 'flip-card1',
149
- 'hm hm-flip-card2' => 'flip-card2',
150
- 'hm hm-folder-network' => 'folder-network',
151
- 'hm hm-folder' => 'folder',
152
- 'hm hm-football' => 'football',
153
- 'hm hm-footer' => 'footer',
154
- 'hm hm-form' => 'form',
155
- 'hm hm-forward' => 'forward',
156
- 'hm hm-fountain-pen' => 'fountain-pen',
157
- 'hm hm-gender-female' => 'gender-female',
158
- 'hm hm-gender-male' => 'gender-male',
159
- 'hm hm-gender-sign' => 'gender-sign',
160
- 'hm hm-gender' => 'gender',
161
- 'hm hm-ghost' => 'ghost',
162
- 'hm hm-gift-box' => 'gift-box',
163
- 'hm hm-globe1' => 'globe1',
164
- 'hm hm-globe2' => 'globe2',
165
- 'hm hm-globe3' => 'globe3',
166
- 'hm hm-globe4' => 'globe4',
167
- 'hm hm-google' => 'google',
168
- 'hm hm-graduate-cap' => 'graduate-cap',
169
- 'hm hm-graph-bar' => 'graph-bar',
170
- 'hm hm-graph-pie' => 'graph-pie',
171
- 'hm hm-graph' => 'graph',
172
- 'hm hm-grid-even' => 'grid-even',
173
- 'hm hm-grid-masonry' => 'grid-masonry',
174
- 'hm hm-grid-twist' => 'grid-twist',
175
- 'hm hm-grid' => 'grid',
176
- 'hm hm-group' => 'group',
177
- 'hm hm-hand-mike' => 'hand-mike',
178
- 'hm hm-hand-watch' => 'hand-watch',
179
- 'hm hm-hand' => 'hand',
180
- 'hm hm-header' => 'header',
181
- 'hm hm-headphone' => 'headphone',
182
- 'hm hm-headset' => 'headset',
183
- 'hm hm-heart-beat' => 'heart-beat',
184
- 'hm hm-hexa' => 'hexa',
185
- 'hm hm-highlighter' => 'highlighter',
186
- 'hm hm-home' => 'home',
187
- 'hm hm-hot-spot' => 'hot-spot',
188
- 'hm hm-hotdog' => 'hotdog',
189
- 'hm hm-ice-cream' => 'ice-cream',
190
- 'hm hm-icon-box' => 'icon-box',
191
- 'hm hm-imac' => 'imac',
192
- 'hm hm-image-compare' => 'image-compare',
193
- 'hm hm-image-slider' => 'image-slider',
194
- 'hm hm-image' => 'image',
195
- 'hm hm-inbox' => 'inbox',
196
- 'hm hm-infinity' => 'infinity',
197
- 'hm hm-info' => 'info',
198
- 'hm hm-injection' => 'injection',
199
- 'hm hm-instagram' => 'instagram',
200
- 'hm hm-jar-chemical' => 'jar-chemical',
201
- 'hm hm-key' => 'key',
202
- 'hm hm-language-change' => 'language-change',
203
- 'hm hm-laptop' => 'laptop',
204
- 'hm hm-layer' => 'layer',
205
- 'hm hm-lens' => 'lens',
206
- 'hm hm-like' => 'like',
207
- 'hm hm-line-graph-pointed' => 'line-graph-pointed',
208
- 'hm hm-link' => 'link',
209
- 'hm hm-linkedin' => 'linkedin',
210
- 'hm hm-linux' => 'linux',
211
- 'hm hm-list-2' => 'list-2',
212
- 'hm hm-list-group' => 'list-group',
213
- 'hm hm-list' => 'list',
214
- 'hm hm-location-pointer' => 'location-pointer',
215
- 'hm hm-lock' => 'lock',
216
- 'hm hm-logo-carousel' => 'logo-carousel',
217
- 'hm hm-logo-grid' => 'logo-grid',
218
- 'hm hm-lotus' => 'lotus',
219
- 'hm hm-love' => 'love',
220
- 'hm hm-madel' => 'madel',
221
- 'hm hm-magic-wand' => 'magic-wand',
222
- 'hm hm-magnet' => 'magnet',
223
- 'hm hm-mail-open' => 'mail-open',
224
- 'hm hm-man-range' => 'man-range',
225
- 'hm hm-map-marker' => 'map-marker',
226
- 'hm hm-map-pointer' => 'map-pointer',
227
- 'hm hm-measurement' => 'measurement',
228
- 'hm hm-memory' => 'memory',
229
- 'hm hm-menu-price' => 'menu-price',
230
- 'hm hm-micro-chip' => 'micro-chip',
231
- 'hm hm-microphone1' => 'microphone1',
232
- 'hm hm-microphone2' => 'microphone2',
233
- 'hm hm-mobile' => 'mobile',
234
- 'hm hm-money-bag' => 'money-bag',
235
- 'hm hm-money' => 'money',
236
- 'hm hm-monitor' => 'monitor',
237
- 'hm hm-mouse' => 'mouse',
238
- 'hm hm-muscle' => 'muscle',
239
- 'hm hm-net' => 'net',
240
- 'hm hm-network1' => 'network1',
241
- 'hm hm-network2' => 'network2',
242
- 'hm hm-newspaper' => 'newspaper',
243
- 'hm hm-nuclear-circle' => 'nuclear-circle',
244
- 'hm hm-office-file' => 'office-file',
245
- 'hm hm-pacman' => 'pacman',
246
- 'hm hm-paper-fold' => 'paper-fold',
247
- 'hm hm-paper-plane-alt' => 'paper-plane-alt',
248
- 'hm hm-paper-plane' => 'paper-plane',
249
- 'hm hm-pause' => 'pause',
250
- 'hm hm-pen-head' => 'pen-head',
251
- 'hm hm-pen-pencil' => 'pen-pencil',
252
- 'hm hm-pen-scale' => 'pen-scale',
253
- 'hm hm-pen-paper' => 'pen-paper',
254
- 'hm hm-pen' => 'pen',
255
- 'hm hm-pencil' => 'pencil',
256
- 'hm hm-pendrive' => 'pendrive',
257
- 'hm hm-phone' => 'phone',
258
- 'hm hm-pillar' => 'pillar',
259
- 'hm hm-pin-man-range' => 'pin-man-range',
260
- 'hm hm-pin-man' => 'pin-man',
261
- 'hm hm-pin' => 'pin',
262
- 'hm hm-plane' => 'plane',
263
- 'hm hm-play-end' => 'play-end',
264
- 'hm hm-play-next' => 'play-next',
265
- 'hm hm-play-previous' => 'play-previous',
266
- 'hm hm-play-start' => 'play-start',
267
- 'hm hm-play-button' => 'play-button',
268
- 'hm hm-play-store' => 'play-store',
269
- 'hm hm-play' => 'play',
270
- 'hm hm-playing-card' => 'playing-card',
271
- 'hm hm-plus-box' => 'plus-box',
272
- 'hm hm-plus-circle' => 'plus-circle',
273
- 'hm hm-plus-gap' => 'plus-gap',
274
- 'hm hm-plus-open' => 'plus-open',
275
- 'hm hm-popup' => 'popup',
276
- 'hm hm-power' => 'power',
277
- 'hm hm-printer' => 'printer',
278
- 'hm hm-progress-bar' => 'progress-bar',
279
- 'hm hm-promo' => 'promo',
280
- 'hm hm-pulse' => 'pulse',
281
- 'hm hm-puzzle' => 'puzzle',
282
- 'hm hm-question' => 'question',
283
- 'hm hm-quote' => 'quote',
284
- 'hm hm-radar' => 'radar',
285
- 'hm hm-radiation' => 'radiation',
286
- 'hm hm-reading-glass-alt' => 'reading-glass-alt',
287
- 'hm hm-reading-glass' => 'reading-glass',
288
- 'hm hm-recycle-bin' => 'recycle-bin',
289
- 'hm hm-recycle' => 'recycle',
290
- 'hm hm-refresh-time' => 'refresh-time',
291
- 'hm hm-reply' => 'reply',
292
- 'hm hm-responsive-device' => 'responsive-device',
293
- 'hm hm-review' => 'review',
294
- 'hm hm-rocket1' => 'rocket1',
295
- 'hm hm-rocket2' => 'rocket2',
296
- 'hm hm-rss' => 'rss',
297
- 'hm hm-safety-cap' => 'safety-cap',
298
- 'hm hm-safety-kit' => 'safety-kit',
299
- 'hm hm-sand-watch' => 'sand-watch',
300
- 'hm hm-scale' => 'scale',
301
- 'hm hm-scanner' => 'scanner',
302
- 'hm hm-scissor' => 'scissor',
303
- 'hm hm-screen' => 'screen',
304
- 'hm hm-search' => 'search',
305
- 'hm hm-seo' => 'seo',
306
- 'hm hm-server-network' => 'server-network',
307
- 'hm hm-server' => 'server',
308
- 'hm hm-share' => 'share',
309
- 'hm hm-shield' => 'shield',
310
- 'hm hm-ship' => 'ship',
311
- 'hm hm-shirt' => 'shirt',
312
- 'hm hm-shopping-bag1' => 'shopping-bag1',
313
- 'hm hm-shopping-bag2' => 'shopping-bag2',
314
- 'hm hm-shopping-bag3' => 'shopping-bag3',
315
- 'hm hm-shopping-bag4' => 'shopping-bag4',
316
- 'hm hm-shuffle' => 'shuffle',
317
- 'hm hm-shutter' => 'shutter',
318
- 'hm hm-sign-in' => 'sign-in',
319
- 'hm hm-sign-out' => 'sign-out',
320
- 'hm hm-sitemap1' => 'sitemap1',
321
- 'hm hm-sitemap2' => 'sitemap2',
322
- 'hm hm-skart' => 'skart',
323
- 'hm hm-skull' => 'skull',
324
- 'hm hm-skyscraper' => 'skyscraper',
325
- 'hm hm-slider-doc' => 'slider-doc',
326
- 'hm hm-slider-h-range' => 'slider-h-range',
327
- 'hm hm-slider-image' => 'slider-image',
328
- 'hm hm-slider-range-h' => 'slider-range-h',
329
- 'hm hm-slider-v-open' => 'slider-v-open',
330
- 'hm hm-slider-video' => 'slider-video',
331
- 'hm hm-slider' => 'slider',
332
- 'hm hm-smart-watch' => 'smart-watch',
333
- 'hm hm-snow' => 'snow',
334
- 'hm hm-spa-face' => 'spa-face',
335
- 'hm hm-spa-stone-flower' => 'spa-stone-flower',
336
- 'hm hm-spa-stone' => 'spa-stone',
337
- 'hm hm-spark' => 'spark',
338
- 'hm hm-speaker-off' => 'speaker-off',
339
- 'hm hm-speaker-on' => 'speaker-on',
340
- 'hm hm-spoon-fork' => 'spoon-fork',
341
- 'hm hm-spoon' => 'spoon',
342
- 'hm hm-star' => 'star',
343
- 'hm hm-step-flow' => 'step-flow',
344
- 'hm hm-steps' => 'steps',
345
- 'hm hm-stop-watch' => 'stop-watch',
346
- 'hm hm-stop' => 'stop',
347
- 'hm hm-support-call' => 'support-call',
348
- 'hm hm-tab' => 'tab',
349
- 'hm hm-table-lamp' => 'table-lamp',
350
- 'hm hm-tablet' => 'tablet',
351
- 'hm hm-tag' => 'tag',
352
- 'hm hm-target-arrow' => 'target-arrow',
353
- 'hm hm-target' => 'target',
354
- 'hm hm-target1' => 'target1',
355
- 'hm hm-team-carousel' => 'team-carousel',
356
- 'hm hm-team-member' => 'team-member',
357
- 'hm hm-tennis-ball' => 'tennis-ball',
358
- 'hm hm-terminal' => 'terminal',
359
- 'hm hm-testimonial-carousel' => 'testimonial-carousel',
360
- 'hm hm-testimonial' => 'testimonial',
361
- 'hm hm-text-animation' => 'text-animation',
362
- 'hm hm-theatre' => 'theatre',
363
- 'hm hm-tick-circle' => 'tick-circle',
364
- 'hm hm-tick' => 'tick',
365
- 'hm hm-tickets' => 'tickets',
366
- 'hm hm-tie-knot' => 'tie-knot',
367
- 'hm hm-tie' => 'tie',
368
- 'hm hm-timeline' => 'timeline',
369
- 'hm hm-toggle' => 'toggle',
370
- 'hm hm-tools' => 'tools',
371
- 'hm hm-tree-square' => 'tree-square',
372
- 'hm hm-twitter-bird' => 'twitter-bird',
373
- 'hm hm-twitter' => 'twitter',
374
- 'hm hm-ufo' => 'ufo',
375
- 'hm hm-umbralla' => 'umbralla',
376
- 'hm hm-unlock' => 'unlock',
377
- 'hm hm-up-down' => 'up-down',
378
- 'hm hm-upload' => 'upload',
379
- 'hm hm-upward-top-right' => 'upward-top-right',
380
- 'hm hm-user-female' => 'user-female',
381
- 'hm hm-user-id' => 'user-id',
382
- 'hm hm-user-male' => 'user-male',
383
- 'hm hm-video-camera' => 'video-camera',
384
- 'hm hm-water-drop' => 'water-drop',
385
- 'hm hm-weather-cloud-day' => 'weather-cloud-day',
386
- 'hm hm-weather-cloud' => 'weather-cloud',
387
- 'hm hm-weather-day-rain' => 'weather-day-rain',
388
- 'hm hm-weather-day-snow' => 'weather-day-snow',
389
- 'hm hm-weather-day-windy-rain' => 'weather-day-windy-rain',
390
- 'hm hm-weather-flood' => 'weather-flood',
391
- 'hm hm-weather-night-cloud' => 'weather-night-cloud',
392
- 'hm hm-weather-rain-alt' => 'weather-rain-alt',
393
- 'hm hm-weather-rain' => 'weather-rain',
394
- 'hm hm-weather-snow' => 'weather-snow',
395
- 'hm hm-weather-sun-rain' => 'weather-sun-rain',
396
- 'hm hm-weather-sun' => 'weather-sun',
397
- 'hm hm-weather-sunny-day' => 'weather-sunny-day',
398
- 'hm hm-weather-thunder' => 'weather-thunder',
399
- 'hm hm-weather-windy-rain' => 'weather-windy-rain',
400
- 'hm hm-webcam1' => 'webcam1',
401
- 'hm hm-webcam2' => 'webcam2',
402
- 'hm hm-weight-scale' => 'weight-scale',
403
- 'hm hm-windows' => 'windows',
404
- 'hm hm-wine-glass2' => 'wine-glass2',
405
- 'hm hm-wine-glass' => 'wine-glass',
406
- 'hm hm-worker-cap' => 'worker-cap',
407
- 'hm hm-youtube' => 'youtube',
408
- ];
409
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plugin.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Happy Elementor Addons
4
  * Plugin URI: https://happyaddons.com/
5
  * Description: <a href="https://happyaddons.com/">HappyAddons</a> is a collection of slick, powerful widgets that works seamlessly with Elementor page builder. It’s trendy look with detail customization features allows to create extraordinary designs instantly. <a href="https://happyaddons.com/">HappyAddons</a> is free, rapidly growing and comes with great support.
6
- * Version: 1.4.1
7
  * Author: HappyMonster
8
  * Author URI: https://happyaddons.com/
9
  * License: GPLv2
@@ -34,11 +34,12 @@ Copyright 2019 HappyMonster <http://happymonster.me>
34
 
35
  defined( 'ABSPATH' ) || die();
36
 
37
- define( 'HAPPY__FILE__', __FILE__ );
38
- define( 'HAPPY_DIR_PATH', plugin_dir_path( HAPPY__FILE__ ) );
39
- define( 'HAPPY_DIR_URL', plugin_dir_url( HAPPY__FILE__ ) );
40
- define( 'HAPPY_ASSETS', trailingslashit( HAPPY_DIR_URL . 'assets' ) );
 
41
 
42
- require HAPPY_DIR_PATH . 'base.php';
43
 
44
  \Happy_Addons\Elementor\Base::instance();
3
  * Plugin Name: Happy Elementor Addons
4
  * Plugin URI: https://happyaddons.com/
5
  * Description: <a href="https://happyaddons.com/">HappyAddons</a> is a collection of slick, powerful widgets that works seamlessly with Elementor page builder. It’s trendy look with detail customization features allows to create extraordinary designs instantly. <a href="https://happyaddons.com/">HappyAddons</a> is free, rapidly growing and comes with great support.
6
+ * Version: 1.5.0
7
  * Author: HappyMonster
8
  * Author URI: https://happyaddons.com/
9
  * License: GPLv2
34
 
35
  defined( 'ABSPATH' ) || die();
36
 
37
+ define( 'HAPPY_ADDONS_VERSION', '1.5.0' );
38
+ define( 'HAPPY_ADDONS__FILE__', __FILE__ );
39
+ define( 'HAPPY_ADDONS_DIR_PATH', plugin_dir_path( HAPPY_ADDONS__FILE__ ) );
40
+ define( 'HAPPY_ADDONS_DIR_URL', plugin_dir_url( HAPPY_ADDONS__FILE__ ) );
41
+ define( 'HAPPY_ADDONS_ASSETS', trailingslashit( HAPPY_ADDONS_DIR_URL . 'assets' ) );
42
 
43
+ require HAPPY_ADDONS_DIR_PATH . 'base.php';
44
 
45
  \Happy_Addons\Elementor\Base::instance();
readme.txt CHANGED
@@ -1,6 +1,6 @@
1
  === Happy Elementor Addons ===
2
  Plugin Name: Happy Elementor Addons
3
- Version: 1.4.1
4
  Author: HappyMonster
5
  Author URI: https://happyaddons.com/
6
  Contributors: thehappymonster, happyaddons, hasinhayder, mosaddek73, tareq1988, obiplabon, sourav926, wedevs
@@ -19,7 +19,7 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
19
  [HappyAddons](https://happyaddons.com/) is a collection of slick, powerful widgets that works seamlessly with Elementor page builder. It’s trendy look with detail customization features allows to create extraordinary designs instantly. [HappyAddons](https://happyaddons.com/) is free, rapidly growing and comes with great support.
20
 
21
 
22
- ### Included 24 Free Widgets
23
 
24
  1. **[Card](https://happyaddons.com/elementor-card-widget-demo/)** - Incredibly powerful widget to demonstrate your products, articles, news, creative posts using a beautiful combination of texts, links, badge and image. Using built in positioning and offset feature you can create eye-candy designs in a twist. [Check demo](https://happyaddons.com/elementor-card-widget-demo/)
25
  2. **[Gradient Heading](https://happyaddons.com/elementor-gradient-heading-widget-demo/)** - Another gem to create eye candy headings for your websites. You can apply different gradient styles, angles, opacity, and positions to make them look even better across different device screens. [Check demo](https://happyaddons.com/elementor-gradient-heading-widget-demo/)
@@ -44,9 +44,15 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
44
  21. **[Step Flow](https://happyaddons.com/elementor-step-flow-widget-demo/)** - Create excellent step by step visual diagram and instructions using this smart widget. Change directions, counters and make them look amazing with icons, texts and colors. [Check demo](https://happyaddons.com/elementor-step-flow-widget-demo/)
45
  22. **[Calendly](https://happyaddons.com/elementor-calendly-widget-demo/)** - Schedule meetings without the back-and-forth emails through Calendly. We are happy to integrate this important application in our HappyAddons. [Check demo](https://happyaddons.com/elementor-calendly-widget-demo/)
46
  23. **[Flip Box](https://happyaddons.com/elementor-flip-box-widget-demo/)** - FlipBox helps you to deliver messages in a beautiful way with before and after effects. [Check demo](https://happyaddons.com/elementor-flip-box-widget-demo/)
47
- 24. **Pricing Table**
 
48
 
49
  ### INCLUDED FREE EXTENSIONS FOR EVERY ELEMENTOR WIDGET
 
 
 
 
 
50
  **Happy Effects**
51
 
52
  1. **[Floating Effects](https://happyaddons.com/elementor-floating-effect-demo/)** - Now you can create stunning animations for any Elementor widget using Floating Effects. Translate, Rotate or Scale - Imagination is the limit!
@@ -134,6 +140,25 @@ It's really easy and super simple to install **Happy Elementor Addons** plugin b
134
 
135
  == Changelog ==
136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  = 1.4.1 - 6 August 2019 =
138
 
139
  * Fix: Elementor frontend script dependency and console error issue
1
  === Happy Elementor Addons ===
2
  Plugin Name: Happy Elementor Addons
3
+ Version: 1.5.0
4
  Author: HappyMonster
5
  Author URI: https://happyaddons.com/
6
  Contributors: thehappymonster, happyaddons, hasinhayder, mosaddek73, tareq1988, obiplabon, sourav926, wedevs
19
  [HappyAddons](https://happyaddons.com/) is a collection of slick, powerful widgets that works seamlessly with Elementor page builder. It’s trendy look with detail customization features allows to create extraordinary designs instantly. [HappyAddons](https://happyaddons.com/) is free, rapidly growing and comes with great support.
20
 
21
 
22
+ ### Included 25 Free Widgets
23
 
24
  1. **[Card](https://happyaddons.com/elementor-card-widget-demo/)** - Incredibly powerful widget to demonstrate your products, articles, news, creative posts using a beautiful combination of texts, links, badge and image. Using built in positioning and offset feature you can create eye-candy designs in a twist. [Check demo](https://happyaddons.com/elementor-card-widget-demo/)
25
  2. **[Gradient Heading](https://happyaddons.com/elementor-gradient-heading-widget-demo/)** - Another gem to create eye candy headings for your websites. You can apply different gradient styles, angles, opacity, and positions to make them look even better across different device screens. [Check demo](https://happyaddons.com/elementor-gradient-heading-widget-demo/)
44
  21. **[Step Flow](https://happyaddons.com/elementor-step-flow-widget-demo/)** - Create excellent step by step visual diagram and instructions using this smart widget. Change directions, counters and make them look amazing with icons, texts and colors. [Check demo](https://happyaddons.com/elementor-step-flow-widget-demo/)
45
  22. **[Calendly](https://happyaddons.com/elementor-calendly-widget-demo/)** - Schedule meetings without the back-and-forth emails through Calendly. We are happy to integrate this important application in our HappyAddons. [Check demo](https://happyaddons.com/elementor-calendly-widget-demo/)
46
  23. **[Flip Box](https://happyaddons.com/elementor-flip-box-widget-demo/)** - FlipBox helps you to deliver messages in a beautiful way with before and after effects. [Check demo](https://happyaddons.com/elementor-flip-box-widget-demo/)
47
+ 24. **[Pricing Table](https://happyaddons.com/elementor-pricing-table-widget-demo/)** - Create beautiful pricing tables with lots of customizations and sleek look-n-feel using this widget. [Check demo](https://happyaddons.com/elementor-pricing-table-widget-demo/)
48
+ 25. **[Image Grid](https://happyaddons.com/elementor-image-grid-widget-demo/)** - Simply beautiful, this widget can help you create stunning number blocks with various styles, look-n-feels that’s literally going to blow your mind. [Check demo](https://happyaddons.com/elementor-image-grid-widget-demo/)
49
 
50
  ### INCLUDED FREE EXTENSIONS FOR EVERY ELEMENTOR WIDGET
51
+
52
+ **Happy Extensions**
53
+ 1. **Background Overlay** - You can add background overlay to any widget now.
54
+ 2. **Happy Icons** - Custom icon fonts library.
55
+
56
  **Happy Effects**
57
 
58
  1. **[Floating Effects](https://happyaddons.com/elementor-floating-effect-demo/)** - Now you can create stunning animations for any Elementor widget using Floating Effects. Translate, Rotate or Scale - Imagination is the limit!
140
 
141
  == Changelog ==
142
 
143
+ = 1.5.0 - 27 August 2019 =
144
+
145
+ - New: Image Grid Widget
146
+ - New: Scheme data for Review Widget
147
+ - New: Background Overlay - global extension for any widget
148
+ - New: Step Flow Widget - direction arrow offset control
149
+ - New: Happy Icons - Custom icon font library
150
+ - Update: Dynamic Tags support
151
+ - Update: New icon manager support with backward compatibility
152
+ - Update: Step Flow Widget default view
153
+ - Update: On demand caching manager
154
+ - Fix: Review ratting icon missing issue
155
+ - Fix: Justified Grid Widget filter menu style issue
156
+ - Fix: Icon Box Widget badge style missing issue
157
+ - Fix: Global widget CSS class missing issue
158
+ - Fix: Section and global widget cache missing issue
159
+ - Fix: Step Flow arrow alignment issue
160
+ - Fix: Skill Bars Widget animation issue
161
+
162
  = 1.4.1 - 6 August 2019 =
163
 
164
  * Fix: Elementor frontend script dependency and console error issue
widgets/card/widget.php CHANGED
@@ -65,6 +65,9 @@ class Card extends Base {
65
  'default' => [
66
  'url' => Utils::get_placeholder_image_src(),
67
  ],
 
 
 
68
  ]
69
  );
70
 
@@ -108,10 +111,14 @@ class Card extends Base {
108
  [
109
  'label' => __( 'Badge Text', 'happy-elementor-addons' ),
110
  'type' => Controls_Manager::TEXT,
 
111
  'default' => __( 'Badget Text', 'happy-elementor-addons' ),
112
  'placeholder' => __( 'Type badge text', 'happy-elementor-addons' ),
113
  'separator' => 'before',
114
  'description' => __( 'Set badget position and control all the style settings from Style tab', 'happy-elementor-addons' ),
 
 
 
115
  ]
116
  );
117
 
@@ -133,6 +140,9 @@ class Card extends Base {
133
  'type' => Controls_Manager::TEXT,
134
  'default' => __( 'Happy Card Title', 'happy-elementor-addons' ),
135
  'placeholder' => __( 'Type Card Title', 'happy-elementor-addons' ),
 
 
 
136
  ]
137
  );
138
 
@@ -143,7 +153,10 @@ class Card extends Base {
143
  'type' => Controls_Manager::TEXTAREA,
144
  'default' => __( 'Happy card description goes here', 'happy-elementor-addons' ),
145
  'placeholder' => __( 'Type card description', 'happy-elementor-addons' ),
146
- 'rows' => 5
 
 
 
147
  ]
148
  );
149
 
@@ -228,9 +241,12 @@ class Card extends Base {
228
  [
229
  'label' => __( 'Text', 'happy-elementor-addons' ),
230
  'type' => Controls_Manager::TEXT,
231
- 'default' => __( 'Button Text', 'happy-elementor-addons' ),
232
  'placeholder' => __( 'Type button text here', 'happy-elementor-addons' ),
233
  'label_block' => true,
 
 
 
234
  ]
235
  );
236
 
@@ -239,18 +255,37 @@ class Card extends Base {
239
  [
240
  'label' => __( 'Link', 'happy-elementor-addons' ),
241
  'type' => Controls_Manager::URL,
242
- 'placeholder' => __( 'https://example.com/', 'happy-elementor-addons' ),
 
 
 
243
  ]
244
  );
245
 
246
- $this->add_control(
247
- 'button_icon',
248
- [
249
- 'label' => __( 'Icon', 'happy-elementor-addons' ),
250
- 'type' => Controls_Manager::ICON,
251
- 'options' => ha_get_happy_icons(),
252
- ]
253
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
 
255
  $this->add_control(
256
  'button_icon_position',
@@ -270,9 +305,7 @@ class Card extends Base {
270
  ],
271
  'default' => 'before',
272
  'toggle' => false,
273
- 'condition' => [
274
- 'button_icon!' => '',
275
- ],
276
  ]
277
  );
278
 
@@ -281,9 +314,7 @@ class Card extends Base {
281
  [
282
  'label' => __( 'Icon Spacing', 'happy-elementor-addons' ),
283
  'type' => Controls_Manager::SLIDER,
284
- 'condition' => [
285
- 'button_icon!' => '',
286
- ],
287
  'selectors' => [
288
  '{{WRAPPER}} .ha-btn--icon-before .ha-btn-icon' => 'margin-right: {{SIZE}}{{UNIT}};',
289
  '{{WRAPPER}} .ha-btn--icon-after .ha-btn-icon' => 'margin-left: {{SIZE}}{{UNIT}};',
@@ -1050,31 +1081,27 @@ class Card extends Base {
1050
  <?php endif; ?>
1051
 
1052
  <?php
1053
- if ( $settings['button_text'] && empty( $settings['button_icon'] ) ) :
1054
  printf( '<a %1$s>%2$s</a>',
1055
  $this->get_render_attribute_string( 'button' ),
1056
  sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) )
1057
  );
1058
- elseif ( empty( $settings['button_text'] ) && $settings['button_icon'] ) :
1059
- printf( '<a %1$s>%2$s</a>',
1060
- $this->get_render_attribute_string( 'button' ),
1061
- sprintf( '<i class="%1$s"></i>', esc_attr( $settings['button_icon'] ) )
1062
- );
1063
- elseif ( $settings['button_text'] && $settings['button_icon'] ) :
1064
  if ( $settings['button_icon_position'] === 'before' ) :
1065
  $this->add_render_attribute( 'button', 'class', 'ha-btn--icon-before' );
1066
- $btn_before = sprintf( '<i class="ha-btn-icon %1$s"></i>', esc_attr( $settings['button_icon'] ) );
1067
- $btn_after = sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) );
 
 
1068
  else :
1069
  $this->add_render_attribute( 'button', 'class', 'ha-btn--icon-after' );
1070
- $btn_before = sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) );
1071
- $btn_after = sprintf( '<i class="ha-btn-icon %1$s"></i>', esc_attr( $settings['button_icon'] ) );
 
 
1072
  endif;
1073
- printf( '<a %1$s>%2$s %3$s</a>',
1074
- $this->get_render_attribute_string( 'button' ),
1075
- $btn_before,
1076
- $btn_after
1077
- );
1078
  endif;
1079
  ?>
1080
  </div>
@@ -1084,6 +1111,13 @@ class Card extends Base {
1084
  public function _content_template() {
1085
  ?>
1086
  <#
 
 
 
 
 
 
 
1087
  view.addInlineEditingAttributes( 'badge_text', 'none' );
1088
  view.addRenderAttribute(
1089
  'badge_text',
@@ -1132,19 +1166,27 @@ class Card extends Base {
1132
  </div>
1133
  <# } #>
1134
 
1135
- <# if ( settings.button_text && ! settings.button_icon ) { #>
 
 
 
 
 
 
 
 
1136
  <a {{{ view.getRenderAttributeString( 'button' ) }}}><span {{{ view.getRenderAttributeString( 'button_text' ) }}}>{{ settings.button_text }}</span></a>
1137
- <# } else if ( ! settings.button_text && settings.button_icon ) { #>
1138
- <a {{{ view.getRenderAttributeString( 'button' ) }}}><i class="{{ settings.button_icon }}"></i></a>
1139
- <# } else if ( settings.button_text && settings.button_icon ) {
1140
  if ( settings.button_icon_position === 'before' ) {
1141
  view.addRenderAttribute( 'button', 'class', 'ha-btn--icon-before' );
1142
- var button_before = '<i class="ha-btn-icon ' + settings.button_icon + '"></i>';
1143
- var button_after = '<span ' + view.getRenderAttributeString( 'button_text' ) + '>' + settings.button_text + '</span>';
1144
  } else {
1145
  view.addRenderAttribute( 'button', 'class', 'ha-btn--icon-after' );
1146
- var button_after = '<i class="ha-btn-icon ' + settings.button_icon + '"></i>';
1147
- var button_before = '<span ' + view.getRenderAttributeString( 'button_text' ) + '>' + settings.button_text + '</span>';
1148
  } #>
1149
  <a {{{ view.getRenderAttributeString( 'button' ) }}}>{{{ button_before }}} {{{ button_after }}}</a>
1150
  <# } #>
65
  'default' => [
66
  'url' => Utils::get_placeholder_image_src(),
67
  ],
68
+ 'dynamic' => [
69
+ 'active' => true,
70
+ ]
71
  ]
72
  );
73
 
111
  [
112
  'label' => __( 'Badge Text', 'happy-elementor-addons' ),
113
  'type' => Controls_Manager::TEXT,
114
+ 'label_block' => true,
115
  'default' => __( 'Badget Text', 'happy-elementor-addons' ),
116
  'placeholder' => __( 'Type badge text', 'happy-elementor-addons' ),
117
  'separator' => 'before',
118
  'description' => __( 'Set badget position and control all the style settings from Style tab', 'happy-elementor-addons' ),
119
+ 'dynamic' => [
120
+ 'active' => true,
121
+ ]
122
  ]
123
  );
124
 
140
  'type' => Controls_Manager::TEXT,
141
  'default' => __( 'Happy Card Title', 'happy-elementor-addons' ),
142
  'placeholder' => __( 'Type Card Title', 'happy-elementor-addons' ),
143
+ 'dynamic' => [
144
+ 'active' => true,
145
+ ]
146
  ]
147
  );
148
 
153
  'type' => Controls_Manager::TEXTAREA,
154
  'default' => __( 'Happy card description goes here', 'happy-elementor-addons' ),
155
  'placeholder' => __( 'Type card description', 'happy-elementor-addons' ),
156
+ 'rows' => 5,
157
+ 'dynamic' => [
158
+ 'active' => true,
159
+ ]
160
  ]
161
  );
162
 
241
  [
242
  'label' => __( 'Text', 'happy-elementor-addons' ),
243
  'type' => Controls_Manager::TEXT,
244
+ 'default' => 'Button Text',
245
  'placeholder' => __( 'Type button text here', 'happy-elementor-addons' ),
246
  'label_block' => true,
247
+ 'dynamic' => [
248
+ 'active' => true,
249
+ ]
250
  ]
251
  );
252
 
255
  [
256
  'label' => __( 'Link', 'happy-elementor-addons' ),
257
  'type' => Controls_Manager::URL,
258
+ 'placeholder' => 'https://happyaddons.com/',
259
+ 'dynamic' => [
260
+ 'active' => true,
261
+ ]
262
  ]
263
  );
264
 
265
+ if ( ha_is_elementor_version( '<', '2.6.0' ) ) {
266
+ $this->add_control(
267
+ 'button_icon',
268
+ [
269
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
270
+ 'label_block' => true,
271
+ 'type' => Controls_Manager::ICON,
272
+ 'options' => ha_get_happy_icons(),
273
+ 'default' => 'fa fa-angle-right',
274
+ ]
275
+ );
276
+
277
+ $condition = ['button_icon!' => ''];
278
+ } else {
279
+ $this->add_control(
280
+ 'button_selected_icon',
281
+ [
282
+ 'type' => Controls_Manager::ICONS,
283
+ 'fa4compatibility' => 'button_icon',
284
+ 'label_block' => true,
285
+ ]
286
+ );
287
+ $condition = ['button_selected_icon[value]!' => ''];
288
+ }
289
 
290
  $this->add_control(
291
  'button_icon_position',
305
  ],
306
  'default' => 'before',
307
  'toggle' => false,
308
+ 'condition' => $condition,
 
 
309
  ]
310
  );
311
 
314
  [
315
  'label' => __( 'Icon Spacing', 'happy-elementor-addons' ),
316
  'type' => Controls_Manager::SLIDER,
317
+ 'condition' => $condition,
 
 
318
  'selectors' => [
319
  '{{WRAPPER}} .ha-btn--icon-before .ha-btn-icon' => 'margin-right: {{SIZE}}{{UNIT}};',
320
  '{{WRAPPER}} .ha-btn--icon-after .ha-btn-icon' => 'margin-left: {{SIZE}}{{UNIT}};',
1081
  <?php endif; ?>
1082
 
1083
  <?php
1084
+ if ( $settings['button_text'] && ( empty( $settings['button_selected_icon'] ) && empty( $settings['button_icon'] ) ) ) :
1085
  printf( '<a %1$s>%2$s</a>',
1086
  $this->get_render_attribute_string( 'button' ),
1087
  sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) )
1088
  );
1089
+ elseif ( empty( $settings['button_text'] ) && ( ! empty( $settings['button_icon'] ) || ! empty( $settings['button_selected_icon'] ) ) ) : ?>
1090
+ <a <?php $this->print_render_attribute_string( 'button' ); ?>><?php ha_render_icon( $settings, 'button_icon', 'button_selected_icon' ); ?></a>
1091
+ <?php elseif ( $settings['button_text'] && ( ! empty( $settings['button_icon'] ) || ! empty( $settings['button_selected_icon'] ) ) ) :
 
 
 
1092
  if ( $settings['button_icon_position'] === 'before' ) :
1093
  $this->add_render_attribute( 'button', 'class', 'ha-btn--icon-before' );
1094
+ $button_text = sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) );
1095
+ ?>
1096
+ <a <?php $this->print_render_attribute_string( 'button' ); ?>><?php ha_render_icon( $settings, 'button_icon', 'button_selected_icon', ['class' => 'ha-btn-icon'] ); ?> <?php echo $button_text; ?></a>
1097
+ <?php
1098
  else :
1099
  $this->add_render_attribute( 'button', 'class', 'ha-btn--icon-after' );
1100
+ $button_text = sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) );
1101
+ ?>
1102
+ <a <?php $this->print_render_attribute_string( 'button' ); ?>><?php echo $button_text; ?> <?php ha_render_icon( $settings, 'button_icon', 'button_selected_icon', ['class' => 'ha-btn-icon'] ); ?></a>
1103
+ <?php
1104
  endif;
 
 
 
 
 
1105
  endif;
1106
  ?>
1107
  </div>
1111
  public function _content_template() {
1112
  ?>
1113
  <#
1114
+ var btnIconHTML = btnMigrated = btnIcon = '';
1115
+
1116
+ if ( ha_has_icon_library() ) {
1117
+ btnIconHTML = elementor.helpers.renderIcon( view, settings.button_selected_icon, { 'aria-hidden': true, 'class': 'ha-btn-icon' }, 'i' , 'object' ),
1118
+ btnMigrated = elementor.helpers.isIconMigrated( settings, 'button_selected_icon' );
1119
+ }
1120
+
1121
  view.addInlineEditingAttributes( 'badge_text', 'none' );
1122
  view.addRenderAttribute(
1123
  'badge_text',
1166
  </div>
1167
  <# } #>
1168
 
1169
+ <# if ( settings.button_selected_icon || settings.button_icon ) {
1170
+ if ( ha_has_icon_library() && btnIconHTML && btnIconHTML.rendered && ( ! settings.button_icon || btnMigrated ) ) {
1171
+ btnIcon = btnIconHTML.value;
1172
+ } else if ( settings.button_icon ) {
1173
+ btnIcon = '<i class="ha-btn-icon ' + settings.button_icon + '" aria-hidden="true"></i>';
1174
+ }
1175
+ } #>
1176
+
1177
+ <# if ( settings.button_text && ( ! settings.button_selected_icon && ! settings.button_icon ) ) { #>
1178
  <a {{{ view.getRenderAttributeString( 'button' ) }}}><span {{{ view.getRenderAttributeString( 'button_text' ) }}}>{{ settings.button_text }}</span></a>
1179
+ <# } else if ( ! settings.button_text && ( settings.button_selected_icon || settings.button_icon ) ) { #>
1180
+ <a {{{ view.getRenderAttributeString( 'button' ) }}}>{{{ btnIcon }}}</a>
1181
+ <# } else if ( settings.button_text && ( settings.button_selected_icon || settings.button_icon ) ) {
1182
  if ( settings.button_icon_position === 'before' ) {
1183
  view.addRenderAttribute( 'button', 'class', 'ha-btn--icon-before' );
1184
+ button_before = btnIcon;
1185
+ button_after = '<span ' + view.getRenderAttributeString( 'button_text' ) + '>' + settings.button_text + '</span>';
1186
  } else {
1187
  view.addRenderAttribute( 'button', 'class', 'ha-btn--icon-after' );
1188
+ button_after = btnIcon;
1189
+ button_before = '<span ' + view.getRenderAttributeString( 'button_text' ) + '>' + settings.button_text + '</span>';
1190
  } #>
1191
  <a {{{ view.getRenderAttributeString( 'button' ) }}}>{{{ button_before }}} {{{ button_after }}}</a>
1192
  <# } #>
widgets/dual-button/widget.php CHANGED
@@ -68,7 +68,10 @@ class Dual_Button extends Base {
68
  'label' => __( 'Text', 'happy-elementor-addons' ),
69
  'label_block'=> true,
70
  'type' => Controls_Manager::TEXT,
71
- 'default' => __( 'Button Text', 'happy-elementor-addons' )
 
 
 
72
  ]
73
  );
74
 
@@ -77,17 +80,35 @@ class Dual_Button extends Base {
77
  [
78
  'label' => __( 'Link', 'happy-elementor-addons' ),
79
  'type' => Controls_Manager::URL,
 
 
 
 
80
  ]
81
  );
82
 
83
- $this->add_control(
84
- 'left_button_icon',
85
- [
86
- 'label' => __( 'Icon', 'happy-elementor-addons' ),
87
- 'type' => Controls_Manager::ICON,
88
- 'options' => ha_get_happy_icons(),
89
- ]
90
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  $this->add_control(
93
  'left_button_icon_position',
@@ -107,9 +128,7 @@ class Dual_Button extends Base {
107
  ],
108
  'toggle' => false,
109
  'default' => 'before',
110
- 'condition' => [
111
- 'left_button_icon!' => '',
112
- ]
113
  ]
114
  );
115
 
@@ -118,9 +137,7 @@ class Dual_Button extends Base {
118
  [
119
  'label' => __( 'Icon Spacing', 'happy-elementor-addons' ),
120
  'type' => Controls_Manager::SLIDER,
121
- 'condition' => [
122
- 'left_button_icon!' => '',
123
- ],
124
  'selectors' => [
125
  '{{WRAPPER}} .ha-dual-btn--left .ha-dual-btn-icon--before' => 'margin-right: {{SIZE}}{{UNIT}};',
126
  '{{WRAPPER}} .ha-dual-btn--left .ha-dual-btn-icon--after' => 'margin-left: {{SIZE}}{{UNIT}};',
@@ -184,18 +201,33 @@ class Dual_Button extends Base {
184
  ]
185
  );
186
 
187
- $this->add_control(
188
- 'button_connector_icon',
189
- [
190
- 'label' => __( 'Icon', 'happy-elementor-addons' ),
191
- 'type' => Controls_Manager::ICON,
192
- 'options' => ha_get_happy_icons(),
193
- 'condition' => [
194
- 'button_connector_hide!' => 'yes',
195
- 'button_connector_type' => 'icon',
 
 
196
  ]
197
- ]
198
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
199
 
200
  $this->end_controls_tab();
201
 
@@ -212,7 +244,10 @@ class Dual_Button extends Base {
212
  'label' => __( 'Text', 'happy-elementor-addons' ),
213
  'label_block'=> true,
214
  'type' => Controls_Manager::TEXT,
215
- 'default' => __( 'Button Text', 'happy-elementor-addons' )
 
 
 
216
  ]
217
  );
218
 
@@ -220,18 +255,37 @@ class Dual_Button extends Base {
220
  'right_button_link',
221
  [
222
  'label' => __( 'Link', 'happy-elementor-addons' ),
223
- 'type' => Controls_Manager::URL
 
 
 
 
224
  ]
225
  );
226
 
227
- $this->add_control(
228
- 'right_button_icon',
229
- [
230
- 'label' => __( 'Icon', 'happy-elementor-addons' ),
231
- 'type' => Controls_Manager::ICON,
232
- 'options' => ha_get_happy_icons(),
233
- ]
234
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
  $this->add_control(
237
  'right_button_icon_position',
@@ -251,9 +305,7 @@ class Dual_Button extends Base {
251
  ],
252
  'toggle' => false,
253
  'default' => 'after',
254
- 'condition' => [
255
- 'right_button_icon!' => ''
256
- ]
257
  ]
258
  );
259
 
@@ -262,9 +314,7 @@ class Dual_Button extends Base {
262
  [
263
  'label' => __( 'Icon Spacing', 'happy-elementor-addons' ),
264
  'type' => Controls_Manager::SLIDER,
265
- 'condition' => [
266
- 'right_button_icon!' => '',
267
- ],
268
  'selectors' => [
269
  '{{WRAPPER}} .ha-dual-btn--right .ha-dual-btn-icon--before' => 'margin-right: {{SIZE}}{{UNIT}};',
270
  '{{WRAPPER}} .ha-dual-btn--right .ha-dual-btn-icon--after' => 'margin-left: {{SIZE}}{{UNIT}};',
@@ -742,23 +792,21 @@ class Dual_Button extends Base {
742
  }
743
  $this->add_inline_editing_attributes( 'left_button_text', 'none' );
744
 
745
- if ( $settings['left_button_icon'] ) {
746
- $this->add_render_attribute( 'left_button_icon', 'class', [
 
747
  'ha-dual-btn-icon',
748
- 'ha-dual-btn-icon--' . esc_attr( $settings['left_button_icon_position'] ),
749
- esc_attr( $settings['left_button_icon'] )
750
- ] );
751
  }
752
 
753
  // Button connector
754
  $this->add_render_attribute( 'button_connector_text', 'class', 'ha-dual-btn-connector' );
755
- if ( $settings['button_connector_type'] === 'icon' ) {
756
  $this->add_render_attribute( 'button_connector_text', 'class', 'ha-dual-btn-connector--icon' );
757
- $connector = sprintf( '<i class="%s"></i>', esc_attr( $settings['button_connector_icon'] ) );
758
  } else {
759
  $this->add_render_attribute( 'button_connector_text', 'class', 'ha-dual-btn-connector--text' );
760
  $this->add_inline_editing_attributes( 'button_connector_text', 'none' );
761
- $connector = esc_html( $settings['button_connector_text'] );
762
  }
763
 
764
  // Right button
@@ -772,85 +820,49 @@ class Dual_Button extends Base {
772
  }
773
  $this->add_inline_editing_attributes( 'right_button_text', 'none' );
774
 
775
- if ( $settings['right_button_icon'] ) {
776
- $this->add_render_attribute( 'right_button_icon', 'class', [
 
777
  'ha-dual-btn-icon',
778
- 'ha-dual-btn-icon--' . esc_attr( $settings['right_button_icon_position'] ),
779
- esc_attr( $settings['right_button_icon'] )
780
- ] );
781
  }
782
  ?>
783
  <div class="ha-dual-btn-wrapper">
784
  <a <?php echo $this->get_render_attribute_string( 'left_button' ); ?>>
785
- <?php if ( $settings['left_button_icon_position'] === 'before' ) : ?>
786
- <i <?php echo $this->get_render_attribute_string( 'left_button_icon' ); ?>></i>
787
  <?php endif; ?>
788
- <span <?php echo $this->get_render_attribute_string( 'left_button_text' ); ?>><?php echo esc_html( $settings['left_button_text'] ); ?></span>
789
- <?php if ( $settings['left_button_icon_position'] === 'after' ) : ?>
790
- <i <?php echo $this->get_render_attribute_string( 'left_button_icon' ); ?>></i>
 
 
791
  <?php endif; ?>
792
  </a>
793
  <?php if ( $settings['button_connector_hide'] !== 'yes' ) : ?>
794
- <span <?php echo $this->get_render_attribute_string( 'button_connector_text' ); ?>><?php echo $connector; ?></span>
 
 
 
 
 
 
795
  <?php endif; ?>
796
  </div>
797
  <div class="ha-dual-btn-wrapper">
798
  <a <?php echo $this->get_render_attribute_string( 'right_button' ); ?>>
799
- <?php if ( $settings['right_button_icon_position'] === 'before' ) : ?>
800
- <i <?php echo $this->get_render_attribute_string( 'right_button_icon' ); ?>></i>
 
 
 
801
  <?php endif; ?>
802
- <span <?php echo $this->get_render_attribute_string( 'right_button_text' ); ?>><?php echo esc_html( $settings['right_button_text'] ); ?></span>
803
- <?php if ( $settings['right_button_icon_position'] === 'after' ) : ?>
804
- <i <?php echo $this->get_render_attribute_string( 'right_button_icon' ); ?>></i>
805
  <?php endif; ?>
806
  </a>
807
  </div>
808
  <?php
809
  }
810
-
811
- /*
812
- public function _content_template() {
813
- ?>
814
- <#
815
- view.addInlineEditingAttributes( 'left_button_text', 'none' );
816
- view.addInlineEditingAttributes( 'right_button_text', 'none' );
817
-
818
- view.addInlineEditingAttributes( 'button_direction_text', 'none' );
819
- view.addRenderAttribute( 'button_direction_text', 'class', 'ha-middle-text' );
820
- #>
821
- <div class="ha-dual-btn">
822
-
823
- <div class="ha-dual-btn-link">
824
- <a href="{{{ settings.left_button_link.url }}}" class="ha-dual-btn-link-primary">
825
-
826
- <i class="{{{ settings.left_icon_picker }}}"></i>
827
- <span {{{ view.getRenderAttributeString( 'left_button_text' ) }}}>
828
- {{{ settings.left_button_text }}}
829
- </span>
830
-
831
- </a>
832
- <# if ( settings.button_direction_show === 'yes' ) { #>
833
- <div {{{ view.getRenderAttributeString( 'button_direction_text' ) }}}>
834
- {{{ settings.button_direction_text }}}
835
- </div>
836
- <# } #>
837
- </div>
838
-
839
- <div class="ha-dual-btn-link">
840
- <a href="{{{ settings.right_button_link.url }}}" class="ha-dual-btn-link-secondary">
841
-
842
- <i class="{{{ settings.right_icon_picker }}}"></i>
843
- <span {{{ view.getRenderAttributeString( 'right_button_text' ) }}}>
844
- {{{ settings.right_button_text }}}
845
- </span>
846
-
847
- </a>
848
- </div>
849
-
850
- </div>
851
-
852
- <?php
853
- }
854
- */
855
-
856
  }
68
  'label' => __( 'Text', 'happy-elementor-addons' ),
69
  'label_block'=> true,
70
  'type' => Controls_Manager::TEXT,
71
+ 'default' => 'Button Text',
72
+ 'dynamic' => [
73
+ 'active' => true,
74
+ ]
75
  ]
76
  );
77
 
80
  [
81
  'label' => __( 'Link', 'happy-elementor-addons' ),
82
  'type' => Controls_Manager::URL,
83
+ 'placeholder' => 'https://happyaddons.com/',
84
+ 'dynamic' => [
85
+ 'active' => true,
86
+ ]
87
  ]
88
  );
89
 
90
+ if ( ha_is_elementor_version( '<', '2.6.0' ) ) {
91
+ $this->add_control(
92
+ 'left_button_icon',
93
+ [
94
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
95
+ 'type' => Controls_Manager::ICON,
96
+ 'options' => ha_get_happy_icons(),
97
+ ]
98
+ );
99
+
100
+ $condition = ['left_button_icon!' => ''];
101
+ } else {
102
+ $this->add_control(
103
+ 'left_button_selected_icon',
104
+ [
105
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
106
+ 'type' => Controls_Manager::ICONS,
107
+ 'fa4compatibility' => 'left_button_icon',
108
+ ]
109
+ );
110
+ $condition = ['left_button_selected_icon[value]!' => ''];
111
+ }
112
 
113
  $this->add_control(
114
  'left_button_icon_position',
128
  ],
129
  'toggle' => false,
130
  'default' => 'before',
131
+ 'condition' => $condition
 
 
132
  ]
133
  );
134
 
137
  [
138
  'label' => __( 'Icon Spacing', 'happy-elementor-addons' ),
139
  'type' => Controls_Manager::SLIDER,
140
+ 'condition' => $condition,
 
 
141
  'selectors' => [
142
  '{{WRAPPER}} .ha-dual-btn--left .ha-dual-btn-icon--before' => 'margin-right: {{SIZE}}{{UNIT}};',
143
  '{{WRAPPER}} .ha-dual-btn--left .ha-dual-btn-icon--after' => 'margin-left: {{SIZE}}{{UNIT}};',
201
  ]
202
  );
203
 
204
+ if ( ha_is_elementor_version( '<', '2.6.0' ) ) {
205
+ $this->add_control(
206
+ 'button_connector_icon',
207
+ [
208
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
209
+ 'type' => Controls_Manager::ICON,
210
+ 'options' => ha_get_happy_icons(),
211
+ 'condition' => [
212
+ 'button_connector_hide!' => 'yes',
213
+ 'button_connector_type' => 'icon',
214
+ ]
215
  ]
216
+ );
217
+ } else {
218
+ $this->add_control(
219
+ 'button_connector_selected_icon',
220
+ [
221
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
222
+ 'type' => Controls_Manager::ICONS,
223
+ 'fa4compatibility' => 'button_connector_icon',
224
+ 'condition' => [
225
+ 'button_connector_hide!' => 'yes',
226
+ 'button_connector_type' => 'icon',
227
+ ]
228
+ ]
229
+ );
230
+ }
231
 
232
  $this->end_controls_tab();
233
 
244
  'label' => __( 'Text', 'happy-elementor-addons' ),
245
  'label_block'=> true,
246
  'type' => Controls_Manager::TEXT,
247
+ 'default' => 'Button Text',
248
+ 'dynamic' => [
249
+ 'active' => true,
250
+ ]
251
  ]
252
  );
253
 
255
  'right_button_link',
256
  [
257
  'label' => __( 'Link', 'happy-elementor-addons' ),
258
+ 'type' => Controls_Manager::URL,
259
+ 'placeholder' => 'https://happyaddons.com/',
260
+ 'dynamic' => [
261
+ 'active' => true,
262
+ ]
263
  ]
264
  );
265
 
266
+ if ( ha_is_elementor_version( '<', '2.6.0' ) ) {
267
+ $this->add_control(
268
+ 'right_button_icon',
269
+ [
270
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
271
+ 'type' => Controls_Manager::ICON,
272
+ 'options' => ha_get_happy_icons(),
273
+ ]
274
+ );
275
+
276
+ $condition = ['right_button_icon!' => ''];
277
+ } else {
278
+ $this->add_control(
279
+ 'right_button_selected_icon',
280
+ [
281
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
282
+ 'type' => Controls_Manager::ICONS,
283
+ 'fa4compatibility' => 'right_button_icon',
284
+ ]
285
+ );
286
+
287
+ $condition = ['right_button_selected_icon[value]!' => ''];
288
+ }
289
 
290
  $this->add_control(
291
  'right_button_icon_position',
305
  ],
306
  'toggle' => false,
307
  'default' => 'after',
308
+ 'condition' => $condition
 
 
309
  ]
310
  );
311
 
314
  [
315
  'label' => __( 'Icon Spacing', 'happy-elementor-addons' ),
316
  'type' => Controls_Manager::SLIDER,
317
+ 'condition' => $condition,
 
 
318
  'selectors' => [
319
  '{{WRAPPER}} .ha-dual-btn--right .ha-dual-btn-icon--before' => 'margin-right: {{SIZE}}{{UNIT}};',
320
  '{{WRAPPER}} .ha-dual-btn--right .ha-dual-btn-icon--after' => 'margin-left: {{SIZE}}{{UNIT}};',
792
  }
793
  $this->add_inline_editing_attributes( 'left_button_text', 'none' );
794
 
795
+ $left_button_atts = [];
796
+ if ( ! empty( $settings['left_button_icon'] ) || ! empty( $settings['left_button_selected_icon'] ) ) {
797
+ $left_button_atts['class'] = [
798
  'ha-dual-btn-icon',
799
+ 'ha-dual-btn-icon--' . esc_attr( $settings['left_button_icon_position'] )
800
+ ];
 
801
  }
802
 
803
  // Button connector
804
  $this->add_render_attribute( 'button_connector_text', 'class', 'ha-dual-btn-connector' );
805
+ if ( $settings['button_connector_type'] === 'icon' && ( ! empty( $settings['button_connector_icon'] ) || ! empty( $settings['button_connector_selected_icon'] ) ) ) {
806
  $this->add_render_attribute( 'button_connector_text', 'class', 'ha-dual-btn-connector--icon' );
 
807
  } else {
808
  $this->add_render_attribute( 'button_connector_text', 'class', 'ha-dual-btn-connector--text' );
809
  $this->add_inline_editing_attributes( 'button_connector_text', 'none' );
 
810
  }
811
 
812
  // Right button
820
  }
821
  $this->add_inline_editing_attributes( 'right_button_text', 'none' );
822
 
823
+ $right_button_atts = [];
824
+ if ( ! empty( $settings['right_button_icon'] ) || ! empty( $settings['right_button_selected_icon'] ) ) {
825
+ $right_button_atts['class'] = [
826
  'ha-dual-btn-icon',
827
+ 'ha-dual-btn-icon--' . esc_attr( $settings['right_button_icon_position'] )
828
+ ];
 
829
  }
830
  ?>
831
  <div class="ha-dual-btn-wrapper">
832
  <a <?php echo $this->get_render_attribute_string( 'left_button' ); ?>>
833
+ <?php if ( $settings['left_button_icon_position'] === 'before' && ( ! empty( $settings['left_button_icon'] ) || ! empty( $settings['left_button_selected_icon'] ) ) ) : ?>
834
+ <?php ha_render_icon( $settings, 'left_button_icon', 'left_button_selected_icon', $left_button_atts ); ?>
835
  <?php endif; ?>
836
+ <?php if ( $settings['left_button_text'] ) : ?>
837
+ <span <?php echo $this->get_render_attribute_string( 'left_button_text' ); ?>><?php echo esc_html( $settings['left_button_text'] ); ?></span>
838
+ <?php endif; ?>
839
+ <?php if ( $settings['left_button_icon_position'] === 'after' && ( ! empty( $settings['left_button_icon'] ) || ! empty( $settings['left_button_selected_icon'] ) ) ) : ?>
840
+ <?php ha_render_icon( $settings, 'left_button_icon', 'left_button_selected_icon', $left_button_atts ); ?>
841
  <?php endif; ?>
842
  </a>
843
  <?php if ( $settings['button_connector_hide'] !== 'yes' ) : ?>
844
+ <span <?php echo $this->get_render_attribute_string( 'button_connector_text' ); ?>>
845
+ <?php if ( $settings['button_connector_type'] === 'icon' && ( ! empty( $settings['button_connector_icon'] ) || ! empty( $settings['button_connector_selected_icon'] ) ) ) : ?>
846
+ <?php ha_render_icon( $settings, 'button_connector_icon', 'button_connector_selected_icon' ); ?>
847
+ <?php else :
848
+ echo esc_html( $settings['button_connector_text'] );
849
+ endif; ?>
850
+ </span>
851
  <?php endif; ?>
852
  </div>
853
  <div class="ha-dual-btn-wrapper">
854
  <a <?php echo $this->get_render_attribute_string( 'right_button' ); ?>>
855
+ <?php if ( $settings['right_button_icon_position'] === 'before' && ( ! empty( $settings['right_button_icon'] ) || ! empty( $settings['right_button_selected_icon'] ) ) ) : ?>
856
+ <?php ha_render_icon( $settings, 'right_button_icon', 'right_button_selected_icon', $right_button_atts ); ?>
857
+ <?php endif; ?>
858
+ <?php if ( $settings['right_button_text'] ) : ?>
859
+ <span <?php echo $this->get_render_attribute_string( 'right_button_text' ); ?>><?php echo esc_html( $settings['right_button_text'] ); ?></span>
860
  <?php endif; ?>
861
+ <?php if ( $settings['right_button_icon_position'] === 'after' && ( ! empty( $settings['right_button_icon'] ) || ! empty( $settings['right_button_selected_icon'] ) ) ) : ?>
862
+ <?php ha_render_icon( $settings, 'right_button_icon', 'right_button_selected_icon', $right_button_atts ); ?>
 
863
  <?php endif; ?>
864
  </a>
865
  </div>
866
  <?php
867
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
868
  }
widgets/flip-box/widget.php CHANGED
@@ -82,18 +82,37 @@ class Flip_Box extends Base {
82
  ]
83
  );
84
 
85
- $this->add_control(
86
- 'front_icon',
87
- [
88
- 'label' => __( 'Icon', 'happy-elementor-addons' ),
89
- 'type' => Controls_Manager::ICON,
90
- 'default' => 'fa fa-home',
91
- 'condition' => [
92
- 'front_icon_type' => 'icon'
93
- ],
94
- 'options' => ha_get_happy_icons(),
95
- ]
96
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
 
98
  $this->add_control(
99
  'front_icon_image',
@@ -105,6 +124,9 @@ class Flip_Box extends Base {
105
  ],
106
  'condition' => [
107
  'front_icon_type' => 'image'
 
 
 
108
  ]
109
  ]
110
  );
@@ -132,8 +154,11 @@ class Flip_Box extends Base {
132
  'label_block' => true,
133
  'separator' => 'before',
134
  'type' => Controls_Manager::TEXT,
135
- 'default' => __( 'Start Marketing', 'happy-elementor-addons' ),
136
  'placeholder' => __( 'Type Flip Box Title', 'happy-elementor-addons' ),
 
 
 
137
  ]
138
  );
139
 
@@ -143,8 +168,11 @@ class Flip_Box extends Base {
143
  'label' => __( 'Description', 'happy-elementor-addons' ),
144
  'label_block' => true,
145
  'type' => Controls_Manager::TEXTAREA,
146
- 'default' => __( 'consectetur adipiscing elit, sed do<br>eiusmod Lorem ipsum dolor sit amet,<br> consectetur.', 'happy-elementor-addons' ),
147
  'placeholder' => __( 'Description', 'happy-elementor-addons' ),
 
 
 
148
  ]
149
  );
150
 
@@ -219,6 +247,9 @@ class Flip_Box extends Base {
219
  ],
220
  'condition' => [
221
  'back_icon_type' => 'image'
 
 
 
222
  ]
223
  ]
224
  );
@@ -239,18 +270,37 @@ class Flip_Box extends Base {
239
  ]
240
  );
241
 
242
- $this->add_control(
243
- 'back_icon',
244
- [
245
- 'label' => __( 'Icon', 'happy-elementor-addons' ),
246
- 'type' => Controls_Manager::ICON,
247
- 'return_value' => 'yes',
248
- 'condition' => [
249
- 'back_icon_type' => 'icon',
250
- ],
251
- 'options' => ha_get_happy_icons(),
252
- ]
253
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
 
255
  $this->add_control(
256
  'back_title',
@@ -261,6 +311,9 @@ class Flip_Box extends Base {
261
  'type' => Controls_Manager::TEXT,
262
  'default' => __( 'Start Marketing', 'happy-elementor-addons' ),
263
  'placeholder' => __( 'Type Flip Box Title', 'happy-elementor-addons' ),
 
 
 
264
  ]
265
  );
266
 
@@ -270,8 +323,11 @@ class Flip_Box extends Base {
270
  'label' => __( 'Description', 'happy-elementor-addons' ),
271
  'label_block' => true,
272
  'type' => Controls_Manager::TEXTAREA,
273
- 'default' => __( 'consectetur adipiscing elit, sed do<br>eiusmod Lorem ipsum dolor sit amet.', 'happy-elementor-addons' ),
274
  'placeholder' => __( 'Description', 'happy-elementor-addons' ),
 
 
 
275
  ]
276
  );
277
 
@@ -438,7 +494,7 @@ class Flip_Box extends Base {
438
  'front_background_image_image[url]!' => ''
439
  ],
440
  'selectors' => [
441
- '{{WRAPPER}} .ha-flip-wrap .ha-flip-box .ha-flip-box-front:before' => 'background-color: {{VALUE}}',
442
  ],
443
  ]
444
  );
@@ -788,7 +844,7 @@ class Flip_Box extends Base {
788
  'back_background_image_background' => 'classic'
789
  ],
790
  'selectors' => [
791
- '{{WRAPPER}} .ha-flip-wrap .ha-flip-box .ha-flip-box-back:before' => 'background-color: {{VALUE}}',
792
  ],
793
  ]
794
  );
@@ -1122,10 +1178,10 @@ class Flip_Box extends Base {
1122
  <div class="ha-flip-box-front">
1123
  <div class="ha-flip-box-front-inner">
1124
  <div class="icon-wrap">
1125
- <?php if ( $settings['front_icon'] ) : ?>
1126
- <div class="ha-flip-icon icon">
1127
- <i class="<?php echo esc_attr( $settings['front_icon'] ); ?>"></i>
1128
- </div>
1129
  <?php endif; ?>
1130
  <?php if ( $settings['front_icon_image'] ) : ?>
1131
  <div class="ha-flip-icon">
@@ -1149,10 +1205,10 @@ class Flip_Box extends Base {
1149
  <div class="ha-flip-box-back">
1150
  <div class="ha-flip-box-back-inner">
1151
  <div class="icon-wrap">
1152
- <?php if ( $settings['back_icon'] ) : ?>
1153
- <div class="ha-flip-icon icon">
1154
- <i class="<?php echo esc_attr( $settings['back_icon'] ); ?>"></i>
1155
- </div>
1156
  <?php endif; ?>
1157
  <?php if ( $settings['back_icon_image'] ) : ?>
1158
  <div class="ha-flip-icon">
82
  ]
83
  );
84
 
85
+ if ( ha_is_elementor_version( '<', '2.6.0' ) ) {
86
+ $this->add_control(
87
+ 'front_icon',
88
+ [
89
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
90
+ 'type' => Controls_Manager::ICON,
91
+ 'options' => ha_get_happy_icons(),
92
+ 'default' => 'fa fa-home',
93
+ 'condition' => [
94
+ 'front_icon_type' => 'icon'
95
+ ],
96
+ ]
97
+ );
98
+ } else {
99
+ $this->add_control(
100
+ 'front_selected_icon',
101
+ [
102
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
103
+ 'type' => Controls_Manager::ICONS,
104
+ 'fa4compatibility' => 'front_icon',
105
+ 'label_block' => true,
106
+ 'default' => [
107
+ 'value' => 'hm hm-home',
108
+ 'library' => 'happy-icons',
109
+ ],
110
+ 'condition' => [
111
+ 'front_icon_type' => 'icon'
112
+ ],
113
+ ]
114
+ );
115
+ }
116
 
117
  $this->add_control(
118
  'front_icon_image',
124
  ],
125
  'condition' => [
126
  'front_icon_type' => 'image'
127
+ ],
128
+ 'dynamic' => [
129
+ 'active' => true,
130
  ]
131
  ]
132
  );
154
  'label_block' => true,
155
  'separator' => 'before',
156
  'type' => Controls_Manager::TEXT,
157
+ 'default' => 'Start Marketing',
158
  'placeholder' => __( 'Type Flip Box Title', 'happy-elementor-addons' ),
159
+ 'dynamic' => [
160
+ 'active' => true,
161
+ ]
162
  ]
163
  );
164
 
168
  'label' => __( 'Description', 'happy-elementor-addons' ),
169
  'label_block' => true,
170
  'type' => Controls_Manager::TEXTAREA,
171
+ 'default' => 'consectetur adipiscing elit, sed do<br>eiusmod Lorem ipsum dolor sit amet,<br> consectetur.',
172
  'placeholder' => __( 'Description', 'happy-elementor-addons' ),
173
+ 'dynamic' => [
174
+ 'active' => true,
175
+ ]
176
  ]
177
  );
178
 
247
  ],
248
  'condition' => [
249
  'back_icon_type' => 'image'
250
+ ],
251
+ 'dynamic' => [
252
+ 'active' => true,
253
  ]
254
  ]
255
  );
270
  ]
271
  );
272
 
273
+ if ( ha_is_elementor_version( '<', '2.6.0' ) ) {
274
+ $this->add_control(
275
+ 'back_icon',
276
+ [
277
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
278
+ 'type' => Controls_Manager::ICON,
279
+ 'options' => ha_get_happy_icons(),
280
+ 'default' => 'fa fa-home',
281
+ 'condition' => [
282
+ 'back_icon_type' => 'icon'
283
+ ],
284
+ ]
285
+ );
286
+ } else {
287
+ $this->add_control(
288
+ 'back_selected_icon',
289
+ [
290
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
291
+ 'type' => Controls_Manager::ICONS,
292
+ 'fa4compatibility' => 'back_icon',
293
+ 'label_block' => true,
294
+ 'default' => [
295
+ 'value' => 'fas fa-smile-wink',
296
+ 'library' => 'fa-solid',
297
+ ],
298
+ 'condition' => [
299
+ 'back_icon_type' => 'icon'
300
+ ],
301
+ ]
302
+ );
303
+ }
304
 
305
  $this->add_control(
306
  'back_title',
311
  'type' => Controls_Manager::TEXT,
312
  'default' => __( 'Start Marketing', 'happy-elementor-addons' ),
313
  'placeholder' => __( 'Type Flip Box Title', 'happy-elementor-addons' ),
314
+ 'dynamic' => [
315
+ 'active' => true,
316
+ ]
317
  ]
318
  );
319
 
323
  'label' => __( 'Description', 'happy-elementor-addons' ),
324
  'label_block' => true,
325
  'type' => Controls_Manager::TEXTAREA,
326
+ 'default' => 'consectetur adipiscing elit, sed do<br>eiusmod Lorem ipsum dolor sit amet.',
327
  'placeholder' => __( 'Description', 'happy-elementor-addons' ),
328
+ 'dynamic' => [
329
+ 'active' => true,
330
+ ]
331
  ]
332
  );
333
 
494
  'front_background_image_image[url]!' => ''
495
  ],
496
  'selectors' => [
497
+ '{{WRAPPER}} .ha-flip-box-front:before' => 'background-color: {{VALUE}}',
498
  ],
499
  ]
500
  );
844
  'back_background_image_background' => 'classic'
845
  ],
846
  'selectors' => [
847
+ '{{WRAPPER}} .ha-flip-box-back:before' => 'background-color: {{VALUE}}',
848
  ],
849
  ]
850
  );
1178
  <div class="ha-flip-box-front">
1179
  <div class="ha-flip-box-front-inner">
1180
  <div class="icon-wrap">
1181
+ <?php if ( ! empty( $settings['front_icon'] ) || ! empty( $settings['front_selected_icon'] ) ) : ?>
1182
+ <span class="ha-flip-icon icon">
1183
+ <?php ha_render_icon( $settings, 'front_icon', 'front_selected_icon' ); ?>
1184
+ </span>
1185
  <?php endif; ?>
1186
  <?php if ( $settings['front_icon_image'] ) : ?>
1187
  <div class="ha-flip-icon">
1205
  <div class="ha-flip-box-back">
1206
  <div class="ha-flip-box-back-inner">
1207
  <div class="icon-wrap">
1208
+ <?php if ( ! empty( $settings['back_icon'] ) || ! empty( $settings['back_selected_icon'] ) ) : ?>
1209
+ <span class="ha-flip-icon icon">
1210
+ <?php ha_render_icon( $settings, 'back_icon', 'back_selected_icon' ); ?>
1211
+ </span>
1212
  <?php endif; ?>
1213
  <?php if ( $settings['back_icon_image'] ) : ?>
1214
  <div class="ha-flip-icon">
widgets/gradient-heading/widget.php CHANGED
@@ -58,8 +58,11 @@ class Gradient_Heading extends Base {
58
  [
59
  'label' => __( 'Title', 'happy-elementor-addons' ),
60
  'type' => Controls_Manager::TEXTAREA,
61
- 'default' => __( 'Happy Gradient Heading', 'happy-elementor-addons' ),
62
  'placeholder' => __( 'Type Gradient Heading Text', 'happy-elementor-addons' ),
 
 
 
63
  ]
64
  );
65
 
@@ -69,7 +72,10 @@ class Gradient_Heading extends Base {
69
  'label' => __( 'Link', 'happy-elementor-addons' ),
70
  'type' => Controls_Manager::URL,
71
  'separator' => 'before',
72
- 'placeholder' => __( 'https://example.com/', 'happy-elementor-addons' ),
 
 
 
73
  ]
74
  );
75
 
58
  [
59
  'label' => __( 'Title', 'happy-elementor-addons' ),
60
  'type' => Controls_Manager::TEXTAREA,
61
+ 'default' => 'Happy Gradient Heading',
62
  'placeholder' => __( 'Type Gradient Heading Text', 'happy-elementor-addons' ),
63
+ 'dynamic' => [
64
+ 'active' => true,
65
+ ]
66
  ]
67
  );
68
 
72
  'label' => __( 'Link', 'happy-elementor-addons' ),
73
  'type' => Controls_Manager::URL,
74
  'separator' => 'before',
75
+ 'placeholder' => 'https://happyaddons.com/',
76
+ 'dynamic' => [
77
+ 'active' => true,
78
+ ]
79
  ]
80
  );
81
 
widgets/icon-box/widget.php CHANGED
@@ -12,6 +12,7 @@ use Elementor\Group_Control_Box_Shadow;
12
  use Elementor\Group_Control_Text_Shadow;
13
  use Elementor\Group_Control_Typography;
14
  use Elementor\Scheme_Typography;
 
15
 
16
  defined( 'ABSPATH' ) || die();
17
 
@@ -54,16 +55,32 @@ class Icon_Box extends Base {
54
  ]
55
  );
56
 
57
- $this->add_control(
58
- 'icon',
59
- [
60
- 'show_label' => false,
61
- 'type' => Controls_Manager::ICON,
62
- 'label_block' => true,
63
- 'options' => ha_get_happy_icons(),
64
- 'default' => 'fa fa-smile-o',
65
- ]
66
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
  $this->add_control(
69
  'title',
@@ -73,6 +90,9 @@ class Icon_Box extends Base {
73
  'label_block' => true,
74
  'default' => __( 'Happy Icon Box', 'happy-elementor-addons' ),
75
  'placeholder' => __( 'Type Icon Box Title', 'happy-elementor-addons' ),
 
 
 
76
  ]
77
  );
78
 
@@ -83,6 +103,9 @@ class Icon_Box extends Base {
83
  'type' => Controls_Manager::TEXT,
84
  'label_block' => true,
85
  'placeholder' => __( 'Type Icon Badge Text', 'happy-elementor-addons' ),
 
 
 
86
  ]
87
  );
88
 
@@ -92,7 +115,10 @@ class Icon_Box extends Base {
92
  'label' => __( 'Box Link', 'happy-elementor-addons' ),
93
  'separator' => 'before',
94
  'type' => Controls_Manager::URL,
95
- 'placeholder' => __( 'https://example.com/', 'happy-elementor-addons' ),
 
 
 
96
  ]
97
  );
98
 
@@ -647,9 +673,7 @@ class Icon_Box extends Base {
647
  }
648
 
649
  if ( \Elementor\Plugin::$instance->editor->is_edit_mode() ) {
650
- if( function_exists( 'render_edit_tools' ) ) {
651
- $this->render_edit_tools();
652
- }
653
  }
654
 
655
  $tag = 'div';
@@ -703,9 +727,9 @@ class Icon_Box extends Base {
703
  <span <?php echo $this->get_render_attribute_string( 'badge_text' ); ?>><?php echo esc_html( $settings['badge_text'] ); ?></span>
704
  <?php endif; ?>
705
 
706
- <?php if ( $settings['icon'] ) : ?>
707
  <span class="ha-icon-box-icon">
708
- <i aria-hidden="true" class="<?php echo esc_attr( $settings['icon'] ); ?>"></i>
709
  </span>
710
  <?php endif; ?>
711
 
@@ -722,6 +746,13 @@ class Icon_Box extends Base {
722
  public function _content_template() {
723
  ?>
724
  <#
 
 
 
 
 
 
 
725
  view.addInlineEditingAttributes( 'title', 'none' );
726
  view.addRenderAttribute( 'title', 'class', 'ha-icon-box-title' );
727
 
@@ -738,11 +769,16 @@ class Icon_Box extends Base {
738
  <span {{{ view.getRenderAttributeString( 'badge_text' ) }}}>{{ settings.badge_text }}</span>
739
  <# } #>
740
 
741
- <# if (settings.icon) { #>
742
  <span class="ha-icon-box-icon">
743
- <i class="{{ settings.icon }}"></i>
 
 
 
 
744
  </span>
745
  <# } #>
 
746
  <# if (settings.title) { #>
747
  <{{ settings.title_tag }} {{{ view.getRenderAttributeString( 'title' ) }}}>{{ settings.title }}</{{ settings.title_tag }}>
748
  <# } #>
12
  use Elementor\Group_Control_Text_Shadow;
13
  use Elementor\Group_Control_Typography;
14
  use Elementor\Scheme_Typography;
15
+ use Happy_Addons\Elementor\Icons_Manager;
16
 
17
  defined( 'ABSPATH' ) || die();
18
 
55
  ]
56
  );
57
 
58
+ if ( ha_is_elementor_version( '<', '2.6.0' ) ) {
59
+ $this->add_control(
60
+ 'icon',
61
+ [
62
+ 'show_label' => false,
63
+ 'type' => Controls_Manager::ICON,
64
+ 'label_block' => true,
65
+ 'options' => ha_get_happy_icons(),
66
+ 'default' => 'fa fa-smile-o',
67
+ ]
68
+ );
69
+ } else {
70
+ $this->add_control(
71
+ 'selected_icon',
72
+ [
73
+ 'show_label' => false,
74
+ 'type' => Controls_Manager::ICONS,
75
+ 'fa4compatibility' => 'icon',
76
+ 'label_block' => true,
77
+ 'default' => [
78
+ 'value' => 'fas fa-smile-wink',
79
+ 'library' => 'fa-solid',
80
+ ]
81
+ ]
82
+ );
83
+ }
84
 
85
  $this->add_control(
86
  'title',
90
  'label_block' => true,
91
  'default' => __( 'Happy Icon Box', 'happy-elementor-addons' ),
92
  'placeholder' => __( 'Type Icon Box Title', 'happy-elementor-addons' ),
93
+ 'dynamic' => [
94
+ 'active' => true,
95
+ ]
96
  ]
97
  );
98
 
103
  'type' => Controls_Manager::TEXT,
104
  'label_block' => true,
105
  'placeholder' => __( 'Type Icon Badge Text', 'happy-elementor-addons' ),
106
+ 'dynamic' => [
107
+ 'active' => true,
108
+ ]
109
  ]
110
  );
111
 
115
  'label' => __( 'Box Link', 'happy-elementor-addons' ),
116
  'separator' => 'before',
117
  'type' => Controls_Manager::URL,
118
+ 'placeholder' => 'https://happyaddons.com/',
119
+ 'dynamic' => [
120
+ 'active' => true,
121
+ ]
122
  ]
123
  );
124
 
673
  }
674
 
675
  if ( \Elementor\Plugin::$instance->editor->is_edit_mode() ) {
676
+ $this->render_edit_tools();
 
 
677
  }
678
 
679
  $tag = 'div';
727
  <span <?php echo $this->get_render_attribute_string( 'badge_text' ); ?>><?php echo esc_html( $settings['badge_text'] ); ?></span>
728
  <?php endif; ?>
729
 
730
+ <?php if ( ! empty( $settings['icon'] ) || ! empty( $settings['selected_icon'] ) ) : ?>
731
  <span class="ha-icon-box-icon">
732
+ <?php ha_render_icon( $settings, 'icon', 'selected_icon' ); ?>
733
  </span>
734
  <?php endif; ?>
735
 
746
  public function _content_template() {
747
  ?>
748
  <#
749
+ var iconHTML = migrated = '';
750
+
751
+ if ( ha_has_icon_library() ) {
752
+ iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, { 'aria-hidden': true }, 'i' , 'object' ),
753
+ migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' );
754
+ }
755
+
756
  view.addInlineEditingAttributes( 'title', 'none' );
757
  view.addRenderAttribute( 'title', 'class', 'ha-icon-box-title' );
758
 
769
  <span {{{ view.getRenderAttributeString( 'badge_text' ) }}}>{{ settings.badge_text }}</span>
770
  <# } #>
771
 
772
+ <# if ( settings.icon || settings.selected_icon ) { #>
773
  <span class="ha-icon-box-icon">
774
+ <# if ( ha_has_icon_library() && iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #>
775
+ {{{ iconHTML.value }}}
776
+ <# } else { #>
777
+ <i class="{{ settings.icon }}" aria-hidden="true"></i>
778
+ <# } #>
779
  </span>
780
  <# } #>
781
+
782
  <# if (settings.title) { #>
783
  <{{ settings.title_tag }} {{{ view.getRenderAttributeString( 'title' ) }}}>{{ settings.title }}</{{ settings.title_tag }}>
784
  <# } #>
widgets/image-compare/widget.php CHANGED
@@ -72,6 +72,9 @@ class Image_Compare extends Base {
72
  'default' => [
73
  'url' => Utils::get_placeholder_image_src(),
74
  ],
 
 
 
75
  ]
76
  );
77
 
@@ -83,6 +86,9 @@ class Image_Compare extends Base {
83
  'default' => __( 'Before', 'happy-elementor-addons' ),
84
  'placeholder' => __( 'Type before image label', 'happy-elementor-addons' ),
85
  'description' => __( 'Label will not be shown if Hide Overlay is enabled in Settings', 'happy-elementor-addons' ),
 
 
 
86
  ]
87
  );
88
 
@@ -103,6 +109,9 @@ class Image_Compare extends Base {
103
  'default' => [
104
  'url' => Utils::get_placeholder_image_src(),
105
  ],
 
 
 
106
  ]
107
  );
108
 
@@ -114,6 +123,9 @@ class Image_Compare extends Base {
114
  'default' => __( 'After', 'happy-elementor-addons' ),
115
  'placeholder' => __( 'Type after image label', 'happy-elementor-addons' ),
116
  'description' => __( 'Label will not be shown if Hide Overlay is enabled in Settings', 'happy-elementor-addons' ),
 
 
 
117
  ]
118
  );
119
 
72
  'default' => [
73
  'url' => Utils::get_placeholder_image_src(),
74
  ],
75
+ 'dynamic' => [
76
+ 'active' => true,
77
+ ]
78
  ]
79
  );
80
 
86
  'default' => __( 'Before', 'happy-elementor-addons' ),
87
  'placeholder' => __( 'Type before image label', 'happy-elementor-addons' ),
88
  'description' => __( 'Label will not be shown if Hide Overlay is enabled in Settings', 'happy-elementor-addons' ),
89
+ 'dynamic' => [
90
+ 'active' => true,
91
+ ]
92
  ]
93
  );
94
 
109
  'default' => [
110
  'url' => Utils::get_placeholder_image_src(),
111
  ],
112
+ 'dynamic' => [
113
+ 'active' => true,
114
+ ]
115
  ]
116
  );
117
 
123
  'default' => __( 'After', 'happy-elementor-addons' ),
124
  'placeholder' => __( 'Type after image label', 'happy-elementor-addons' ),
125
  'description' => __( 'Label will not be shown if Hide Overlay is enabled in Settings', 'happy-elementor-addons' ),
126
+ 'dynamic' => [
127
+ 'active' => true,
128
+ ]
129
  ]
130
  );
131
 
widgets/image-grid/widget.php ADDED
@@ -0,0 +1,721 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Image grid widget class
4
+ *
5
+ * @package Happy_Addons
6
+ */
7
+ namespace Happy_Addons\Elementor\Widget;
8
+
9
+ use Elementor\Group_Control_Css_Filter;
10
+ use Elementor\Repeater;
11
+ use Elementor\Controls_Manager;
12
+ use Elementor\Group_Control_Border;
13
+ use Elementor\Group_Control_Box_Shadow;
14
+ use Elementor\Group_Control_Image_Size;
15
+ use Elementor\Group_Control_Typography;
16
+ use Elementor\Scheme_Typography;
17
+
18
+ defined( 'ABSPATH' ) || die();
19
+
20
+ class Image_Grid extends Base {
21
+
22
+ /**
23
+ * Get widget title.
24
+ *
25
+ * @since 1.0.0
26
+ * @access public
27
+ *
28
+ * @return string Widget title.
29
+ */
30
+ public function get_title() {
31
+ return __( 'Image Grid', 'happy-elementor-addons' );
32
+ }
33
+
34
+ /**
35
+ * Get widget icon.
36
+ *
37
+ * @since 1.0.0
38
+ * @access public
39
+ *
40
+ * @return string Widget icon.
41
+ */
42
+ public function get_icon() {
43
+ return 'hm hm-grid-even';
44
+ }
45
+
46
+ public function get_keywords() {
47
+ return [ 'gallery', 'image', 'masonry', 'even', 'portfolio', 'filterable', 'grid' ];
48
+ }
49
+
50
+ protected function register_content_controls() {
51
+ $this->start_controls_section(
52
+ '_section_gallery',
53
+ [
54
+ 'label' => __( 'Gallery', 'happy-elementor-addons' ),
55
+ 'tab' => Controls_Manager::TAB_CONTENT,
56
+ ]
57
+ );
58
+
59
+ $repeater = new Repeater();
60
+
61
+ $repeater->add_control(
62
+ 'filter',
63
+ [
64
+ 'label' => __( 'Filter Name', 'happy-elementor-addons' ),
65
+ 'type' => Controls_Manager::TEXT,
66
+ 'placeholder' => __( 'Type gallery filter name', 'happy-elementor-addons' ),
67
+ 'description' => __( 'Filter menu will be built using filter name', 'happy-elementor-addons' ),
68
+ 'default' => __( 'Image Grid', 'happy-elementor-addons' ),
69
+ ]
70
+ );
71
+
72
+ $repeater->add_control(
73
+ 'images',
74
+ [
75
+ 'type' => Controls_Manager::GALLERY,
76
+ ]
77
+ );
78
+
79
+ $this->add_control(
80
+ 'gallery',
81
+ [
82
+ 'type' => Controls_Manager::REPEATER,
83
+ 'fields' => $repeater->get_controls(),
84
+ 'title_field' => 'Filter Group: {{ filter }}',
85
+ 'default' => [
86
+ [
87
+ 'filter' => __( 'Image Grid', 'happy-elementor-addons' ),
88
+ ]
89
+ ]
90
+ ]
91
+ );
92
+
93
+ $this->add_group_control(
94
+ Group_Control_Image_Size::get_type(),
95
+ [
96
+ 'name' => 'thumbnail',
97
+ 'default' => 'medium_large',
98
+ 'separator' => 'before',
99
+ 'exclude' => [
100
+ 'custom'
101
+ ]
102
+ ]
103
+ );
104
+
105
+ $this->end_controls_section();
106
+
107
+ $this->start_controls_section(
108
+ '_section_settings',
109
+ [
110
+ 'label' => __( 'Settings', 'happy-elementor-addons' ),
111
+ 'tab' => Controls_Manager::TAB_CONTENT,
112
+ ]
113
+ );
114
+
115
+ $this->add_control(
116
+ 'show_filter',
117
+ [
118
+ 'label' => __( 'Show Filter?', 'happy-elementor-addons' ),
119
+ 'type' => Controls_Manager::SWITCHER,
120
+ 'label_on' => __( 'Yes', 'happy-elementor-addons' ),
121
+ 'label_off' => __( 'No', 'happy-elementor-addons' ),
122
+ 'return_value' => 'yes',
123
+ 'description' => __( 'Enable to display filter navigation. Filter navigation will be built using filter name from gallery', 'happy-elementor-addons' )
124
+ ]
125
+ );
126
+
127
+ $this->add_control(
128
+ 'show_all_filter',
129
+ [
130
+ 'label' => __( 'Show All Filter?', 'happy-elementor-addons' ),
131
+ 'type' => Controls_Manager::SWITCHER,
132
+ 'label_on' => __( 'Yes', 'happy-elementor-addons' ),
133
+ 'label_off' => __( 'No', 'happy-elementor-addons' ),
134
+ 'return_value' => 'yes',
135
+ 'default' => 'yes',
136
+ 'description' => __( 'Enable to display all filter button', 'happy-elementor-addons' ),
137
+ 'condition' => [
138
+ 'show_filter' => 'yes'
139
+ ]
140
+ ]
141
+ );
142
+
143
+ $this->add_control(
144
+ 'all_filter_label',
145
+ [
146
+ 'label' => __( 'Filter Label', 'happy-elementor-addons' ),
147
+ 'type' => Controls_Manager::TEXT,
148
+ 'default' => __( 'All', 'happy-elementor-addons' ),
149
+ 'placeholder' => __( 'Type filter label', 'happy-elementor-addons' ),
150
+ 'description' => __( 'Type all filter label', 'happy-elementor-addons' ),
151
+ 'condition' => [
152
+ 'show_all_filter' => 'yes',
153
+ 'show_filter' => 'yes'
154
+ ]
155
+ ]
156
+ );
157
+
158
+ $this->add_responsive_control(
159
+ 'columns',
160
+ [
161
+ 'label' => __( 'Columns', 'happy-elementor-addons' ),
162
+ 'type' => Controls_Manager::SELECT,
163
+ 'options' => [
164
+ 2 => __( '2 Columns', 'happy-elementor-addons' ),
165
+ 3 => __( '3 Columns', 'happy-elementor-addons' ),
166
+ 4 => __( '4 Columns', 'happy-elementor-addons' ),
167
+ 5 => __( '5 Columns', 'happy-elementor-addons' ),
168
+ ],
169
+ 'desktop_default' => 4,
170
+ 'tablet_default' => 3,
171
+ 'mobile_default' => 2,
172
+ 'prefix_class' => 'ha-image-grid--col-',
173
+ 'selectors' => [
174
+ '{{WRAPPER}} .ha-image-grid-item' => 'width: calc(100% / {{VALUE}});',
175
+ ]
176
+ ]
177
+ );
178
+
179
+ $this->add_control(
180
+ 'layout',
181
+ [
182
+ 'label' => __( 'Layout', 'happy-elementor-addons' ),
183
+ 'type' => Controls_Manager::SELECT,
184
+ 'options' => [
185
+ 'even' => __( 'Even', 'happy-elementor-addons' ),
186
+ 'fitRows' => __( 'Fit Rows', 'happy-elementor-addons' ),
187
+ 'masonry' => __( 'Masonry', 'happy-elementor-addons' ),
188
+ ],
189
+ 'default' => 'masonry',
190
+ 'render' => 'none',
191
+ 'frontend_available' => true,
192
+ 'prefix_class' => 'ha-image-grid--layout-',
193
+ ]
194
+ );
195
+
196
+ $this->end_controls_section();
197
+ }
198
+
199
+ protected function register_style_controls() {
200
+ $this->start_controls_section(
201
+ '_section_style_image',
202
+ [
203
+ 'label' => __( 'Image', 'happy-elementor-addons' ),
204
+ 'tab' => Controls_Manager::TAB_STYLE,
205
+ ]
206
+ );
207
+
208
+ $this->add_control(
209
+ 'image_height',
210
+ [
211
+ 'label' => __( 'Height', 'happy-elementor-addons' ),
212
+ 'description' => __( 'Image height is only applicable for Even layout', 'happy-elementor-addons' ),
213
+ 'type' => Controls_Manager::SLIDER,
214
+ 'range' => [
215
+ 'px' => [
216
+ 'min' => 100,
217
+ 'max' => 1000
218
+ ]
219
+ ],
220
+ 'selectors' => [
221
+ '{{WRAPPER}} .ha-image-grid-inner' => 'height: {{SIZE}}{{UNIT}}',
222
+ ],
223
+ 'condition' => [
224
+ 'layout' => 'even',
225
+ ]
226
+ ]
227
+ );
228
+
229
+ $this->add_responsive_control(
230
+ 'image_margin',
231
+ [
232
+ 'label' => __( 'Margin', 'happy-elementor-addons' ),
233
+ 'type' => Controls_Manager::DIMENSIONS,
234
+ 'size_units' => [ 'px' ],
235
+ 'selectors' => [
236
+ '{{WRAPPER}} .ha-image-grid-inner' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
237
+ ],
238
+ ]
239
+ );
240
+
241
+ $this->add_responsive_control(
242
+ 'image_border_radius',
243
+ [
244
+ 'label' => __( 'Border Radius', 'happy-elementor-addons' ),
245
+ 'type' => Controls_Manager::DIMENSIONS,
246
+ 'size_units' => [ 'px', '%' ],
247
+ 'selectors' => [
248
+ '{{WRAPPER}} .ha-image-grid-inner, {{WRAPPER}} .ha-image-grid-inner > img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
249
+ ],
250
+ ]
251
+ );
252
+
253
+ $this->add_group_control(
254
+ Group_Control_Box_Shadow::get_type(),
255
+ [
256
+ 'name' => 'image_box_shadow',
257
+ 'selector' => '{{WRAPPER}} .ha-image-grid-inner'
258
+ ]
259
+ );
260
+
261
+ $this->start_controls_tabs(
262
+ '_tabs_image_effects',
263
+ [
264
+ 'separator' => 'before'
265
+ ]
266
+ );
267
+
268
+ $this->start_controls_tab(
269
+ '_tab_image_effects_normal',
270
+ [
271
+ 'label' => __( 'Normal', 'happy-elementor-addons' ),
272
+ ]
273
+ );
274
+
275
+ $this->add_control(
276
+ 'image_opacity',
277
+ [
278
+ 'label' => __( 'Opacity', 'happy-elementor-addons' ),
279
+ 'type' => Controls_Manager::SLIDER,
280
+ 'range' => [
281
+ 'px' => [
282
+ 'max' => 1,
283
+ 'min' => 0.10,
284
+ 'step' => 0.01,
285
+ ],
286
+ ],
287
+ 'selectors' => [
288
+ '{{WRAPPER}} .ha-image-grid-inner > img' => 'opacity: {{SIZE}};',
289
+ ],
290
+ ]
291
+ );
292
+
293
+ $this->add_group_control(
294
+ Group_Control_Css_Filter::get_type(),
295
+ [
296
+ 'name' => 'image_css_filters',
297
+ 'selector' => '{{WRAPPER}} .ha-image-grid-inner > img',
298
+ ]
299
+ );
300
+
301
+ $this->end_controls_tab();
302
+
303
+ $this->start_controls_tab( 'hover',
304
+ [
305
+ 'label' => __( 'Hover', 'happy-elementor-addons' ),
306
+ ]
307
+ );
308
+
309
+ $this->add_control(
310
+ 'image_opacity_hover',
311
+ [
312
+ 'label' => __( 'Opacity', 'happy-elementor-addons' ),
313
+ 'type' => Controls_Manager::SLIDER,
314
+ 'range' => [
315
+ 'px' => [
316
+ 'max' => 1,
317
+ 'min' => 0.10,
318
+ 'step' => 0.01,
319
+ ],
320
+ ],
321
+ 'selectors' => [
322
+ '{{WRAPPER}} .ha-image-grid-inner:hover > img' => 'opacity: {{SIZE}};',
323
+ ],
324
+ ]
325
+ );
326
+
327
+ $this->add_group_control(
328
+ Group_Control_Css_Filter::get_type(),
329
+ [
330
+ 'name' => 'image_css_filters_hover',
331
+ 'selector' => '{{WRAPPER}} .ha-image-grid-inner:hover > img',
332
+ ]
333
+ );
334
+
335
+ $this->add_control(
336
+ 'image_background_hover_transition',
337
+ [
338
+ 'label' => __( 'Transition Duration', 'happy-elementor-addons' ),
339
+ 'type' => Controls_Manager::SLIDER,
340
+ 'range' => [
341
+ 'px' => [
342
+ 'max' => 3,
343
+ 'step' => 0.1,
344
+ ],
345
+ ],
346
+ 'selectors' => [
347
+ '{{WRAPPER}} .ha-image-grid-inner > img' => 'transition-duration: {{SIZE}}s',
348
+ ],
349
+ ]
350
+ );
351
+
352
+ $this->add_control(
353
+ 'image_hover_animation',
354
+ [
355
+ 'label' => __( 'Hover Animation', 'happy-elementor-addons' ),
356
+ 'type' => Controls_Manager::HOVER_ANIMATION,
357
+ 'default' => 'grow',
358
+ 'label_block' => false,
359
+ ]
360
+ );
361
+
362
+ $this->end_controls_tab();
363
+ $this->end_controls_tabs();
364
+
365
+ $this->end_controls_section();
366
+
367
+ $this->start_controls_section(
368
+ '_section_style_menu',
369
+ [
370
+ 'label' => __( 'Filter Menu', 'happy-elementor-addons' ),
371
+ 'tab' => Controls_Manager::TAB_STYLE,
372
+ ]
373
+ );
374
+
375
+ $this->add_control(
376
+ '_heading_menu',
377
+ [
378
+ 'label' => __( 'Menu', 'happy-elementor-addons' ),
379
+ 'type' => Controls_Manager::HEADING,
380
+ ]
381
+ );
382
+
383
+ $this->add_responsive_control(
384
+ 'menu_margin',
385
+ [
386
+ 'label' => __( 'Margin', 'happy-elementor-addons' ),
387
+ 'type' => Controls_Manager::DIMENSIONS,
388
+ 'size_units' => [ 'px', '%' ],
389
+ 'selectors' => [
390
+ '{{WRAPPER}} .ha-gallery-filter' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
391
+ ],
392
+ ]
393
+ );
394
+
395
+ $this->add_control(
396
+ '_heading_buttons',
397
+ [
398
+ 'label' => __( 'Filter Buttons', 'happy-elementor-addons' ),
399
+ 'type' => Controls_Manager::HEADING,
400
+ 'separator' => 'before',
401
+ ]
402
+ );
403
+
404
+ $this->add_responsive_control(
405
+ 'button_padding',
406
+ [
407
+ 'label' => __( 'Padding', 'happy-elementor-addons' ),
408
+ 'type' => Controls_Manager::DIMENSIONS,
409
+ 'size_units' => [ 'px', 'em', '%' ],
410
+ 'selectors' => [
411
+ '{{WRAPPER}} .ha-gallery-filter > li > button' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
412
+ ],
413
+ ]
414
+ );
415
+
416
+ $this->add_responsive_control(
417
+ 'button_spacing',
418
+ [
419
+ 'label' => __( 'Spacing', 'happy-elementor-addons' ),
420
+ 'type' => Controls_Manager::SLIDER,
421
+ 'size_units' => ['px'],
422
+ 'selectors' => [
423
+ '{{WRAPPER}} .ha-gallery-filter > li:not(:last-child)' => 'margin-right: {{SIZE}}{{UNIT}};',
424
+ ],
425
+ ]
426
+ );
427
+
428
+ $this->add_group_control(
429
+ Group_Control_Border::get_type(),
430
+ [
431
+ 'name' => 'button_border',
432
+ 'selector' => '{{WRAPPER}} .ha-gallery-filter > li > button'
433
+ ]
434
+ );
435
+
436
+ $this->add_responsive_control(
437
+ 'button_border_radius',
438
+ [
439
+ 'label' => __( 'Border Radius', 'happy-elementor-addons' ),
440
+ 'type' => Controls_Manager::DIMENSIONS,
441
+ 'size_units' => [ 'px', '%' ],
442
+ 'selectors' => [
443
+ '{{WRAPPER}} .ha-gallery-filter > li > button' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
444
+ ],
445
+ ]
446
+ );
447
+
448
+ $this->add_group_control(
449
+ Group_Control_Box_Shadow::get_type(),
450
+ [
451
+ 'name' => 'button_box_shadow',
452
+ 'exclude' => [
453
+ 'box_shadow_position',
454
+ ],
455
+ 'selector' => '{{WRAPPER}} .ha-gallery-filter > li > button'
456
+ ]
457
+ );
458
+
459
+ $this->add_group_control(
460
+ Group_Control_Typography::get_type(),
461
+ [
462
+ 'name' => 'button_typography',
463
+ 'selector' => '{{WRAPPER}} .ha-gallery-filter > li > button',
464
+ 'scheme' => Scheme_Typography::TYPOGRAPHY_3,
465
+ ]
466
+ );
467
+
468
+ $this->add_responsive_control(
469
+ 'button_align',
470
+ [
471
+ 'label' => __( 'Alignment', 'happy-elementor-addons' ),
472
+ 'type' => Controls_Manager::CHOOSE,
473
+ 'label_block' => false,
474
+ 'options' => [
475
+ 'left' => [
476
+ 'title' => __( 'Left', 'happy-elementor-addons' ),
477
+ 'icon' => 'eicon-h-align-left',
478
+ ],
479
+ 'center' => [
480
+ 'title' => __( 'Center', 'happy-elementor-addons' ),
481
+ 'icon' => 'eicon-h-align-center',
482
+ ],
483
+ 'right' => [
484
+ 'title' => __( 'Right', 'happy-elementor-addons' ),
485
+ 'icon' => 'eicon-h-align-right',
486
+ ],
487
+ ],
488
+ 'desktop_default' => 'left',
489
+ 'toggle' => false,
490
+ 'selectors' => [
491
+ '{{WRAPPER}} .ha-gallery-filter' => 'text-align: {{VALUE}};'
492
+ ]
493
+ ]
494
+ );
495
+
496
+ $this->start_controls_tabs( '_tabs_style_button' );
497
+
498
+ $this->start_controls_tab(
499
+ '_tab_button_normal',
500
+ [
501
+ 'label' => __( 'Normal', 'happy-elementor-addons' ),
502
+ ]
503
+ );
504
+
505
+ $this->add_control(
506
+ 'button_color',
507
+ [
508
+ 'label' => __( 'Text Color', 'happy-elementor-addons' ),
509
+ 'type' => Controls_Manager::COLOR,
510
+ 'default' => '',
511
+ 'selectors' => [
512
+ '{{WRAPPER}} .ha-gallery-filter > li > button' => 'color: {{VALUE}};',
513
+ ],
514
+ ]
515
+ );
516
+
517
+ $this->add_control(
518
+ 'button_bg_color',
519
+ [
520
+ 'label' => __( 'Background Color', 'happy-elementor-addons' ),
521
+ 'type' => Controls_Manager::COLOR,
522
+ 'selectors' => [
523
+ '{{WRAPPER}} .ha-gallery-filter > li > button' => 'background-color: {{VALUE}};',
524
+ ],
525
+ ]
526
+ );
527
+
528
+ $this->end_controls_tab();
529
+
530
+ $this->start_controls_tab(
531
+ '_tab_button_hover',
532
+ [
533
+ 'label' => __( 'Hover', 'happy-elementor-addons' ),
534
+ ]
535
+ );
536
+
537
+ $this->add_control(
538
+ 'button_hover_color',
539
+ [
540
+ 'label' => __( 'Text Color', 'happy-elementor-addons' ),
541
+ 'type' => Controls_Manager::COLOR,
542
+ 'selectors' => [
543
+ '{{WRAPPER}} .ha-gallery-filter > li > button:hover, {{WRAPPER}} .ha-gallery-filter > li > button:focus, {{WRAPPER}} .ha-gallery-filter > .ha-filter-active > button:hover, {{WRAPPER}} .ha-gallery-filter > .ha-filter-active > button:focus' => 'color: {{VALUE}};',
544
+ ],
545
+ ]
546
+ );
547
+
548
+ $this->add_control(
549
+ 'button_hover_bg_color',
550
+ [
551
+ 'label' => __( 'Background Color', 'happy-elementor-addons' ),
552
+ 'type' => Controls_Manager::COLOR,
553
+ 'selectors' => [
554
+ '{{WRAPPER}} .ha-gallery-filter > li > button:hover, {{WRAPPER}} .ha-gallery-filter > li > button:focus, {{WRAPPER}} .ha-gallery-filter > .ha-filter-active > button:hover, {{WRAPPER}} .ha-gallery-filter > .ha-filter-active > button:focus' => 'background-color: {{VALUE}};',
555
+ ],
556
+ ]
557
+ );
558
+
559
+ $this->add_control(
560
+ 'button_hover_border_color',
561
+ [
562
+ 'label' => __( 'Border Color', 'happy-elementor-addons' ),
563
+ 'type' => Controls_Manager::COLOR,
564
+ 'condition' => [
565
+ 'button_border_border!' => '',
566
+ ],
567
+ 'selectors' => [
568
+ '{{WRAPPER}} .ha-gallery-filter > li > button:hover, {{WRAPPER}} .ha-gallery-filter > li > button:focus, {{WRAPPER}} .ha-gallery-filter > .ha-filter-active > button:hover, {{WRAPPER}} .ha-gallery-filter > .ha-filter-active > button:focus' => 'border-color: {{VALUE}};',
569
+ ],
570
+ ]
571
+ );
572
+
573
+ $this->end_controls_tab();
574
+
575
+ $this->start_controls_tab(
576
+ '_tab_button_active',
577
+ [
578
+ 'label' => __( 'Active', 'happy-elementor-addons' ),
579
+ ]
580
+ );
581
+
582
+ $this->add_control(
583
+ 'button_active_color',
584
+ [
585
+ 'label' => __( 'Text Color', 'happy-elementor-addons' ),
586
+ 'type' => Controls_Manager::COLOR,
587
+ 'selectors' => [
588
+ '{{WRAPPER}} .ha-gallery-filter > .ha-filter-active > button' => 'color: {{VALUE}};',
589
+ ],
590
+ ]
591
+ );
592
+
593
+ $this->add_control(
594
+ 'button_active_bg_color',
595
+ [
596
+ 'label' => __( 'Background Color', 'happy-elementor-addons' ),
597
+ 'type' => Controls_Manager::COLOR,
598
+ 'selectors' => [
599
+ '{{WRAPPER}} .ha-gallery-filter > .ha-filter-active > button' => 'background-color: {{VALUE}};',
600
+ ],
601
+ ]
602
+ );
603
+
604
+ $this->add_control(
605
+ 'button_active_border_color',
606
+ [
607
+ 'label' => __( 'Border Color', 'happy-elementor-addons' ),
608
+ 'type' => Controls_Manager::COLOR,
609
+ 'condition' => [
610
+ 'button_border_border!' => '',
611
+ ],
612
+ 'selectors' => [
613
+ '{{WRAPPER}} .ha-gallery-filter > .ha-filter-active > button' => 'border-color: {{VALUE}};',
614
+ ],
615
+ ]
616
+ );
617
+
618
+ $this->end_controls_tab();
619
+ $this->end_controls_tabs();
620
+
621
+ $this->end_controls_section();
622
+ }
623
+
624
+ protected function get_gallery_data() {
625
+ $gallery = $this->get_settings_for_display( 'gallery' );
626
+
627
+ if ( ! is_array( $gallery ) || empty( $gallery ) ) {
628
+ return [];
629
+ }
630
+
631
+ $menu = [];
632
+ $items = [];
633
+
634
+ foreach ( $gallery as $item ) {
635
+ if ( empty( $item['images'] ) ) {
636
+ continue;
637
+ }
638
+
639
+ $images = $item['images'];
640
+ $filter = 'ha-is--' . sanitize_title_with_dashes( $item['filter'] );
641
+
642
+ if ( $filter && ! isset( $data[ $filter ] ) ) {
643
+ $menu[ $filter ] = $item['filter'];
644
+ }
645
+
646
+ foreach ( $images as $image ) {
647
+ if ( ! isset( $items[ $image['id'] ] ) ) {
648
+ $items[ $image['id'] ] = [ $filter ];
649
+ } else {
650
+ array_push( $items[ $image['id'] ], $filter );
651
+ }
652
+ }
653
+ }
654
+
655
+ return [
656
+ 'menu' => $menu,
657
+ 'items' => $items
658
+ ];
659
+ }
660
+
661
+ protected function render() {
662
+ $settings = $this->get_settings_for_display();
663
+ $gallery = $this->get_gallery_data();
664
+
665
+ if ( empty( $gallery ) ) {
666
+ return;
667
+ }
668
+
669
+ $this->add_render_attribute( 'container', 'class', 'ha-image-grid-container hajs-isotope' );
670
+
671
+ if ( \Elementor\Plugin::$instance->editor->is_edit_mode() ) {
672
+ $this->add_render_attribute( 'container', 'class', 'hajs-isotope-' . $this->get_id() );
673
+ }
674
+
675
+ if ( $settings['show_filter'] ) : ?>
676
+
677
+ <ul class="ha-gallery-filter hajs-gallery-filter">
678
+ <?php if ( $settings['show_all_filter'] ) : ?>
679
+ <li class="ha-filter-active"><button type="button" data-filter="*"><?php echo esc_html( $settings['all_filter_label'] ); ?></button></li>
680
+ <?php endif; ?>
681
+ <?php foreach ( $gallery['menu'] as $key => $val ) : ?>
682
+ <li><button type="button" data-filter=".<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $val ); ?></button></li>
683
+ <?php endforeach; ?>
684
+ </ul>
685
+
686
+ <?php endif; ?>
687
+
688
+ <div <?php $this->print_render_attribute_string( 'container' ); ?>>
689
+
690
+ <?php foreach ( $gallery['items'] as $id => $filters ) : ?>
691
+
692
+ <figure class="ha-image-grid-item <?php echo esc_attr( implode( ' ', $filters ) ); ?>">
693
+ <div class="ha-image-grid-inner">
694
+ <?php echo wp_get_attachment_image(
695
+ $id,
696
+ $settings['thumbnail_size'],
697
+ false,
698
+ [
699
+ 'alt' => wp_get_attachment_caption( $id ),
700
+ 'class' => 'elementor-animation-' . esc_attr( $settings['image_hover_animation'] )
701
+ ]
702
+ ); ?>
703
+ </div>
704
+ </figure>
705
+
706
+ <?php endforeach; ?>
707
+
708
+ </div>
709
+
710
+ <?php
711
+ /**
712
+ * Happy isotope hack.
713
+ *
714
+ * This piece of code may seem unnecessary to you
715
+ * but it saved me from hell!!!
716
+ */
717
+ if ( \Elementor\Plugin::$instance->editor->is_edit_mode() ) :
718
+ printf( '<script>jQuery(".hajs-isotope-%s").isotope();</script>', $this->get_id() );
719
+ endif;
720
+ }
721
+ }
widgets/infobox/widget.php CHANGED
@@ -90,6 +90,9 @@ class InfoBox extends Base {
90
  ],
91
  'condition' => [
92
  'type' => 'image'
 
 
 
93
  ]
94
  ]
95
  );
@@ -114,18 +117,37 @@ class InfoBox extends Base {
114
  ]
115
  );
116
 
117
- $this->add_control(
118
- 'icon',
119
- [
120
- 'label' => __( 'Icon', 'happy-elementor-addons' ),
121
- 'type' => Controls_Manager::ICON,
122
- 'default' => 'fa fa-smile-o',
123
- 'options' => ha_get_happy_icons(),
124
- 'condition' => [
125
- 'type' => 'icon'
 
 
 
126
  ]
127
- ]
128
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
 
130
  $this->end_controls_section();
131
 
@@ -145,6 +167,9 @@ class InfoBox extends Base {
145
  'type' => Controls_Manager::TEXT,
146
  'default' => __( 'Happy Info Box Title', 'happy-elementor-addons' ),
147
  'placeholder' => __( 'Type Info Box Title', 'happy-elementor-addons' ),
 
 
 
148
  ]
149
  );
150
 
@@ -155,7 +180,10 @@ class InfoBox extends Base {
155
  'type' => Controls_Manager::TEXTAREA,
156
  'default' => __( 'Happy info box description goes here', 'happy-elementor-addons' ),
157
  'placeholder' => __( 'Type info box description', 'happy-elementor-addons' ),
158
- 'rows' => 5
 
 
 
159
  ]
160
  );
161
 
@@ -243,6 +271,9 @@ class InfoBox extends Base {
243
  'default' => __( 'Button Text', 'happy-elementor-addons' ),
244
  'placeholder' => __( 'Type button text here', 'happy-elementor-addons' ),
245
  'label_block' => true,
 
 
 
246
  ]
247
  );
248
 
@@ -251,19 +282,37 @@ class InfoBox extends Base {
251
  [
252
  'label' => __( 'Link', 'happy-elementor-addons' ),
253
  'type' => Controls_Manager::URL,
254
- 'placeholder' => __( 'https://example.com/', 'happy-elementor-addons' ),
 
 
 
255
  ]
256
  );
257
 
258
- $this->add_control(
259
- 'button_icon',
260
- [
261
- 'label' => __( 'Icon', 'happy-elementor-addons' ),
262
- 'type' => Controls_Manager::ICON,
263
- 'options' => ha_get_happy_icons(),
264
- 'default' => 'fa fa-angle-right'
265
- ]
266
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
 
268
  $this->add_control(
269
  'button_icon_position',
@@ -283,9 +332,7 @@ class InfoBox extends Base {
283
  ],
284
  'default' => 'after',
285
  'toggle' => false,
286
- 'condition' => [
287
- 'button_icon!' => '',
288
- ],
289
  ]
290
  );
291
 
@@ -297,9 +344,7 @@ class InfoBox extends Base {
297
  'default' => [
298
  'size' => 10
299
  ],
300
- 'condition' => [
301
- 'button_icon!' => '',
302
- ],
303
  'selectors' => [
304
  '{{WRAPPER}} .ha-btn--icon-before .ha-btn-icon' => 'margin-right: {{SIZE}}{{UNIT}};',
305
  '{{WRAPPER}} .ha-btn--icon-after .ha-btn-icon' => 'margin-left: {{SIZE}}{{UNIT}};',
@@ -886,9 +931,9 @@ class InfoBox extends Base {
886
  <?php echo Group_Control_Image_Size::get_attachment_image_html( $settings, 'thumbnail', 'image' ); ?>
887
  </figure>
888
  <?php endif;
889
- elseif ( $settings['icon'] ) : ?>
890
  <figure class="ha-infobox-figure ha-infobox-figure--icon">
891
- <i aria-hidden="true" class="<?php echo esc_attr( $settings['icon'] ); ?>"></i>
892
  </figure>
893
  <?php endif; ?>
894
 
@@ -910,31 +955,27 @@ class InfoBox extends Base {
910
  <?php endif; ?>
911
 
912
  <?php
913
- if ( $settings['button_text'] && empty( $settings['button_icon'] ) ) :
914
  printf( '<a %1$s>%2$s</a>',
915
  $this->get_render_attribute_string( 'button' ),
916
  sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) )
917
  );
918
- elseif ( empty( $settings['button_text'] ) && $settings['button_icon'] ) :
919
- printf( '<a %1$s>%2$s</a>',
920
- $this->get_render_attribute_string( 'button' ),
921
- sprintf( '<i class="%1$s"></i>', esc_attr( $settings['button_icon'] ) )
922
- );
923
- elseif ( $settings['button_text'] && $settings['button_icon'] ) :
924
  if ( $settings['button_icon_position'] === 'before' ) :
925
  $this->add_render_attribute( 'button', 'class', 'ha-btn--icon-before' );
926
- $btn_before = sprintf( '<i class="ha-btn-icon %1$s"></i>', esc_attr( $settings['button_icon'] ) );
927
- $btn_after = sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) );
 
 
928
  else :
929
  $this->add_render_attribute( 'button', 'class', 'ha-btn--icon-after' );
930
- $btn_before = sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) );
931
- $btn_after = sprintf( '<i class="ha-btn-icon %1$s"></i>', esc_attr( $settings['button_icon'] ) );
 
 
932
  endif;
933
- printf( '<a %1$s>%2$s %3$s</a>',
934
- $this->get_render_attribute_string( 'button' ),
935
- $btn_before,
936
- $btn_after
937
- );
938
  endif;
939
  ?>
940
  </div>
@@ -944,6 +985,15 @@ class InfoBox extends Base {
944
  public function _content_template() {
945
  ?>
946
  <#
 
 
 
 
 
 
 
 
 
947
  view.addInlineEditingAttributes( 'title', 'none' );
948
  view.addRenderAttribute( 'title', 'class', 'ha-infobox-title' );
949
 
@@ -971,9 +1021,13 @@ class InfoBox extends Base {
971
  <img src="{{ image_url }}">
972
  </figure>
973
  <# }
974
- } else if (settings.icon) { #>
975
  <figure class="ha-infobox-figure ha-infobox-figure--icon">
976
- <i aria-hidden="true" class="{{ settings.icon }}"></i>
 
 
 
 
977
  </figure>
978
  <# } #>
979
 
@@ -988,19 +1042,27 @@ class InfoBox extends Base {
988
  </div>
989
  <# } #>
990
 
991
- <# if ( settings.button_text && ! settings.button_icon ) { #>
 
 
 
 
 
 
 
 
992
  <a {{{ view.getRenderAttributeString( 'button' ) }}}><span {{{ view.getRenderAttributeString( 'button_text' ) }}}>{{ settings.button_text }}</span></a>
993
- <# } else if ( ! settings.button_text && settings.button_icon ) { #>
994
- <a {{{ view.getRenderAttributeString( 'button' ) }}}><i class="{{ settings.button_icon }}"></i></a>
995
- <# } else if ( settings.button_text && settings.button_icon ) {
996
  var button_before = button_after = '';
997
  if ( settings.button_icon_position === 'before' ) {
998
  view.addRenderAttribute( 'button', 'class', 'ha-btn--icon-before' );
999
- button_before = '<i class="ha-btn-icon ' + settings.button_icon + '"></i>';
1000
  button_after = '<span ' + view.getRenderAttributeString( 'button_text' ) + '>' + settings.button_text + '</span>';
1001
  } else {
1002
  view.addRenderAttribute( 'button', 'class', 'ha-btn--icon-after' );
1003
- button_after = '<i class="ha-btn-icon ' + settings.button_icon + '"></i>';
1004
  button_before = '<span ' + view.getRenderAttributeString( 'button_text' ) + '>' + settings.button_text + '</span>';
1005
  } #>
1006
  <a {{{ view.getRenderAttributeString( 'button' ) }}}>{{{ button_before }}} {{{ button_after }}}</a>
90
  ],
91
  'condition' => [
92
  'type' => 'image'
93
+ ],
94
+ 'dynamic' => [
95
+ 'active' => true,
96
  ]
97
  ]
98
  );
117
  ]
118
  );
119
 
120
+ if ( ha_is_elementor_version( '<', '2.6.0' ) ) {
121
+ $this->add_control(
122
+ 'icon',
123
+ [
124
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
125
+ 'label_block' => true,
126
+ 'type' => Controls_Manager::ICON,
127
+ 'options' => ha_get_happy_icons(),
128
+ 'default' => 'fa fa-smile-o',
129
+ 'condition' => [
130
+ 'type' => 'icon'
131
+ ]
132
  ]
133
+ );
134
+ } else {
135
+ $this->add_control(
136
+ 'selected_icon',
137
+ [
138
+ 'type' => Controls_Manager::ICONS,
139
+ 'fa4compatibility' => 'icon',
140
+ 'label_block' => true,
141
+ 'default' => [
142
+ 'value' => 'fas fa-smile-wink',
143
+ 'library' => 'fa-solid',
144
+ ],
145
+ 'condition' => [
146
+ 'type' => 'icon'
147
+ ]
148
+ ]
149
+ );
150
+ }
151
 
152
  $this->end_controls_section();
153
 
167
  'type' => Controls_Manager::TEXT,
168
  'default' => __( 'Happy Info Box Title', 'happy-elementor-addons' ),
169
  'placeholder' => __( 'Type Info Box Title', 'happy-elementor-addons' ),
170
+ 'dynamic' => [
171
+ 'active' => true,
172
+ ]
173
  ]
174
  );
175
 
180
  'type' => Controls_Manager::TEXTAREA,
181
  'default' => __( 'Happy info box description goes here', 'happy-elementor-addons' ),
182
  'placeholder' => __( 'Type info box description', 'happy-elementor-addons' ),
183
+ 'rows' => 5,
184
+ 'dynamic' => [
185
+ 'active' => true,
186
+ ]
187
  ]
188
  );
189
 
271
  'default' => __( 'Button Text', 'happy-elementor-addons' ),
272
  'placeholder' => __( 'Type button text here', 'happy-elementor-addons' ),
273
  'label_block' => true,
274
+ 'dynamic' => [
275
+ 'active' => true,
276
+ ]
277
  ]
278
  );
279
 
282
  [
283
  'label' => __( 'Link', 'happy-elementor-addons' ),
284
  'type' => Controls_Manager::URL,
285
+ 'placeholder' => __( 'https://happyaddons.com/', 'happy-elementor-addons' ),
286
+ 'dynamic' => [
287
+ 'active' => true,
288
+ ]
289
  ]
290
  );
291
 
292
+ if ( ha_is_elementor_version( '<', '2.6.0' ) ) {
293
+ $this->add_control(
294
+ 'button_icon',
295
+ [
296
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
297
+ 'label_block' => true,
298
+ 'type' => Controls_Manager::ICON,
299
+ 'options' => ha_get_happy_icons(),
300
+ 'default' => 'fa fa-angle-right',
301
+ ]
302
+ );
303
+
304
+ $condition = ['button_icon!' => ''];
305
+ } else {
306
+ $this->add_control(
307
+ 'button_selected_icon',
308
+ [
309
+ 'type' => Controls_Manager::ICONS,
310
+ 'fa4compatibility' => 'button_icon',
311
+ 'label_block' => true,
312
+ ]
313
+ );
314
+ $condition = ['button_selected_icon[value]!' => ''];
315
+ }
316
 
317
  $this->add_control(
318
  'button_icon_position',
332
  ],
333
  'default' => 'after',
334
  'toggle' => false,
335
+ 'condition' => $condition,
 
 
336
  ]
337
  );
338
 
344
  'default' => [
345
  'size' => 10
346
  ],
347
+ 'condition' => $condition,
 
 
348
  'selectors' => [
349
  '{{WRAPPER}} .ha-btn--icon-before .ha-btn-icon' => 'margin-right: {{SIZE}}{{UNIT}};',
350
  '{{WRAPPER}} .ha-btn--icon-after .ha-btn-icon' => 'margin-left: {{SIZE}}{{UNIT}};',
931
  <?php echo Group_Control_Image_Size::get_attachment_image_html( $settings, 'thumbnail', 'image' ); ?>
932
  </figure>
933
  <?php endif;
934
+ elseif ( ! empty( $settings['icon'] ) || ! empty( $settings['selected_icon'] ) ) : ?>
935
  <figure class="ha-infobox-figure ha-infobox-figure--icon">
936
+ <?php ha_render_icon( $settings, 'icon', 'selected_icon' ); ?>
937
  </figure>
938
  <?php endif; ?>
939
 
955
  <?php endif; ?>
956
 
957
  <?php
958
+ if ( $settings['button_text'] && ( empty( $settings['button_selected_icon'] ) && empty( $settings['button_icon'] ) ) ) :
959
  printf( '<a %1$s>%2$s</a>',
960
  $this->get_render_attribute_string( 'button' ),
961
  sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) )
962
  );
963
+ elseif ( empty( $settings['button_text'] ) && ( ! empty( $settings['button_icon'] ) || ! empty( $settings['button_selected_icon'] ) ) ) : ?>
964
+ <a <?php $this->print_render_attribute_string( 'button' ); ?>><?php ha_render_icon( $settings, 'button_icon', 'button_selected_icon' ); ?></a>
965
+ <?php elseif ( $settings['button_text'] && ( ! empty( $settings['button_icon'] ) || ! empty( $settings['button_selected_icon'] ) ) ) :
 
 
 
966
  if ( $settings['button_icon_position'] === 'before' ) :
967
  $this->add_render_attribute( 'button', 'class', 'ha-btn--icon-before' );
968
+ $button_text = sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) );
969
+ ?>
970
+ <a <?php $this->print_render_attribute_string( 'button' ); ?>><?php ha_render_icon( $settings, 'button_icon', 'button_selected_icon', ['class' => 'ha-btn-icon'] ); ?> <?php echo $button_text; ?></a>
971
+ <?php
972
  else :
973
  $this->add_render_attribute( 'button', 'class', 'ha-btn--icon-after' );
974
+ $button_text = sprintf( '<span %1$s>%2$s</span>', $this->get_render_attribute_string( 'button_text' ), esc_html( $settings['button_text'] ) );
975
+ ?>
976
+ <a <?php $this->print_render_attribute_string( 'button' ); ?>><?php echo $button_text; ?> <?php ha_render_icon( $settings, 'button_icon', 'button_selected_icon', ['class' => 'ha-btn-icon'] ); ?></a>
977
+ <?php
978
  endif;
 
 
 
 
 
979
  endif;
980
  ?>
981
  </div>
985
  public function _content_template() {
986
  ?>
987
  <#
988
+ var iconHTML = migrated = btnIconHTML = btnMigrated = btnIcon = '';
989
+
990
+ if ( ha_has_icon_library() ) {
991
+ iconHTML = elementor.helpers.renderIcon( view, settings.selected_icon, { 'aria-hidden': true }, 'i' , 'object' ),
992
+ migrated = elementor.helpers.isIconMigrated( settings, 'selected_icon' );
993
+ btnIconHTML = elementor.helpers.renderIcon( view, settings.button_selected_icon, { 'aria-hidden': true, 'class': 'ha-btn-icon' }, 'i' , 'object' ),
994
+ btnMigrated = elementor.helpers.isIconMigrated( settings, 'button_selected_icon' );
995
+ }
996
+
997
  view.addInlineEditingAttributes( 'title', 'none' );
998
  view.addRenderAttribute( 'title', 'class', 'ha-infobox-title' );
999
 
1021
  <img src="{{ image_url }}">
1022
  </figure>
1023
  <# }
1024
+ } else if ( settings.icon || settings.selected_icon ) { #>
1025
  <figure class="ha-infobox-figure ha-infobox-figure--icon">
1026
+ <# if ( ha_has_icon_library() && iconHTML && iconHTML.rendered && ( ! settings.icon || migrated ) ) { #>
1027
+ {{{ iconHTML.value }}}
1028
+ <# } else { #>
1029
+ <i class="{{ settings.icon }}" aria-hidden="true"></i>
1030
+ <# } #>
1031
  </figure>
1032
  <# } #>
1033
 
1042
  </div>
1043
  <# } #>
1044
 
1045
+ <# if ( settings.button_selected_icon || settings.button_icon ) {
1046
+ if ( ha_has_icon_library() && btnIconHTML && btnIconHTML.rendered && ( ! settings.button_icon || btnMigrated ) ) {
1047
+ btnIcon = btnIconHTML.value;
1048
+ } else if ( settings.button_icon ) {
1049
+ btnIcon = '<i class="ha-btn-icon ' + settings.button_icon + '" aria-hidden="true"></i>';
1050
+ }
1051
+ } #>
1052
+
1053
+ <# if ( settings.button_text && ( ! settings.button_selected_icon && ! settings.button_icon ) ) { #>
1054
  <a {{{ view.getRenderAttributeString( 'button' ) }}}><span {{{ view.getRenderAttributeString( 'button_text' ) }}}>{{ settings.button_text }}</span></a>
1055
+ <# } else if ( ! settings.button_text && ( settings.button_selected_icon || settings.button_icon ) ) { #>
1056
+ <a {{{ view.getRenderAttributeString( 'button' ) }}}>{{{ btnIcon }}}</a>
1057
+ <# } else if ( settings.button_text && ( settings.button_selected_icon || settings.button_icon ) ) {
1058
  var button_before = button_after = '';
1059
  if ( settings.button_icon_position === 'before' ) {
1060
  view.addRenderAttribute( 'button', 'class', 'ha-btn--icon-before' );
1061
+ button_before = btnIcon;
1062
  button_after = '<span ' + view.getRenderAttributeString( 'button_text' ) + '>' + settings.button_text + '</span>';
1063
  } else {
1064
  view.addRenderAttribute( 'button', 'class', 'ha-btn--icon-after' );
1065
+ button_after = btnIcon;
1066
  button_before = '<span ' + view.getRenderAttributeString( 'button_text' ) + '>' + settings.button_text + '</span>';
1067
  } #>
1068
  <a {{{ view.getRenderAttributeString( 'button' ) }}}>{{{ button_before }}} {{{ button_after }}}</a>
widgets/member/widget.php CHANGED
@@ -113,6 +113,9 @@ class Member extends Base {
113
  'default' => [
114
  'url' => Utils::get_placeholder_image_src(),
115
  ],
 
 
 
116
  ]
117
  );
118
 
@@ -131,8 +134,11 @@ class Member extends Base {
131
  'label' => __( 'Name', 'happy-elementor-addons' ),
132
  'label_block' => true,
133
  'type' => Controls_Manager::TEXT,
134
- 'default' => __( 'Happy Member Name', 'happy-elementor-addons' ),
135
  'placeholder' => __( 'Type Member Name', 'happy-elementor-addons' ),
 
 
 
136
  ]
137
  );
138
 
@@ -144,6 +150,9 @@ class Member extends Base {
144
  'type' => Controls_Manager::TEXT,
145
  'default' => __( 'Happy Officer', 'happy-elementor-addons' ),
146
  'placeholder' => __( 'Type Member Job Title', 'happy-elementor-addons' ),
 
 
 
147
  ]
148
  );
149
 
@@ -153,7 +162,10 @@ class Member extends Base {
153
  'label' => __( 'Short Bio', 'happy-elementor-addons' ),
154
  'type' => Controls_Manager::TEXTAREA,
155
  'placeholder' => __( 'Write something amazing about the happy member', 'happy-elementor-addons' ),
156
- 'rows' => 5
 
 
 
157
  ]
158
  );
159
 
@@ -257,6 +269,9 @@ class Member extends Base {
257
  'show_external' => false,
258
  'condition' => [
259
  'name!' => 'email'
 
 
 
260
  ]
261
  ]
262
  );
@@ -270,6 +285,9 @@ class Member extends Base {
270
  'input_type' => 'email',
271
  'condition' => [
272
  'name' => 'email'
 
 
 
273
  ]
274
  ]
275
  );
113
  'default' => [
114
  'url' => Utils::get_placeholder_image_src(),
115
  ],
116
+ 'dynamic' => [
117
+ 'active' => true,
118
+ ]
119
  ]
120
  );
121
 
134
  'label' => __( 'Name', 'happy-elementor-addons' ),
135
  'label_block' => true,
136
  'type' => Controls_Manager::TEXT,
137
+ 'default' => 'Happy Member Name',
138
  'placeholder' => __( 'Type Member Name', 'happy-elementor-addons' ),
139
+ 'dynamic' => [
140
+ 'active' => true,
141
+ ]
142
  ]
143
  );
144
 
150
  'type' => Controls_Manager::TEXT,
151
  'default' => __( 'Happy Officer', 'happy-elementor-addons' ),
152
  'placeholder' => __( 'Type Member Job Title', 'happy-elementor-addons' ),
153
+ 'dynamic' => [
154
+ 'active' => true,
155
+ ]
156
  ]
157
  );
158
 
162
  'label' => __( 'Short Bio', 'happy-elementor-addons' ),
163
  'type' => Controls_Manager::TEXTAREA,
164
  'placeholder' => __( 'Write something amazing about the happy member', 'happy-elementor-addons' ),
165
+ 'rows' => 5,
166
+ 'dynamic' => [
167
+ 'active' => true,
168
+ ]
169
  ]
170
  );
171
 
269
  'show_external' => false,
270
  'condition' => [
271
  'name!' => 'email'
272
+ ],
273
+ 'dynamic' => [
274
+ 'active' => true,
275
  ]
276
  ]
277
  );
285
  'input_type' => 'email',
286
  'condition' => [
287
  'name' => 'email'
288
+ ],
289
+ 'dynamic' => [
290
+ 'active' => true,
291
  ]
292
  ]
293
  );
widgets/number/widget.php CHANGED
@@ -68,7 +68,10 @@ class Number extends Base {
68
  'label' => __( 'Text', 'happy-elementor-addons' ),
69
  'label_block' => false,
70
  'type' => Controls_Manager::TEXT,
71
- 'default' => 7
 
 
 
72
  ]
73
  );
74
 
68
  'label' => __( 'Text', 'happy-elementor-addons' ),
69
  'label_block' => false,
70
  'type' => Controls_Manager::TEXT,
71
+ 'default' => 7,
72
+ 'dynamic' => [
73
+ 'active' => true,
74
+ ]
75
  ]
76
  );
77
 
widgets/pricing-table/widget.php CHANGED
@@ -6,16 +6,12 @@
6
  */
7
  namespace Happy_Addons\Elementor\Widget;
8
 
9
- use Elementor\Group_Control_Css_Filter;
10
  use Elementor\Group_Control_Text_Shadow;
11
  use Elementor\Repeater;
12
  use Elementor\Scheme_Typography;
13
- use Elementor\Utils;
14
- use Elementor\Control_Media;
15
  use Elementor\Controls_Manager;
16
  use Elementor\Group_Control_Border;
17
  use Elementor\Group_Control_Box_Shadow;
18
- use Elementor\Group_Control_Image_Size;
19
  use Elementor\Group_Control_Typography;
20
 
21
  defined( 'ABSPATH' ) || die();
@@ -66,6 +62,9 @@ class Pricing_Table extends Base {
66
  'type' => Controls_Manager::TEXT,
67
  'label_block' => false,
68
  'default' => __( 'Basic', 'happy-elementor-addons' ),
 
 
 
69
  ]
70
  );
71
 
@@ -108,6 +107,9 @@ class Pricing_Table extends Base {
108
  'custom' => __( 'Custom', 'happy-elementor-addons' ),
109
  ],
110
  'default' => 'dollar',
 
 
 
111
  ]
112
  );
113
 
@@ -128,6 +130,9 @@ class Pricing_Table extends Base {
128
  'label' => __( 'Price', 'happy-elementor-addons' ),
129
  'type' => Controls_Manager::TEXT,
130
  'default' => '9.99',
 
 
 
131
  ]
132
  );
133
 
@@ -137,6 +142,9 @@ class Pricing_Table extends Base {
137
  'label' => __( 'Period', 'happy-elementor-addons' ),
138
  'type' => Controls_Manager::TEXT,
139
  'default' => __( 'Per Month', 'happy-elementor-addons' ),
 
 
 
140
  ]
141
  );
142
 
@@ -156,6 +164,9 @@ class Pricing_Table extends Base {
156
  'type' => Controls_Manager::TEXT,
157
  'default' => __( 'Features', 'happy-elementor-addons' ),
158
  'separator' => 'after',
 
 
 
159
  ]
160
  );
161
 
@@ -167,21 +178,50 @@ class Pricing_Table extends Base {
167
  'label' => __( 'Text', 'elementor-pro' ),
168
  'type' => Controls_Manager::TEXT,
169
  'default' => __( 'Exciting Feature', 'elementor-pro' ),
 
 
 
170
  ]
171
  );
172
 
173
- $repeater->add_control(
174
- 'icon',
175
- [
176
- 'label' => __( 'Icon', 'elementor-pro' ),
177
- 'type' => Controls_Manager::ICON,
178
- 'default' => 'fa fa-check',
179
- 'include' => [
180
- 'fa fa-check',
181
- 'fa fa-close',
 
 
 
 
182
  ]
183
- ]
184
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
 
186
  $this->add_control(
187
  'features_list',
@@ -229,6 +269,9 @@ class Pricing_Table extends Base {
229
  'default' => __( 'Subscribe', 'happy-elementor-addons' ),
230
  'placeholder' => __( 'Type button text here', 'happy-elementor-addons' ),
231
  'label_block' => false,
 
 
 
232
  ]
233
  );
234
 
@@ -238,7 +281,7 @@ class Pricing_Table extends Base {
238
  'label' => __( 'Link', 'happy-elementor-addons' ),
239
  'type' => Controls_Manager::URL,
240
  'label_block' => true,
241
- 'placeholder' => __( 'https://example.com/', 'happy-elementor-addons' ),
242
  'dynamic' => [
243
  'active' => true,
244
  ],
@@ -299,6 +342,9 @@ class Pricing_Table extends Base {
299
  'placeholder' => __( 'Type badge text', 'happy-elementor-addons' ),
300
  'condition' => [
301
  'show_badge' => 'yes'
 
 
 
302
  ]
303
  ]
304
  );
@@ -948,9 +994,9 @@ class Pricing_Table extends Base {
948
  $this->add_render_attribute( $name_key, 'class', 'ha-pricing-table-feature-text' );
949
  ?>
950
  <li class="<?php echo esc_attr( 'elementor-repeater-item-' . $feature['_id'] ); ?>">
951
- <?php if ( $feature['icon'] ) : ?>
952
- <i class="<?php echo esc_attr( $feature['icon'] ); ?>"></i>
953
- <?php endif; ?>
954
  <span <?php $this->print_render_attribute_string( $name_key ); ?>><?php echo $feature['text']; ?></span>
955
  </li>
956
  <?php endforeach; ?>
6
  */
7
  namespace Happy_Addons\Elementor\Widget;
8
 
 
9
  use Elementor\Group_Control_Text_Shadow;
10
  use Elementor\Repeater;
11
  use Elementor\Scheme_Typography;
 
 
12
  use Elementor\Controls_Manager;
13
  use Elementor\Group_Control_Border;
14
  use Elementor\Group_Control_Box_Shadow;
 
15
  use Elementor\Group_Control_Typography;
16
 
17
  defined( 'ABSPATH' ) || die();
62
  'type' => Controls_Manager::TEXT,
63
  'label_block' => false,
64
  'default' => __( 'Basic', 'happy-elementor-addons' ),
65
+ 'dynamic' => [
66
+ 'active' => true
67
+ ]
68
  ]
69
  );
70
 
107
  'custom' => __( 'Custom', 'happy-elementor-addons' ),
108
  ],
109
  'default' => 'dollar',
110
+ 'dynamic' => [
111
+ 'active' => true
112
+ ]
113
  ]
114
  );
115
 
130
  'label' => __( 'Price', 'happy-elementor-addons' ),
131
  'type' => Controls_Manager::TEXT,
132
  'default' => '9.99',
133
+ 'dynamic' => [
134
+ 'active' => true
135
+ ]
136
  ]
137
  );
138
 
142
  'label' => __( 'Period', 'happy-elementor-addons' ),
143
  'type' => Controls_Manager::TEXT,
144
  'default' => __( 'Per Month', 'happy-elementor-addons' ),
145
+ 'dynamic' => [
146
+ 'active' => true
147
+ ]
148
  ]
149
  );
150
 
164
  'type' => Controls_Manager::TEXT,
165
  'default' => __( 'Features', 'happy-elementor-addons' ),
166
  'separator' => 'after',
167
+ 'dynamic' => [
168
+ 'active' => true
169
+ ]
170
  ]
171
  );
172
 
178
  'label' => __( 'Text', 'elementor-pro' ),
179
  'type' => Controls_Manager::TEXT,
180
  'default' => __( 'Exciting Feature', 'elementor-pro' ),
181
+ 'dynamic' => [
182
+ 'active' => true
183
+ ]
184
  ]
185
  );
186
 
187
+ if ( ha_is_elementor_version( '<', '2.6.0' ) ) {
188
+ $repeater->add_control(
189
+ 'icon',
190
+ [
191
+ 'label' => __( 'Icon', 'elementor-pro' ),
192
+ 'type' => Controls_Manager::ICON,
193
+ 'label_block' => false,
194
+ 'options' => ha_get_happy_icons(),
195
+ 'default' => 'fa fa-check',
196
+ 'include' => [
197
+ 'fa fa-check',
198
+ 'fa fa-close',
199
+ ]
200
  ]
201
+ );
202
+ } else {
203
+ $repeater->add_control(
204
+ 'selected_icon',
205
+ [
206
+ 'label' => __( 'Icon', 'elementor-pro' ),
207
+ 'type' => Controls_Manager::ICONS,
208
+ 'fa4compatibility' => 'icon',
209
+ 'default' => [
210
+ 'value' => 'fas fa-check',
211
+ 'library' => 'fa-solid',
212
+ ],
213
+ 'recommended' => [
214
+ 'fa-regular' => [
215
+ 'check-square',
216
+ 'window-close',
217
+ ],
218
+ 'fa-solid' => [
219
+ 'check',
220
+ ]
221
+ ]
222
+ ]
223
+ );
224
+ }
225
 
226
  $this->add_control(
227
  'features_list',
269
  'default' => __( 'Subscribe', 'happy-elementor-addons' ),
270
  'placeholder' => __( 'Type button text here', 'happy-elementor-addons' ),
271
  'label_block' => false,
272
+ 'dynamic' => [
273
+ 'active' => true
274
+ ]
275
  ]
276
  );
277
 
281
  'label' => __( 'Link', 'happy-elementor-addons' ),
282
  'type' => Controls_Manager::URL,
283
  'label_block' => true,
284
+ 'placeholder' => 'https://happyaddons.com/',
285
  'dynamic' => [
286
  'active' => true,
287
  ],
342
  'placeholder' => __( 'Type badge text', 'happy-elementor-addons' ),
343
  'condition' => [
344
  'show_badge' => 'yes'
345
+ ],
346
+ 'dynamic' => [
347
+ 'active' => true
348
  ]
349
  ]
350
  );
994
  $this->add_render_attribute( $name_key, 'class', 'ha-pricing-table-feature-text' );
995
  ?>
996
  <li class="<?php echo esc_attr( 'elementor-repeater-item-' . $feature['_id'] ); ?>">
997
+ <?php if ( ! empty( $feature['icon'] ) || ! empty( $feature['selected_icon'] ) ) :
998
+ ha_render_icon( $feature, 'icon', 'selected_icon' );
999
+ endif; ?>
1000
  <span <?php $this->print_render_attribute_string( $name_key ); ?>><?php echo $feature['text']; ?></span>
1001
  </li>
1002
  <?php endforeach; ?>
widgets/review/widget.php CHANGED
@@ -14,6 +14,7 @@ use Elementor\Group_Control_Border;
14
  use Elementor\Group_Control_Box_Shadow;
15
  use Elementor\Group_Control_Image_Size;
16
  use Elementor\Group_Control_Typography;
 
17
 
18
  defined( 'ABSPATH' ) || die();
19
 
@@ -49,18 +50,92 @@ class Review extends Base {
49
 
50
  protected function register_content_controls() {
51
  $this->start_controls_section(
52
- '_section_content',
53
  [
54
- 'label' => __( 'Content', 'happy-elementor-addons' ),
55
  'tab' => Controls_Manager::TAB_CONTENT,
56
  ]
57
  );
58
 
59
- $this->start_controls_tabs( '_tab_content' );
60
- $this->start_controls_tab(
61
- '_tab_reviewer',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  [
63
  'label' => __( 'Reviewer', 'happy-elementor-addons' ),
 
64
  ]
65
  );
66
 
@@ -72,6 +147,9 @@ class Review extends Base {
72
  'default' => [
73
  'url' => Utils::get_placeholder_image_src(),
74
  ],
 
 
 
75
  ]
76
  );
77
 
@@ -80,8 +158,11 @@ class Review extends Base {
80
  [
81
  'label' => __( 'Name', 'happy-elementor-addons' ),
82
  'type' => Controls_Manager::TEXT,
83
- 'default' => __( 'Happy Reviewer', 'happy-elementor-addons' ),
84
  'placeholder' => __( 'Type Reviewer Name', 'happy-elementor-addons' ),
 
 
 
85
  ]
86
  );
87
 
@@ -92,6 +173,9 @@ class Review extends Base {
92
  'type' => Controls_Manager::TEXT,
93
  'default' => __( 'Happy Officer', 'happy-elementor-addons' ),
94
  'placeholder' => __( 'Type Reviewer Job Title', 'happy-elementor-addons' ),
 
 
 
95
  ]
96
  );
97
 
@@ -100,7 +184,7 @@ class Review extends Base {
100
  [
101
  'name' => 'thumbnail',
102
  'default' => 'large',
103
- 'separator' => 'none',
104
  ]
105
  );
106
 
@@ -130,101 +214,11 @@ class Review extends Base {
130
  ]
131
  );
132
 
133
- $this->add_control(
134
- 'title_tag',
135
- [
136
- 'label' => __( 'Name HTML Tag', 'happy-elementor-addons' ),
137
- 'type' => Controls_Manager::CHOOSE,
138
- 'options' => [
139
- 'h1' => [
140
- 'title' => __( 'H1', 'happy-elementor-addons' ),
141
- 'icon' => 'eicon-editor-h1'
142
- ],
143
- 'h2' => [
144
- 'title' => __( 'H2', 'happy-elementor-addons' ),
145
- 'icon' => 'eicon-editor-h2'
146
- ],
147
- 'h3' => [
148
- 'title' => __( 'H3', 'happy-elementor-addons' ),
149
- 'icon' => 'eicon-editor-h3'
150
- ],
151
- 'h4' => [
152
- 'title' => __( 'H4', 'happy-elementor-addons' ),
153
- 'icon' => 'eicon-editor-h4'
154
- ],
155
- 'h5' => [
156
- 'title' => __( 'H5', 'happy-elementor-addons' ),
157
- 'icon' => 'eicon-editor-h5'
158
- ],
159
- 'h6' => [
160
- 'title' => __( 'H6', 'happy-elementor-addons' ),
161
- 'icon' => 'eicon-editor-h6'
162
- ]
163
- ],
164
- 'default' => 'h2',
165
- 'toggle' => false,
166
- ]
167
- );
168
-
169
- $this->end_controls_tab();
170
-
171
- $this->start_controls_tab(
172
- '_tab_review',
173
- [
174
- 'label' => __( 'Review', 'happy-elementor-addons' ),
175
- ]
176
- );
177
- $this->add_control(
178
- 'ratting',
179
- [
180
- 'label' => __( 'Ratting', 'happy-elementor-addons' ),
181
- 'type' => Controls_Manager::SLIDER,
182
- 'default' => [
183
- 'unit' => 'px',
184
- 'size' => 4.2,
185
- ],
186
- 'size_units' => [ 'px' ],
187
- 'range' => [
188
- 'px' => [
189
- 'min' => 0,
190
- 'max' => 5,
191
- 'step' => .1,
192
- ],
193
- ],
194
- ]
195
- );
196
-
197
- $this->add_control(
198
- 'ratting_style',
199
- [
200
- 'label' => __( 'Style', 'happy-elementor-addons' ),
201
- 'type' => Controls_Manager::SELECT,
202
- 'options' => [
203
- 'star' => __( 'Star Rating', 'happy-elementor-addons' ),
204
- 'num' => __( 'Number Rating', 'happy-elementor-addons' ),
205
- ],
206
- 'default' => 'star',
207
- ]
208
- );
209
-
210
- $this->add_control(
211
- 'review',
212
- [
213
- 'label' => __( 'Review', 'happy-elementor-addons' ),
214
- 'type' => Controls_Manager::TEXTAREA,
215
- 'default' => __( 'Happy reviewer is super excited being part of happy addons family', 'happy-elementor-addons' ),
216
- 'placeholder' => __( 'Type amazing review from happy reviewer', 'happy-elementor-addons' ),
217
- ]
218
- );
219
- $this->end_controls_tab();
220
- $this->end_controls_tabs();
221
-
222
  $this->add_responsive_control(
223
  'align',
224
  [
225
  'label' => __( 'Alignment', 'happy-elementor-addons' ),
226
  'type' => Controls_Manager::CHOOSE,
227
- 'separator' => 'before',
228
  'options' => [
229
  'left' => [
230
  'title' => __( 'Left', 'happy-elementor-addons' ),
@@ -251,15 +245,38 @@ class Review extends Base {
251
  );
252
 
253
  $this->add_control(
254
- 'review_position',
255
  [
256
- 'label' => __( 'Review Position', 'happy-elementor-addons' ),
257
- 'type' => Controls_Manager::SELECT,
258
  'options' => [
259
- 'before' => __( 'Review Before', 'happy-elementor-addons' ),
260
- 'after' => __( 'Review After', 'happy-elementor-addons' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  ],
262
- 'default' => 'before',
 
263
  ]
264
  );
265
 
@@ -268,129 +285,67 @@ class Review extends Base {
268
 
269
  protected function register_style_controls() {
270
  $this->start_controls_section(
271
- '_section_photo_style',
272
  [
273
- 'label' => __( 'Photo', 'happy-elementor-addons' ),
274
  'tab' => Controls_Manager::TAB_STYLE,
275
  ]
276
  );
277
 
278
  $this->add_responsive_control(
279
- 'image_width',
280
  [
281
- 'label' => __( 'Width', 'happy-elementor-addons' ),
282
  'type' => Controls_Manager::SLIDER,
283
- 'size_units' => [ 'px', '%' ],
284
- 'range' => [
285
- 'px' => [
286
- 'min' => 70,
287
- 'max' => 500,
288
- ],
289
- '%' => [
290
- 'min' => 10,
291
- 'max' => 100,
292
- ],
293
- ],
294
  'selectors' => [
295
- '{{WRAPPER}} .ha-review-figure' => 'flex: 0 0 {{SIZE}}{{UNIT}}; max-width: {{SIZE}}{{UNIT}};',
296
- '{{WRAPPER}}.ha-review--right .ha-review-body, {{WRAPPER}}.ha-review--left .ha-review-body' => 'flex: 0 0 calc(100% - {{SIZE || 150}}{{UNIT}}); max-width: calc(100% - {{SIZE || 150}}{{UNIT}});',
297
  ],
298
  ]
299
  );
300
 
301
  $this->add_responsive_control(
302
- 'image_height',
303
  [
304
- 'label' => __( 'Height', 'happy-elementor-addons' ),
305
  'type' => Controls_Manager::SLIDER,
306
- 'size_units' => [ 'px' ],
307
- 'range' => [
308
- 'px' => [
309
- 'min' => 70,
310
- 'max' => 500,
311
- ],
312
- ],
313
  'selectors' => [
314
- '{{WRAPPER}} .ha-review-figure' => 'height: {{SIZE}}{{UNIT}};',
315
  ],
316
  ]
317
  );
318
 
319
- $this->add_control(
320
- 'offset_toggle',
321
- [
322
- 'label' => __( 'Offset', 'happy-elementor-addons' ),
323
- 'type' => Controls_Manager::POPOVER_TOGGLE,
324
- 'label_off' => __( 'None', 'your-plugin' ),
325
- 'label_on' => __( 'Custom', 'your-plugin' ),
326
- 'return_value' => 'yes',
327
- ]
328
- );
329
-
330
- $this->start_popover();
331
-
332
  $this->add_responsive_control(
333
- 'image_offset_x',
334
  [
335
- 'label' => __( 'Offset X', 'happy-elementor-addons' ),
336
- 'type' => Controls_Manager::SLIDER,
337
- 'size_units' => ['px'],
338
- 'condition' => [
339
- 'offset_toggle' => 'yes'
340
- ],
341
- 'range' => [
342
- 'px' => [
343
- 'min' => -1000,
344
- 'max' => 1000,
345
- ],
346
  ],
347
- 'render_type' => 'ui'
348
  ]
349
  );
350
 
351
- $this->add_responsive_control(
352
- 'image_offset_y',
353
  [
354
- 'label' => __( 'Offset Y', 'happy-elementor-addons' ),
355
- 'type' => Controls_Manager::SLIDER,
356
- 'size_units' => ['px'],
357
- 'condition' => [
358
- 'offset_toggle' => 'yes'
359
- ],
360
- 'range' => [
361
- 'px' => [
362
- 'min' => -1000,
363
- 'max' => 1000,
364
- ],
365
- ],
366
  'selectors' => [
367
- // Left image position styles
368
- '(desktop){{WRAPPER}}.ha-review--left .ha-review-body' => 'margin-left: {{image_offset_x.SIZE || 0}}{{UNIT}}; flex: 0 0 calc((100% - {{image_width.SIZE || 150}}{{image_width.UNIT}}) + (-1 * {{image_offset_x.SIZE || 0}}{{UNIT}})); max-width: calc((100% - {{image_width.SIZE || 150}}{{image_width.UNIT}}) + (-1 * {{image_offset_x.SIZE || 0}}{{UNIT}}));',
369
- '(tablet){{WRAPPER}}.ha-review--left .ha-review-body' => 'margin-left: {{image_offset_x_tablet.SIZE || 0}}{{UNIT}}; flex: 0 0 calc((100% - {{image_width_tablet.SIZE || 150}}{{image_width_tablet.UNIT}}) + (-1 * {{image_offset_x_tablet.SIZE || 0}}{{UNIT}})); max-width: calc((100% - {{image_width_tablet.SIZE || 150}}{{image_width_tablet.UNIT}}) + (-1 * {{image_offset_x_tablet.SIZE || 0}}{{UNIT}}));',
370
- '(mobile){{WRAPPER}}.ha-review--left .ha-review-body' => 'margin-left: {{image_offset_x_mobile.SIZE || 0}}{{UNIT}}; flex: 0 0 calc((100% - {{image_width_mobile.SIZE || 150}}{{image_width_mobile.UNIT}}) + (-1 * {{image_offset_x_mobile.SIZE || 0}}{{UNIT}})); max-width: calc((100% - {{image_width_mobile.SIZE || 150}}{{image_width_mobile.UNIT}}) + (-1 * {{image_offset_x_mobile.SIZE || 0}}{{UNIT}}));',
371
- // Image right position styles
372
- '(desktop){{WRAPPER}}.ha-review--right .ha-review-body' => 'margin-right: calc(-1 * {{image_offset_x.SIZE || 0}}{{UNIT}}); flex: 0 0 calc((100% - {{image_width.SIZE || 150}}{{image_width.UNIT}}) + {{image_offset_x.SIZE || 0}}{{UNIT}}); max-width: calc((100% - {{image_width.SIZE || 150}}{{image_width.UNIT}}) + {{image_offset_x.SIZE || 0}}{{UNIT}});',
373
- '(tablet){{WRAPPER}}.ha-review--right .ha-review-body' => 'margin-right: calc(-1 * {{image_offset_x_tablet.SIZE || 0}}{{UNIT}}); flex: 0 0 calc((100% - {{image_width_tablet.SIZE || 150}}{{image_width_tablet.UNIT}}) + {{image_offset_x_tablet.SIZE || 0}}{{UNIT}}); max-width: calc((100% - {{image_width_tablet.SIZE || 150}}{{image_width_tablet.UNIT}}) + {{image_offset_x_tablet.SIZE || 0}}{{UNIT}});',
374
- '(mobile){{WRAPPER}}.ha-review--right .ha-review-body' => 'margin-right: calc(-1 * {{image_offset_x_mobile.SIZE || 0}}{{UNIT}}); flex: 0 0 calc((100% - {{image_width_mobile.SIZE || 150}}{{image_width_mobile.UNIT}}) + {{image_offset_x_mobile.SIZE || 0}}{{UNIT}}); max-width: calc((100% - {{image_width_mobile.SIZE || 150}}{{image_width_mobile.UNIT}}) + {{image_offset_x_mobile.SIZE || 0}}{{UNIT}});',
375
- // Image translate styles
376
- '(desktop){{WRAPPER}} .ha-review-figure' => '-ms-transform: translate({{image_offset_x.SIZE || 0}}{{UNIT}}, {{image_offset_y.SIZE || 0}}{{UNIT}}); -webkit-transform: translate({{image_offset_x.SIZE || 0}}{{UNIT}}, {{image_offset_y.SIZE || 0}}{{UNIT}}); transform: translate({{image_offset_x.SIZE || 0}}{{UNIT}}, {{image_offset_y.SIZE || 0}}{{UNIT}});',
377
- '(tablet){{WRAPPER}} .ha-review-figure' => '-ms-transform: translate({{image_offset_x_tablet.SIZE || 0}}{{UNIT}}, {{image_offset_y_tablet.SIZE || 0}}{{UNIT}}); -webkit-transform: translate({{image_offset_x_tablet.SIZE || 0}}{{UNIT}}, {{image_offset_y_tablet.SIZE || 0}}{{UNIT}}); transform: translate({{image_offset_x_tablet.SIZE || 0}}{{UNIT}}, {{image_offset_y_tablet.SIZE || 0}}{{UNIT}});',
378
- '(mobile){{WRAPPER}} .ha-review-figure' => '-ms-transform: translate({{image_offset_x_mobile.SIZE || 0}}{{UNIT}}, {{image_offset_y_mobile.SIZE || 0}}{{UNIT}}); -webkit-transform: translate({{image_offset_x_mobile.SIZE || 0}}{{UNIT}}, {{image_offset_y_mobile.SIZE || 0}}{{UNIT}}); transform: translate({{image_offset_x_mobile.SIZE || 0}}{{UNIT}}, {{image_offset_y_mobile.SIZE || 0}}{{UNIT}});',
379
- // Review body styles
380
- '{{WRAPPER}}.ha-review--top .ha-review-body' => 'margin-top: {{SIZE}}{{UNIT}};',
381
  ],
382
  ]
383
  );
384
- $this->end_popover();
385
 
386
- $this->add_responsive_control(
387
- 'image_padding',
388
  [
389
- 'label' => __( 'Padding', 'happy-elementor-addons' ),
390
- 'type' => Controls_Manager::DIMENSIONS,
391
- 'size_units' => [ 'px', 'em', '%' ],
392
  'selectors' => [
393
- '{{WRAPPER}} .ha-review-figure > img' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
394
  ],
395
  ]
396
  );
@@ -398,31 +353,20 @@ class Review extends Base {
398
  $this->add_group_control(
399
  Group_Control_Border::get_type(),
400
  [
401
- 'name' => 'image_border',
402
- 'selector' => '{{WRAPPER}} .ha-review-figure > img',
403
  ]
404
  );
405
 
406
- $this->add_responsive_control(
407
- 'image_border_radius',
408
  [
409
  'label' => __( 'Border Radius', 'happy-elementor-addons' ),
410
  'type' => Controls_Manager::DIMENSIONS,
411
  'size_units' => [ 'px', '%' ],
412
  'selectors' => [
413
- '{{WRAPPER}} .ha-review-figure > img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
414
- ],
415
- ]
416
- );
417
-
418
- $this->add_group_control(
419
- Group_Control_Box_Shadow::get_type(),
420
- [
421
- 'name' => 'image_box_shadow',
422
- 'exclude' => [
423
- 'box_shadow_position',
424
  ],
425
- 'selector' => '{{WRAPPER}} .ha-review-figure > img',
426
  ]
427
  );
428
 
@@ -431,7 +375,7 @@ class Review extends Base {
431
  $this->start_controls_section(
432
  '_section_review_style',
433
  [
434
- 'label' => __( 'Review', 'happy-elementor-addons' ),
435
  'tab' => Controls_Manager::TAB_STYLE,
436
  ]
437
  );
@@ -574,67 +518,129 @@ class Review extends Base {
574
  $this->end_controls_section();
575
 
576
  $this->start_controls_section(
577
- '_section_ratting_style',
578
  [
579
- 'label' => __( 'Ratting', 'happy-elementor-addons' ),
580
  'tab' => Controls_Manager::TAB_STYLE,
581
  ]
582
  );
583
 
584
  $this->add_responsive_control(
585
- 'ratting_size',
586
  [
587
- 'label' => __( 'Size', 'happy-elementor-addons' ),
588
  'type' => Controls_Manager::SLIDER,
589
- 'size_units' => ['px'],
 
 
 
 
 
 
 
 
 
 
590
  'selectors' => [
591
- '{{WRAPPER}} .ha-review-ratting' => 'font-size: {{SIZE}}{{UNIT}};',
 
592
  ],
593
  ]
594
  );
595
 
596
  $this->add_responsive_control(
597
- 'ratting_spacing',
598
  [
599
- 'label' => __( 'Bottom Spacing', 'happy-elementor-addons' ),
600
  'type' => Controls_Manager::SLIDER,
601
- 'size_units' => ['px'],
 
 
 
 
 
 
602
  'selectors' => [
603
- '{{WRAPPER}} .ha-review-ratting' => 'margin-bottom: {{SIZE}}{{UNIT}};',
604
  ],
605
  ]
606
  );
607
 
 
 
 
 
 
 
 
 
 
 
 
 
 
608
  $this->add_responsive_control(
609
- 'ratting_padding',
610
  [
611
- 'label' => __( 'Padding', 'happy-elementor-addons' ),
612
- 'type' => Controls_Manager::DIMENSIONS,
613
- 'size_units' => [ 'px', 'em', '%' ],
614
- 'selectors' => [
615
- '{{WRAPPER}} .ha-review-ratting' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
616
  ],
 
 
 
 
 
 
 
617
  ]
618
  );
619
 
620
- $this->add_control(
621
- 'ratting_color',
622
  [
623
- 'label' => __( 'Text Color', 'happy-elementor-addons' ),
624
- 'type' => Controls_Manager::COLOR,
 
 
 
 
 
 
 
 
 
 
625
  'selectors' => [
626
- '{{WRAPPER}} .ha-review-ratting' => 'color: {{VALUE}}',
 
 
 
 
 
 
 
 
 
 
 
 
 
627
  ],
628
  ]
629
  );
 
630
 
631
- $this->add_control(
632
- 'ratting_bg_color',
633
  [
634
- 'label' => __( 'Background Color', 'happy-elementor-addons' ),
635
- 'type' => Controls_Manager::COLOR,
 
636
  'selectors' => [
637
- '{{WRAPPER}} .ha-review-ratting' => 'background-color: {{VALUE}}',
638
  ],
639
  ]
640
  );
@@ -642,42 +648,66 @@ class Review extends Base {
642
  $this->add_group_control(
643
  Group_Control_Border::get_type(),
644
  [
645
- 'name' => 'ratting_border',
646
- 'selector' => '{{WRAPPER}} .ha-review-ratting',
647
  ]
648
  );
649
 
650
- $this->add_control(
651
- 'ratting_border_radius',
652
  [
653
  'label' => __( 'Border Radius', 'happy-elementor-addons' ),
654
  'type' => Controls_Manager::DIMENSIONS,
655
  'size_units' => [ 'px', '%' ],
656
  'selectors' => [
657
- '{{WRAPPER}} .ha-review-ratting' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
658
  ],
659
  ]
660
  );
661
 
 
 
 
 
 
 
 
 
 
 
 
662
  $this->end_controls_section();
663
  }
664
 
665
  protected function render() {
666
  $settings = $this->get_settings_for_display();
667
 
 
 
 
668
  $this->add_inline_editing_attributes( 'title', 'none' );
669
  $this->add_render_attribute( 'title', 'class', 'ha-review-reviewer' );
 
 
 
670
 
671
  $this->add_inline_editing_attributes( 'job_title', 'none' );
672
  $this->add_render_attribute( 'job_title', 'class', 'ha-review-position' );
673
 
674
  $this->add_inline_editing_attributes( 'review', 'basic' );
675
  $this->add_render_attribute( 'review', 'class', 'ha-review-desc' );
 
676
 
677
  $this->add_render_attribute( 'ratting', 'class', [
678
  'ha-review-ratting',
679
  'ha-review-ratting--' . $settings['ratting_style']
680
  ] );
 
 
 
 
 
 
681
  ?>
682
 
683
  <?php if ( $settings['image']['url'] || $settings['image']['id'] ) :
@@ -712,11 +742,19 @@ class Review extends Base {
712
  <?php endif; ?>
713
 
714
  <div <?php echo $this->get_render_attribute_string( 'ratting' ); ?>>
 
 
715
  <?php if ( $settings['ratting_style'] === 'num' ) : ?>
716
- <?php echo esc_html( $settings['ratting']['size'] ); ?> <i class="fa fa-star"></i>
717
- <?php else : ?>
718
- <span><span style="width:<?php echo ($settings['ratting']['size'] * 20); ?>%"></span></span>
719
- <?php endif; ?>
 
 
 
 
 
 
720
  </div>
721
  </div>
722
 
@@ -726,6 +764,10 @@ class Review extends Base {
726
  </div>
727
  <?php endif; ?>
728
  </div>
 
 
 
 
729
  <?php
730
  }
731
 
@@ -741,6 +783,8 @@ class Review extends Base {
741
  view.addInlineEditingAttributes( 'review', 'basic' );
742
  view.addRenderAttribute( 'review', 'class', 'ha-review-desc' );
743
 
 
 
744
  if (settings.image.url || settings.image.id) {
745
  var image = {
746
  id: settings.image.id,
@@ -771,10 +815,16 @@ class Review extends Base {
771
  <div {{{ view.getRenderAttributeString( 'job_title' ) }}}>{{ settings.job_title }}</div>
772
  <# } #>
773
  <# if ( settings.ratting_style === 'num' ) { #>
774
- <div class="ha-review-ratting ha-review-ratting--num">{{ settings.ratting.size }} <i class="fa fa-star"></i></div>
775
- <# } else { var ratingPercent = ( settings.ratting.size * 20 ) #>
776
  <div class="ha-review-ratting ha-review-ratting--star">
777
- <span><span style="width:{{ ratingPercent }}%"></span></span>
 
 
 
 
 
 
778
  </div>
779
  <# } #>
780
  </div>
@@ -786,4 +836,5 @@ class Review extends Base {
786
  </div>
787
  <?php
788
  }
 
789
  }
14
  use Elementor\Group_Control_Box_Shadow;
15
  use Elementor\Group_Control_Image_Size;
16
  use Elementor\Group_Control_Typography;
17
+ use ParagonIE\Sodium\Core\Curve25519\Ge\P3;
18
 
19
  defined( 'ABSPATH' ) || die();
20
 
50
 
51
  protected function register_content_controls() {
52
  $this->start_controls_section(
53
+ '_section_review',
54
  [
55
+ 'label' => __( 'Review', 'happy-elementor-addons' ),
56
  'tab' => Controls_Manager::TAB_CONTENT,
57
  ]
58
  );
59
 
60
+ $this->add_control(
61
+ 'ratting',
62
+ [
63
+ 'label' => __( 'Ratting', 'happy-elementor-addons' ),
64
+ 'type' => Controls_Manager::SLIDER,
65
+ 'default' => [
66
+ 'unit' => 'px',
67
+ 'size' => 4.2,
68
+ ],
69
+ 'size_units' => [ 'px' ],
70
+ 'range' => [
71
+ 'px' => [
72
+ 'min' => 0,
73
+ 'max' => 5,
74
+ 'step' => .5,
75
+ ],
76
+ ],
77
+ 'dynamic' => [
78
+ 'active' => true,
79
+ ]
80
+ ]
81
+ );
82
+
83
+ $this->add_control(
84
+ 'ratting_style',
85
+ [
86
+ 'label' => __( 'Style', 'happy-elementor-addons' ),
87
+ 'type' => Controls_Manager::SELECT,
88
+ 'options' => [
89
+ 'star' => __( 'Star Rating', 'happy-elementor-addons' ),
90
+ 'num' => __( 'Number Rating', 'happy-elementor-addons' ),
91
+ ],
92
+ 'default' => 'star',
93
+ ]
94
+ );
95
+
96
+ $this->add_control(
97
+ 'review',
98
+ [
99
+ 'label' => __( 'Review', 'happy-elementor-addons' ),
100
+ 'type' => Controls_Manager::TEXTAREA,
101
+ 'default' => __( 'Happy reviewer is super excited being part of happy addons family', 'happy-elementor-addons' ),
102
+ 'placeholder' => __( 'Type amazing review from happy reviewer', 'happy-elementor-addons' ),
103
+ 'dynamic' => [
104
+ 'active' => true,
105
+ ]
106
+ ]
107
+ );
108
+
109
+ $this->add_control(
110
+ 'review_for',
111
+ [
112
+ 'label' => __( 'Review For', 'happy-elementor-addons' ),
113
+ 'type' => Controls_Manager::TEXT,
114
+ 'placeholder' => __( 'Movie, Games, Software name etc.', 'happy-elementor-addons' ),
115
+ 'description' => __( '[This field is only for structured data (schema.org) purpose] Obviously this review belongs to something like Movie, Games, Software or Service. So type the name of that thing.', 'happy-elementor-addons' ),
116
+ ]
117
+ );
118
+
119
+ $this->add_control(
120
+ 'review_position',
121
+ [
122
+ 'label' => __( 'Review Position', 'happy-elementor-addons' ),
123
+ 'type' => Controls_Manager::SELECT,
124
+ 'options' => [
125
+ 'before' => __( 'Review Before', 'happy-elementor-addons' ),
126
+ 'after' => __( 'Review After', 'happy-elementor-addons' ),
127
+ ],
128
+ 'default' => 'before',
129
+ ]
130
+ );
131
+
132
+ $this->end_controls_section();
133
+
134
+ $this->start_controls_section(
135
+ '_section_reviewer',
136
  [
137
  'label' => __( 'Reviewer', 'happy-elementor-addons' ),
138
+ 'tab' => Controls_Manager::TAB_CONTENT,
139
  ]
140
  );
141
 
147
  'default' => [
148
  'url' => Utils::get_placeholder_image_src(),
149
  ],
150
+ 'dynamic' => [
151
+ 'active' => true,
152
+ ]
153
  ]
154
  );
155
 
158
  [
159
  'label' => __( 'Name', 'happy-elementor-addons' ),
160
  'type' => Controls_Manager::TEXT,
161
+ 'default' => 'Happy Reviewer',
162
  'placeholder' => __( 'Type Reviewer Name', 'happy-elementor-addons' ),
163
+ 'dynamic' => [
164
+ 'active' => true,
165
+ ]
166
  ]
167
  );
168
 
173
  'type' => Controls_Manager::TEXT,
174
  'default' => __( 'Happy Officer', 'happy-elementor-addons' ),
175
  'placeholder' => __( 'Type Reviewer Job Title', 'happy-elementor-addons' ),
176
+ 'dynamic' => [
177
+ 'active' => true,
178
+ ]
179
  ]
180
  );
181
 
184
  [
185
  'name' => 'thumbnail',
186
  'default' => 'large',
187
+ 'separator' => 'before',
188
  ]
189
  );
190
 
214
  ]
215
  );
216
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  $this->add_responsive_control(
218
  'align',
219
  [
220
  'label' => __( 'Alignment', 'happy-elementor-addons' ),
221
  'type' => Controls_Manager::CHOOSE,
 
222
  'options' => [
223
  'left' => [
224
  'title' => __( 'Left', 'happy-elementor-addons' ),
245
  );
246
 
247
  $this->add_control(
248
+ 'title_tag',
249
  [
250
+ 'label' => __( 'Name HTML Tag', 'happy-elementor-addons' ),
251
+ 'type' => Controls_Manager::CHOOSE,
252
  'options' => [
253
+ 'h1' => [
254
+ 'title' => __( 'H1', 'happy-elementor-addons' ),
255
+ 'icon' => 'eicon-editor-h1'
256
+ ],
257
+ 'h2' => [
258
+ 'title' => __( 'H2', 'happy-elementor-addons' ),
259
+ 'icon' => 'eicon-editor-h2'
260
+ ],
261
+ 'h3' => [
262
+ 'title' => __( 'H3', 'happy-elementor-addons' ),
263
+ 'icon' => 'eicon-editor-h3'
264
+ ],
265
+ 'h4' => [
266
+ 'title' => __( 'H4', 'happy-elementor-addons' ),
267
+ 'icon' => 'eicon-editor-h4'
268
+ ],
269
+ 'h5' => [
270
+ 'title' => __( 'H5', 'happy-elementor-addons' ),
271
+ 'icon' => 'eicon-editor-h5'
272
+ ],
273
+ 'h6' => [
274
+ 'title' => __( 'H6', 'happy-elementor-addons' ),
275
+ 'icon' => 'eicon-editor-h6'
276
+ ]
277
  ],
278
+ 'default' => 'h2',
279
+ 'toggle' => false,
280
  ]
281
  );
282
 
285
 
286
  protected function register_style_controls() {
287
  $this->start_controls_section(
288
+ '_section_ratting_style',
289
  [
290
+ 'label' => __( 'Ratting', 'happy-elementor-addons' ),
291
  'tab' => Controls_Manager::TAB_STYLE,
292
  ]
293
  );
294
 
295
  $this->add_responsive_control(
296
+ 'ratting_size',
297
  [
298
+ 'label' => __( 'Size', 'happy-elementor-addons' ),
299
  'type' => Controls_Manager::SLIDER,
300
+ 'size_units' => ['px'],
 
 
 
 
 
 
 
 
 
 
301
  'selectors' => [
302
+ '{{WRAPPER}} .ha-review-ratting' => 'font-size: {{SIZE}}{{UNIT}};',
 
303
  ],
304
  ]
305
  );
306
 
307
  $this->add_responsive_control(
308
+ 'ratting_spacing',
309
  [
310
+ 'label' => __( 'Bottom Spacing', 'happy-elementor-addons' ),
311
  'type' => Controls_Manager::SLIDER,
312
+ 'size_units' => ['px'],
 
 
 
 
 
 
313
  'selectors' => [
314
+ '{{WRAPPER}} .ha-review-ratting' => 'margin-bottom: {{SIZE}}{{UNIT}};',
315
  ],
316
  ]
317
  );
318
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  $this->add_responsive_control(
320
+ 'ratting_padding',
321
  [
322
+ 'label' => __( 'Padding', 'happy-elementor-addons' ),
323
+ 'type' => Controls_Manager::DIMENSIONS,
324
+ 'size_units' => [ 'px', 'em', '%' ],
325
+ 'selectors' => [
326
+ '{{WRAPPER}} .ha-review-ratting' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
 
 
 
 
 
 
327
  ],
 
328
  ]
329
  );
330
 
331
+ $this->add_control(
332
+ 'ratting_color',
333
  [
334
+ 'label' => __( 'Text Color', 'happy-elementor-addons' ),
335
+ 'type' => Controls_Manager::COLOR,
 
 
 
 
 
 
 
 
 
 
336
  'selectors' => [
337
+ '{{WRAPPER}} .ha-review-ratting' => 'color: {{VALUE}}',
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  ],
339
  ]
340
  );
 
341
 
342
+ $this->add_control(
343
+ 'ratting_bg_color',
344
  [
345
+ 'label' => __( 'Background Color', 'happy-elementor-addons' ),
346
+ 'type' => Controls_Manager::COLOR,
 
347
  'selectors' => [
348
+ '{{WRAPPER}} .ha-review-ratting' => 'background-color: {{VALUE}}',
349
  ],
350
  ]
351
  );
353
  $this->add_group_control(
354
  Group_Control_Border::get_type(),
355
  [
356
+ 'name' => 'ratting_border',
357
+ 'selector' => '{{WRAPPER}} .ha-review-ratting',
358
  ]
359
  );
360
 
361
+ $this->add_control(
362
+ 'ratting_border_radius',
363
  [
364
  'label' => __( 'Border Radius', 'happy-elementor-addons' ),
365
  'type' => Controls_Manager::DIMENSIONS,
366
  'size_units' => [ 'px', '%' ],
367
  'selectors' => [
368
+ '{{WRAPPER}} .ha-review-ratting' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
 
 
 
 
 
 
 
 
 
 
369
  ],
 
370
  ]
371
  );
372
 
375
  $this->start_controls_section(
376
  '_section_review_style',
377
  [
378
+ 'label' => __( 'Review & Reviewer', 'happy-elementor-addons' ),
379
  'tab' => Controls_Manager::TAB_STYLE,
380
  ]
381
  );
518
  $this->end_controls_section();
519
 
520
  $this->start_controls_section(
521
+ '_section_photo_style',
522
  [
523
+ 'label' => __( 'Photo', 'happy-elementor-addons' ),
524
  'tab' => Controls_Manager::TAB_STYLE,
525
  ]
526
  );
527
 
528
  $this->add_responsive_control(
529
+ 'image_width',
530
  [
531
+ 'label' => __( 'Width', 'happy-elementor-addons' ),
532
  'type' => Controls_Manager::SLIDER,
533
+ 'size_units' => [ 'px', '%' ],
534
+ 'range' => [
535
+ 'px' => [
536
+ 'min' => 70,
537
+ 'max' => 500,
538
+ ],
539
+ '%' => [
540
+ 'min' => 10,
541
+ 'max' => 100,
542
+ ],
543
+ ],
544
  'selectors' => [
545
+ '{{WRAPPER}} .ha-review-figure' => 'flex: 0 0 {{SIZE}}{{UNIT}}; max-width: {{SIZE}}{{UNIT}};',
546
+ '{{WRAPPER}}.ha-review--right .ha-review-body, {{WRAPPER}}.ha-review--left .ha-review-body' => 'flex: 0 0 calc(100% - {{SIZE || 150}}{{UNIT}}); max-width: calc(100% - {{SIZE || 150}}{{UNIT}});',
547
  ],
548
  ]
549
  );
550
 
551
  $this->add_responsive_control(
552
+ 'image_height',
553
  [
554
+ 'label' => __( 'Height', 'happy-elementor-addons' ),
555
  'type' => Controls_Manager::SLIDER,
556
+ 'size_units' => [ 'px' ],
557
+ 'range' => [
558
+ 'px' => [
559
+ 'min' => 70,
560
+ 'max' => 500,
561
+ ],
562
+ ],
563
  'selectors' => [
564
+ '{{WRAPPER}} .ha-review-figure' => 'height: {{SIZE}}{{UNIT}};',
565
  ],
566
  ]
567
  );
568
 
569
+ $this->add_control(
570
+ 'offset_toggle',
571
+ [
572
+ 'label' => __( 'Offset', 'happy-elementor-addons' ),
573
+ 'type' => Controls_Manager::POPOVER_TOGGLE,
574
+ 'label_off' => __( 'None', 'your-plugin' ),
575
+ 'label_on' => __( 'Custom', 'your-plugin' ),
576
+ 'return_value' => 'yes',
577
+ ]
578
+ );
579
+
580
+ $this->start_popover();
581
+
582
  $this->add_responsive_control(
583
+ 'image_offset_x',
584
  [
585
+ 'label' => __( 'Offset X', 'happy-elementor-addons' ),
586
+ 'type' => Controls_Manager::SLIDER,
587
+ 'size_units' => ['px'],
588
+ 'condition' => [
589
+ 'offset_toggle' => 'yes'
590
  ],
591
+ 'range' => [
592
+ 'px' => [
593
+ 'min' => -1000,
594
+ 'max' => 1000,
595
+ ],
596
+ ],
597
+ 'render_type' => 'ui'
598
  ]
599
  );
600
 
601
+ $this->add_responsive_control(
602
+ 'image_offset_y',
603
  [
604
+ 'label' => __( 'Offset Y', 'happy-elementor-addons' ),
605
+ 'type' => Controls_Manager::SLIDER,
606
+ 'size_units' => ['px'],
607
+ 'condition' => [
608
+ 'offset_toggle' => 'yes'
609
+ ],
610
+ 'range' => [
611
+ 'px' => [
612
+ 'min' => -1000,
613
+ 'max' => 1000,
614
+ ],
615
+ ],
616
  'selectors' => [
617
+ // Left image position styles
618
+ '(desktop){{WRAPPER}}.ha-review--left .ha-review-body' => 'margin-left: {{image_offset_x.SIZE || 0}}{{UNIT}}; flex: 0 0 calc((100% - {{image_width.SIZE || 150}}{{image_width.UNIT}}) + (-1 * {{image_offset_x.SIZE || 0}}{{UNIT}})); max-width: calc((100% - {{image_width.SIZE || 150}}{{image_width.UNIT}}) + (-1 * {{image_offset_x.SIZE || 0}}{{UNIT}}));',
619
+ '(tablet){{WRAPPER}}.ha-review--left .ha-review-body' => 'margin-left: {{image_offset_x_tablet.SIZE || 0}}{{UNIT}}; flex: 0 0 calc((100% - {{image_width_tablet.SIZE || 150}}{{image_width_tablet.UNIT}}) + (-1 * {{image_offset_x_tablet.SIZE || 0}}{{UNIT}})); max-width: calc((100% - {{image_width_tablet.SIZE || 150}}{{image_width_tablet.UNIT}}) + (-1 * {{image_offset_x_tablet.SIZE || 0}}{{UNIT}}));',
620
+ '(mobile){{WRAPPER}}.ha-review--left .ha-review-body' => 'margin-left: {{image_offset_x_mobile.SIZE || 0}}{{UNIT}}; flex: 0 0 calc((100% - {{image_width_mobile.SIZE || 150}}{{image_width_mobile.UNIT}}) + (-1 * {{image_offset_x_mobile.SIZE || 0}}{{UNIT}})); max-width: calc((100% - {{image_width_mobile.SIZE || 150}}{{image_width_mobile.UNIT}}) + (-1 * {{image_offset_x_mobile.SIZE || 0}}{{UNIT}}));',
621
+ // Image right position styles
622
+ '(desktop){{WRAPPER}}.ha-review--right .ha-review-body' => 'margin-right: calc(-1 * {{image_offset_x.SIZE || 0}}{{UNIT}}); flex: 0 0 calc((100% - {{image_width.SIZE || 150}}{{image_width.UNIT}}) + {{image_offset_x.SIZE || 0}}{{UNIT}}); max-width: calc((100% - {{image_width.SIZE || 150}}{{image_width.UNIT}}) + {{image_offset_x.SIZE || 0}}{{UNIT}});',
623
+ '(tablet){{WRAPPER}}.ha-review--right .ha-review-body' => 'margin-right: calc(-1 * {{image_offset_x_tablet.SIZE || 0}}{{UNIT}}); flex: 0 0 calc((100% - {{image_width_tablet.SIZE || 150}}{{image_width_tablet.UNIT}}) + {{image_offset_x_tablet.SIZE || 0}}{{UNIT}}); max-width: calc((100% - {{image_width_tablet.SIZE || 150}}{{image_width_tablet.UNIT}}) + {{image_offset_x_tablet.SIZE || 0}}{{UNIT}});',
624
+ '(mobile){{WRAPPER}}.ha-review--right .ha-review-body' => 'margin-right: calc(-1 * {{image_offset_x_mobile.SIZE || 0}}{{UNIT}}); flex: 0 0 calc((100% - {{image_width_mobile.SIZE || 150}}{{image_width_mobile.UNIT}}) + {{image_offset_x_mobile.SIZE || 0}}{{UNIT}}); max-width: calc((100% - {{image_width_mobile.SIZE || 150}}{{image_width_mobile.UNIT}}) + {{image_offset_x_mobile.SIZE || 0}}{{UNIT}});',
625
+ // Image translate styles
626
+ '(desktop){{WRAPPER}} .ha-review-figure' => '-ms-transform: translate({{image_offset_x.SIZE || 0}}{{UNIT}}, {{image_offset_y.SIZE || 0}}{{UNIT}}); -webkit-transform: translate({{image_offset_x.SIZE || 0}}{{UNIT}}, {{image_offset_y.SIZE || 0}}{{UNIT}}); transform: translate({{image_offset_x.SIZE || 0}}{{UNIT}}, {{image_offset_y.SIZE || 0}}{{UNIT}});',
627
+ '(tablet){{WRAPPER}} .ha-review-figure' => '-ms-transform: translate({{image_offset_x_tablet.SIZE || 0}}{{UNIT}}, {{image_offset_y_tablet.SIZE || 0}}{{UNIT}}); -webkit-transform: translate({{image_offset_x_tablet.SIZE || 0}}{{UNIT}}, {{image_offset_y_tablet.SIZE || 0}}{{UNIT}}); transform: translate({{image_offset_x_tablet.SIZE || 0}}{{UNIT}}, {{image_offset_y_tablet.SIZE || 0}}{{UNIT}});',
628
+ '(mobile){{WRAPPER}} .ha-review-figure' => '-ms-transform: translate({{image_offset_x_mobile.SIZE || 0}}{{UNIT}}, {{image_offset_y_mobile.SIZE || 0}}{{UNIT}}); -webkit-transform: translate({{image_offset_x_mobile.SIZE || 0}}{{UNIT}}, {{image_offset_y_mobile.SIZE || 0}}{{UNIT}}); transform: translate({{image_offset_x_mobile.SIZE || 0}}{{UNIT}}, {{image_offset_y_mobile.SIZE || 0}}{{UNIT}});',
629
+ // Review body styles
630
+ '{{WRAPPER}}.ha-review--top .ha-review-body' => 'margin-top: {{SIZE}}{{UNIT}};',
631
  ],
632
  ]
633
  );
634
+ $this->end_popover();
635
 
636
+ $this->add_responsive_control(
637
+ 'image_padding',
638
  [
639
+ 'label' => __( 'Padding', 'happy-elementor-addons' ),
640
+ 'type' => Controls_Manager::DIMENSIONS,
641
+ 'size_units' => [ 'px', 'em', '%' ],
642
  'selectors' => [
643
+ '{{WRAPPER}} .ha-review-figure > img' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
644
  ],
645
  ]
646
  );
648
  $this->add_group_control(
649
  Group_Control_Border::get_type(),
650
  [
651
+ 'name' => 'image_border',
652
+ 'selector' => '{{WRAPPER}} .ha-review-figure > img',
653
  ]
654
  );
655
 
656
+ $this->add_responsive_control(
657
+ 'image_border_radius',
658
  [
659
  'label' => __( 'Border Radius', 'happy-elementor-addons' ),
660
  'type' => Controls_Manager::DIMENSIONS,
661
  'size_units' => [ 'px', '%' ],
662
  'selectors' => [
663
+ '{{WRAPPER}} .ha-review-figure > img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
664
  ],
665
  ]
666
  );
667
 
668
+ $this->add_group_control(
669
+ Group_Control_Box_Shadow::get_type(),
670
+ [
671
+ 'name' => 'image_box_shadow',
672
+ 'exclude' => [
673
+ 'box_shadow_position',
674
+ ],
675
+ 'selector' => '{{WRAPPER}} .ha-review-figure > img',
676
+ ]
677
+ );
678
+
679
  $this->end_controls_section();
680
  }
681
 
682
  protected function render() {
683
  $settings = $this->get_settings_for_display();
684
 
685
+ $this->add_render_attribute( '_wrapper', 'itemscope' );
686
+ $this->add_render_attribute( '_wrapper', 'itemtype', 'https://schema.org/Review' );
687
+
688
  $this->add_inline_editing_attributes( 'title', 'none' );
689
  $this->add_render_attribute( 'title', 'class', 'ha-review-reviewer' );
690
+ $this->add_render_attribute( 'title', 'itemprop', 'author' );
691
+ $this->add_render_attribute( 'title', 'itemscope', '' );
692
+ $this->add_render_attribute( 'title', 'itemtype', 'https://schema.org/Person' );
693
 
694
  $this->add_inline_editing_attributes( 'job_title', 'none' );
695
  $this->add_render_attribute( 'job_title', 'class', 'ha-review-position' );
696
 
697
  $this->add_inline_editing_attributes( 'review', 'basic' );
698
  $this->add_render_attribute( 'review', 'class', 'ha-review-desc' );
699
+ $this->add_render_attribute( 'review', 'itemprop', 'reviewBody' );
700
 
701
  $this->add_render_attribute( 'ratting', 'class', [
702
  'ha-review-ratting',
703
  'ha-review-ratting--' . $settings['ratting_style']
704
  ] );
705
+
706
+ $this->add_render_attribute( 'ratting', 'itemprop', 'reviewRating' );
707
+ $this->add_render_attribute( 'ratting', 'itemscope' );
708
+ $this->add_render_attribute( 'ratting', 'itemtype', 'https://schema.org/Rating' );
709
+
710
+ $ratting = max( 0, $settings['ratting']['size'] );
711
  ?>
712
 
713
  <?php if ( $settings['image']['url'] || $settings['image']['id'] ) :
742
  <?php endif; ?>
743
 
744
  <div <?php echo $this->get_render_attribute_string( 'ratting' ); ?>>
745
+ <meta itemprop="ratingValue" content="<?php echo esc_attr( $ratting ); ?>">
746
+
747
  <?php if ( $settings['ratting_style'] === 'num' ) : ?>
748
+ <?php echo esc_html( $ratting ); ?> <i class="fa fa-star" aria-hidden="true"></i>
749
+ <?php else :
750
+ for ( $i = 1; $i <= 5; ++$i ) :
751
+ if ( $i <= $ratting ) {
752
+ echo '<i class="fa fa-star" aria-hidden="true"></i>';
753
+ } else {
754
+ echo '<i class="fa fa-star-o" aria-hidden="true"></i>';
755
+ }
756
+ endfor;
757
+ endif; ?>
758
  </div>
759
  </div>
760
 
764
  </div>
765
  <?php endif; ?>
766
  </div>
767
+
768
+ <span class="ha-screen-reader-text" itemprop="itemReviewed" itemscope itemtype="https://schema.org/Thing">
769
+ <span itemprop="name"><?php echo esc_html( $settings['review_for'] ); ?></span>
770
+ </span>
771
  <?php
772
  }
773
 
783
  view.addInlineEditingAttributes( 'review', 'basic' );
784
  view.addRenderAttribute( 'review', 'class', 'ha-review-desc' );
785
 
786
+ var ratting = Math.max(0, settings.ratting.size);
787
+
788
  if (settings.image.url || settings.image.id) {
789
  var image = {
790
  id: settings.image.id,
815
  <div {{{ view.getRenderAttributeString( 'job_title' ) }}}>{{ settings.job_title }}</div>
816
  <# } #>
817
  <# if ( settings.ratting_style === 'num' ) { #>
818
+ <div class="ha-review-ratting ha-review-ratting--num">{{ ratting }} <i class="fa fa-star"></i></div>
819
+ <# } else { #>
820
  <div class="ha-review-ratting ha-review-ratting--star">
821
+ <# _.each(_.range(1, 6), function(i) {
822
+ if (i <= ratting) {
823
+ print('<i class="fa fa-star"></i>');
824
+ } else {
825
+ print('<i class="fa fa-star-o"></i>');
826
+ }
827
+ }); #>
828
  </div>
829
  <# } #>
830
  </div>
836
  </div>
837
  <?php
838
  }
839
+
840
  }
widgets/step-flow/widget.php CHANGED
@@ -53,15 +53,32 @@ class Step_Flow extends Base {
53
  ]
54
  );
55
 
56
- $this->add_control(
57
- 'icon',
58
- [
59
- 'label' => __( 'Icon', 'happy-elementor-addons' ),
60
- 'type' => Controls_Manager::ICON,
61
- 'default' => 'fa fa-home',
62
- 'options' => ha_get_happy_icons(),
63
- ]
64
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
  $this->add_control(
67
  'badge',
@@ -70,7 +87,10 @@ class Step_Flow extends Base {
70
  'type' => Controls_Manager::TEXT,
71
  'placeholder' => __( 'Badge', 'happy-elementor-addons' ),
72
  'description' => __( 'Keep it blank, if you want to remove the Badge', 'happy-elementor-addons' ),
73
- 'default' => __( '01', 'happy-elementor-addons' ),
 
 
 
74
  ]
75
  );
76
 
@@ -83,6 +103,9 @@ class Step_Flow extends Base {
83
  'placeholder' => __( 'Title', 'happy-elementor-addons' ),
84
  'default' => __( 'Start Marketing', 'happy-elementor-addons' ),
85
  'separator' => 'before',
 
 
 
86
  ]
87
  );
88
 
@@ -92,7 +115,10 @@ class Step_Flow extends Base {
92
  'label' => __( 'Description', 'happy-elementor-addons' ),
93
  'type' => Controls_Manager::TEXTAREA,
94
  'placeholder' => __( 'Description', 'happy-elementor-addons' ),
95
- 'default' => __( 'consectetur adipiscing elit, sed do<br>eiusmod Lorem ipsum dolor sit amet,<br> consectetur.', 'happy-elementor-addons' ),
 
 
 
96
  ]
97
  );
98
 
@@ -101,7 +127,10 @@ class Step_Flow extends Base {
101
  [
102
  'label' => __( 'Link', 'happy-elementor-addons' ),
103
  'type' => Controls_Manager::URL,
104
- 'placeholder' => __( 'https://example.com', 'happy-elementor-addons' ),
 
 
 
105
  ]
106
  );
107
 
@@ -503,14 +532,15 @@ class Step_Flow extends Base {
503
  'dotted' => __( 'Dotted', 'happy-elementor-addons' ),
504
  'dashed' => __( 'Dashed', 'happy-elementor-addons' ),
505
  ],
506
- 'default' => 'dashed',
507
  'selectors' => [
508
- '{{WRAPPER}} .ha-step-arrow' => 'border-top-style: {{VALUE}}',
 
509
  ],
510
  ]
511
  );
512
 
513
- $this->add_control(
514
  'direction_width',
515
  [
516
  'label' => __( 'Width', 'happy-elementor-addons' ),
@@ -528,6 +558,53 @@ class Step_Flow extends Base {
528
  ]
529
  );
530
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
531
  $this->add_control(
532
  'direction_color',
533
  [
@@ -535,7 +612,7 @@ class Step_Flow extends Base {
535
  'type' => Controls_Manager::COLOR,
536
  'selectors' => [
537
  '{{WRAPPER}} .ha-step-arrow' => 'border-color: {{VALUE}};',
538
- '{{WRAPPER}} .ha-step-arrow:after' => 'color: {{VALUE}};',
539
  ],
540
  ]
541
  );
@@ -573,7 +650,9 @@ class Step_Flow extends Base {
573
  <div class="ha-step-arrow"></div>
574
  <?php endif; ?>
575
 
576
- <i class="<?php echo esc_attr( $settings['icon'] ); ?>"></i>
 
 
577
 
578
  <?php if ( $settings['badge'] ) : ?>
579
  <span <?php $this->print_render_attribute_string( 'badge' ); ?>><?php echo esc_html( $settings['badge'] ); ?></span>
53
  ]
54
  );
55
 
56
+ if ( ha_is_elementor_version( '<', '2.6.0' ) ) {
57
+ $this->add_control(
58
+ 'icon',
59
+ [
60
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
61
+ 'type' => Controls_Manager::ICON,
62
+ 'label_block' => true,
63
+ 'options' => ha_get_happy_icons(),
64
+ 'default' => 'hm hm-finger-index',
65
+ ]
66
+ );
67
+ } else {
68
+ $this->add_control(
69
+ 'selected_icon',
70
+ [
71
+ 'label' => __( 'Icon', 'happy-elementor-addons' ),
72
+ 'type' => Controls_Manager::ICONS,
73
+ 'fa4compatibility' => 'icon',
74
+ 'label_block' => true,
75
+ 'default' => [
76
+ 'value' => 'hm hm-finger-index',
77
+ 'library' => 'happy-icons',
78
+ ]
79
+ ]
80
+ );
81
+ }
82
 
83
  $this->add_control(
84
  'badge',
87
  'type' => Controls_Manager::TEXT,
88
  'placeholder' => __( 'Badge', 'happy-elementor-addons' ),
89
  'description' => __( 'Keep it blank, if you want to remove the Badge', 'happy-elementor-addons' ),
90
+ 'default' => __( 'Step 1', 'happy-elementor-addons' ),
91
+ 'dynamic' => [
92
+ 'active' => true,
93
+ ]
94
  ]
95
  );
96
 
103
  'placeholder' => __( 'Title', 'happy-elementor-addons' ),
104
  'default' => __( 'Start Marketing', 'happy-elementor-addons' ),
105
  'separator' => 'before',
106
+ 'dynamic' => [
107
+ 'active' => true,
108
+ ]
109
  ]
110
  );
111
 
115
  'label' => __( 'Description', 'happy-elementor-addons' ),
116
  'type' => Controls_Manager::TEXTAREA,
117
  'placeholder' => __( 'Description', 'happy-elementor-addons' ),
118
+ 'default' => 'consectetur adipiscing elit, sed do<br>eiusmod Lorem ipsum dolor sit amet,<br> consectetur.',
119
+ 'dynamic' => [
120
+ 'active' => true,
121
+ ]
122
  ]
123
  );
124
 
127
  [
128
  'label' => __( 'Link', 'happy-elementor-addons' ),
129
  'type' => Controls_Manager::URL,
130
+ 'placeholder' => 'https://happyaddons.com/',
131
+ 'dynamic' => [
132
+ 'active' => true,
133
+ ]
134
  ]
135
  );
136
 
532
  'dotted' => __( 'Dotted', 'happy-elementor-addons' ),
533
  'dashed' => __( 'Dashed', 'happy-elementor-addons' ),
534
  ],
535
+ 'default' => 'solid',
536
  'selectors' => [
537
+ '{{WRAPPER}} .ha-step-arrow, {{WRAPPER}} .ha-step-arrow:after' => 'border-top-style: {{VALUE}};',
538
+ '{{WRAPPER}} .ha-step-arrow:after' => 'border-right-style: {{VALUE}};',
539
  ],
540
  ]
541
  );
542
 
543
+ $this->add_responsive_control(
544
  'direction_width',
545
  [
546
  'label' => __( 'Width', 'happy-elementor-addons' ),
558
  ]
559
  );
560
 
561
+ $this->add_control(
562
+ 'direction_offset_toggle',
563
+ [
564
+ 'label' => __( 'Offset', 'happy-elementor-addons' ),
565
+ 'type' => Controls_Manager::POPOVER_TOGGLE,
566
+ 'label_off' => __( 'None', 'happy-elementor-addons' ),
567
+ 'label_on' => __( 'Custom', 'happy-elementor-addons' ),
568
+ 'return_value' => 'yes',
569
+ ]
570
+ );
571
+
572
+ $this->start_popover();
573
+
574
+ $this->add_responsive_control(
575
+ 'direction_offset_y',
576
+ [
577
+ 'label' => __( 'Offset Top', 'happy-elementor-addons' ),
578
+ 'type' => Controls_Manager::SLIDER,
579
+ 'size_units' => ['px', '%'],
580
+ 'condition' => [
581
+ 'direction_offset_toggle' => 'yes'
582
+ ],
583
+ 'render_type' => 'ui',
584
+ 'selectors' => [
585
+ '{{WRAPPER}} .ha-step-arrow' => 'top: {{SIZE}}{{UNIT}};',
586
+ ],
587
+ ]
588
+ );
589
+
590
+ $this->add_responsive_control(
591
+ 'direction_offset_x',
592
+ [
593
+ 'label' => __( 'Offset Left', 'happy-elementor-addons' ),
594
+ 'type' => Controls_Manager::SLIDER,
595
+ 'size_units' => ['px', '%'],
596
+ 'condition' => [
597
+ 'direction_offset_toggle' => 'yes'
598
+ ],
599
+ 'render_type' => 'ui',
600
+ 'selectors' => [
601
+ '{{WRAPPER}} .ha-step-arrow' => 'left: calc( 100% + {{SIZE}}{{UNIT}} );',
602
+ ],
603
+ ]
604
+ );
605
+
606
+ $this->end_popover();
607
+
608
  $this->add_control(
609
  'direction_color',
610
  [
612
  'type' => Controls_Manager::COLOR,
613
  'selectors' => [
614
  '{{WRAPPER}} .ha-step-arrow' => 'border-color: {{VALUE}};',
615
+ '{{WRAPPER}} .ha-step-arrow:after' => 'border-color: {{VALUE}};',
616
  ],
617
  ]
618
  );
650
  <div class="ha-step-arrow"></div>
651
  <?php endif; ?>
652
 
653
+ <?php if ( ! empty( $settings['icon'] ) || ! empty( $settings['selected_icon'] ) ) :
654
+ ha_render_icon( $settings, 'icon', 'selected_icon' );
655
+ endif; ?>
656
 
657
  <?php if ( $settings['badge'] ) : ?>
658
  <span <?php $this->print_render_attribute_string( 'badge' ); ?>><?php echo esc_html( $settings['badge'] ); ?></span>