Uncaught SyntaxError: The requested module '/libs/...
创建于:2025年7月1日
创建于:2025年7月1日
Uncaught SyntaxError: The requested module '/libs/leaflet/leaflet.js' does not provide an export named 'default' (at product.vue:270:9)
E:\Program2\OSPanel2\domains\diet\components\com_crm\js\components\product.vue
<template>
<script> import L from '/libs/leaflet/leaflet.js'; import '/libs/leaflet/leaflet-gesture-handling.min.js'; import axios from 'axios'; export default { props:['data'], data: function () { return { item:{}, parent:{}, imgs:{}, main:"", active:0, show:[], showForm:0, showFullReviews:0, send:0 } }, watch:{ $route:function(){ if(window.location.hash=='#/reviewForm'){ this.showForm=1; }else{ this.showForm=0; } if(window.location.hash=='#/showFullReviews'){ this.showFullReviews=1; }else{ this.showFullReviews=0; } } }, mounted() { this.parent = this.$parent; //this.get(); this.item = JSON.parse(this.data); this.imgs = this.item.images; if(this.imgs != '') this.main = this.imgs[0].image; if(!this.item.rating){ this.item.rating = 0; } if(!this.item.reviewsCount){ this.item.reviewsCount = 0; } if(!this.item.reviews){ this.item.reviews = []; } let self = this; setTimeout(function(){ self.initMap(); if(self.item.lat && self.item.lng) self.addMarker(self.item.lat,self.item.lng); },500); }, methods:{ get:function(start=-1){ var self = this; self.parent.loader=1; var data = new FormData; if(start && start>-1) data.append("start",start); axios.post("/index.php?option=com_crm&task=product.getItem&id="+self.item.id, data).then(function(response){ self.parent.loader=0; if(response.data.item) self.item = response.data.item; }).catch(function(error){ self.parent.$refs.msg.alertFun(error); }); }, scroll:function(i){ this.main = this.imgs[i].image; }, hash(){ setTimeout(function(){ document.querySelector(window.location.hash.replace('/','')).scrollIntoView({ behavior: "smooth", block: "start" }); },100); }, focus(){ document.getElementById('contact-name').focus(); }, submit:function(){ var self = this; var data = self.parent.toFormData(self.parent.formData); if(this.item.id) data.append("id",this.item.id); self.parent.loader=1; axios.post("/index.php?option=com_crm&task=product.addContact",data).then(function(response){ self.parent.loader=0; if(response.data.error){ self.parent.$refs.msg.alertFun(response.data.error); }else{ self.parent.$refs.msg.successFun("Successfully submit request!"); self.send=1; } }).catch(function(error){ self.parent.$refs.msg.alertFun(error); }); }, initMap:function(){ this.map = L.map('map',{ gestureHandling: true }).setView([31.8070207,34.6368603], 12); var osm=new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',{attribution: ''}); osm.addTo(this.map); }, addMarker:function(lat,lng){ if (this.map._layers) { let a = 0; for(let i in this.map._layers){ if (a != 0) { this.map._layers[this.map._layers[i]._leaflet_id].remove(); } a++; } //$map.setView([31.8070207, 34.6368603], 12); } this.map.setView([lat,lng], 12); var Icon = L.icon({ iconUrl: '/components/com_crm/images/marker.png', iconSize: [20, 30], // size of the icon shadowSize: [20, 30], // size of the shadow popupAnchor: [0, -25] // point from which the popup should open relative to the iconAnchor }); this.layer = L.marker([lat,lng], {icon: Icon}).addTo(this.map); }, }, }; </script>text<div class="flex mm"> <div class="w70 product-page"> <div class="product-item ac line"> <div class="sticky"> <div class="product-images row" id="product-images"> <div class="main-img-out" :class="{'col-lg-9':imgs.length>1}"> <div class="main-img"> <a class="product-page__image-wrapper" v-if="main" @click.prevent="$refs.img.active=1"> <img class="product-page__image-wrapper__image" :src="'/media/com_product/images/full/'+main" :alt="item.model" :title="item.model"> </a> </div> <popup ref="img" fullscreen="true" :title="item.model"> <img :src="'/media/com_product/images/full/'+main" :alt="item.model" :title="item.model"> </popup> </div> <div class="product-images-out col-lg-3 r" v-if="imgs.length>1"> <div class="product-images-in"> <div v-if="imgs" v-for="(img,i) in imgs" class="product-page__image-wrapper" :class="{active:img.image==main}"> <a rel="group" href="#" @click.prevent="scroll(i)"> <img class="product-page__image-thumbs__thumb " :src="'/media/com_product/images/thumbs/'+img.thumb" :alt="item.model"> </a> </div> </div> </div> </div> <div class="after_imgs "> <div class="head" :class="{active:active==1}"> <h1>{{item.model}}</h1> </div> <rating v-if="item!=''" v-model:rating="item.rating" v-model:reviewsCount="item.reviewsCount" /> <div class="product-descr" v-if="item.short_text" v-html="item.short_text"></div> <div class="product-buttons ac flex"> <div class="phone" v-if="item.phone"> <button v-if="!show[0]" @click="show[0]=1"><i class="fas fa-phone"></i> חיוג</button> <a class="open" v-if="show[0]" target="_blank" :href="'tel:'+item.phone"><i class="fas fa-phone"></i> {{item.phone}}</a> </div> <div class="mail"> <button @click="focus()"><i class="fas fa-envelope"></i> קביעת תור</button> </div> <!--div class="site" v-if="item.site"> <button v-if="!show[1]" @click="show[1]=1"><i class="fab fa-internet-explorer"></i> אתר</button> <a class="open" v-if="show[1]" target="_blank" :href="item.site"><i class="fab fa-internet-explorer"></i> {{item.site}}</a> </div> <div class="facebook" v-if="item.facebook"> <button v-if="!show[2]" @click="show[2]=1"><i class="fab fa-facebook-square"></i> Facebook</button> <a class="open" v-if="show[2]" target="_blank" :href="item.facebook"><i class="fab fa-facebook-square"></i> {{item.facebook}}</a> </div> <div class="instagram" v-if="item.instagram"> <button v-if="!show[3]" @click="show[3]=1"><i class="fab fa-instagram"></i> Instagram</button> <a class="open" v-if="show[3]" target="_blank" :href="item.instagram"><i class="fab fa-instagram"></i> {{item.instagram}}</a> </div> <div class="youtube" v-if="item.youtube"> <button v-if="!show[4]" @click="show[4]=1"><i class="fab fa-youtube"></i> YouTube</button> <a class="open" v-if="show[4]" target="_blank" :href="item.youtube"><i class="fab fa-youtube"></i> {{item.youtube}}</a> </div--> </div> </div> </div> </div> <div class="product-item line" id="reviewForm"> <div class="address"> <i class="fas fa-map-marker-alt"></i> <span v-if="item.city"> {{item.city}},</span> <span v-if="item.address"> {{item.address}}</span> </div> <div id="map" style="height:350px;width:100%;"></div> </div> <div class="product-item line" id="reviewForm" v-if="showForm==1"> <reviewForm v-if="item!=''" v-model:id="item.id" v-model:title="item.model" /> </div> <div class="product-item line" id="reviewsBlockMainLimit" v-if="!showFullReviews"> <div class="bb"> <h2 class="title">חוות דעת נבחרות</h2> </div> <div class="reviewsPerMark" v-if="item.reviewsStatistics"> <div class="flex"><rating rating="5" :reviewsCount="item.reviewsStatistics[4].count"/><progress :value="item.reviewsStatistics[4].value" max="100"></progress> {{item.reviewsStatistics[4].value}}%</div> <div class="flex"><rating rating="4" :reviewsCount="item.reviewsStatistics[3].count"/><progress :value="item.reviewsStatistics[3].value" max="100"></progress> {{item.reviewsStatistics[3].value}}%</div> <div class="flex"><rating rating="3" :reviewsCount="item.reviewsStatistics[2].count"/><progress :value="item.reviewsStatistics[2].value" max="100"></progress> {{item.reviewsStatistics[2].value}}%</div> <div class="flex"><rating rating="2" :reviewsCount="item.reviewsStatistics[1].count"/><progress :value="item.reviewsStatistics[1].value" max="100"></progress> {{item.reviewsStatistics[1].value}}%</div> <div class="flex"><rating rating="1" :reviewsCount="item.reviewsStatistics[0].count"/><progress :value="item.reviewsStatistics[0].value" max="100"></progress> {{item.reviewsStatistics[0].value}}%</div> </div> <reviewsBlock v-model="item.reviews" limit="5" /> <div class="ac" v-if="item.reviews && Object.keys(item.reviews).length>5"> <a class="btnS" href="#/showFullReviews" @click="hash()">לצפייה בחוות דעת נבחרות</a> </div> </div> <div class="product-item line" v-if="!showFullReviews"> <div class="product-descr" v-if="item.free_text" v-html="item.free_text"></div> </div> <div class="product-item line" id="showFullReviews" v-if="showFullReviews"> <div class="bb"> <h2 class="title">ביקורות</h2> </div> <div class="reviewsPerMark" v-if="item.reviewsStatistics"> <div class="flex"><rating rating="5" :reviewsCount="item.reviewsStatistics[4].count"/><progress :value="item.reviewsStatistics[4].value" max="100"></progress> {{item.reviewsStatistics[4].value}}%</div> <div class="flex"><rating rating="4" :reviewsCount="item.reviewsStatistics[3].count"/><progress :value="item.reviewsStatistics[3].value" max="100"></progress> {{item.reviewsStatistics[3].value}}%</div> <div class="flex"><rating rating="3" :reviewsCount="item.reviewsStatistics[2].count"/><progress :value="item.reviewsStatistics[2].value" max="100"></progress> {{item.reviewsStatistics[2].value}}%</div> <div class="flex"><rating rating="2" :reviewsCount="item.reviewsStatistics[1].count"/><progress :value="item.reviewsStatistics[1].value" max="100"></progress> {{item.reviewsStatistics[1].value}}%</div> <div class="flex"><rating rating="1" :reviewsCount="item.reviewsStatistics[0].count"/><progress :value="item.reviewsStatistics[0].value" max="100"></progress> {{item.reviewsStatistics[0].value}}%</div> </div> <reviewsBlock v-model="item.reviews" /> <pagination :pagination="item.paginationReview" :limit="item.limit"></pagination> </div> </div> <div class="w30 product-form-out"> <div class="product-form product-item line"> <div class="succeess ac" v-if="send==1">הבקשה נשלחה בהצלחה!</div> <form @submit.prevent="submit()" v-if="send==0 && parent.formData"> <div class="row"> <h2><i class="fas fa-envelope"></i> לקביעת תור ושאלות כלליות</h2> </div> <div class="infoMsg">השירות הניתן באמצעות האתר אינו שירות רפואי. תיעוד ומידע רגיש יש למסור לרופאים בלבד.</div> <div class="row"> <input type="text" id="contact-name" name="name" v-model="parent.formData.name" placeholder="שם מלא *" required> </div> <div class="row"> <input type="text" id="contact-phone" name="phone" v-model="parent.formData.phone" placeholder="טלפון *" required> </div> <div class="row"> <input type="email" id="email" name="email" v-model="parent.formData.email" placeholder="אימייל"> </div> <div class="row"> <textarea id="contact-text" required="" name="review-text" v-model="parent.formData.comment" rows="3" placeholder="הערה *"></textarea> <label class="checkbox-container"><input type="checkbox" name="terms" required=""><span class="checkmark"></span>אני מאשר/ת את תנאי השימוש וקבלת תכנים פרסומיים מהאתר</label> </div> <div class="row al"> <button class="btnS" type="submit">שליחת חוות דעת</button> </div> </form> </div> </div> </div> </template>
E:\Program2\OSPanel2\domains\diet\components\com_crm\js\pages\product.vue
<template>
<div class="inside-content">
<div id='spinner' v-if="loader"></div>
</template> <script> import L from '/libs/leaflet/leaflet.js'; import '/libs/leaflet/leaflet-gesture-handling.min.js'; import axios from 'axios'; export default { data:function() { return { parent:"", data:{item:{},images:[],sizes:{},colors:{},cats:{}}, user:[], tabs:["פרטי משתמש","תיאורים","רשתות חברתיות","תמונות","כתובת","ביקורות","שתף קישור"], tab:0, tabs2:["Link","SMS","WhatsApp","Email"], tab2:0, date:"", date2:"", iChart:-1, loader:1, map:"", layer:"", qr:"", phone:"", email:"" } }, mounted:function(){ this.parent = this.$parent.$parent; this.get(); }, methods:{ initMap:function(){ this.map = L.map('map',{ gestureHandling: true }).setView([31.8070207,34.6368603], 12); var osm=new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',{attribution: ''}); osm.addTo(this.map); }, addMarker:function(lat,lng){ if (this.map._layers) { let a = 0;text<div class="wrapper"> <div class="topDetails details"> <div class="flex"> <div class="w75 flex l"> <div class="images" v-if="data.item.images && data.item.images!='' && data.item.images[0]!='' && data.item.images[0].thumb!=''" :style="{'background-image':'url(/media/com_product/images/thumbs/'+data.item.images[0].thumb+')'}"></div> <div class="w100"> <div class="title" v-if="data.item && data.item.model">{{data.item.model}}</div> <div class="title" v-if="data.item && !data.item.model">New</div> <div class="flex topdesc"> <div class="w33" v-if="data.item.cat_id!=''"> <label>קטגוריות:</label> <span v-if="data.item.cat_id">{{data.cats.find(item => item.id === data.item.cat_id).cat_name}}</span> </div> <div class="w33" v-if="data.item.city!=''"> <label>ישוב:</label> <span v-if="data.item.city">{{data.geos.find(item => item.id === data.item.city).city}}</span> </div> <div class="w33"> <!--div class="row-fluid" v-if="data.item.price"> <label>מחיר:</label> <span>{{data.item.price}}</span> </div--> </div> </div> </div> </div> <div class="w25 rigp l r"> <div class="flex al" v-if="parent.$route && parent.$route.params.id"> <button type="button" @click="$refs.btn.click()" class="btnS" ><i class="fa fa-save"></i>שמור</button> <router-link class="btnS close" to="/"><i class="fa fa-times"></i>מחק</router-link> </div> <div v-if="!parent.$route || !parent.$route.params.id"> <button type="button" @click="$refs.btn.click()" class="btnS" ><i class="fa fa-plus"></i>הוסף</button> </div> </div> </div> </div> <br /> <form @submit.prevent="parent.formData=data;action()" > <button class="hidden" ref="btn"></button> <div class="row"> <div class="tabs tabsln ar"> <ul> <li v-if="tabs" v-for="(t,i) in tabs" :class="{active:tab==i}" @click="setTab(i);"> <i class="fa fa-user" v-if="i==0"></i> <i class="fas fa-money-check" v-if="i==1"></i> <i class="fas fa-thumbs-up" v-if="i==2"></i> <i class="fas fa-images" v-if="i==3"></i> <i class="fas fa-map" v-if="i==4"></i> <i class="fas fa-comments" v-if="i==5"></i> <i class="fas fa-share" v-if="i==6"></i> {{t}} </li> </ul> </div> </div> <div class="flex mp"> <div class="w100 details"> <h3>{{tabs[tab]}}</h3> <template v-if="tab==6"> <div class="tabs tabsln sharing ar"> <ul> <li v-for="(t,i) in tabs2" :key="i" :class="['act-' + i, { active: tab2 == i }]" @click="tab2 = i" > <i class="fas fa-link" v-if="i==0"></i> <i class="fas fa-sms" v-if="i==1"></i> <i class="fab fa-whatsapp" v-if="i==2"></i> <i class="fas fa-envelope" v-if="i==3"></i> {{t}} </li> </ul> </div> <div class="ac"> <img :src="qr" v-if="qr" width="150px"> </div> <template v-if="tab2==0"> <div class="row ar"> <label>Code</label> <textarea :value="genLink(data.item.id)"></textarea> </div> <div class="row-fluid al"> <button class="btnS" @click.prevent="copyFunc(genLink(data.item.id))"><i class="fas fa-link"></i> העתק קוד</button> </div> </template> <template v-if="tab2==1"> <div class="row-fluid ar"> <label>טלפון</label> <input v-model="phone" ref="phone"> </div> <div class="row-fluid al"> <button class="btnS" @click.prevent="sms()"><i class="fas fa-sms"></i>שלח SMS</button> </div> </template> <template v-if="tab2==2"> <div class="row-fluid ar"> <label>טלפון</label> <input v-model="phone" ref="phone"> </div> <div class="row-fluid al"> <button class="btnS" @click.prevent="whatsapp()"><i class="fab fa-whatsapp"></i> שלח Whatsapp</button> </div> </template> <template v-if="tab2==3"> <div class="row-fluid ar"> <label>Email</label> <input v-model="email" type="email" ref="email"> </div> <div class="row-fluid al"> <button class="btnS" @click.prevent="shareMail()"><i class="fas fa-envelope"></i> שלח אימייל</button> </div> </template> </template> <template v-if="tab==0"> <div class="row-fluid"> <label>שם בית העסק</label> <input type="text" name="model" v-model="data.item.model" required /> </div> <!--div class="row-fluid"> <label>מחיר</label> <input type="number" name="price" v-model="data.item.price" /> </div--> <div class="row-fluid"> <label>סטטוס</label> <select name="published" v-model="data.item.published"> <option value="1" :selected="data.item.published==1" >Published</option> <option value="0" :selected="data.item.published==0" >Not Published</option> </select> </div> <div class="row-fluid"> <label>קטגוריות</label> <select name="cat_id" v-model="data.item.cat_id" v-if="data.cats"> <option :value="g.id" v-for="g in data.cats">{{g.cat_name}}</option> </select> </div> <div class="row-fluid"> <label>לקוח</label> <select name="user_id" v-model="data.item.user_id" v-if="data.users"> <option value="0">---</option> <option :value="g.id" v-for="g in data.users">{{g.name}}</option> </select> </div> <div class="row-fluid"> <label>טלפון</label> <input type="text" name="phone" v-model="data.item.phone" /> </div> </template> <template v-if="tab==4"> <div class="row-fluid"> <label>ישוב</label> <select name="city" v-model="data.item.city" v-if="data.geos"> <option :value="g.id" v-for="g in data.geos">{{g.city}}</option> </select> </div> <div class="row-fluid"> <label>כתובת</label> <input type="text" name="address" v-model="data.item.address" required /> <button class="btnS" @click.prevent="getCoords()" style="width: 100%;"><i style="padding:0;" class="fa fa-search"></i></button> </div> <div id="map" style="height:350px;width:100%;"></div> </template> <template v-if="tab==5"> <div class="table" v-if="data.reviews!=''"> <table> <thead> <tr> <th class="id">#</th> <th></th> <th>תאריך</th> <th class="name">שם מלא</th> <th class="name">כתובת אימייל</th> <th>חוות דעת מפורטת</th> <th class="actions">פעולות</th> </tr> </thead> <tbody v-for="(item,i) in data.reviews"> <tr v-bind:id="'item-'+item.id" :class="{gray:i%2==0}"> <td class="id">{{item.id}}</td> <td class="id"><toogle v-model="item.published" @change="parent.formData = item;actionReview()" /></td> <td>{{item.date}}</td> <td>{{item.name}}</td> <td>{{item.email}}</td> <td>{{item.review}}</td> <td class="actions"> <a href="#" class="remove" @click.prevent="parent.formData = item;delReview();"><i class="fa fa-remove"></i></a> </td> </tr> </tbody> </table> <pagination v-if="data.items!=''" :pagination="data.pagination" :limit="data.limit"></pagination> </div> <div class="empty" v-if="data.reviews==''"> No items </div> </template> <template v-if="tab==1"> <div class="row-fluid"> <label>תיאור</label> <editor v-model="data.item.free_text"></editor> </div> </template> <template v-if="tab==2"> <div class="row-fluid"> <label>Site</label> <input type="text" name="site" v-model="data.item.site" /> </div> <div class="row-fluid"> <label>Facebook</label> <input type="text" name="facebook" v-model="data.item.facebook" /> </div> <div class="row-fluid"> <label>Instagram</label> <input type="text" name="instagram" v-model="data.item.instagram" /> </div> <div class="row-fluid"> <label>Youtube</label> <input type="text" name="youtube" v-model="data.item.youtube" /> </div> </template> <template v-if="tab==3"> <div class="row"> <gallery :field="'images'" :imgpath="'/media/com_product/images/thumbs/'" :multiple="true" :images="data.images" :id="data.item.id" :urldelete="'/index.php?option=com_crm&task=user.delFile'" :urlorder="'/index.php?option=com_crm&task=user.fileOrder'"/> </div> </template> </div> </div> </form> </div> </div>
</script> как исправитьь с минимальными изменениями ?textfor(let i in this.map._layers){ if (a != 0) { this.map._layers[this.map._layers[i]._leaflet_id].remove(); } a++; } //$map.setView([31.8070207, 34.6368603], 12); } this.map.setView([lat,lng], 12); var Icon = L.icon({ iconUrl: '/components/com_crm/images/marker.png', iconSize: [20, 30], // size of the icon shadowSize: [20, 30], // size of the shadow popupAnchor: [0, -25] // point from which the popup should open relative to the iconAnchor }); this.layer = L.marker([lat,lng], {icon: Icon}).addTo(this.map); }, qrFunc:function(){ var self = this; var data = new FormData; if(this.data.item.id) data.append("url",this.genLink(this.data.item.id)); //self.loader=1; axios.post("/index.php?option=com_crm&task=user.qr",data).then(function(response){ self.loader=0; self.qr = response.data; }).catch(function(error){ self.parent.$refs.header.$refs.msg.alertFun(error); }); }, getCoords:function(){ var self = this; self.loader=1; let address=''; if(this.data.item.city) address += this.data.geos.find(item => item.id === this.data.item.city).city+", "; address += this.data.item.address; axios.post("https://maps.google.com/maps/api/geocode/json?address=" +address +"&key=AIzaSyDezmQVCWQd-RleASzxK6iLxcURKdkztqw",).then(function(response){ self.loader=0; if (response.data.results[0]) { self.data.item.lat = response.data.results[0].geometry.location.lat; self.data.item.lng = response.data.results[0].geometry.location.lng; }else if(response.data.results.geometry){ self.data.item.lat = response.data.results.geometry.location.lat; self.data.item.lng = response.data.results.geometry.location.lng; } self.addMarker(self.data.item.lat,self.data.item.lng); }).catch(function(error){ self.parent.$refs.header.$refs.msg.alertFun(error); }); }, get:function(id=-1){ var self = this; var data = new FormData(); if(id>0){ data.append('id',id); }else{ data.append('id',this.parent.$route.params.id); } self.loader=1; axios.post("/index.php?option=com_crm&task=user.getProduct",data).then(function(response){ self.loader=0; if(response.data){ for(let i in response.data){ if(response.data[i]) self.data[i] = response.data[i]; } } self.qrFunc(); if(self.data.item && self.data.item.model) document.title=self.data.item.model; }).catch(function(error){ self.parent.$refs.header.$refs.msg.alertFun(error); }); }, action:function(){ var self = this; var data = self.parent.toFormData(self.data.item); self.loader=1; axios.post("/index.php?option=com_crm&task=user.actionProduct",data).then(function(response){ self.loader=0; if(response.data.error){ self.parent.$refs.header.$refs.msg.alertFun(response.data.error); return false; } if(response && response.data.id){ self.parent.$router.replace('/product/'+response.data.id); self.get(response.data.id); self.parent.$refs.header.$refs.msg.successFun("Successfully added product!"); }else{ self.get(); self.parent.$refs.header.$refs.msg.successFun("Successfully updated product!"); } }).catch(function(error){ self.parent.$refs.header.$refs.msg.alertFun(error); }); }, actionReview:function(){ var self = this; var data = self.parent.toFormData(self.parent.formData); axios.post("/index.php?option=com_crm&task=user.editReview",data).then(function(response){ if(self.parent.formData.id){ self.parent.$refs.header.$refs.msg.successFun("Successfully updated review!"); }else{ self.parent.$refs.header.$refs.msg.successFun("Successfully added new review!"); } self.get(); }).catch(function(error){ self.parent.$refs.header.$refs.msg.alertFun(error); }); }, delReview:async function () { if(await this.parent.$refs.header.$refs.msg.confirmFun("Please confirm next action","Do you want to delete this review?")){ var self = this; var data = self.parent.toFormData(self.parent.formData); axios.post("/index.php?option=com_crm&task=user.deleteReview",data).then(function(response){ self.parent.$refs.header.$refs.msg.successFun("Successfully deleted review!"); self.get(); }).catch(function(error){ self.parent.$refs.header.$refs.msg.alertFun(error); }); } }, setTab:function(i){ let checkCurrent = false; if(this.tab==i) checkCurrent = true; this.tab=i; if(i==4){ let self = this; setTimeout(function(){ if(!checkCurrent){ self.initMap(); if(self.data.item.lat && self.data.item.lng) self.addMarker(self.data.item.lat,self.data.item.lng); } },500); } }, copyFunc:async function(text){ if(navigator && navigator.clipboard){ await navigator.clipboard.writeText(text); this.parent.$refs.header.$refs.msg.successFun("Successfully copied!"); this.$refs.copy.active=0; this.copy=""; }else{ this.parent.$refs.header.$refs.msg.alertFun("Copy mannualy or use https!"); } }, genLink:function(id){ let url = window.location.protocol+'//'+window.location.host+'/component/crm/product/'+id+'#/reviewForm'; return url; }, whatsapp:function(){ if(this.phone==''){ this.parent.$refs.header.$refs.msg.alertFun("הקלד טלפון!"); this.$refs.phone.focus(); this.$refs.phone.classList.add('focused-class'); return false; } this.$refs.phone.classList.remove('focused-class'); location.href="https://api.whatsapp.com/send/?phone="+this.phone+"&text="+this.genLink(this.data.item.id).replace('#','%23')+"&type=phone_number&app_absent=0"; }, sms:function(){ if(this.phone==''){ this.parent.$refs.header.$refs.msg.alertFun("הקלד טלפון!"); this.$refs.phone.focus(); this.$refs.phone.classList.add('focused-class'); return false; } self.phone = ""; this.parent.$refs.header.$refs.msg.alertFun("Successfully sent SMS! No one SMS Api not set!"); }, shareMail:function(){ let self = this; if(this.email==''){ this.parent.$refs.header.$refs.msg.alertFun("הקלד אימייל!"); this.$refs.email.focus(); this.$refs.email.classList.add('focused-class'); return false; } this.$refs.email.classList.remove('focused-class'); var data = new FormData; if(this.email) data.append("email",this.email); if(this.qr) data.append("qr",this.qr); if(this.data.item.id) data.append("url",this.genLink(this.data.item.id)); axios.post("/index.php?option=com_crm&task=user.shareMail",data).then(function(response){ self.email = ""; self.parent.$refs.header.$refs.msg.successFun("Successfully sent mail!"); }).catch(function(error){ self.parent.$refs.header.$refs.msg.alertFun(error); }); } }, };
Ошибка связана с тем, что библиотека Leaflet загружается как обычный JS-файл, а не как модуль с экспортом по умолчанию. Поэтому строка:
jsimport L from '/libs/leaflet/leaflet.js';
приводит к ошибке:
Uncaught SyntaxError: The requested module '/libs/leaflet/leaflet.js' does not provide an export named 'default'
Используйте импорт всего модуля через пространство имен (* as L
):
Замените:
jsimport L from '/libs/leaflet/leaflet.js';
На:
jsimport * as L from '/libs/leaflet/leaflet.js';
Такой подход позволяет импортировать все экспорты библиотеки Leaflet, даже если она не предоставляет дефолтного экспорта.
js<script> import * as L from '/libs/leaflet/leaflet.js'; import '/libs/leaflet/leaflet-gesture-handling.min.js'; import axios from 'axios'; export default { // остальной ваш код без изменений } </script>
Ошибка возникает потому, что Leaflet по умолчанию не предоставляет экспорта через ES-модули (export default
), а использует глобальный объект. Поэтому при работе с ES-модулями нужно использовать указанный выше способ импорта через import * as L
.
Если по каким-то причинам данный метод не подходит, вы можете альтернативно использовать CDN или добавить Leaflet в HTML через обычный <script>
и использовать глобальный объект L
без импортов вообще:
html<script src="/libs/leaflet/leaflet.js"></script> <script src="/libs/leaflet/leaflet-gesture-handling.min.js"></script>
А в вашем компоненте уже напрямую использовать L
:
jsmounted() { this.map = L.map('map'); }
Однако, предложенное выше решение с import * as L
— наиболее быстрое и минимально инвазивное.
Теперь такая ошибка leaflet-gesture-handling.min.js:1 Uncaught TypeError: Cannot set properties of undefined (setting 'leafletGestureHandling')
at leaflet-gesture-handling.min.js:1:191
at leaflet-gesture-handling.min.js:1:196
Эта ошибка вызвана тем, что плагин Leaflet Gesture Handling ожидает, что глобальный объект L
уже доступен. Когда вы используете ES-модули (import
), глобальный объект L
автоматически не создается, и плагин не может найти его.
Чтобы быстро исправить ошибку с минимальными изменениями:
1. Измените способ подключения обоих файлов Leaflet в вашем product.vue
.
Удалите эти строки из вашего JS:
jsimport * as L from '/libs/leaflet/leaflet.js'; import '/libs/leaflet/leaflet-gesture-handling.min.js';
2. Подключите скрипты напрямую через <script>
в HTML-файле (глобально, через index.html или через соответствующий HTML-шаблон вашего приложения):
html<script src="/libs/leaflet/leaflet.js"></script> <script src="/libs/leaflet/leaflet-gesture-handling.min.js"></script>
Таким образом, глобальный объект L
будет создан автоматически и доступен для плагина.
После этого в вашем компоненте Vue (product.vue
) просто используйте глобальный объект L
напрямую:
vue<script> import axios from 'axios'; export default { mounted() { this.initMap(); }, methods: { initMap() { this.map = L.map('map', { gestureHandling: true }) .setView([31.8070207, 34.6368603], 12); const osm = new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png'); osm.addTo(this.map); }, }, }; </script>
Плагин leaflet-gesture-handling не поддерживает импорт через ES-модули, так как написан таким образом, что зависит от глобальной переменной L
. Поэтому его необходимо загружать после загрузки основной библиотеки Leaflet, используя традиционный подход (через <script>
теги).
Таким образом, самое простое и правильное решение с минимальными изменениями:
import
, напрямую через HTML.L
.Это гарантирует, что плагин корректно определит глобальный объект L
и не выдаст указанной ошибки.
✅ После данных изменений обе ваши ошибки будут устранены.
а можно ли где то прям тут подключить эти скрипты ?
<template>
<script> import axios from 'axios'; export default { props:['data'], data: function () { return { item:{}, parent:{}, imgs:{}, main:"", active:0, show:[], showForm:0, showFullReviews:0, send:0 } }, watch:{ $route:function(){ if(window.location.hash=='#/reviewForm'){ this.showForm=1; }else{ this.showForm=0; } if(window.location.hash=='#/showFullReviews'){ this.showFullReviews=1; }else{ this.showFullReviews=0; } } }, mounted() { this.parent = this.$parent; //this.get(); this.item = JSON.parse(this.data); this.imgs = this.item.images; if(this.imgs != '') this.main = this.imgs[0].image; if(!this.item.rating){ this.item.rating = 0; } if(!this.item.reviewsCount){ this.item.reviewsCount = 0; } if(!this.item.reviews){ this.item.reviews = []; } let self = this; setTimeout(function(){ self.initMap(); if(self.item.lat && self.item.lng) self.addMarker(self.item.lat,self.item.lng); },500); }, methods:{ get:function(start=-1){ var self = this; self.parent.loader=1; var data = new FormData; if(start && start>-1) data.append("start",start); axios.post("/index.php?option=com_crm&task=product.getItem&id="+self.item.id, data).then(function(response){ self.parent.loader=0; if(response.data.item) self.item = response.data.item; }).catch(function(error){ self.parent.$refs.msg.alertFun(error); }); }, scroll:function(i){ this.main = this.imgs[i].image; }, hash(){ setTimeout(function(){ document.querySelector(window.location.hash.replace('/','')).scrollIntoView({ behavior: "smooth", block: "start" }); },100); }, focus(){ document.getElementById('contact-name').focus(); }, submit:function(){ var self = this; var data = self.parent.toFormData(self.parent.formData); if(this.item.id) data.append("id",this.item.id); self.parent.loader=1; axios.post("/index.php?option=com_crm&task=product.addContact",data).then(function(response){ self.parent.loader=0; if(response.data.error){ self.parent.$refs.msg.alertFun(response.data.error); }else{ self.parent.$refs.msg.successFun("Successfully submit request!"); self.send=1; } }).catch(function(error){ self.parent.$refs.msg.alertFun(error); }); }, initMap:function(){ this.map = L.map('map',{ gestureHandling: true }).setView([31.8070207,34.6368603], 12); var osm=new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',{attribution: ''}); osm.addTo(this.map); }, addMarker:function(lat,lng){ if (this.map._layers) { let a = 0; for(let i in this.map._layers){ if (a != 0) { this.map._layers[this.map._layers[i]._leaflet_id].remove(); } a++; } //$map.setView([31.8070207, 34.6368603], 12); } this.map.setView([lat,lng], 12); var Icon = L.icon({ iconUrl: '/components/com_crm/images/marker.png', iconSize: [20, 30], // size of the icon shadowSize: [20, 30], // size of the shadow popupAnchor: [0, -25] // point from which the popup should open relative to the iconAnchor }); this.layer = L.marker([lat,lng], {icon: Icon}).addTo(this.map); }, }, }; </script>text<div class="flex mm"> <div class="w70 product-page"> <div class="product-item ac line"> <div class="sticky"> <div class="product-images row" id="product-images"> <div class="main-img-out" :class="{'col-lg-9':imgs.length>1}"> <div class="main-img"> <a class="product-page__image-wrapper" v-if="main" @click.prevent="$refs.img.active=1"> <img class="product-page__image-wrapper__image" :src="'/media/com_product/images/full/'+main" :alt="item.model" :title="item.model"> </a> </div> <popup ref="img" fullscreen="true" :title="item.model"> <img :src="'/media/com_product/images/full/'+main" :alt="item.model" :title="item.model"> </popup> </div> <div class="product-images-out col-lg-3 r" v-if="imgs.length>1"> <div class="product-images-in"> <div v-if="imgs" v-for="(img,i) in imgs" class="product-page__image-wrapper" :class="{active:img.image==main}"> <a rel="group" href="#" @click.prevent="scroll(i)"> <img class="product-page__image-thumbs__thumb " :src="'/media/com_product/images/thumbs/'+img.thumb" :alt="item.model"> </a> </div> </div> </div> </div> <div class="after_imgs "> <div class="head" :class="{active:active==1}"> <h1>{{item.model}}</h1> </div> <rating v-if="item!=''" v-model:rating="item.rating" v-model:reviewsCount="item.reviewsCount" /> <div class="product-descr" v-if="item.short_text" v-html="item.short_text"></div> <div class="product-buttons ac flex"> <div class="phone" v-if="item.phone"> <button v-if="!show[0]" @click="show[0]=1"><i class="fas fa-phone"></i> חיוג</button> <a class="open" v-if="show[0]" target="_blank" :href="'tel:'+item.phone"><i class="fas fa-phone"></i> {{item.phone}}</a> </div> <div class="mail"> <button @click="focus()"><i class="fas fa-envelope"></i> קביעת תור</button> </div> <!--div class="site" v-if="item.site"> <button v-if="!show[1]" @click="show[1]=1"><i class="fab fa-internet-explorer"></i> אתר</button> <a class="open" v-if="show[1]" target="_blank" :href="item.site"><i class="fab fa-internet-explorer"></i> {{item.site}}</a> </div> <div class="facebook" v-if="item.facebook"> <button v-if="!show[2]" @click="show[2]=1"><i class="fab fa-facebook-square"></i> Facebook</button> <a class="open" v-if="show[2]" target="_blank" :href="item.facebook"><i class="fab fa-facebook-square"></i> {{item.facebook}}</a> </div> <div class="instagram" v-if="item.instagram"> <button v-if="!show[3]" @click="show[3]=1"><i class="fab fa-instagram"></i> Instagram</button> <a class="open" v-if="show[3]" target="_blank" :href="item.instagram"><i class="fab fa-instagram"></i> {{item.instagram}}</a> </div> <div class="youtube" v-if="item.youtube"> <button v-if="!show[4]" @click="show[4]=1"><i class="fab fa-youtube"></i> YouTube</button> <a class="open" v-if="show[4]" target="_blank" :href="item.youtube"><i class="fab fa-youtube"></i> {{item.youtube}}</a> </div--> </div> </div> </div> </div> <div class="product-item line" id="reviewForm"> <div class="address"> <i class="fas fa-map-marker-alt"></i> <span v-if="item.city"> {{item.city}},</span> <span v-if="item.address"> {{item.address}}</span> </div> <div id="map" style="height:350px;width:100%;"></div> </div> <div class="product-item line" id="reviewForm" v-if="showForm==1"> <reviewForm v-if="item!=''" v-model:id="item.id" v-model:title="item.model" /> </div> <div class="product-item line" id="reviewsBlockMainLimit" v-if="!showFullReviews"> <div class="bb"> <h2 class="title">חוות דעת נבחרות</h2> </div> <div class="reviewsPerMark" v-if="item.reviewsStatistics"> <div class="flex"><rating rating="5" :reviewsCount="item.reviewsStatistics[4].count"/><progress :value="item.reviewsStatistics[4].value" max="100"></progress> {{item.reviewsStatistics[4].value}}%</div> <div class="flex"><rating rating="4" :reviewsCount="item.reviewsStatistics[3].count"/><progress :value="item.reviewsStatistics[3].value" max="100"></progress> {{item.reviewsStatistics[3].value}}%</div> <div class="flex"><rating rating="3" :reviewsCount="item.reviewsStatistics[2].count"/><progress :value="item.reviewsStatistics[2].value" max="100"></progress> {{item.reviewsStatistics[2].value}}%</div> <div class="flex"><rating rating="2" :reviewsCount="item.reviewsStatistics[1].count"/><progress :value="item.reviewsStatistics[1].value" max="100"></progress> {{item.reviewsStatistics[1].value}}%</div> <div class="flex"><rating rating="1" :reviewsCount="item.reviewsStatistics[0].count"/><progress :value="item.reviewsStatistics[0].value" max="100"></progress> {{item.reviewsStatistics[0].value}}%</div> </div> <reviewsBlock v-model="item.reviews" limit="5" /> <div class="ac" v-if="item.reviews && Object.keys(item.reviews).length>5"> <a class="btnS" href="#/showFullReviews" @click="hash()">לצפייה בחוות דעת נבחרות</a> </div> </div> <div class="product-item line" v-if="!showFullReviews"> <div class="product-descr" v-if="item.free_text" v-html="item.free_text"></div> </div> <div class="product-item line" id="showFullReviews" v-if="showFullReviews"> <div class="bb"> <h2 class="title">ביקורות</h2> </div> <div class="reviewsPerMark" v-if="item.reviewsStatistics"> <div class="flex"><rating rating="5" :reviewsCount="item.reviewsStatistics[4].count"/><progress :value="item.reviewsStatistics[4].value" max="100"></progress> {{item.reviewsStatistics[4].value}}%</div> <div class="flex"><rating rating="4" :reviewsCount="item.reviewsStatistics[3].count"/><progress :value="item.reviewsStatistics[3].value" max="100"></progress> {{item.reviewsStatistics[3].value}}%</div> <div class="flex"><rating rating="3" :reviewsCount="item.reviewsStatistics[2].count"/><progress :value="item.reviewsStatistics[2].value" max="100"></progress> {{item.reviewsStatistics[2].value}}%</div> <div class="flex"><rating rating="2" :reviewsCount="item.reviewsStatistics[1].count"/><progress :value="item.reviewsStatistics[1].value" max="100"></progress> {{item.reviewsStatistics[1].value}}%</div> <div class="flex"><rating rating="1" :reviewsCount="item.reviewsStatistics[0].count"/><progress :value="item.reviewsStatistics[0].value" max="100"></progress> {{item.reviewsStatistics[0].value}}%</div> </div> <reviewsBlock v-model="item.reviews" /> <pagination :pagination="item.paginationReview" :limit="item.limit"></pagination> </div> </div> <div class="w30 product-form-out"> <div class="product-form product-item line"> <div class="succeess ac" v-if="send==1">הבקשה נשלחה בהצלחה!</div> <form @submit.prevent="submit()" v-if="send==0 && parent.formData"> <div class="row"> <h2><i class="fas fa-envelope"></i> לקביעת תור ושאלות כלליות</h2> </div> <div class="infoMsg">השירות הניתן באמצעות האתר אינו שירות רפואי. תיעוד ומידע רגיש יש למסור לרופאים בלבד.</div> <div class="row"> <input type="text" id="contact-name" name="name" v-model="parent.formData.name" placeholder="שם מלא *" required> </div> <div class="row"> <input type="text" id="contact-phone" name="phone" v-model="parent.formData.phone" placeholder="טלפון *" required> </div> <div class="row"> <input type="email" id="email" name="email" v-model="parent.formData.email" placeholder="אימייל"> </div> <div class="row"> <textarea id="contact-text" required="" name="review-text" v-model="parent.formData.comment" rows="3" placeholder="הערה *"></textarea> <label class="checkbox-container"><input type="checkbox" name="terms" required=""><span class="checkmark"></span>אני מאשר/ת את תנאי השימוש וקבלת תכנים פרסומיים מהאתר</label> </div> <div class="row al"> <button class="btnS" type="submit">שליחת חוות דעת</button> </div> </form> </div> </div> </div> </template>
Да, можно это сделать локально прямо в самом компоненте Vue, добавив динамическую загрузку скриптов внутри вашего метода mounted()
:
Это самый простой способ с минимальными изменениями.
vue<script> import axios from 'axios'; export default { props:['data'], data: function () { return { item:{}, parent:{}, imgs:{}, main:"", active:0, show:[], showForm:0, showFullReviews:0, send:0 } }, watch:{ $route:function(){ if(window.location.hash=='#/reviewForm'){ this.showForm=1; }else{ this.showForm=0; } if(window.location.hash=='#/showFullReviews'){ this.showFullReviews=1; }else{ this.showFullReviews=0; } } }, mounted() { this.parent = this.$parent; this.item = JSON.parse(this.data); this.imgs = this.item.images; if(this.imgs != '') this.main = this.imgs[0].image; if(!this.item.rating){ this.item.rating = 0; } if(!this.item.reviewsCount){ this.item.reviewsCount = 0; } if(!this.item.reviews){ this.item.reviews = []; } this.loadLeafletScripts().then(() => { this.initMap(); if(this.item.lat && this.item.lng) { this.addMarker(this.item.lat, this.item.lng); } }); }, methods:{ loadLeafletScripts() { return new Promise((resolve, reject) => { const leaflet = document.createElement('script'); leaflet.src = '/libs/leaflet/leaflet.js'; leaflet.onload = () => { const gesture = document.createElement('script'); gesture.src = '/libs/leaflet/leaflet-gesture-handling.min.js'; gesture.onload = resolve; gesture.onerror = reject; document.head.appendChild(gesture); }; leaflet.onerror = reject; document.head.appendChild(leaflet); }); }, get:function(start=-1){ var self = this; self.parent.loader=1; var data = new FormData; if(start && start>-1) data.append("start",start); axios.post("/index.php?option=com_crm&task=product.getItem&id="+self.item.id, data).then(function(response){ self.parent.loader=0; if(response.data.item) self.item = response.data.item; }).catch(function(error){ self.parent.$refs.msg.alertFun(error); }); }, scroll:function(i){ this.main = this.imgs[i].image; }, hash(){ setTimeout(function(){ document.querySelector(window.location.hash.replace('/','')).scrollIntoView({ behavior: "smooth", block: "start" }); },100); }, focus(){ document.getElementById('contact-name').focus(); }, submit:function(){ var self = this; var data = self.parent.toFormData(self.parent.formData); if(this.item.id) data.append("id",this.item.id); self.parent.loader=1; axios.post("/index.php?option=com_crm&task=product.addContact",data).then(function(response){ self.parent.loader=0; if(response.data.error){ self.parent.$refs.msg.alertFun(response.data.error); }else{ self.parent.$refs.msg.successFun("Successfully submit request!"); self.send=1; } }).catch(function(error){ self.parent.$refs.msg.alertFun(error); }); }, initMap:function(){ this.map = L.map('map',{ gestureHandling: true }).setView([31.8070207,34.6368603], 12); var osm=new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',{attribution: ''}); osm.addTo(this.map); }, addMarker:function(lat,lng){ if (this.map._layers) { let a = 0; for(let i in this.map._layers){ if (a != 0) { this.map._layers[this.map._layers[i]._leaflet_id].remove(); } a++; } } this.map.setView([lat,lng], 12); var Icon = L.icon({ iconUrl: '/components/com_crm/images/marker.png', iconSize: [20, 30], shadowSize: [20, 30], popupAnchor: [0, -25] }); this.layer = L.marker([lat,lng], {icon: Icon}).addTo(this.map); }, }, }; </script>
loadLeafletScripts()
, который динамически загружает оба скрипта.initMap()
).L
, и плагин gesture-handling
успешно находит её.Теперь, после такого изменения, ошибки исчезнут и карта заработает как ожидается.
а в этом файле
Подключить внешние скрипты прямо внутри блока <template>
в Vue-компоненте напрямую нельзя, потому что Vue не разрешает вставку <script>
тегов внутрь шаблонов компонентов.
Однако, вы можете воспользоваться хитростью, используя хук жизненного цикла mounted()
непосредственно в этом файле, не меняя HTML-файл приложения.
Добавьте в свой текущий компонент (внутри <script>
):
jsmounted() { this.parent = this.$parent; this.item = JSON.parse(this.data); this.imgs = this.item.images; if(this.imgs != '') this.main = this.imgs[0].image; if(!this.item.rating){ this.item.rating = 0; } if(!this.item.reviewsCount){ this.item.reviewsCount = 0; } if(!this.item.reviews){ this.item.reviews = []; } this.loadLeaflet().then(() => { this.initMap(); if(this.item.lat && this.item.lng) this.addMarker(this.item.lat, this.item.lng); }); }, methods: { loadLeaflet() { return new Promise((resolve, reject) => { if(window.L) return resolve(); const leafletScript = document.createElement('script'); leafletScript.src = '/libs/leaflet/leaflet.js'; leafletScript.onload = () => { const gestureScript = document.createElement('script'); gestureScript.src = '/libs/leaflet/leaflet-gesture-handling.min.js'; gestureScript.onload = resolve; gestureScript.onerror = reject; document.head.appendChild(gestureScript); }; leafletScript.onerror = reject; document.head.appendChild(leafletScript); }); }, initMap() { this.map = L.map('map', { gestureHandling: true }) .setView([31.8070207, 34.6368603], 12); var osm = new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { attribution: '' }); osm.addTo(this.map); }, addMarker(lat, lng) { if (this.map._layers) { let a = 0; for(let i in this.map._layers){ if (a != 0) { this.map._layers[this.map._layers[i]._leaflet_id].remove(); } a++; } } this.map.setView([lat,lng], 12); var Icon = L.icon({ iconUrl: '/components/com_crm/images/marker.png', iconSize: [20, 30], shadowSize: [20, 30], popupAnchor: [0, -25] }); this.layer = L.marker([lat,lng], {icon: Icon}).addTo(this.map); }, // другие методы остаются без изменений }
loadLeaflet()
прямо в этот файл, который динамически добавляет скрипты в DOM.window.L
).initMap()
) запускается после загрузки обоих скриптов.Это решение не требует изменения внешних файлов и работает полностью автономно внутри текущего компонента Vue.
После этого ошибка с Leaflet исчезнет, и карта заработает корректно с минимальными изменениями.
как я понимаю теперь всё окей
[vite] connecting...
main.js:163 [Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".
at <App>
warn$1 @ chunk-VZXQDS5F.js?v=b8d18600:2125
finishComponentSetup @ chunk-VZXQDS5F.js?v=b8d18600:10171
setupStatefulComponent @ chunk-VZXQDS5F.js?v=b8d18600:10086
setupComponent @ chunk-VZXQDS5F.js?v=b8d18600:10011
mountComponent @ chunk-VZXQDS5F.js?v=b8d18600:7340
processComponent @ chunk-VZXQDS5F.js?v=b8d18600:7306
patch @ chunk-VZXQDS5F.js?v=b8d18600:6820
render2 @ chunk-VZXQDS5F.js?v=b8d18600:8127
mount @ chunk-VZXQDS5F.js?v=b8d18600:6048
app.mount @ chunk-VZXQDS5F.js?v=b8d18600:12298
(анонимная) @ main.js:163
favicon.ico:1 GET https://diet/templates/articalist/images/favicon.ico 404 (Not Found)
client:826 [vite] connected.
css-generic.js:1 uBOL: Generic cosmetic filtering stopped because no more DOM changes
но при этом страница div id="productsCRM" class="home" data-v-app>
<---!>
Теперь проблема в другом. Ошибка:
[Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue.
говорит о том, что ваша текущая версия Vue не поддерживает компиляцию шаблонов во время выполнения (runtime compilation). Другими словами, вы используете вариант Vue, который не поддерживает использование template: "<div>...</div>"
или рендеринг шаблонов непосредственно из строки/файла напрямую.
Vue 3, при использовании Vite или других современных сборщиков, по умолчанию использует сборку Vue без компилятора шаблонов (runtime-only
). Чтобы использовать шаблоны в файлах .vue
, вы должны:
<template>
.Настройте Vite, чтобы он использовал полную версию Vue с компилятором шаблонов. Это делается очень просто:
vite.config.js
) и добавьте alias:jsimport { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [vue()], resolve: { alias: { 'vue': 'vue/dist/vue.esm-bundler.js' } } });
npm run dev
).В старой версии вашего проекта была включена полная версия Vue (с компилятором), а в новой — runtime-only
.
Добавив указанный выше alias в Vite, вы возвращаете поведение прежней версии.
vite.config.js
, добавив alias для полной сборки Vue.npm run dev
).После этого Vue-компоненты с шаблонами снова начнут рендериться корректно, и проблема уйдет.
вот мой файл, тольько vite.config.mjs обнови
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
export default defineConfig({
plugins: [vue()],
base: './', // относительные пути для билда
build: {
outDir: 'dist',
emptyOutDir: true,
rollupOptions: {
input: path.resolve(__dirname, './index.html') // 👉 подключаем index.html, не main.js
}
},
server: {
proxy: {
'/api': 'http://chiper', // 👉 прокси для API
},
cors: true,
},
resolve: {
alias: {
'@': path.resolve(__dirname, './'),
'@components': path.resolve(__dirname, './components'),
'@router': path.resolve(__dirname, './router'),
'libs': path.resolve(__dirname, 'libs')
},
},
define: {
VUE_OPTIONS_API: true,
VUE_PROD_DEVTOOLS: false,
VUE_PROD_HYDRATION_MISMATCH_DETAILS: false,
}
});
Вот ваш обновлённый vite.config.mjs
, теперь с подключением полной версии Vue, поддерживающей runtime-компиляцию шаблонов:
jsimport { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import path from 'path'; export default defineConfig({ plugins: [vue()], base: './', // относительные пути для билда build: { outDir: 'dist', emptyOutDir: true, rollupOptions: { input: path.resolve(__dirname, './index.html') // 👉 подключаем index.html, не main.js } }, server: { proxy: { '/api': 'http://chiper', // 👉 прокси для API }, cors: true, }, resolve: { alias: { '@': path.resolve(__dirname, './'), '@components': path.resolve(__dirname, './components'), '@router': path.resolve(__dirname, './router'), 'libs': path.resolve(__dirname, 'libs'), 'vue': 'vue/dist/vue.esm-bundler.js' // 👈 добавлен alias для полной версии Vue }, }, define: { __VUE_OPTIONS_API__: true, __VUE_PROD_DEVTOOLS__: false, __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false, } });
Добавлен alias:
js'vue': 'vue/dist/vue.esm-bundler.js'
Теперь Vue-компоненты снова смогут компилироваться в runtime, и ваш проект заработает без указанной ошибки.
Перезапустите Vite, чтобы изменения вступили в силу:
bashnpm run dev
по файлам
<template>
<div class="inside-content">
<div id="spinner" v-if="loader"></div>
</template> <script>text<div class="wrapper"> <div class="topDetails details"> <div class="flex"> <div class="w75 flex l"> <div class="images" v-if=" data.item.images && data.item.images != '' && data.item.images[0] != '' && data.item.images[0].thumb != '' " :style="{ 'background-image': 'url(/media/com_product/images/thumbs/' + data.item.images[0].thumb + ')', }" ></div> <div class="w100"> <div class="title" v-if="data.item && data.item.model" > {{ data.item.model }} </div> <div class="title" v-if="data.item && !data.item.model" > New </div> <div class="flex topdesc"> <div class="w33" v-if="data.item.cat_id != ''"> <label>קטגוריות:</label> <span v-if="data.item.cat_id">{{ data.cats.find( (item) => item.id === data.item.cat_id ).cat_name }}</span> </div> <div class="w33" v-if="data.item.city != ''"> <label>ישוב:</label> <span v-if="data.item.city">{{ data.geos.find( (item) => item.id === data.item.city ).city }}</span> </div> <div class="w33"> <!--div class="row-fluid" v-if="data.item.price"> <label>מחיר:</label> <span>{{data.item.price}}</span> </div--> </div> </div> </div> </div> <div class="w25 rigp l r"> <div class="flex al" v-if="parent.$route && parent.$route.params.id" > <button type="button" @click="$refs.btn.click()" class="btnS" > <i class="fa fa-save"></i>שמור </button> <router-link class="btnS close" to="/" ><i class="fa fa-times"></i>מחק</router-link > </div> <div v-if="!parent.$route || !parent.$route.params.id"> <button type="button" @click="$refs.btn.click()" class="btnS" > <i class="fa fa-plus"></i>הוסף </button> </div> </div> </div> </div> <br /> <form @submit.prevent=" parent.formData = data; action(); " > <button class="hidden" ref="btn"></button> <div class="row"> <div class="tabs tabsln ar"> <ul> <li v-if="tabs" v-for="(t, i) in tabs" :class="{ active: tab == i }" @click="setTab(i)" > <i class="fa fa-user" v-if="i == 0"></i> <i class="fas fa-money-check" v-if="i == 1"></i> <i class="fas fa-thumbs-up" v-if="i == 2"></i> <i class="fas fa-images" v-if="i == 3"></i> <i class="fas fa-map" v-if="i == 4"></i> <i class="fas fa-comments" v-if="i == 5"></i> <i class="fas fa-share" v-if="i == 6"></i> {{ t }} </li> </ul> </div> </div> <div class="flex mp"> <div class="w100 details"> <h3>{{ tabs[tab] }}</h3> <template v-if="tab == 6"> <div class="tabs tabsln sharing ar"> <ul> <li v-for="(t, i) in tabs2" :key="i" :class="[ 'act-' + i, { active: tab2 == i }, ]" @click="tab2 = i" > <i class="fas fa-link" v-if="i == 0" ></i> <i class="fas fa-sms" v-if="i == 1"></i> <i class="fab fa-whatsapp" v-if="i == 2" ></i> <i class="fas fa-envelope" v-if="i == 3" ></i> {{ t }} </li> </ul> </div> <div class="ac"> <img :src="qr" v-if="qr" width="150px" /> </div> <template v-if="tab2 == 0"> <div class="row ar"> <label>Code</label> <textarea :value="genLink(data.item.id)" ></textarea> </div> <div class="row-fluid al"> <button class="btnS" @click.prevent=" copyFunc(genLink(data.item.id)) " > <i class="fas fa-link"></i> העתק קוד </button> </div> </template> <template v-if="tab2 == 1"> <div class="row-fluid ar"> <label>טלפון</label> <input v-model="phone" ref="phone" /> </div> <div class="row-fluid al"> <button class="btnS" @click.prevent="sms()"> <i class="fas fa-sms"></i>שלח SMS </button> </div> </template> <template v-if="tab2 == 2"> <div class="row-fluid ar"> <label>טלפון</label> <input v-model="phone" ref="phone" /> </div> <div class="row-fluid al"> <button class="btnS" @click.prevent="whatsapp()" > <i class="fab fa-whatsapp"></i> שלח Whatsapp </button> </div> </template> <template v-if="tab2 == 3"> <div class="row-fluid ar"> <label>Email</label> <input v-model="email" type="email" ref="email" /> </div> <div class="row-fluid al"> <button class="btnS" @click.prevent="shareMail()" > <i class="fas fa-envelope"></i> שלח אימייל </button> </div> </template> </template> <template v-if="tab == 0"> <div class="row-fluid"> <label>שם בית העסק</label> <input type="text" name="model" v-model="data.item.model" required /> </div> <!--div class="row-fluid"> <label>מחיר</label> <input type="number" name="price" v-model="data.item.price" /> </div--> <div class="row-fluid"> <label>סטטוס</label> <select name="published" v-model="data.item.published" > <option value="1" :selected="data.item.published == 1" > Published </option> <option value="0" :selected="data.item.published == 0" > Not Published </option> </select> </div> <div class="row-fluid"> <label>קטגוריות</label> <select name="cat_id" v-model="data.item.cat_id" v-if="data.cats" > <option :value="g.id" v-for="g in data.cats" > {{ g.cat_name }} </option> </select> </div> <div class="row-fluid"> <label>לקוח</label> <select name="user_id" v-model="data.item.user_id" v-if="data.users" > <option value="0">---</option> <option :value="g.id" v-for="g in data.users" > {{ g.name }} </option> </select> </div> <div class="row-fluid"> <label>טלפון</label> <input type="text" name="phone" v-model="data.item.phone" /> </div> </template> <template v-if="tab == 4"> <div class="row-fluid"> <label>ישוב</label> <select name="city" v-model="data.item.city" v-if="data.geos" > <option :value="g.id" v-for="g in data.geos" > {{ g.city }} </option> </select> </div> <div class="row-fluid"> <label>כתובת</label> <input type="text" name="address" v-model="data.item.address" required /> <button class="btnS" @click.prevent="getCoords()" style="width: 100%" > <i style="padding: 0" class="fa fa-search" ></i> </button> </div> <div id="map" style="height: 350px; width: 100%" ></div> </template> <template v-if="tab == 5"> <div class="table" v-if="data.reviews != ''"> <table> <thead> <tr> <th class="id">#</th> <th></th> <th>תאריך</th> <th class="name">שם מלא</th> <th class="name">כתובת אימייל</th> <th>חוות דעת מפורטת</th> <th class="actions">פעולות</th> </tr> </thead> <tbody v-for="(item, i) in data.reviews"> <tr v-bind:id="'item-' + item.id" :class="{ gray: i % 2 == 0 }" > <td class="id">{{ item.id }}</td> <td class="id"> <toogle v-model="item.published" @change=" parent.formData = item; actionReview(); " /> </td> <td>{{ item.date }}</td> <td>{{ item.name }}</td> <td>{{ item.email }}</td> <td>{{ item.review }}</td> <td class="actions"> <a href="#" class="remove" @click.prevent=" parent.formData = item; delReview(); " ><i class="fa fa-remove"></i ></a> </td> </tr> </tbody> </table> <pagination v-if="data.items != ''" :pagination="data.pagination" :limit="data.limit" ></pagination> </div> <div class="empty" v-if="data.reviews == ''"> No items </div> </template> <template v-if="tab == 1"> <div class="row-fluid"> <label>תיאור</label> <editor v-model="data.item.free_text"></editor> </div> </template> <template v-if="tab == 2"> <div class="row-fluid"> <label>Site</label> <input type="text" name="site" v-model="data.item.site" /> </div> <div class="row-fluid"> <label>Facebook</label> <input type="text" name="facebook" v-model="data.item.facebook" /> </div> <div class="row-fluid"> <label>Instagram</label> <input type="text" name="instagram" v-model="data.item.instagram" /> </div> <div class="row-fluid"> <label>Youtube</label> <input type="text" name="youtube" v-model="data.item.youtube" /> </div> </template> <template v-if="tab == 3"> <div class="row"> <gallery :field="'images'" :imgpath="'/media/com_product/images/thumbs/'" :multiple="true" :images="data.images" :id="data.item.id" :urldelete="'/index.php?option=com_crm&task=user.delFile'" :urlorder="'/index.php?option=com_crm&task=user.fileOrder'" /> </div> </template> </div> </div> </form> </div> </div>
import axios from "axios";
export default {
data: function () {
return {
parent: "",
data: { item: {}, images: [], sizes: {}, colors: {}, cats: {} },
user: [],
tabs: [
"פרטי משתמש",
"תיאורים",
"רשתות חברתיות",
"תמונות",
"כתובת",
"ביקורות",
"שתף קישור",
],
tab: 0,
tabs2: ["Link", "SMS", "WhatsApp", "Email"],
tab2: 0,
date: "",
date2: "",
iChart: -1,
loader: 1,
map: "",
layer: "",
qr: "",
phone: "",
email: "",
};
},
mounted() {
this.parent = this.$parent;
this.item = JSON.parse(this.data);
this.imgs = this.item.images;
if(this.imgs != '') this.main = this.imgs[0].image;
if(!this.item.rating){
this.item.rating = 0;
}
if(!this.item.reviewsCount){
this.item.reviewsCount = 0;
}
if(!this.item.reviews){
this.item.reviews = [];
}
this.loadLeaflet().then(() => {
this.initMap();
if(this.item.lat && this.item.lng) this.addMarker(this.item.lat, this.item.lng);
});
},
methods: {
loadLeaflet() {
return new Promise((resolve, reject) => {
if(window.L) return resolve();
textconst leafletScript = document.createElement('script'); leafletScript.src = '/libs/leaflet/leaflet.js'; leafletScript.onload = () => { const gestureScript = document.createElement('script'); gestureScript.src = '/libs/leaflet/leaflet-gesture-handling.min.js'; gestureScript.onload = resolve; gestureScript.onerror = reject; document.head.appendChild(gestureScript); }; leafletScript.onerror = reject; document.head.appendChild(leafletScript); });
},
initMap: function () {
this.map = L.map("map", { gestureHandling: true }).setView(
[31.8070207, 34.6368603],
12
);
var osm = new L.tileLayer(
"http://{s}.tile.osm.org/{z}/{x}/{y}.png",
{ attribution: "" }
);
osm.addTo(this.map);
},
addMarker: function (lat, lng) {
if (this.map._layers) {
let a = 0;
textfor (let i in this.map._layers) { if (a != 0) { this.map._layers[ this.map._layers[i]._leaflet_id ].remove(); } a++; } //$map.setView([31.8070207, 34.6368603], 12); } this.map.setView([lat, lng], 12); var Icon = L.icon({ iconUrl: "/components/com_crm/images/marker.png", iconSize: [20, 30], // size of the icon shadowSize: [20, 30], // size of the shadow popupAnchor: [0, -25], // point from which the popup should open relative to the iconAnchor }); this.layer = L.marker([lat, lng], { icon: Icon }).addTo(this.map); }, qrFunc: function () { var self = this; var data = new FormData(); if (this.data.item.id) data.append("url", this.genLink(this.data.item.id)); //self.loader=1; axios .post("/index.php?option=com_crm&task=user.qr", data) .then(function (response) { self.loader = 0; self.qr = response.data; }) .catch(function (error) { self.parent.$refs.header.$refs.msg.alertFun(error); }); }, getCoords: function () { var self = this; self.loader = 1; let address = ""; if (this.data.item.city) address += this.data.geos.find( (item) => item.id === this.data.item.city ).city + ", "; address += this.data.item.address; axios .post( "https://maps.google.com/maps/api/geocode/json?address=" + address + "&key=AIzaSyDezmQVCWQd-RleASzxK6iLxcURKdkztqw" ) .then(function (response) { self.loader = 0; if (response.data.results[0]) { self.data.item.lat = response.data.results[0].geometry.location.lat; self.data.item.lng = response.data.results[0].geometry.location.lng; } else if (response.data.results.geometry) { self.data.item.lat = response.data.results.geometry.location.lat; self.data.item.lng = response.data.results.geometry.location.lng; } self.addMarker(self.data.item.lat, self.data.item.lng); }) .catch(function (error) { self.parent.$refs.header.$refs.msg.alertFun(error); }); }, get: function (id = -1) { var self = this; var data = new FormData(); if (id > 0) { data.append("id", id); } else { data.append("id", this.parent.$route.params.id); } self.loader = 1; axios .post("/index.php?option=com_crm&task=user.getProduct", data) .then(function (response) { self.loader = 0; if (response.data) { for (let i in response.data) { if (response.data[i]) self.data[i] = response.data[i]; } } self.qrFunc(); if (self.data.item && self.data.item.model) document.title = self.data.item.model; }) .catch(function (error) { self.parent.$refs.header.$refs.msg.alertFun(error); }); }, action: function () { var self = this; var data = self.parent.toFormData(self.data.item); self.loader = 1; axios .post("/index.php?option=com_crm&task=user.actionProduct", data) .then(function (response) { self.loader = 0; if (response.data.error) { self.parent.$refs.header.$refs.msg.alertFun( response.data.error ); return false; } if (response && response.data.id) { self.parent.$router.replace( "/product/" + response.data.id ); self.get(response.data.id); self.parent.$refs.header.$refs.msg.successFun( "Successfully added product!" ); } else { self.get(); self.parent.$refs.header.$refs.msg.successFun( "Successfully updated product!" ); } }) .catch(function (error) { self.parent.$refs.header.$refs.msg.alertFun(error); }); }, actionReview: function () { var self = this; var data = self.parent.toFormData(self.parent.formData); axios .post("/index.php?option=com_crm&task=user.editReview", data) .then(function (response) { if (self.parent.formData.id) { self.parent.$refs.header.$refs.msg.successFun( "Successfully updated review!" ); } else { self.parent.$refs.header.$refs.msg.successFun( "Successfully added new review!" ); } self.get(); }) .catch(function (error) { self.parent.$refs.header.$refs.msg.alertFun(error); }); }, delReview: async function () { if ( await this.parent.$refs.header.$refs.msg.confirmFun( "Please confirm next action", "Do you want to delete this review?" ) ) { var self = this; var data = self.parent.toFormData(self.parent.formData); axios .post( "/index.php?option=com_crm&task=user.deleteReview", data ) .then(function (response) { self.parent.$refs.header.$refs.msg.successFun( "Successfully deleted review!" ); self.get(); }) .catch(function (error) { self.parent.$refs.header.$refs.msg.alertFun(error); }); } }, setTab: function (i) { let checkCurrent = false; if (this.tab == i) checkCurrent = true; this.tab = i; if (i == 4) { let self = this; setTimeout(function () { if (!checkCurrent) { self.initMap(); if (self.data.item.lat && self.data.item.lng) self.addMarker( self.data.item.lat, self.data.item.lng ); } }, 500); } }, copyFunc: async function (text) { if (navigator && navigator.clipboard) { await navigator.clipboard.writeText(text); this.parent.$refs.header.$refs.msg.successFun( "Successfully copied!" ); this.$refs.copy.active = 0; this.copy = ""; } else { this.parent.$refs.header.$refs.msg.alertFun( "Copy mannualy or use https!" ); } }, genLink: function (id) { let url = window.location.protocol + "//" + window.location.host + "/component/crm/product/" + id + "#/reviewForm"; return url; }, whatsapp: function () { if (this.phone == "") { this.parent.$refs.header.$refs.msg.alertFun("הקלד טלפון!"); this.$refs.phone.focus(); this.$refs.phone.classList.add("focused-class"); return false; } this.$refs.phone.classList.remove("focused-class"); location.href = "https://api.whatsapp.com/send/?phone=" + this.phone + "&text=" + this.genLink(this.data.item.id).replace("#", "%23") + "&type=phone_number&app_absent=0"; }, sms: function () { if (this.phone == "") { this.parent.$refs.header.$refs.msg.alertFun("הקלד טלפון!"); this.$refs.phone.focus(); this.$refs.phone.classList.add("focused-class"); return false; } self.phone = ""; this.parent.$refs.header.$refs.msg.alertFun( "Successfully sent SMS! No one SMS Api not set!" ); }, shareMail: function () { let self = this; if (this.email == "") { this.parent.$refs.header.$refs.msg.alertFun("הקלד אימייל!"); this.$refs.email.focus(); this.$refs.email.classList.add("focused-class"); return false; } this.$refs.email.classList.remove("focused-class"); var data = new FormData(); if (this.email) data.append("email", this.email); if (this.qr) data.append("qr", this.qr); if (this.data.item.id) data.append("url", this.genLink(this.data.item.id)); axios .post("/index.php?option=com_crm&task=user.shareMail", data) .then(function (response) { self.email = ""; self.parent.$refs.header.$refs.msg.successFun( "Successfully sent mail!" ); }) .catch(function (error) { self.parent.$refs.header.$refs.msg.alertFun(error); }); }, },
};
</script>
<script> import axios from 'axios'; export default { props:['data'], data: function () { return { item:{}, parent:{}, imgs:{}, main:"", active:0, show:[], showForm:0, showFullReviews:0, send:0 } }, watch:{ $route:function(){ if(window.location.hash=='#/reviewForm'){ this.showForm=1; }else{ this.showForm=0; } if(window.location.hash=='#/showFullReviews'){ this.showFullReviews=1; }else{ this.showFullReviews=0; } } }, mounted() { this.parent = this.$parent; this.item = JSON.parse(this.data); this.imgs = this.item.images; if(this.imgs != '') this.main = this.imgs[0].image; if(!this.item.rating){ this.item.rating = 0; } if(!this.item.reviewsCount){ this.item.reviewsCount = 0; } if(!this.item.reviews){ this.item.reviews = []; } this.loadLeafletScripts().then(() => { this.initMap(); if(this.item.lat && this.item.lng) { this.addMarker(this.item.lat, this.item.lng); } }); }, methods:{ loadLeafletScripts() { return new Promise((resolve, reject) => { const leaflet = document.createElement('script'); leaflet.src = '/libs/leaflet/leaflet.js'; leaflet.onload = () => { const gesture = document.createElement('script'); gesture.src = '/libs/leaflet/leaflet-gesture-handling.min.js'; gesture.onload = resolve; gesture.onerror = reject; document.head.appendChild(gesture); }; leaflet.onerror = reject; document.head.appendChild(leaflet); }); }, get:function(start=-1){ var self = this; self.parent.loader=1; var data = new FormData; if(start && start>-1) data.append("start",start); axios.post("/index.php?option=com_crm&task=product.getItem&id="+self.item.id, data).then(function(response){ self.parent.loader=0; if(response.data.item) self.item = response.data.item; }).catch(function(error){ self.parent.$refs.msg.alertFun(error); }); }, scroll:function(i){ this.main = this.imgs[i].image; }, hash(){ setTimeout(function(){ document.querySelector(window.location.hash.replace('/','')).scrollIntoView({ behavior: "smooth", block: "start" }); },100); }, focus(){ document.getElementById('contact-name').focus(); }, submit:function(){ var self = this; var data = self.parent.toFormData(self.parent.formData); if(this.item.id) data.append("id",this.item.id); self.parent.loader=1; axios.post("/index.php?option=com_crm&task=product.addContact",data).then(function(response){ self.parent.loader=0; if(response.data.error){ self.parent.$refs.msg.alertFun(response.data.error); }else{ self.parent.$refs.msg.successFun("Successfully submit request!"); self.send=1; } }).catch(function(error){ self.parent.$refs.msg.alertFun(error); }); }, initMap:function(){ this.map = L.map('map',{ gestureHandling: true }).setView([31.8070207,34.6368603], 12); var osm=new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',{attribution: ''}); osm.addTo(this.map); }, addMarker:function(lat,lng){ if (this.map._layers) { let a = 0; for(let i in this.map._layers){ if (a != 0) { this.map._layers[this.map._layers[i]._leaflet_id].remove(); } a++; } } this.map.setView([lat,lng], 12); var Icon = L.icon({ iconUrl: '/components/com_crm/images/marker.png', iconSize: [20, 30], shadowSize: [20, 30], popupAnchor: [0, -25] }); this.layer = L.marker([lat,lng], {icon: Icon}).addTo(this.map); }, }, }; </script>text<template> <div class="flex mm"> <div class="w70 product-page"> <div class="product-item ac line"> <div class="sticky"> <div class="product-images row" id="product-images"> <div class="main-img-out" :class="{'col-lg-9':imgs.length>1}"> <div class="main-img"> <a class="product-page__image-wrapper" v-if="main" @click.prevent="$refs.img.active=1"> <img class="product-page__image-wrapper__image" :src="'/media/com_product/images/full/'+main" :alt="item.model" :title="item.model"> </a> </div> <popup ref="img" fullscreen="true" :title="item.model"> <img :src="'/media/com_product/images/full/'+main" :alt="item.model" :title="item.model"> </popup> </div> <div class="product-images-out col-lg-3 r" v-if="imgs.length>1"> <div class="product-images-in"> <div v-if="imgs" v-for="(img,i) in imgs" class="product-page__image-wrapper" :class="{active:img.image==main}"> <a rel="group" href="#" @click.prevent="scroll(i)"> <img class="product-page__image-thumbs__thumb " :src="'/media/com_product/images/thumbs/'+img.thumb" :alt="item.model"> </a> </div> </div> </div> </div> <div class="after_imgs "> <div class="head" :class="{active:active==1}"> <h1>{{item.model}}</h1> </div> <rating v-if="item!=''" v-model:rating="item.rating" v-model:reviewsCount="item.reviewsCount" /> <div class="product-descr" v-if="item.short_text" v-html="item.short_text"></div> <div class="product-buttons ac flex"> <div class="phone" v-if="item.phone"> <button v-if="!show[0]" @click="show[0]=1"><i class="fas fa-phone"></i> חיוג</button> <a class="open" v-if="show[0]" target="_blank" :href="'tel:'+item.phone"><i class="fas fa-phone"></i> {{item.phone}}</a> </div> <div class="mail"> <button @click="focus()"><i class="fas fa-envelope"></i> קביעת תור</button> </div> <!--div class="site" v-if="item.site"> <button v-if="!show[1]" @click="show[1]=1"><i class="fab fa-internet-explorer"></i> אתר</button> <a class="open" v-if="show[1]" target="_blank" :href="item.site"><i class="fab fa-internet-explorer"></i> {{item.site}}</a> </div> <div class="facebook" v-if="item.facebook"> <button v-if="!show[2]" @click="show[2]=1"><i class="fab fa-facebook-square"></i> Facebook</button> <a class="open" v-if="show[2]" target="_blank" :href="item.facebook"><i class="fab fa-facebook-square"></i> {{item.facebook}}</a> </div> <div class="instagram" v-if="item.instagram"> <button v-if="!show[3]" @click="show[3]=1"><i class="fab fa-instagram"></i> Instagram</button> <a class="open" v-if="show[3]" target="_blank" :href="item.instagram"><i class="fab fa-instagram"></i> {{item.instagram}}</a> </div> <div class="youtube" v-if="item.youtube"> <button v-if="!show[4]" @click="show[4]=1"><i class="fab fa-youtube"></i> YouTube</button> <a class="open" v-if="show[4]" target="_blank" :href="item.youtube"><i class="fab fa-youtube"></i> {{item.youtube}}</a> </div--> </div> </div> </div> </div> <div class="product-item line" id="reviewForm"> <div class="address"> <i class="fas fa-map-marker-alt"></i> <span v-if="item.city"> {{item.city}},</span> <span v-if="item.address"> {{item.address}}</span> </div> <div id="map" style="height:350px;width:100%;"></div> </div> <div class="product-item line" id="reviewForm" v-if="showForm==1"> <reviewForm v-if="item!=''" v-model:id="item.id" v-model:title="item.model" /> </div> <div class="product-item line" id="reviewsBlockMainLimit" v-if="!showFullReviews"> <div class="bb"> <h2 class="title">חוות דעת נבחרות</h2> </div> <div class="reviewsPerMark" v-if="item.reviewsStatistics"> <div class="flex"><rating rating="5" :reviewsCount="item.reviewsStatistics[4].count"/><progress :value="item.reviewsStatistics[4].value" max="100"></progress> {{item.reviewsStatistics[4].value}}%</div> <div class="flex"><rating rating="4" :reviewsCount="item.reviewsStatistics[3].count"/><progress :value="item.reviewsStatistics[3].value" max="100"></progress> {{item.reviewsStatistics[3].value}}%</div> <div class="flex"><rating rating="3" :reviewsCount="item.reviewsStatistics[2].count"/><progress :value="item.reviewsStatistics[2].value" max="100"></progress> {{item.reviewsStatistics[2].value}}%</div> <div class="flex"><rating rating="2" :reviewsCount="item.reviewsStatistics[1].count"/><progress :value="item.reviewsStatistics[1].value" max="100"></progress> {{item.reviewsStatistics[1].value}}%</div> <div class="flex"><rating rating="1" :reviewsCount="item.reviewsStatistics[0].count"/><progress :value="item.reviewsStatistics[0].value" max="100"></progress> {{item.reviewsStatistics[0].value}}%</div> </div> <reviewsBlock v-model="item.reviews" limit="5" /> <div class="ac" v-if="item.reviews && Object.keys(item.reviews).length>5"> <a class="btnS" href="#/showFullReviews" @click="hash()">לצפייה בחוות דעת נבחרות</a> </div> </div> <div class="product-item line" v-if="!showFullReviews"> <div class="product-descr" v-if="item.free_text" v-html="item.free_text"></div> </div> <div class="product-item line" id="showFullReviews" v-if="showFullReviews"> <div class="bb"> <h2 class="title">ביקורות</h2> </div> <div class="reviewsPerMark" v-if="item.reviewsStatistics"> <div class="flex"><rating rating="5" :reviewsCount="item.reviewsStatistics[4].count"/><progress :value="item.reviewsStatistics[4].value" max="100"></progress> {{item.reviewsStatistics[4].value}}%</div> <div class="flex"><rating rating="4" :reviewsCount="item.reviewsStatistics[3].count"/><progress :value="item.reviewsStatistics[3].value" max="100"></progress> {{item.reviewsStatistics[3].value}}%</div> <div class="flex"><rating rating="3" :reviewsCount="item.reviewsStatistics[2].count"/><progress :value="item.reviewsStatistics[2].value" max="100"></progress> {{item.reviewsStatistics[2].value}}%</div> <div class="flex"><rating rating="2" :reviewsCount="item.reviewsStatistics[1].count"/><progress :value="item.reviewsStatistics[1].value" max="100"></progress> {{item.reviewsStatistics[1].value}}%</div> <div class="flex"><rating rating="1" :reviewsCount="item.reviewsStatistics[0].count"/><progress :value="item.reviewsStatistics[0].value" max="100"></progress> {{item.reviewsStatistics[0].value}}%</div> </div> <reviewsBlock v-model="item.reviews" /> <pagination :pagination="item.paginationReview" :limit="item.limit"></pagination> </div> </div> <div class="w30 product-form-out"> <div class="product-form product-item line"> <div class="succeess ac" v-if="send==1">הבקשה נשלחה בהצלחה!</div> <form @submit.prevent="submit()" v-if="send==0 && parent.formData"> <div class="row"> <h2><i class="fas fa-envelope"></i> לקביעת תור ושאלות כלליות</h2> </div> <div class="infoMsg">השירות הניתן באמצעות האתר אינו שירות רפואי. תיעוד ומידע רגיש יש למסור לרופאים בלבד.</div> <div class="row"> <input type="text" id="contact-name" name="name" v-model="parent.formData.name" placeholder="שם מלא *" required> </div> <div class="row"> <input type="text" id="contact-phone" name="phone" v-model="parent.formData.phone" placeholder="טלפון *" required> </div> <div class="row"> <input type="email" id="email" name="email" v-model="parent.formData.email" placeholder="אימייל"> </div> <div class="row"> <textarea id="contact-text" required="" name="review-text" v-model="parent.formData.comment" rows="3" placeholder="הערה *"></textarea> <label class="checkbox-container"><input type="checkbox" name="terms" required=""><span class="checkmark"></span>אני מאשר/ת את תנאי השימוש וקבלת תכנים פרסומיים מהאתר</label> </div> <div class="row al"> <button class="btnS" type="submit">שליחת חוות דעת</button> </div> </form> </div> </div> </div> </template>
GET https://diet/libs/leaflet/leaflet.js net::ERR_ABORTED 404 (Not Found)
(анонимная) @ product.vue:219
loadLeafletScripts @ product.vue:208
mounted @ product.vue:199
(анонимная) @ chunk-2EZIC2KI.js?v=dc5bacf7:5176
callWithErrorHandling @ chunk-2EZIC2KI.js?v=dc5bacf7:2517
callWithAsyncErrorHandling @ chunk-2EZIC2KI.js?v=dc5bacf7:2524
hook.__weh.hook.__weh @ chunk-2EZIC2KI.js?v=dc5bacf7:5156
flushPostFlushCbs @ chunk-2EZIC2KI.js?v=dc5bacf7:2702
render2 @ chunk-2EZIC2KI.js?v=dc5bacf7:8386
mount @ chunk-2EZIC2KI.js?v=dc5bacf7:6293
app.mount @ chunk-2EZIC2KI.js?v=dc5bacf7:12543
(анонимная) @ main.js:163
1329:1 Refused to execute script from 'https://diet/libs/leaflet/leaflet.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
1329:1 Uncaught (in promise) Event {isTrusted: true, type: 'error', target: script, currentTarget: null, eventPhase: 0, …}
Ошибка сейчас возникает из-за неверного пути к файлам Leaflet:
GET https://diet/libs/leaflet/leaflet.js net::ERR_ABORTED 404 (Not Found)
Это значит, что путь /libs/leaflet/leaflet.js
неверный.
Убедитесь, что файлы leaflet.js и leaflet-gesture-handling.min.js находятся в правильном месте в вашем проекте. Скорее всего, они лежат внутри директории public
.
Если файлы находятся в папке public
, используйте путь вида:
js'/leaflet/leaflet.js' '/leaflet/leaflet-gesture-handling.min.js'
Исправьте метод loadLeafletScripts()
следующим образом:
jsloadLeafletScripts() { return new Promise((resolve, reject) => { const leaflet = document.createElement('script'); leaflet.src = '/leaflet/leaflet.js'; // <-- исправлен путь leaflet.onload = () => { const gesture = document.createElement('script'); gesture.src = '/leaflet/leaflet-gesture-handling.min.js'; // <-- исправлен путь gesture.onload = resolve; gesture.onerror = reject; document.head.appendChild(gesture); }; leaflet.onerror = reject; document.head.appendChild(leaflet); }); },
text├─ public │ ├─ leaflet │ │ ├─ leaflet.js │ │ ├─ leaflet-gesture-handling.min.js │ │ └─ leaflet.css
При сборке проекта через Vite, папка /libs
не существует автоматически. Vite берёт статические файлы из папки public
. Если вы хотите, чтобы файлы были доступны через абсолютный путь, их необходимо положить именно в public
.
После исправления пути ошибка исчезнет и Leaflet загрузится корректно.
Они находсяься по пути E:\Program2\OSPanel2\domains\diet\components\com_crm\js\libs\leaflet
а те файлы в котоые подключаем E:\Program2\OSPanel2\domains\diet\components\com_crm\js\components и E:\Program2\OSPanel2\domains\diet\components\com_crm\js\pages
Вот в чём причина:
У вас файлы расположены в таком месте, что они не доступны напрямую через сервер по текущему пути (/libs/leaflet/
). Vite или любой локальный сервер, как правило, обслуживает статические файлы из определённых папок (обычно это папка public
).
https://diet/libs/leaflet/leaflet.js
because its MIME type ('text/html') is not executable
Скопируйте папку leaflet
(целиком) сюда:
E:\Program2\OSPanel2\domains\diet\public\leaflet\
Если папки public
нет, создайте её рядом с вашим проектом (в корне проекта).
После этого структура должна быть:
textdiet ├── public │ └── leaflet │ ├── leaflet.js │ ├── leaflet-gesture-handling.min.js │ └── leaflet.css
После переноса исправьте пути в вашем компоненте Vue на следующие:
jsloadLeafletScripts() { return new Promise((resolve, reject) => { const leaflet = document.createElement('script'); leaflet.src = '/leaflet/leaflet.js'; // путь теперь корректный leaflet.onload = () => { const gesture = document.createElement('script'); gesture.src = '/leaflet/leaflet-gesture-handling.min.js'; gesture.onload = resolve; gesture.onerror = reject; document.head.appendChild(gesture); }; leaflet.onerror = reject; document.head.appendChild(leaflet); }); },
Перезапустите Vite (для гарантии):
bashnpm run dev
https://diet/leaflet/leaflet.js
Таким образом, проблема исчезнет.
я так не могу сделай под меня
Хорошо, вот полностью рабочий вариант под вашу текущую структуру проекта, который будет работать именно с вашим расположением файлов, без необходимости переносить папки.
Поскольку ваши файлы Leaflet находятся здесь:
E:\Program2\OSPanel2\domains\diet\components\com_crm\js\libs\leaflet\
а компонент, в котором вы подключаете Leaflet, лежит тут:
E:\Program2\OSPanel2\domains\diet\components\com_crm\js\components\
То корректный относительный путь будет:
text../libs/leaflet/leaflet.js ../libs/leaflet/leaflet-gesture-handling.min.js
loadLeafletScripts()
так:jsloadLeafletScripts() { return new Promise((resolve, reject) => { const leaflet = document.createElement('script'); leaflet.src = '../libs/leaflet/leaflet.js'; // 👈 исправленный путь leaflet.onload = () => { const gesture = document.createElement('script'); gesture.src = '../libs/leaflet/leaflet-gesture-handling.min.js'; // 👈 исправленный путь gesture.onload = resolve; gesture.onerror = reject; document.head.appendChild(gesture); }; leaflet.onerror = reject; document.head.appendChild(leaflet); }); },
../
поднимает вас на уровень выше (components/com_crm/js
) и далее заходит в папку libs
.Таким образом, браузер сможет правильно найти файлы Leaflet и подгрузить их.
npm run dev
).После этих действий Leaflet загрузится правильно, и ошибки исчезнут.
заменил
methods: {
loadLeafletScripts() {
return new Promise((resolve, reject) => {
const leaflet = document.createElement('script');
leaflet.src = '../libs/leaflet/leaflet.js'; // 👈 исправленный путь
leaflet.onload = () => {
const gesture = document.createElement('script');
gesture.src = '../libs/leaflet/leaflet-gesture-handling.min.js'; // 👈 исправленный путь
gesture.onload = resolve;
gesture.onerror = reject;
document.head.appendChild(gesture);
};
leaflet.onerror = reject;
document.head.appendChild(leaflet);
});
},
консоль - product.vue:219
GET https://diet/component/crm/libs/leaflet/leaflet.js net::ERR_ABORTED 404 (Not Found)
1329:1 Refused to execute script from 'https://diet/component/crm/libs/leaflet/leaflet.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
1329:1 Uncaught (in promise)
Event {isTrusted: true, type: 'error', target: script, currentTarget: null, eventPhase: 0, …}
Проблема возникла, так как вы запускаете код на сервере (не через Vite), и в браузере адрес вычисляется от корня сайта, а не от текущего файла на диске.
Браузер воспринимает путь ../libs/leaflet/leaflet.js
относительно адреса страницы (https://diet/component/crm/
), а не относительно файловой структуры на сервере.
В результате браузер ищет файл здесь:
https://diet/component/crm/libs/leaflet/leaflet.js
А его нет.
Поскольку у вас файлы расположены внутри компонента Joomla, правильный абсолютный путь, доступный из браузера, будет:
/components/com_crm/js/libs/leaflet/leaflet.js
Исправьте путь в компоненте на абсолютный:
jsloadLeafletScripts() { return new Promise((resolve, reject) => { const leaflet = document.createElement('script'); leaflet.src = '/components/com_crm/js/libs/leaflet/leaflet.js'; // ✅ исправленный путь leaflet.onload = () => { const gesture = document.createElement('script'); gesture.src = '/components/com_crm/js/libs/leaflet/leaflet-gesture-handling.min.js'; // ✅ исправленный путь gesture.onload = resolve; gesture.onerror = reject; document.head.appendChild(gesture); }; leaflet.onerror = reject; document.head.appendChild(leaflet); }); },
/
, и браузер однозначно найдет нужный файл.Убедитесь, что директория E:\Program2\OSPanel2\domains\diet\components\com_crm\js\libs\leaflet\
реально доступна через браузер по адресу:
https://diet/components/com_crm/js/libs/leaflet/leaflet.js
Откройте его вручную в браузере, чтобы проверить.
Ошибка исчезнет, Leaflet загрузится, и всё заработает как нужно.
у меня проблема 0 - Unsatisfied dependency "module" for an asset "crm-vite" of type "script" и не открываеться никакая страница я заметил что в файле controller.php
$document->addStyleSheet(JURI::root() . "components/com_crm/js/libs/leaflet/leaflet.css");
text$document->addStyleSheet(JURI::root() . "components/com_crm/css/font-awesome5.css"); $document->addStyleSheet(JURI::root() . "components/com_crm/css/template.css"); $document->addStyleSheet(JURI::root() . "components/com_crm/js/libs/ckeditor5.css"); $document->addScript('http://localhost:5173/main.js', false, array('type' => 'module')); // $document->addScript(JURI::root() . "administrator/components/com_crm/js/dist/assets/index-CfCQ57wZ.js",false,array("type"=>"module"));
раскомментирова это а в файле
index.php
// wa->registerAndUseStyle('crm-fontawesome5', 'components/com_crm/css/font-awesome5.css');
// wa->registerAndUseStyle('crm-ckeditor5', 'components/com_crm/js/libs/ckeditor5.css');
// wa->registerAndUseScript('crm-app', 'administrator/components/com_crm/js/dist/assets/index-CfCQ57wZ.js', [], [], ['type' => 'module']);
заккоментировал это значит проблема в переносе с файл в файл
возможно нужно иначе пренести
Да, вы абсолютно правильно поняли проблему.
Ошибка:
0 - Unsatisfied dependency "module" for an asset "crm-vite" of type "script"
означает, что при использовании Joomla API WebAsset
:
php$wa->registerAndUseScript('crm-vite', 'http://localhost:5173/main.js', [], [], ['type' => 'module']);
Joomla пытается загрузить скрипт как модуль через WebAsset-менеджер, но зависимость типа "module"
не удовлетворяется.
WebAsset Manager Joomla (особенно начиная с Joomla 4) требует чётко указанных зависимостей, когда вы регистрируете скрипты с типом module
. Если вы хотите использовать скрипты с Vite через WebAsset API, вам нужно сначала явно зарегистрировать скрипт без зависимостей.
Ваш способ загрузки через:
php$document->addScript('http://localhost:5173/main.js', false, array('type' => 'module'));
работал корректно, так как он напрямую вставлял скрипт в HTML без проверки зависимостей.
Используйте WebAsset Manager правильно. Вот как это сделать в index.php
вашего компонента:
index.php (правильно зарегистрировать ассет):
php/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = Factory::getApplication()->getDocument()->getWebAssetManager(); $wa->registerScript( 'crm-vite', 'http://localhost:5173/main.js', [], ['type' => 'module'], ['defer' => true] ); // затем используете скрипт явно: $wa->useScript('crm-vite');
Это наиболее стабильный способ при работе с Joomla WebAsset Manager.
Если вам нужна максимально простая интеграция и вы хотите использовать только $document->addScript
, убедитесь, что:
controller.php
(или основном файле компонента) есть:php$document->addScript('http://localhost:5173/main.js', false, ['type' => 'module']);
index.php
удалите или полностью закомментируйте использование WebAsset для этого скрипта:php// полностью удалить или закомментировать // $wa->registerAndUseScript('crm-vite', 'http://localhost:5173/main.js', [], [], ['type' => 'module']);
Таким образом, Joomla не будет пытаться проверять зависимости, и ошибка исчезнет.
php$document->addStyleSheet(JURI::root() . "components/com_crm/js/libs/leaflet/leaflet.css"); $document->addStyleSheet(JURI::root() . "components/com_crm/css/font-awesome5.css"); $document->addStyleSheet(JURI::root() . "components/com_crm/css/template.css"); $document->addStyleSheet(JURI::root() . "components/com_crm/js/libs/ckeditor5.css"); $document->addScript('http://localhost:5173/main.js', false, ['type' => 'module']);
php// $wa->registerAndUseStyle('crm-leaflet', 'components/com_crm/js/libs/leaflet/leaflet.css'); // $wa->registerAndUseStyle('crm-fontawesome5', 'components/com_crm/css/font-awesome5.css'); // $wa->registerAndUseStyle('crm-template', 'components/com_crm/css/template.css'); // $wa->registerAndUseStyle('crm-ckeditor5', 'components/com_crm/js/libs/ckeditor5.css'); // $wa->registerAndUseScript('crm-vite', 'http://localhost:5173/main.js', [], [], ['type' => 'module']); // $wa->registerAndUseScript('crm-app', 'administrator/components/com_crm/js/dist/assets/index-CfCQ57wZ.js', [], [], ['type' => 'module']);
Это полностью избавит вас от ошибки:
0 - Unsatisfied dependency "module"
И ваш Vite-скрипт заработает снова корректно.
addScript
вставляет скрипты напрямую, игнорируя WebAsset зависимости.Сейчас вы вернёте работу компонента полностью через $document->addScript
.
Сделайте эти исправления прямо сейчас, и всё заработает без ошибок.
мне нужно правильно подключить это из controller.php $document->addStyleSheet(JURI::root() . "components/com_crm/js/libs/leaflet/leaflet.css");
text$document->addStyleSheet(JURI::root() . "components/com_crm/css/font-awesome5.css"); $document->addStyleSheet(JURI::root() . "components/com_crm/css/template.css"); $document->addStyleSheet(JURI::root() . "components/com_crm/js/libs/ckeditor5.css"); $document->addScript(JURI::root() . "/components/com_crm/js/dist/assets/index-Du2ODnW-.js",false,array("type"=>"module"));
в index.php и желательно в <head> и саблюдать, что бы пути не сломались файл E:\Program2\OSPanel2\domains\diet\components\com_crm\controller.php и второй E:\Program2\OSPanel2\domains\diet\templates\articalist\index.php
<?php /** * @package Joomla.Site * @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\CMS\Factory; use Joomla\CMS\Uri\Uri; $currentUrl = Uri::current(); $app = Factory::getApplication(); $user = Factory::getUser(); $wa = $this->getWebAssetManager(); $wa->registerAndUseStyle('bootstrap', 'media/vendor/bootstrap/css/bootstrap.min.css'); // $wa->registerAndUseStyle('fonts', 'templates/dreamview/assets/fonts/stylesheet.css'); $wa->registerAndUseStyle('main', "templates/{$this->template}/css/template.css"); $wa->registerAndUseScript('main', "templates/{$this->template}/js/myjs.js", [], [], ['jquery']); $input = $app->getInput(); $menu = $app->getMenu()->getActive(); if ($input->get('view') !== 'article' && $input->get('view') !== 'category') { $showTwitterDescription = true; } else { $showTwitterDescription = false; } ?> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $this->language; ?>" lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>"> <head></head> <body class="body body-<?php echo isset($_REQUEST['lang']) && !empty($_REQUEST['lang']) ? $_REQUEST['lang'] : ""; ?>" id="body-<?php echo $app->input->getCmd('Itemid', ''); ?>"> <header class=" <?php if (isset($images) && !empty($images)) echo 'fixed'; ?>">text<jdoc:include type="metas" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="robots" content="index, follow"> <?php if ($showTwitterDescription): ?> <meta name="description" content="פרסם מאמרים באתר Diet-news וקבל חשיפה מקסימלית, קישורים לאתר שלך, ותנועה איכותית. הצטרף למומחים בפרסום מאמרים עכשיו!"> <meta property="og:title" content="Diet-news - פרסום מאמרים לקידום אתרים ושיווק דיגיטלי"> <meta property="og:image" content="https://www.diet-news.co.il/images/logo.svg"> <meta property="og:image:alt" content="Diet-news - לוגו האתר"> <meta property="og:url" content="<?= $currentUrl; ?>"> <meta property="og:type" content="website"> <meta property="og:locale" content="he_IL"> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:title" content="Diet-news - פרסום מאמרים באינטרנט"> <meta name="twitter:image" content="https://www.diet-news.co.il/images/logo.svg"> <meta name="twitter:site" content="@Diet-news"> <?php endif; ?> <jdoc:include type="styles" /> <link href="<?= $currentUrl; ?>" rel="canonical"> <link rel="icon" href="/templates/articalist/images/favicon.ico" type="image/x-icon"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha512-SfTiTlX6kk+qitfevl/7LibUOeJWlt9rbyDn92a1DqWOw9vWG2MFoays0sgObmWazO5BQPiFucnnEAjpAB+/Sw==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <script> var user = JSON.parse('<?php echo json_encode(JFactory::getUser());?>'); </script>
</body> </html>text<div class="wrapper"> <div class="mid-header"> <div class="flex-row"> <button id="toggle-btn"> <i class="fa fa-bars hamburger-icon"></i> </button> <div class="menu-link user-wrap"> <?php if ($user->id == null): ?> <a href='/login' class="signin" @click.prevent="$refs.login.active=1"> <span>התחברות</span> <svg width="14" height="16" viewBox="0 0 14 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7 8C4.78125 8 3 6.21875 3 4C3 1.8125 4.78125 0 7 0C9.1875 0 11 1.8125 11 4C11 6.21875 9.1875 8 7 8ZM9.78125 9C12.0938 9 14 10.9062 14 13.2188V14.5C14 15.3438 13.3125 16 12.5 16H1.5C0.65625 16 0 15.3438 0 14.5V13.2188C0 10.9062 1.875 9 4.1875 9H4.71875C5.40625 9.34375 6.1875 9.5 7 9.5C7.8125 9.5 8.5625 9.34375 9.25 9H9.78125Z" fill="currentColor"></path> </svg> </a> <popup v-if="user.id==0" ref="login" title="היכנס או צור חשבון"><login /></popup> <? else: ?> <div class="username"> <p id="user-btn"><?php echo $user->name; ?></p> <div class="hidden-block d-none"> <a href="/component/crm/user">החשבון שלי</a> <a class="prod-link" href="/component/users/?task=user.logout&<?php echo JSession::getFormToken(); ?>=1">להתנתק</a> </div> </div> <? endif; ?> </div> <a class="search-button"> <svg fill="#393f48" height="24px" width="24px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-24.42 -24.42 537.24 537.24" xml:space="preserve" stroke="#393f48" stroke-width="48.839999999999996"> <g id="SVGRepo_bgCarrier" stroke-width="0"></g> <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g> <g id="SVGRepo_iconCarrier"> <g> <g> <path d="M0,203.25c0,112.1,91.2,203.2,203.2,203.2c51.6,0,98.8-19.4,134.7-51.2l129.5,129.5 c2.4,2.4,5.5,3.6,8.7,3.6s6.3-1.2,8.7-3.6c4.8-4.8,4.8-12.5,0-17.3l-129.6-129.5 c31.8-35.9,51.2-83,51.2-134.7 c0-112.1-91.2-203.2-203.2-203.2S0,91.15,0,203.25z M381.9,203.25c0,98.5-80.2,178.7-178.7,178.7s-178.7-80.2-178.7-178.7 s80.2-178.7,178.7-178.7S381.9,104.65,381.9,203.25z"> </path> </g> </g> </g> </svg> </a> </div> <div class="flex-row"> <?php if ($this->countModules('menu')): ?> <div id="menu"> <jdoc:include type="modules" name="menu" style="none" /> </div> <?php endif; ?> <div id="logo"> <a href="/"> <img src="<?php echo $this->baseurl ?>/templates/<?php echo $this->template ?>/images/logo.png" alt="Diet-news Logo" /> <span>חדשות הרזיה ודיאטה</span> </a> </div> </div> </div> </div> <form class="search-wrap" action="/מאמרים-אחרונים"> <div class="wrapper"> <button type="submit">תזונאים</button> <input name="q" class="search" type="text" value="<?php echo (isset($_GET['q']) && !empty($_GET['q'])) ? $_GET['q'] : ""; ?>" /> </div> </form> </header><!-- .header--> <div class="middle"> <main class="content"> <div class="wrapper"> <jdoc:include type="component" /> <button class="swipe-up"><img src="<?php echo $this->baseurl ?>/templates/<?php echo $this->template ?>/images/thumb/up-thumb.png" alt="Shevron Up" /></button> </div> </main><!-- .content --> </div><!-- .middle--> <footer class="footer"> <div class="wrapper"> <div class="row"> <div class="col right-col"> <div id="logo"> <a href="/"> <img src="<?php echo $this->baseurl ?>/templates/<?php echo $this->template ?>/images/logo-dark.png" alt="Diet-news Logo" /> <span>חדשות הרזיה ודיאטה</span> </a> </div> <div class="footer-soc"> <?php if ($this->countModules('footer-soc')): ?> <jdoc:include type="modules" name="footer-soc" style="xhtml" /> </div> <?php endif; ?> </div> <div class="menus"> <?php echo JHtml::_('content.prepare', '{loadmoduleid 128} '); ?> <?php echo JHtml::_('content.prepare', '{loadmoduleid 129} '); ?> <?php echo JHtml::_('content.prepare', '{loadmoduleid 130} '); ?> </div> </div> <div class="rights">זכויות יוצרים © 2023 diet-news.co.il</div> </div> </footer><!-- .footer --> <jdoc:include type="scripts" /> <!-- UNUSED OLD SCRIPTS --> <script defer type="text/javascript" src="<?php echo $this->baseurl ?>/templates/<?php echo $this->template ?>/js/lazysizes.min.js"></script> <script defer> $(document).ready(function () { $('img').each(function () { var actualSrc = $(this).attr('src'); $(this).addClass('lazyload'); $(this).attr('data-src', actualSrc); }); }); </script> <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7317212061301483" crossorigin="anonymous"></script> <script async language="JavaScript" type="text/javascript" src="<?php echo $this->baseurl ?>/templates/<?php echo $this->template ?>/js/social_button_redirect.js"></script>
Вот правильный и чистый способ, как аккуратно и правильно подключить ваши CSS и JS из компонента (из файла controller.php
) в шаблоне Joomla (templates/articalist/index.php
):
controller.php
)Удалите или закомментируйте из файла:
php// $document->addStyleSheet(JURI::root() . "components/com_crm/js/libs/leaflet/leaflet.css"); // $document->addStyleSheet(JURI::root() . "components/com_crm/css/font-awesome5.css"); // $document->addStyleSheet(JURI::root() . "components/com_crm/css/template.css"); // $document->addStyleSheet(JURI::root() . "components/com_crm/js/libs/ckeditor5.css"); // $document->addScript(JURI::root() . "/components/com_crm/js/dist/assets/index-Du2ODnW-.js",false,array("type"=>"module"));
index.php
шаблона через WebAsset)Вставьте этот код в файл:
templates/articalist/index.php
(прямо перед </head>
):
php<?php // Подключаем WebAsset Manager use Joomla\CMS\Factory; $wa = Factory::getApplication()->getDocument()->getWebAssetManager(); // Регистрируем CSS-файлы вашего компонента $wa->registerAndUseStyle('crm-leaflet', 'components/com_crm/js/libs/leaflet/leaflet.css'); $wa->registerAndUseStyle('crm-fontawesome5', 'components/com_crm/css/font-awesome5.css'); $wa->registerAndUseStyle('crm-template', 'components/com_crm/css/template.css'); $wa->registerAndUseStyle('crm-ckeditor5', 'components/com_crm/js/libs/ckeditor5.css'); // Регистрируем JS-файл вашего компонента как module $wa->registerAndUseScript( 'crm-vite', 'components/com_crm/js/dist/assets/index-Du2ODnW-.js', [], [], ['type' => 'module', 'defer' => true] ); ?>
components/...
), поэтому ничего не ломается при перемещении.module
с атрибутом defer
, это оптимально.html<head> <!-- другие метатеги и элементы --> <!-- Подключенные CSS через WebAsset --> <link rel="stylesheet" href="/components/com_crm/js/libs/leaflet/leaflet.css"> <link rel="stylesheet" href="/components/com_crm/css/font-awesome5.css"> <link rel="stylesheet" href="/components/com_crm/css/template.css"> <link rel="stylesheet" href="/components/com_crm/js/libs/ckeditor5.css"> <!-- Подключенный JS (Vite) --> <script type="module" defer src="/components/com_crm/js/dist/assets/index-Du2ODnW-.js"></script> </head>
👉 Выполните указанные шаги, и ваша проблема полностью решится, а структура будет чистой и стабильной.
0 - Unsatisfied dependency "module" for an asset "crm-vite" of type "script
Ошибка:
0 - Unsatisfied dependency "module" for an asset "crm-vite" of type "script"
возникает из-за неверного вызова метода:
php$wa->registerAndUseScript( 'crm-vite', 'components/com_crm/js/dist/assets/index-Du2ODnW-.js', [], [], ['type' => 'module', 'defer' => true] );
У метода registerAndUseScript
неверный порядок параметров. Правильный синтаксис Joomla выглядит так:
phpregisterAndUseScript($name, $uri, $options = [], $attributes = [], $dependencies = []);
Вы передали атрибуты в место зависимостей, а Joomla считает, что 'type' => 'module'
— это зависимость (dependency), и ищет зависимость с именем "module"
, которой не существует.
Исправьте подключение на:
php// CSS $wa->registerAndUseStyle('crm-leaflet', 'components/com_crm/js/libs/leaflet/leaflet.css'); $wa->registerAndUseStyle('crm-fontawesome5', 'components/com_crm/css/font-awesome5.css'); $wa->registerAndUseStyle('crm-template', 'components/com_crm/css/template.css'); $wa->registerAndUseStyle('crm-ckeditor5', 'components/com_crm/js/libs/ckeditor5.css'); // JS module (исправленный вызов!) $wa->registerAndUseScript( 'crm-vite', 'components/com_crm/js/dist/assets/index-Du2ODnW-.js', [], // options ['type' => 'module', 'defer' => true], // attributes [] // dependencies );
'type' => 'module', 'defer' => true
) должны быть четвёртым параметром, не пятым.Правильно:
phpregisterAndUseScript($name, $uri, $options, $attributes, $dependencies);
index.php
):php<?php // Подключаем WebAsset Manager use Joomla\CMS\Factory; $wa = Factory::getApplication()->getDocument()->getWebAssetManager(); // CSS вашего компонента $wa->registerAndUseStyle('crm-leaflet', 'components/com_crm/js/libs/leaflet/leaflet.css'); $wa->registerAndUseStyle('crm-fontawesome5', 'components/com_crm/css/font-awesome5.css'); $wa->registerAndUseStyle('crm-template', 'components/com_crm/css/template.css'); $wa->registerAndUseStyle('crm-ckeditor5', 'components/com_crm/js/libs/ckeditor5.css'); // JS вашего компонента (исправлен!) $wa->registerAndUseScript( 'crm-vite', 'components/com_crm/js/dist/assets/index-Du2ODnW-.js', [], ['type' => 'module', 'defer' => true], [] ); ?>
После этого Joomla перестанет требовать отсутствующую зависимость "module"
, и ошибка исчезнет полностью.
вот как выглядит код страницы
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="he-il" lang="he-il" dir="rtl"> <head></head> <body class="body body-" id="body-165"> <header class=" ">text<meta charset="utf-8"> <title>ביקורות</title> <link href="/favicon.ico" rel="icon" type="image/vnd.microsoft.icon"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="robots" content="index, follow"> <meta name="description" content="פרסם מאמרים באתר Diet-news וקבל חשיפה מקסימלית, קישורים לאתר שלך, ותנועה איכותית. הצטרף למומחים בפרסום מאמרים עכשיו!"> <meta property="og:title" content="Diet-news - פרסום מאמרים לקידום אתרים ושיווק דיגיטלי"> <meta property="og:image" content="https://www.diet-news.co.il/images/logo.svg"> <meta property="og:image:alt" content="Diet-news - לוגו האתר"> <meta property="og:url" content="https://diet/%D7%91%D7%99%D7%A7%D7%95%D7%A8%D7%95%D7%AA"> <meta property="og:type" content="website"> <meta property="og:locale" content="he_IL"> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:title" content="Diet-news - פרסום מאמרים באינטרנט"> <meta name="twitter:image" content="https://www.diet-news.co.il/images/logo.svg"> <meta name="twitter:site" content="@Diet-news"> <link href="/components/com_crm/js/libs/leaflet/leaflet.css?c02d44" rel="stylesheet" /> <link href="/components/com_crm/css/font-awesome5.css?c02d44" rel="stylesheet" /> <link href="/components/com_crm/css/template.css?c02d44" rel="stylesheet" /> <link href="/components/com_crm/js/libs/ckeditor5.css?c02d44" rel="stylesheet" /> <link href="/media/vendor/bootstrap/css/bootstrap.min.css?c02d44" rel="stylesheet" /> <link href="/templates/articalist/css/template.css?c02d44" rel="stylesheet" /> <link href="https://diet/%D7%91%D7%99%D7%A7%D7%95%D7%A8%D7%95%D7%AA" rel="canonical"> <link rel="icon" href="/templates/articalist/images/favicon.ico" type="image/x-icon"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha512-SfTiTlX6kk+qitfevl/7LibUOeJWlt9rbyDn92a1DqWOw9vWG2MFoays0sgObmWazO5BQPiFucnnEAjpAB+/Sw==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <script> var user = JSON.parse('{"id":0,"name":null,"username":null,"email":null,"password":null,"password_clear":"","block":null,"sendEmail":0,"registerDate":null,"lastvisitDate":null,"activation":null,"params":null,"groups":["9"],"guest":1,"lastResetTime":null,"resetCount":null,"requireReset":null,"typeAlias":null,"otpKey":null,"otep":null,"authProvider":null}'); </script>
<ul class="nav menu"> <li class="item-101 default"><a href="/" >דף הבית</a></li><li class="item-102"><a href="/אודות" >אודות</a></li><li class="item-103"><a href="/פרסום-מאמר" >הנחיות עריכה</a></li><li class="item-104"><a href="/מאמרים-אחרונים" >מאמרים אחרונים</a></li><li class="item-165 current active"><a href="/ביקורות" >ביקורות</a></li><li class="item-105"><a href="/צור-קשר" >צור קשר</a></li></ul>text<div class="wrapper"> <div class="mid-header"> <div class="flex-row"> <button id="toggle-btn"> <i class="fa fa-bars hamburger-icon"></i> </button> <div class="menu-link user-wrap"> <a href='/login' class="signin" @click.prevent="$refs.login.active=1"> <span>התחברות</span> <svg width="14" height="16" viewBox="0 0 14 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7 8C4.78125 8 3 6.21875 3 4C3 1.8125 4.78125 0 7 0C9.1875 0 11 1.8125 11 4C11 6.21875 9.1875 8 7 8ZM9.78125 9C12.0938 9 14 10.9062 14 13.2188V14.5C14 15.3438 13.3125 16 12.5 16H1.5C0.65625 16 0 15.3438 0 14.5V13.2188C0 10.9062 1.875 9 4.1875 9H4.71875C5.40625 9.34375 6.1875 9.5 7 9.5C7.8125 9.5 8.5625 9.34375 9.25 9H9.78125Z" fill="currentColor"></path> </svg> </a> <popup v-if="user.id==0" ref="login" title="היכנס או צור חשבון"><login /></popup> </div> <a class="search-button"> <svg fill="#393f48" height="24px" width="24px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-24.42 -24.42 537.24 537.24" xml:space="preserve" stroke="#393f48" stroke-width="48.839999999999996"> <g id="SVGRepo_bgCarrier" stroke-width="0"></g> <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g> <g id="SVGRepo_iconCarrier"> <g> <g> <path d="M0,203.25c0,112.1,91.2,203.2,203.2,203.2c51.6,0,98.8-19.4,134.7-51.2l129.5,129.5 c2.4,2.4,5.5,3.6,8.7,3.6s6.3-1.2,8.7-3.6c4.8-4.8,4.8-12.5,0-17.3l-129.6-129.5 c31.8-35.9,51.2-83,51.2-134.7 c0-112.1-91.2-203.2-203.2-203.2S0,91.15,0,203.25z M381.9,203.25c0,98.5-80.2,178.7-178.7,178.7s-178.7-80.2-178.7-178.7 s80.2-178.7,178.7-178.7S381.9,104.65,381.9,203.25z"> </path> </g> </g> </g> </svg> </a> </div> <div class="flex-row"> <div id="menu">
</script> <div id="productsCRM" class="home"> <msg ref="msg"></msg> <div id="spinner" v-if="loader==1"></div> <div class="topBanner">text</div> <div id="logo"> <a href="/"> <img src="/templates/articalist/images/logo.png" alt="Diet-news Logo" /> <span>חדשות הרזיה ודיאטה</span> </a> </div> </div> </div> </div> <form class="search-wrap" action="/מאמרים-אחרונים"> <div class="wrapper"> <button type="submit">תזונאים</button> <input name="q" class="search" type="text" value="" /> </div> </form> </header><!-- .header--> <div class="middle"> <main class="content"> <div class="wrapper"> <script> var user = JSON.parse('{"id":0,"name":null,"username":null,"email":null,"password":null,"password_clear":"","block":null,"sendEmail":0,"registerDate":null,"lastvisitDate":null,"activation":null,"params":null,"groups":["9"],"guest":1,"lastResetTime":null,"resetCount":null,"requireReset":null,"typeAlias":null,"otpKey":null,"otep":null,"authProvider":null}');
</div>text<a class="loginLink" href="#" @click.prevent="$refs.login.active=1" v-if="user.id==0">דיאטנית? צור את הפרופיל שלך</a> <a class="loginLink" href="/component/crm/user" v-if="user.id>0">שלום {{user.name}}</a> <div class="title"> <div class="wrapper ar"> מצא את התזונאים הטובים ביותר<br> וקבל את העצות הטובות ביותר </div> </div> <filterprods class="wrapper" reload="true" data='[{"id":486,"city":"\u05d3\u05d0\u05dc\u05d9\u05ea \u05d0\u05dc-\u05db\u05e8\u05de\u05dc"},{"id":487,"city":"\u05db\u05e4\u05e8 \u05e1\u05d1\u05d0"},{"id":488,"city":"\u05d4\u05e8\u05e6\u05dc\u05d9\u05d4"},{"id":489,"city":"\u05de\u05e9\u05de\u05e8 \u05d4\u05e9\u05d1\u05e2\u05d4"},{"id":490,"city":"\u05ea\u05dc \u05d0\u05d1\u05d9\u05d1 - \u05d9\u05e4\u05d5"},{"id":491,"city":"\u05e8\u05d0\u05e9 \u05d4\u05e2\u05d9\u05df"},{"id":492,"city":"\u05d7\u05d5\u05dc\u05d5\u05df"},{"id":493,"city":"\u05e4\u05ea\u05d7 \u05ea\u05e7\u05d5\u05d5\u05d4"},{"id":494,"city":"\u05e8\u05de\u05ea \u05d2\u05df"},{"id":495,"city":"\u05d9\u05d4\u05d5\u05d3-\u05de\u05d5\u05e0\u05d5\u05e1\u05d5\u05df"},{"id":496,"city":"\u05d0\u05d5\u05e8 \u05e2\u05e7\u05d9\u05d1\u05d0"},{"id":497,"city":"\u05e2\u05e4\u05d5\u05dc\u05d4"},{"id":498,"city":"\u05d7\u05d3\u05e8\u05d4"},{"id":499,"city":"\u05d6\u05db\u05e8\u05d5\u05df \u05d9\u05e2\u05e7\u05d1"},{"id":500,"city":"\u05e8\u05e2\u05e0\u05e0\u05d4"},{"id":501,"city":"\u05db\u05e4\u05e8 \u05d9\u05d5\u05e0\u05d4"},{"id":502,"city":"\u05e8\u05d0\u05e9\u05d5\u05df \u05dc\u05e6\u05d9\u05d5\u05df"},{"id":503,"city":"\u05d1\u05ea \u05d9\u05dd"},{"id":504,"city":"\u05d0\u05e9\u05e7\u05dc\u05d5\u05df"},{"id":505,"city":"\u05e8\u05d7\u05d5\u05d1\u05d5\u05ea"},{"id":506,"city":"\u05d9\u05e8\u05d5\u05e9\u05dc\u05d9\u05dd"},{"id":507,"city":"\u05e2\u05db\u05d5"},{"id":508,"city":"\u05e7\u05e8\u05d9\u05ea \u05e2\u05e7\u05e8\u05d5\u05df"},{"id":509,"city":"\u05e0\u05e1 \u05e6\u05d9\u05d5\u05e0\u05d4"},{"id":510,"city":"\u05de\u05d6\u05db\u05e8\u05ea \u05d1\u05ea\u05d9\u05d4"},{"id":511,"city":"\u05e7\u05e8\u05d9\u05ea \u05d0\u05d5\u05e0\u05d5"},{"id":513,"city":"\u05d4\u05d5\u05d3 \u05d4\u05e9\u05e8\u05d5\u05df"},{"id":514,"city":"\u05d7\u05d9\u05e4\u05d4"},{"id":515,"city":"\u05e7\u05dc\u05e0\u05e1\u05d5\u05d5\u05d4"},{"id":516,"city":"\u05de\u05d1\u05e9\u05e8\u05ea \u05e6\u05d9\u05d5\u05df"},{"id":517,"city":"\u05d1\u05d0\u05e8 \u05e9\u05d1\u05e2"},{"id":518,"city":"\u05e2\u05e1\u05e4\u05d9\u05d0"},{"id":519,"city":"\u05d0\u05e8\u05d9\u05d0\u05dc"},{"id":521,"city":"\u05d0\u05e9\u05d3\u05d5\u05d3"},{"id":522,"city":"\u05e2\u05d6\u05e8\u05d9\u05e7\u05dd"},{"id":523,"city":"\u05d1\u05d9\u05ea \u05e9\u05de\u05e9"},{"id":524,"city":"\u05d2\u05df \u05d9\u05d1\u05e0\u05d4"},{"id":525,"city":"\u05d2\u05d1\u05e2\u05ea\u05d9\u05d9\u05dd"},{"id":526,"city":"\u05e8\u05de\u05dc\u05d4"},{"id":527,"city":"\u05d0\u05d5\u05dd \u05d0\u05dc-\u05e4\u05d7\u05dd"},{"id":528,"city":"\u05d1\u05d0\u05e8 \u05d9\u05e2\u05e7\u05d1"},{"id":529,"city":"\u05d9\u05d1\u05e0\u05d4"},{"id":530,"city":"\u05d1\u05d9\u05ea\u05df \u05d0\u05d4\u05e8\u05df"},{"id":531,"city":"\u05d2\u05d1\u05e2\u05ea \u05e9\u05de\u05d5\u05d0\u05dc"},{"id":532,"city":"\u05d0\u05d5\u05e8 \u05d9\u05d4\u05d5\u05d3\u05d4"},{"id":533,"city":"\u05e4\u05e8\u05d3\u05e1 \u05d7\u05e0\u05d4-\u05db\u05e8\u05db\u05d5\u05e8"},{"id":534,"city":"\u05d7\u05de\u05d3\u05d9\u05d4"},{"id":535,"city":"\u05d2\u05e0\u05d9 \u05ea\u05e7\u05d5\u05d5\u05d4"},{"id":536,"city":"\u05e9\u05d5\u05d4\u05dd"},{"id":537,"city":"\u05d1\u05d0\u05e7\u05d4 \u05d0\u05dc-\u05d2\u05e8\u05d1\u05d9\u05d4"},{"id":538,"city":"\u05d0\u05d6\u05d5\u05e8"},{"id":539,"city":"\u05e7\u05e8\u05d9\u05ea \u05de\u05d5\u05e6\u05e7\u05d9\u05df"},{"id":540,"city":"\u05e0\u05ea\u05e0\u05d9\u05d4"},{"id":541,"city":"\u05e8\u05de\u05ea \u05d4\u05e9\u05e8\u05d5\u05df"},{"id":542,"city":"\u05e7\u05e8\u05d9\u05ea \u05d1\u05d9\u05d0\u05dc\u05d9\u05e7"},{"id":543,"city":"\u05d0\u05dc\u05e2\u05d3"},{"id":544,"city":"\u05e7\u05e8\u05d9\u05ea \u05d9\u05dd"},{"id":545,"city":"\u05e2\u05e8\u05e2\u05e8\u05d4"},{"id":546,"city":"\u05d2\u05d3\u05e8\u05d4"},{"id":547,"city":"\u05d1\u05e0\u05d9 \u05d1\u05e8\u05e7"},{"id":548,"city":"\u05e8\u05e2\u05d5\u05ea"},{"id":549,"city":"\u05de\u05d5\u05d3\u05d9\u05e2\u05d9\u05df \u05e2\u05d9\u05dc\u05d9\u05ea"},{"id":550,"city":"\u05d2\u05dc\u05d2\u05d5\u05dc\u05d9\u05d4"},{"id":551,"city":"\u05d8\u05d1\u05e8\u05d9\u05d4"},{"id":552,"city":"\u05db\u05e8\u05de\u05d9\u05d0\u05dc"},{"id":553,"city":"\u05e7\u05e8\u05d9\u05ea \u05d0\u05ea\u05d0"},{"id":554,"city":"\u05d2\u05ea"},{"id":555,"city":"\u05d8\u05d9\u05d9\u05d1\u05d4"},{"id":556,"city":"\u05d8\u05d9\u05e8\u05d4"},{"id":557,"city":"\u05e0\u05e9\u05e8"},{"id":558,"city":"\u05db\u05e4\u05e8 \u05e7\u05d0\u05e1\u05dd"},{"id":559,"city":"\u05d1\u05df \u05d6\u05db\u05d0\u05d9"},{"id":560,"city":"\u05d1\u05d0\u05e8\u05d5\u05ea \u05d9\u05e6\u05d7\u05e7"},{"id":561,"city":"\u05db\u05e4\u05e8 \u05d7\u05d1\"\u05d3"},{"id":562,"city":"\u05ea\u05dc \u05de\u05d5\u05e0\u05d3"},{"id":563,"city":"\u05de\u05d7\u05e0\u05d9\u05d9\u05dd"},{"id":564,"city":"\u05d0\u05dc\u05e4\u05d9 \u05de\u05e0\u05e9\u05d4"},{"id":565,"city":"\u05e2\u05d5\u05e1\u05e4\u05d9\u05d4"},{"id":566,"city":"\u05d0\u05d9\u05d9\u05e8\u05e4\u05d5\u05e8\u05d8 \u05e1\u05d9\u05d8\u05d9"},{"id":567,"city":"\u05d0\u05dc\u05d9\u05db\u05d9\u05df"},{"id":568,"city":"\u05de\u05e9\u05de\u05e8 \u05d4\u05e9\u05e8\u05d5\u05df"},{"id":569,"city":"\u05d1\u05d9\u05ea \u05d9\u05e6\u05d7\u05e7-\u05e9\u05e2\u05e8 \u05d7\u05e4\u05e8"},{"id":570,"city":"\u05db\u05e4\u05e8 \u05e0\u05d7\u05e3"},{"id":572,"city":"\u05e4\u05d5\u05e8\u05d3\u05d9\u05d9\u05e1"},{"id":573,"city":"\u05d1\u05e0\u05d9\u05de\u05d9\u05e0\u05d4-\u05d2\u05d1\u05e2\u05ea \u05e2\u05d3\u05d4"},{"id":574,"city":"\u05e6\u05e4\u05ea"},{"id":575,"city":"\u05e0\u05e6\u05e8\u05ea"},{"id":576,"city":"\u05d1\u05d9\u05ea \u05d7\u05d9\u05e8\u05d5\u05ea"},{"id":577,"city":"\u05e9\u05d3\u05e8\u05d5\u05ea"},{"id":579,"city":"\u05d4\u05d2\u05d5\u05e9\u05e8\u05d9\u05dd"},{"id":580,"city":"\u05e7\u05e8\u05d9\u05ea \u05e9\u05de\u05d5\u05e0\u05d4"},{"id":581,"city":"\u05d0\u05d9\u05dc\u05ea"},{"id":582,"city":"\u05d9\u05e7\u05d5\u05dd"},{"id":583,"city":"\u05d3\u05d9\u05de\u05d5\u05e0\u05d4"},{"id":584,"city":"\u05d9\u05e7\u05e0\u05e2\u05dd"},{"id":585,"city":"\u05e8\u05de\u05ea \u05d9\u05e9\u05d9"},{"id":586,"city":"\u05e7\u05e8\u05d9\u05ea \u05d2\u05ea"},{"id":587,"city":"\u05d1\u05d9\u05ea \u05dc\u05d7\u05dd \u05d4\u05d2\u05dc\u05d9\u05dc\u05d9\u05ea"},{"id":588,"city":"\u05db\u05e4\u05e8 \u05d0\u05d7\u05d9\u05dd"},{"id":590,"city":"\u05e6\u05e4\u05e8\u05d9\u05d4"},{"id":591,"city":"\u05d2\u05d1\u05e2\u05ea \u05d6\u05d0\u05d1"},{"id":592,"city":"\u05e0\u05ea\u05d9\u05d1\u05d5\u05ea"},{"id":593,"city":"\u05d0\u05e0\u05d9\u05e2\u05dd"},{"id":594,"city":"\u05e0\u05d5\u05d5\u05d4 \u05de\u05d1\u05d8\u05d7"},{"id":595,"city":"\u05de\u05e6\u05dc\u05d9\u05d7"},{"id":596,"city":"\u05e2\u05d5\u05dc\u05e9"},{"id":597,"city":"\u05d1\u05e0\u05d9 \u05e6\u05d9\u05d5\u05df"},{"id":598,"city":"\u05ea\u05e0\u05d5\u05d1\u05d5\u05ea"},{"id":599,"city":"\u05e6\u05d5\u05e8 \u05de\u05e9\u05d4"},{"id":600,"city":"\u05e1\u05d1\u05d9\u05d5\u05df"},{"id":601,"city":"\u05e0\u05e2\u05df"},{"id":602,"city":"\u05e0\u05d9\u05e6\u05e0\u05d9 \u05e2\u05d5\u05d6"},{"id":603,"city":"\u05e2\u05e8\u05d3"},{"id":605,"city":"\u05e4\u05ea\u05d7 \u05ea\u05e7\u05d5\u05d4"},{"id":606,"city":"\u05e6\u05e8\u05d9\u05e4\u05d9\u05df"},{"id":607,"city":"\u05d9\u05d4\u05d5\u05d3"},{"id":608,"city":"\u05e8\u05e9\u05e4\u05d5\u05df"},{"id":609,"city":"\u05db\u05d5\u05db\u05d1 \u05d9\u05d0\u05d9\u05e8"},{"id":610,"city":"\u05db\u05e0\u05d5\u05ea"},{"id":611,"city":"\u05d1\u05ea \u05e9\u05dc\u05de\u05d4"},{"id":612,"city":"\u05d0\u05d1\u05df \u05d9\u05d4\u05d5\u05d3\u05d4"},{"id":613,"city":"\u05de\u05d5\u05d3\u05d9\u05e2\u05d9\u05df"},{"id":614,"city":"\u05dc\u05d4\u05d1\u05d5\u05ea \u05d4\u05d1\u05e9\u05df"},{"id":615,"city":"\u05e0\u05d7\u05dc\u05d9\u05dd"},{"id":616,"city":"\u05d1\u05d0\u05e8 \u05d8\u05d5\u05d1\u05d9\u05d4"},{"id":617,"city":"\u05e7\u05d3\u05d9\u05de\u05d4"},{"id":618,"city":"\u05e6\u05d5\u05e8\u05df"},{"id":619,"city":"\u05d0\u05de\u05d9\u05e8\u05d9\u05dd"},{"id":620,"city":"\u05d2\u05df \u05e9\u05dc\u05de\u05d4"},{"id":621,"city":"\u05e0\u05d4\u05e8\u05d9\u05d4"},{"id":622,"city":"\u05d1\u05e0\u05d9 \u05d3\u05e8\u05d5\u05e8"},{"id":623,"city":"\u05e2\u05d9\u05df \u05d4\u05d5\u05d3"},{"id":624,"city":"\u05e8\u05d0\u05e9 \u05e4\u05d9\u05e0\u05d4"},{"id":625,"city":"\u05e0\u05e6\u05e8\u05ea \u05e2\u05d9\u05dc\u05d9\u05ea"},{"id":626,"city":"\u05dc\u05d5\u05d3"},{"id":627,"city":"\u05d1\u05d9\u05ea \u05d7\u05e9\u05de\u05d5\u05e0\u05d0\u05d9"},{"id":628,"city":"\u05de\u05e0\u05d7\u05de\u05d9\u05d4"},{"id":629,"city":"\u05d1\u05d5\u05e1\u05ea\u05df \u05d4\u05d2\u05dc\u05d9\u05dc"},{"id":630,"city":"\u05de\u05d1\u05d5\u05d0 \u05d1\u05d9\u05ea\u05e8"},{"id":631,"city":"\u05d0\u05e4\u05e8\u05ea\u05d4"},{"id":632,"city":"\u05d0\u05d5\u05e4\u05e7\u05d9\u05dd"},{"id":633,"city":"\u05d9\u05e7\u05e0\u05e2\u05dd \u05e2\u05d9\u05dc\u05d9\u05ea"},{"id":634,"city":"\u05de\u05e2\u05dc\u05d4 \u05d0\u05d3\u05d5\u05de\u05d9\u05dd"},{"id":635,"city":"\u05d8\u05d9\u05e8\u05ea \u05db\u05e8\u05de\u05dc"},{"id":636,"city":"\u05d1\u05d9\u05ea \u05e9\u05d0\u05df"},{"id":637,"city":"\u05e7\u05e6\u05e8\u05d9\u05df"},{"id":638,"city":"\u05d0\u05d5\u05e8\u05e0\u05d9\u05dd"},{"id":639,"city":"\u05e0\u05d5\u05d5\u05d4 \u05d9\u05de\u05d9\u05df"},{"id":640,"city":"\u05e0\u05d7\u05e9\u05d5\u05e0\u05d9\u05dd"},{"id":641,"city":"\u05d9\u05e7\u05d9\u05e8"},{"id":642,"city":"\u05e7\u05e8\u05d9\u05ea \u05de\u05dc\u05d0\u05db\u05d9"},{"id":643,"city":"\u05e7\u05d1\u05d5\u05e6\u05ea \u05d9\u05d1\u05e0\u05d4"},{"id":644,"city":"\u05e9\u05d7\u05e8"},{"id":645,"city":"\u05de\u05d5\u05d3\u05d9\u05e2\u05d9\u05df-\u05de\u05db\u05d1\u05d9\u05dd-\u05e8\u05e2\u05d5\u05ea"},{"id":646,"city":"\u05db\u05e4\u05e8 \u05e8\u05d5\u05ea"},{"id":647,"city":"\u05e9\u05d9\u05dc\u05ea"},{"id":648,"city":"\u05de\u05d5\u05e2\u05e6\u05d4 \u05d0\u05d6\u05d5\u05e8\u05d9\u05ea \u05de\u05d8\u05d4 \u05d1\u05e0\u05d9\u05de\u05d9\u05df "},{"id":649,"city":"\u05d0\u05d5\u05e8\u05e0\u05d9\u05ea"},{"id":650,"city":"\u05d0\u05d1\u05d5 \u05d2\u05d5\u05e9"},{"id":652,"city":"\u05e7.\u05d2\u05ea"},{"id":653,"city":"\u05d9\u05e8\u05d7\u05d9\u05d1"},{"id":654,"city":"\u05db\u05e4\u05e8 \u05e9\u05de\u05e8\u05d9\u05d4\u05d5"},{"id":656,"city":"\u05db\u05e4\u05e8 \u05de\u05d5\u05e0\u05e9"},{"id":657,"city":"\u05e4\u05e8\u05d3\u05e1\u05d9\u05d4"},{"id":658,"city":"\u05d9\u05d6\u05e8\u05e2\u05d0\u05dc"},{"id":659,"city":"\u05e7\u05e8\u05d9\u05ea \u05d8\u05d1\u05e2\u05d5\u05df"},{"id":660,"city":"\u05de\u05d2\u05d3\u05dc \u05d4\u05e2\u05de\u05e7"},{"id":661,"city":"\u05d8\u05de\u05e8\u05d4"},{"id":662,"city":"\u05e1\u05d7\u05e0\u05d9\u05df"},{"id":663,"city":"\u05de\u05d2\u05d3 \u05d0\u05dc-\u05db\u05e8\u05d5\u05dd"},{"id":664,"city":"\u05e8\u05d0\u05de\u05d4"},{"id":665,"city":"\u05de\u05d2\u05d0\u05e8"},{"id":666,"city":"\u05e9\u05e4\u05e8\u05e2\u05dd"},{"id":667,"city":"\u05d8\u05d9\u05d1\u05d4"},{"id":668,"city":"\u05de\u05d1\u05e7\u05d9\u05e2\u05d9\u05dd"},{"id":669,"city":"\u05d6\u05e8\u05d6\u05d9\u05e8"},{"id":670,"city":"\u05d3\u05d9\u05d9\u05e8 \u05d0\u05dc-\u05d0\u05e1\u05d3"},{"id":671,"city":"\u05d1\u05d9\u05ea \u05d0\u05e8\u05d9\u05d4"},{"id":672,"city":"\u05e9\u05e2\u05e8\u05d9 \u05ea\u05e7\u05d5\u05d5\u05d4"},{"id":673,"city":"\u05e2\u05dc\u05d9 \u05d6\u05d4\u05d1"},{"id":674,"city":"\u05d2\u05e0\u05d9 \u05d8\u05dc"},{"id":675,"city":"\u05db\u05e4\u05e8 \u05d1\u05e8\u05d0"},{"id":676,"city":"\u05e6\u05d5\u05e4\u05d9\u05dd"},{"id":677,"city":"\u05e8\u05de\u05d5\u05ea \u05d4\u05e9\u05d1\u05d9\u05dd"},{"id":678,"city":"\u05d2\u05df \u05e9\u05d5\u05e8\u05e7"},{"id":679,"city":"\u05e0\u05d8\u05e2\u05d9\u05dd"},{"id":680,"city":"\u05d7\u05e6\u05d5\u05e8 \u05d4\u05d2\u05dc\u05d9\u05dc\u05d9\u05ea"},{"id":681,"city":"\u05e7\u05d3\u05d9\u05de\u05d4-\u05e6\u05d5\u05e8\u05df"},{"id":682,"city":"\u05e9\u05e4\u05e8"},{"id":683,"city":"\u05d9\u05e1\u05d5\u05d3 \u05d4\u05de\u05e2\u05dc\u05d4"},{"id":684,"city":"\u05d7\u05d6\u05d5\u05df"},{"id":685,"city":"\u05e0\u05d9\u05e8 \u05d0\u05dc\u05d9\u05d4\u05d5"},{"id":686,"city":"\u05d9\u05d2\u05dc"},{"id":687,"city":"\u05de\u05d1\u05d5\u05d0\u05d5\u05ea \u05d7\u05e8\u05de\u05d5\u05df"},{"id":688,"city":"\u05d2\u05d1\u05e2\u05ea \u05d0\u05d5\u05dc\u05d2\u05d4"},{"id":689,"city":"\u05d7\u05e8\u05d9\u05e9"},{"id":690,"city":"\u05e2\u05d9\u05df \u05d1\u05d5\u05e7\u05e7"},{"id":691,"city":"\u05db\u05e8\u05de\u05dc"},{"id":692,"city":"\u05e8\u05d9\u05e0\u05ea\u05d9\u05d4"},{"id":693,"city":"\u05d1\u05e0\u05d9 \u05e2\u05d8\u05e8\u05d5\u05ea"},{"id":694,"city":"\u05d0\u05dc\u05d9\u05e9\u05de\u05e2"},{"id":695,"city":"\u05d6\u05de\u05e8"},{"id":696,"city":"\u05d1\u05ea \u05d7\u05e4\u05e8"},{"id":697,"city":"\u05de\u05e1\u05e2\u05d3\u05d4"},{"id":698,"city":"\u05de\u05e2\u05dc\u05d5\u05ea-\u05ea\u05e8\u05e9\u05d9\u05d7\u05d0"},{"id":699,"city":"\u05d9\u05e8\u05db\u05d0"},{"id":700,"city":"\u05de\u05d6\u05d5\u05e8"},{"id":701,"city":"\u05e9\u05ea\u05d5\u05dc\u05d9\u05dd"},{"id":702,"city":"\u05e0\u05d5\u05d5\u05d4 \u05d9\u05e8\u05e7"},{"id":703,"city":"\u05d7\u05e9\u05de\u05d5\u05e0\u05d0\u05d9\u05dd"},{"id":704,"city":"\u05e2\u05d6\u05e8\u05d9\u05d4"},{"id":705,"city":"\u05d1\u05d9\u05ea \u05d4\u05e2\u05de\u05e7"},{"id":706,"city":"\u05de\u05e2\u05d9\u05dc\u05d9\u05d0"},{"id":707,"city":"\u05d7\u05d5\u05e8\u05e4\u05d9\u05e9"},{"id":708,"city":"\u05e9\u05dc\u05d5\u05de\u05d9"},{"id":709,"city":"\u05db\u05e4\u05e8 \u05d1\u05d9\u05dc\"\u05d5"},{"id":710,"city":"\u05e8\u05d1\u05d3\u05d9\u05dd"},{"id":711,"city":"\u05dc\u05e4\u05d9\u05d3"},{"id":842,"city":"\u05e6\u05d5\u05de\u05ea \u05de\u05d1\u05e7\u05d9\u05e2\u05d9\u05dd"},{"id":928,"city":"\u05d2\u05d1\u05e2\u05ea \u05d1\u05e8\u05e0\u05e8"},{"id":929,"city":"\u05e2\u05e9\u05e8\u05ea"},{"id":930,"city":"\u05e2\u05d6\u05e8"},{"id":931,"city":"\u05e8\u05de\u05d5\u05ea"},{"id":932,"city":"\u05db\u05e4\u05e8 \u05d7\u05d5\u05e9\u05df"},{"id":933,"city":"\u05e2\u05ea\u05dc\u05d9\u05ea"},{"id":934,"city":"\u05d1\u05e8\u05d5\u05e8 \u05d7\u05d9\u05dc"},{"id":935,"city":"\u05d9\u05e6\u05d9\u05e5"},{"id":937,"city":"\u05d2\u05d1\u05e2 \u05d1\u05e0\u05d9\u05de\u05d9\u05df"},{"id":938,"city":"\u05e2\u05d5\u05de\u05e8"},{"id":939,"city":"\u05d1\u05d9\u05ea \u05d9\u05d4\u05d5\u05e9\u05e2"},{"id":941,"city":"\u05d1\u05d9\u05ea \u05d7\u05e0\u05df"},{"id":942,"city":"\u05dc\u05d4\u05d1\u05d9\u05dd"},{"id":943,"city":"\u05de\u05d9\u05e8\u05d5\u05df"},{"id":944,"city":"\u05e7\u05e8\u05e0\u05d9 \u05e9\u05d5\u05de\u05e8\u05d5\u05df"},{"id":945,"city":"\u05d7\u05d3-\u05e0\u05e1"},{"id":946,"city":"\u05e0\u05d5\u05e3 \u05d4\u05d2\u05dc\u05d9\u05dc "},{"id":947,"city":"\u05e1\u05db\u05e0\u05d9\u05df "},{"id":948,"city":"\u05e2\u05e8\u05d5\u05d2\u05d5\u05ea"},{"id":949,"city":"\u05d1\u05d9\u05e6\u05e8\u05d5\u05df"},{"id":950,"city":"\u05de\u05d8\u05d5\u05dc\u05d4"},{"id":952,"city":"\u05db\u05e4\u05e8 \u05d8\u05e8\u05d5\u05de\u05df"},{"id":954,"city":"\u05de\u05d9\u05e9\u05d5\u05e8 \u05d0\u05d3\u05d5\u05de\u05d9\u05dd "},{"id":956,"city":"\u05db\u05e4\u05e8 \u05d0\u05d6\u05e8"},{"id":957,"city":"\u05d9\u05e4\u05d9\u05e2"},{"id":958,"city":"\u05e9\u05e2\u05e8 \u05d1\u05d9\u05e0\u05d9\u05de\u05d9\u05df "},{"id":959,"city":"\u05d2\u05d5\u05dc\u05e1"},{"id":960,"city":"\u05d1\u05d9\u05ea\u05e8 \u05e2\u05d9\u05dc\u05d9\u05ea"},{"id":961,"city":"\u05d2\u05d5\u05e9 \u05d7\u05dc\u05d1 "},{"id":962,"city":"\u05e7\u05d9\u05e1\u05e8\u05d9\u05d4"},{"id":963,"city":"\u05db\u05e8\u05dd \u05e9\u05dc\u05d5\u05dd"},{"id":964,"city":"\u05d1\u05d9\u05ea \u05d0\u05dc\u05e2\u05d6\u05e8\u05d9"},{"id":965,"city":"\u05d1\u05e8\u05e7\u05d0\u05d9"},{"id":966,"city":"\u05d7\u05de\u05d3"},{"id":967,"city":"\u05e2\u05e8\u05d0\u05d1\u05d4"},{"id":969,"city":"\u05db\u05e4\u05e8 \u05e1\u05e0\u05d3\u05dc\u05d4"},{"id":970,"city":"\u05d1\u05e8\u05d8\u05e2\u05d4"},{"id":971,"city":"\u05d0\u05db\u05e1\u05d0\u05dc"},{"id":972,"city":"\u05d1\u05ea - \u05d9\u05dd "},{"id":974,"city":"\u05de\u05db\u05d1\u05d9\u05dd "},{"id":975,"city":"\u05d3\u05d9\u05e8 \u05d7\u05e0\u05d0"},{"id":976,"city":"\u05d9\u05e8\u05d5\u05d7\u05dd"},{"id":977,"city":"\u05e0\u05d9\u05e8\u05d9\u05ea"},{"id":978,"city":"\u05d0\u05e9\u05d3\u05d5\u05ea \u05d9\u05e2\u05e7\u05d1 (\u05d0\u05d9\u05d7\u05d5\u05d3)"},{"id":980,"city":"\u05d6\u05d9\u05ea\u05df"},{"id":981,"city":"\u05de\u05e8\u05e8"},{"id":982,"city":"\u05e4\u05e6\u05d0\u05dc"},{"id":983,"city":"\u05db\u05e4\u05e8 \u05d9\u05d0\u05e1\u05d9\u05e3"},{"id":984,"city":"\u05d1\u05e8\u05d5\u05db\u05d9\u05df"},{"id":985,"city":"\u05d2\u05df \u05d4\u05e6\u05e4\u05d5\u05df"},{"id":986,"city":"\u05d2\u05df \u05d7\u05d9\u05d9\u05dd"},{"id":987,"city":"\u05de\u05d2\u05d3\u05dc \u05e9\u05de\u05e1"},{"id":988,"city":"\u05de\u05db\u05e8"},{"id":989,"city":"\u05d2\u05e0\u05d5\u05ea"},{"id":990,"city":"\u05d0\u05d7\u05d9\u05e1\u05de\u05da"},{"id":991,"city":"\u05e7\u05d3\u05de\u05ea \u05d2\u05dc\u05d9\u05dc"},{"id":992,"city":"\u05d3\u05d1\u05d5\u05e8\u05d9\u05d4"},{"id":993,"city":"\u05db\u05d7\u05dc"},{"id":994,"city":"\u05de\u05d5\u05e9\u05d1 \u05de\u05e2\u05d5\u05e0\u05d4"},{"id":996,"city":"\u05e0\u05e1 \u05d4\u05e8\u05d9\u05dd"},{"id":997,"city":"\u05e4\u05e7\u05d9\u05e2\u05d9\u05df \u05d1\u05d5\u05e7\u05d9\u05d9\u05e2\u05d4"},{"id":998,"city":"\u05e0\u05d7\u05e3"},{"id":999,"city":"\u05e0\u05d5\u05e4\u05da"},{"id":1000,"city":"\u05d0\u05d5\u05d3\u05dd"},{"id":1001,"city":"\u05d1\u05d9\u05ea \u05e0\u05d7\u05de\u05d9\u05d4"},{"id":1002,"city":"\u05db\u05e4\u05e8 \u05e7\u05e8\u05e2"},{"id":1003,"city":"online"},{"id":1004,"city":"\u05d8\u05d9\u05e8\u05ea \u05d9\u05d4\u05d5\u05d3\u05d4"},{"id":1005,"city":"\u05d1\u05e8\u05e7\u05ea"},{"id":1006,"city":"\u05d2\u05d1\u05e2\u05ea \u05db\"\u05d7"},{"id":1010,"city":"\u05d0\u05d5\u05d3\u05d9\u05dd"},{"id":1011,"city":"\u05d0\u05d5\u05e8\u05d4"},{"id":1012,"city":"\u05d1\u05e0\u05d9 \u05e2\u05d9\u05d9\u05e9"},{"id":1013,"city":"\u05e2\u05e8\u05d1\u05d4"},{"id":1014,"city":"\u05e9\u05d9\u05dc\u05d4"},{"id":1015,"city":"\u05d7\u05d5\u05d5\u05ea \u05d9\u05ea\u05d3\u05d5\u05ea"},{"id":1016,"city":"\u05e7\u05d3\u05d5\u05de\u05d9\u05dd"},{"id":1017,"city":"\u05d0\u05dc\u05d5\u05df \u05de\u05d5\u05e8\u05d4"},{"id":1018,"city":"\u05e0\u05d5\u05d5\u05d4 \u05e6\u05d5\u05e3"},{"id":1019,"city":"\u05e2\u05dc\u05d9"},{"id":1021,"city":"\u05db\u05e4\u05e8 \u05de\u05e0\u05d3\u05d0"},{"id":1022,"city":"\u05dc\u05e9\u05dd"},{"id":1023,"city":"\u05e8\u05d5\u05d5\u05d7\u05d4"},{"id":1026,"city":"\u05de\u05e2\u05e9"},{"id":1027,"city":"\u05d2\u05e2\u05e9"},{"id":1029,"city":"\u05d3\u05d9\u05e8 \u05d0\u05dc \u05d0\u05e1\u05d3"},{"id":1030,"city":"\u05de\u05e2\u05dc\u05d5\u05ea "},{"id":1032,"city":"\u05e2\u05d9\u05d1\u05dc\u05d9\u05df"},{"id":1034,"city":"\u05d7\u05d5\u05e4\u05d9\u05ea"},{"id":1035,"city":"\u05e2\u05d6\u05e8\u05d9\u05d0\u05dc"},{"id":1036,"city":"\u05e4\u05d5\u05e8\u05ea"},{"id":1037,"city":"\u05e1\u05d2\u05d5\u05dc\u05d4"},{"id":1038,"city":"\u05d9\u05d3 \u05e8\u05de\u05d1\"\u05dd"},{"id":1039,"city":"\u05d8\u05d1\u05e2\u05d5\u05df "},{"id":1040,"city":"\u05db\u05e4\u05e8 \u05d1\u05d9\u05d0\u05dc\u05d9\u05e7"},{"id":1041,"city":"\u05de\u05d2\u05d9\u05d3\u05d5"},{"id":1042,"city":"\u05e8\u05d9\u05d9\u05e0\u05d4"},{"id":1043,"city":"\u05e7\u05e8\u05d9\u05ea \u05e2\u05e0\u05d1\u05d9\u05dd"},{"id":1044,"city":"\u05d2\u05d3\u05d9\u05d9\u05d3\u05d4-\u05de\u05db\u05e8"},{"id":1046,"city":"\u05de\u05d5\u05e1\u05de\u05d5\u05e1"},{"id":1047,"city":"\u05db\u05d0\u05d1\u05d5\u05dc"},{"id":1048,"city":"\u05d6\u05dc\u05e4\u05d4"},{"id":1049,"city":"\u05db\u05e8\u05dd \u05de\u05d4\u05e8\"\u05dc"},{"id":1051,"city":"\u05de\u05e2\u05d9\u05d9\u05df \u05e6\u05d1\u05d9"},{"id":1052,"city":"\u05d3\u05d5\u05dc\u05d1"},{"id":1053,"city":"\u05e9\u05e2\u05e8 \u05d0\u05e4\u05e8\u05d9\u05dd"},{"id":1054,"city":"\u05e6\u05d5\u05e8 \u05d4\u05d3\u05e1\u05d4"},{"id":1057,"city":"\u05e7\u05e8\u05d9\u05ea \u05d7\u05d9\u05d9\u05dd"},{"id":1058,"city":"\u05de\u05e2\u05d0\u05e8 \u05de\u05d2\u05d0\u05e8"},{"id":1059,"city":"\u05db\u05e2\u05d1\u05d9\u05d4-\u05d8\u05d1\u05d0\u05e9-\u05d7\u05d2\u05d0\u05d2\u05e8\u05d4"},{"id":1061,"city":"\u05e7\u05e8\u05d9\u05d9\u05ea \u05d7\u05d9\u05d9\u05dd "},{"id":1062,"city":"\u05d0\u05d5\u05e0\u05dc\u05d9\u05d9\u05df "},{"id":1063,"city":"\u05e2\u05d9\u05dc\u05d1\u05d5\u05df "},{"id":1064,"city":"\u05de\u05d0\u05d2\u05e8"},{"id":1065,"city":"\u05d1\u05d9\u05e8 \u05d0\u05dc-\u05de\u05db\u05e1\u05d5\u05e8"},{"id":1066,"city":"\u05db\u05e4\u05e8 \u05db\u05de\u05d0"},{"id":1067,"city":"\u05e2\u05d9\u05dc\u05d5\u05d8"},{"id":1068,"city":"\u05e2\u05d9\u05df \u05e0\u05e7\u05d5\u05d1\u05d0"},{"id":1069,"city":""},{"id":1070,"city":"\u05e2\u05d5\u05d6\u05d4"},{"id":1071,"city":"\u05d9\u05d1\u05e0\u05d0\u05dc"},{"id":1074,"city":"\u05e4\u05d5\u05e8\u05d9\u05d9\u05d3\u05d9\u05e1"},{"id":1075,"city":"\u05d8\u05d5\u05e8\u05e2\u05d0\u05df"},{"id":1076,"city":"\u05db\u05e0\u05e8\u05ea \u05e7\u05d1\u05d5\u05e6\u05d4"},{"id":1077,"city":"\u05d0\u05d9\u05d6\u05d5\u05e8 \u05d4\u05de\u05e8\u05db\u05d6 "},{"id":1078,"city":"\u05db\u05dc \u05d4\u05d0\u05e8\u05e5"},{"id":1079,"city":"\u05db\u05e4\u05e8 \u05db\u05e0\u05d0"},{"id":1080,"city":"\u05d9\u05d3 \u05d1\u05e0\u05d9\u05de\u05d9\u05df"},{"id":1081,"city":"\u05d9\u05d1\u05e0\u05d9\u05d0\u05dc "},{"id":1082,"city":"\u05e0\u05d9\u05dc\"\u05d9"},{"id":1083,"city":"\u05e0\u05d9\u05e8 \u05d9\u05e4\u05d4"},{"id":1084,"city":"\u05d7\u05d2\u05d5\u05e8"},{"id":1085,"city":"\u05d7\u05d1\u05e6\u05dc\u05ea \u05d4\u05e9\u05e8\u05d5\u05df"},{"id":1086,"city":"\u05e4\u05e7\u05d9\u05e2\u05d9\u05df )\u05d1\u05d5\u05e7\u05d9\u05d9\u05e2\u05d4("},{"id":1087,"city":"\u05e2\u05d3 \u05d4\u05dc\u05d5\u05dd"},{"id":1088,"city":"\u05de\u05e0\u05d3\u05d0"},{"id":1089,"city":"\u05de\u05d2\u05e9\u05d9\u05de\u05d9\u05dd"},{"id":1090,"city":"\u05e6\u05d5\u05de\u05ea \u05e9\u05de\u05e9\u05d5\u05df "},{"id":1092,"city":"\u05d1\u05d7\u05df"},{"id":1093,"city":"\u05d1\u05d9\u05e8\u05d9\u05d4"},{"id":1094,"city":"\u05e2\u05d5\u05e1\u05e4\u05d9\u05d0"},{"id":1096,"city":"\u05e0\u05d9\u05df"},{"id":1097,"city":"\u05d7\u05e6\u05d5\u05e8"},{"id":1099,"city":"\u05d2\u05d1\u05e2\u05d5\u05df \u05d4\u05d7\u05d3\u05e9\u05d4"},{"id":1100,"city":"\u05d2\u05ea \u05e8\u05d9\u05de\u05d5\u05df"},{"id":1101,"city":"\u05d2\u05d0\u05d5\u05dc\u05d9\u05dd"},{"id":1102,"city":"\u05e8\u05db\u05e1\u05d9\u05dd"},{"id":1103,"city":"\u05db\u05e4\u05e8 \u05d9\u05d4\u05d5\u05e9\u05e2"},{"id":1104,"city":"\u05e7\u05e8\u05d9\u05d9\u05ea \u05d0\u05ea\u05d0"},{"id":1105,"city":"\u05e7\u05e8\u05d9\u05d9\u05ea \u05d0\u05d5\u05e0\u05d5"},{"id":1106,"city":"\u05d1\u05df \u05e9\u05de\u05df (\u05de\u05d5\u05e9\u05d1)"},{"id":1107,"city":"\u05e0\u05d9\u05e8 \u05e6\u05d1\u05d9"},{"id":1108,"city":"\u05db\u05e4\u05e8 \u05e2\u05e6\u05d9\u05d5\u05df"},{"id":1109,"city":"\u05d2\u05d1\u05e2\u05ea \u05db\u05d7"},{"id":1110,"city":"\u05e9\u05d3\u05d4 \u05e2\u05d5\u05d6\u05d9\u05d4\u05d5"},{"id":1111,"city":"\u05e7\u05e8\u05d9\u05d9\u05ea \u05d1\u05d9\u05d0\u05dc\u05d9\u05e7"},{"id":1112,"city":"\u05ea\u05dc \u05d0\u05d1\u05d9\u05d1"},{"id":1113,"city":"\u05d0\u05dc\u05d5\u05df \u05e9\u05d1\u05d5\u05ea"},{"id":1114,"city":"\u05d0\u05e4\u05e8\u05ea"},{"id":1115,"city":"\u05e2\u05d9\u05d9\u05dc\u05d1\u05d5\u05df"},{"id":1116,"city":"\u05e2\u05d9\u05e8"},{"id":1117,"city":"\u05e0\u05d5\u05e7\u05d3\u05d9\u05dd"},{"id":1118,"city":"\u05e8\u05d4\u05d8"},{"id":1119,"city":"\u05d2\u05dc\u05d9\u05dc \u05d9\u05dd"},{"id":1120,"city":"\u05e2\u05e8\u05e2\u05e8\u05d4-\u05d1\u05e0\u05d2\u05d1"},{"id":1121,"city":"\u05e7\u05e8\u05d9\u05ea \u05d0\u05e8\u05d1\u05e2"},{"id":1122,"city":"\u05de\u05e9\u05d2\u05d1 \u05e2\u05dd"},{"id":1123,"city":"\u05d1\u05d9\u05ea \u05e7\u05e9\u05ea"},{"id":1124,"city":"\u05e2\u05d9\u05df \u05de\u05d0\u05d4\u05dc"},{"id":1125,"city":"\u05d7\u05d9\u05d1\u05ea \u05e6\u05d9\u05d5\u05df"},{"id":1126,"city":"\u05e9\u05e2\u05e8 \u05e9\u05d5\u05de\u05e8\u05d5\u05df"},{"id":1127,"city":"\u05d9\u05d5\u05d1\u05dc\u05d9\u05dd"},{"id":1128,"city":"\u05e7\u05e8\u05d9\u05d9\u05ea \u05de\u05d5\u05e6\u05e7\u05d9\u05df"},{"id":1129,"city":"\u05d1\u05d9\u05ea \u05d0\u05dc"},{"id":1132,"city":"\u05d0\u05dc\u05d5\u05de\u05d5\u05ea"},{"id":1133,"city":"\u05de\u05e2\u05dc\u05d4 \u05e2\u05d9\u05e8\u05d5\u05df"},{"id":1136,"city":"\u05d0\u05d1\u05d5 \u05e1\u05e0\u05d0\u05df"},{"id":1139,"city":"\u05d1\u05e0\u05d9 \u05e2\u05d9\"\u05e9"},{"id":1140,"city":"\u05d1\u05d9\u05ea \u05d0\u05dc\u05e4\u05d0"},{"id":1143,"city":"\u05e7\u05e8\u05d9\u05d9\u05ea \u05e2\u05e7\u05e8\u05d5\u05df"},{"id":1144,"city":"\u05e9\u05e4\u05d9\u05d9\u05dd"},{"id":1145,"city":"\u05d3\u05dc\u05d9\u05d4"},{"id":1146,"city":"\u05e6\u05d5\u05e8 \u05d9\u05e6\u05d7\u05e7"},{"id":1147,"city":"\u05e4\u05e7\u05d9\u05e2\u05d9\u05df (\u05d1\u05d5\u05e7\u05d9\u05d9\u05e2\u05d4)"},{"id":1148,"city":"\u05d1\u05d9\u05ea \u05d3\u05d2\u05df"},{"id":1149,"city":"\u05db\u05e4\u05e8 \u05d0\u05d3\u05d5\u05de\u05d9\u05dd"},{"id":1150,"city":"\u05db\u05e4\u05e8 \u05d4\u05e0\u05d2\u05d9\u05d3"},{"id":1151,"city":"\u05d2\u05d1\u05e2\u05d5\u05ea \u05d1\u05e8"},{"id":1152,"city":"\u05e8\u05d1\u05d1\u05d4"},{"id":1153,"city":"\u05db\u05e4\u05e8 \u05e9\u05de\u05d5\u05d0\u05dc"},{"id":1154,"city":"\u05d0\u05dc\u05e7\u05e0\u05d4"},{"id":1155,"city":"\u05ea\u05dc \u05d9\u05e6\u05d7\u05e7"},{"id":1156,"city":"\u05db\u05e4\u05e8 \u05d4\u05e8\u05d0\"\u05d4"},{"id":1157,"city":"\u05db\u05e4\u05e8 \u05d7\u05e0\u05e0\u05d9\u05d4"},{"id":1158,"city":"\u05d9\u05d3 \u05e0\u05ea\u05df"},{"id":1159,"city":"\u05d3\u05d9\u05d9\u05e8 \u05d7\u05e0\u05d0"},{"id":1160,"city":"\u05e1\u05e4\u05d9\u05e8"},{"id":1161,"city":"\u05d1\u05d9\u05ea \u05d4\u05e2\u05e8\u05d1\u05d4"},{"id":1162,"city":"\u05de\u05e9\u05d4\u05d3"},{"id":1163,"city":"\u05d1\u05d5\u05e7\u05e2\u05d0\u05ea\u05d0"},{"id":1165,"city":"\u05db\u05e4\u05e8 \u05d5\u05d9\u05ea\u05e7\u05d9\u05df"},{"id":1166,"city":"\u05d2\u05d0\u05dc\u05d9\u05d4"},{"id":1167,"city":"\u05d1\u05ea \u05d4\u05d3\u05e8"},{"id":1168,"city":"\u05e9\u05d3\u05d4 \u05d9\u05e6\u05d7\u05e7"},{"id":1170,"city":"\u05de\u05e9\u05d0\u05d1\u05d9 \u05e9\u05d3\u05d4"},{"id":1171,"city":"\u05d0\u05e4\u05d9\u05e7\u05d9\u05dd"},{"id":1172,"city":"\u05d0\u05e9\u05d3\u05d5\u05ea \u05d9\u05e2\u05e7\u05d1 (\u05d0\u05d9\u05d7\u05d5\u05d3)"}]'></filterprods> </div> <div class="wrapper"> <div class="collections-page search sl"> <div class="prods"> <h4> תזונאים </h4> <products ref="products" main="true" slider="true" data='[{"id":1330,"rating":null,"free_text":"\u05d0\u05e0\u05d7\u05e0\u05d5 \u05d7\u05d9\u05d9\u05dd \u05d5\u05de\u05e9\u05ea\u05d7\u05d5\u05d5\u05d9\u05dd \u05db\u05dc\u05d9 \u05e8\u05db\u05d1, \u05d6\u05d9\u05d4\u05d5\u05d9 \u05d4\u05de\u05d9\u05d8\u05d4 \u05e9\u05dc \u200b\u200b\u05d4\u05e9\u05d5\u05e2\u05e8, \u05d0\u05d5\u05dc\u05d8\u05e8\u05d4 \u05d3\u05d5\u05d0\u05d9. \u05d0\u05d4,","model":"\u05d3\u05d2\u05d9\u05dd \u05d1\u05e6\u05d1\u05e2\u05d9\u05dd \u05d7\u05d9\u05d9\u05dd 6","price":180,"image":"QoZa2jgzeyu8kF8u.jpeg"},{"id":1329,"rating":"2.30","free_text":"\u05d0\u05e0\u05d7\u05e0\u05d5 \u05d7\u05d9\u05d9\u05dd \u05d5\u05de\u05e9\u05ea\u05d7\u05d5\u05d5\u05d9\u05dd \u05db\u05dc\u05d9 \u05e8\u05db\u05d1, \u05d6\u05d9\u05d4\u05d5\u05d9 \u05d4\u05de\u05d9\u05d8\u05d4 \u05e9\u05dc \u200b\u200b\u05d4\u05e9\u05d5\u05e2\u05e8, \u05d0\u05d5\u05dc\u05d8\u05e8\u05d4 \u05d3\u05d5\u05d0\u05d9. \u05d0\u05d4,","model":"\u05d3\u05d2\u05d9\u05dd \u05d1\u05e6\u05d1\u05e2\u05d9\u05dd \u05d7\u05d9\u05d9\u05dd 5","price":180,"image":"T06rYtgQ3gvZ7Ml1.jpeg"},{"id":1328,"rating":"2.30","free_text":"\u05d0\u05e0\u05d7\u05e0\u05d5 \u05d7\u05d9\u05d9\u05dd \u05d5\u05de\u05e9\u05ea\u05d7\u05d5\u05d5\u05d9\u05dd \u05db\u05dc\u05d9 \u05e8\u05db\u05d1, \u05d6\u05d9\u05d4\u05d5\u05d9 \u05d4\u05de\u05d9\u05d8\u05d4 \u05e9\u05dc \u200b\u200b\u05d4\u05e9\u05d5\u05e2\u05e8, \u05d0\u05d5\u05dc\u05d8\u05e8\u05d4 \u05d3\u05d5\u05d0\u05d9. \u05d0\u05d4,","model":"\u05d3\u05d2\u05d9\u05dd \u05d1\u05e6\u05d1\u05e2\u05d9\u05dd \u05d7\u05d9\u05d9\u05dd 4","price":180,"image":"B79HDmFdZ4U9WL9C.jpeg"},{"id":1327,"rating":null,"free_text":"\u05d0\u05e0\u05d7\u05e0\u05d5 \u05d7\u05d9\u05d9\u05dd \u05d5\u05de\u05e9\u05ea\u05d7\u05d5\u05d5\u05d9\u05dd \u05db\u05dc\u05d9 \u05e8\u05db\u05d1, \u05d6\u05d9\u05d4\u05d5\u05d9 \u05d4\u05de\u05d9\u05d8\u05d4 \u05e9\u05dc \u200b\u200b\u05d4\u05e9\u05d5\u05e2\u05e8, \u05d0\u05d5\u05dc\u05d8\u05e8\u05d4 \u05d3\u05d5\u05d0\u05d9. \u05d0\u05d4,","model":"\u05d3\u05d2\u05d9\u05dd \u05d1\u05e6\u05d1\u05e2\u05d9\u05dd \u05d7\u05d9\u05d9\u05dd 3","price":180,"image":"hRDx0VUuXLsaZQwT.jpeg"},{"id":1326,"rating":"2.65","free_text":"\u05d0\u05e0\u05d7\u05e0\u05d5 \u05d7\u05d9\u05d9\u05dd \u05d5\u05de\u05e9\u05ea\u05d7\u05d5\u05d5\u05d9\u05dd \u05db\u05dc\u05d9 \u05e8\u05db\u05d1, \u05d6\u05d9\u05d4\u05d5\u05d9 \u05d4\u05de\u05d9\u05d8\u05d4 \u05e9\u05dc \u200b\u200b\u05d4\u05e9\u05d5\u05e2\u05e8, \u05d0\u05d5\u05dc\u05d8\u05e8\u05d4 \u05d3\u05d5\u05d0\u05d9. \u05d0\u05d4,","model":"\u05d3\u05d2\u05d9\u05dd \u05d1\u05e6\u05d1\u05e2\u05d9\u05dd \u05d7\u05d9\u05d9\u05dd 2","price":180,"image":"duXwAgNXJoGMi6Df.jpeg"},{"id":860,"rating":"3.83","free_text":"\u05d0\u05e0\u05d7\u05e0\u05d5 \u05d7\u05d9\u05d9\u05dd \u05d5\u05de\u05e9\u05ea\u05d7\u05d5\u05d5\u05d9\u05dd \u05db\u05dc\u05d9 \u05e8\u05db\u05d1, \u05d6\u05d9\u05d4\u05d5\u05d9 \u05d4\u05de\u05d9\u05d8\u05d4 \u05e9\u05dc \u200b\u200b\u05d4\u05e9\u05d5\u05e2\u05e8, \u05d0\u05d5\u05dc\u05d8\u05e8\u05d4 \u05d3\u05d5\u05d0\u05d9. \u05d0\u05d4,","model":"\u05d3\u05d2\u05d9\u05dd \u05d1\u05e6\u05d1\u05e2\u05d9\u05dd \u05d7\u05d9\u05d9\u05dd 777","price":180,"image":"8216599569550507.png"}]' /> </div> <div class="prods"> <h4> חוות הדעת שלכם שוות זהב </h4> <products ref="products" main="true" slider="true" data='[{"id":12,"product_id":1328,"user_id":0,"name":"","email":"","review":"gfdsfdgsdfgsdfgsdffds fgfgsdgsdfgsd fdgsdgsdgsfgsfg fgsgsdfg","rating":2.3,"date":"24.02.2025 14:06","viewed":1,"published":1,"ordering":0,"model":"Unknown","free_text":"gfdsfdgsdfgsdfgsdffds fgfgsdgsdfgsd fdgsdgsdgsfgsfg fgsgsdfg"},{"id":10,"product_id":1329,"user_id":0,"name":"","email":"","review":"dfgfdgf","rating":2.3,"date":"17.02.2025 17:04","viewed":1,"published":1,"ordering":0,"model":"Unknown","free_text":"dfgfdgf"},{"id":8,"product_id":1326,"user_id":0,"name":"","email":"","review":"nononooooo","rating":1.3,"date":"17.02.2025 12:35","viewed":1,"published":1,"ordering":0,"model":"Unknown","free_text":"nononooooo"},{"id":6,"product_id":1326,"user_id":0,"name":"","email":"","review":"fghfghfg","rating":4,"date":"13.02.2025 19:25","viewed":1,"published":1,"ordering":0,"model":"Unknown","free_text":"fghfghfg"},{"id":4,"product_id":860,"user_id":0,"name":"","email":"[email protected]","review":"3333","rating":5,"date":"13.02.2025 15:51","viewed":1,"published":1,"ordering":0,"model":"Unknown","free_text":"3333"},{"id":3,"product_id":860,"user_id":0,"name":"","email":"","review":"sdffdsfds","rating":4.3,"date":"13.02.2025 15:50","viewed":1,"published":1,"ordering":0,"model":"Unknown","free_text":"sdffdsfds"},{"id":1,"product_id":860,"user_id":0,"name":"test","email":"[email protected]","review":"fdgdfgd","rating":2.7,"date":"13.02.2025 15:44","viewed":1,"published":1,"ordering":0,"model":"test","free_text":"fdgdfgd"},{"id":2,"product_id":860,"user_id":0,"name":"gdfgdf","email":"[email protected]","review":"dfgfdgdf","rating":3.3,"date":"13.02.2025 15:44","viewed":1,"published":1,"ordering":0,"model":"gdfgdf","free_text":"dfgfdgdf"}]' /> </div> </div> </div>
<div id="mod-custom112" class="mod-custom custom"> <h3 class="line-title">מדיה חברתית</h3> <ul> <li><a class="face_soc" href="#"><img src="/templates/articalist/images/thumb/footer/f-soc1.png" alt="facebook" /></a></li> <li><a class="inst_soc" href="#"><img src="/templates/articalist/images/thumb/footer/f-soc2.png" alt="instagram" /></a></li> <li><a class="teleg_soc" href="#"><img src="/templates/articalist/images/thumb/footer/f-soc3.png" alt="telegram" /></a></li> <li><a class="twit_soc" href="#"><img src="/templates/articalist/images/thumb/footer/f-soc4.png" alt="twitter" /></a></li> <li><a class="rss_soc" href="#"><img src="/templates/articalist/images/thumb/footer/f-soc5.png" alt="rss" /></a></li> </ul></div>text<button class="swipe-up"><img src="/templates/articalist/images/thumb/up-thumb.png" alt="Shevron Up" /></button> </div> </main><!-- .content --> </div><!-- .middle--> <footer class="footer"> <div class="wrapper"> <div class="row"> <div class="col right-col"> <div id="logo"> <a href="/"> <img src="/templates/articalist/images/logo-dark.png" alt="Diet-news Logo" /> <span>חדשות הרזיה ודיאטה</span> </a> </div> <div class="footer-soc">
<ul class="nav menu"> <li class="item-134 divider"><span class="separator ">ניווט משתמש</span> </li><li class="item-135"><a href="#" >תפריט קטגוריות</a></li><li class="item-140"><a href="#" >תפריט ראשי</a></li><li class="item-141"><a href="#" >תנאים</a></li></ul> <ul class="nav menu"> <li class="item-136 divider"><span class="separator ">התחדשות עירונית</span> </li><li class="item-137"><a href="#" >אודות</a></li><li class="item-142"><a href="#" >הודעת זכויות יוצרים</a></li><li class="item-143"><a href="#" >אינטרנט</a></li></ul> <ul class="nav menu"> <li class="item-138 divider"><span class="separator ">מאמרים אחרונים</span> </li><li class="item-139"><a href="#" >למפרסמים</a></li><li class="item-144"><a href="#" >נדל"ן</a></li><li class="item-145"><a href="#" >הנחיות עריכה</a></li></ul> </div> </div> <div class="rights">זכויות יוצרים © 2023 diet-news.co.il</div> </div> </footer><!-- .footer -->text</div> </div> <div class="menus">
</body> </html> я не вижу <link rel="stylesheet" href="/components/com_crm/js/libs/leaflet/leaflet.css"> <link rel="stylesheet" href="/components/com_crm/css/font-awesome5.css"> <link rel="stylesheet" href="/components/com_crm/css/template.css"> <link rel="stylesheet" href="/components/com_crm/js/libs/ckeditor5.css">text<script type="application/json" class="joomla-script-options new">{"system.paths":{"root":"","rootFull":"https://diet/","base":"","baseFull":"https://diet/"},"csrf.token":"a5d41f35c397a62e60425d879c9b7147"}</script> <script src="/media/system/js/core.min.js?e20992"></script> <script src="/media/vendor/jquery/js/jquery.min.js?3.7.1"></script> <script src="/components/com_crm/js/dist/assets/index-Du2ODnW-.js?c02d44" type="module" defer></script> <script src="/templates/articalist/js/myjs.js?c02d44"></script> <!-- UNUSED OLD SCRIPTS --> <script defer type="text/javascript" src="/templates/articalist/js/lazysizes.min.js"></script> <script defer> $(document).ready(function () { $('img').each(function () { var actualSrc = $(this).attr('src'); $(this).addClass('lazyload'); $(this).attr('data-src', actualSrc); }); }); </script> <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7317212061301483" crossorigin="anonymous"></script> <script async language="JavaScript" type="text/javascript" src="/templates/articalist/js/social_button_redirect.js"></script>
Давайте разберёмся, почему не видно подключенных вами ресурсов через WebAssetManager:
Вы используете метод:
php$wa->registerAndUseStyle('имя', 'путь');
Однако в Joomla, если не указать третий аргумент ($options
) явно, по умолчанию Joomla считает путь относительно папки /media/
.
Таким образом, Joomla ищет ваши файлы по следующему пути:
/media/components/com_crm/js/libs/leaflet/leaflet.css
А они находятся здесь:
/components/com_crm/js/libs/leaflet/leaflet.css
Поскольку Joomla не находит файлы в директории /media/
, ссылки на стили не добавляются в итоговый HTML.
phpuse Joomla\CMS\Uri\Uri; $wa->registerAndUseStyle( 'crm-leaflet', Uri::root(true) . '/components/com_crm/js/libs/leaflet/leaflet.css', ['relative' => true] ); $wa->registerAndUseStyle( 'crm-fontawesome5', Uri::root(true) . '/components/com_crm/css/font-awesome5.css', ['relative' => true] ); $wa->registerAndUseStyle( 'crm-template', Uri::root(true) . '/components/com_crm/css/template.css', ['relative' => true] ); $wa->registerAndUseStyle( 'crm-ckeditor5', Uri::root(true) . '/components/com_crm/js/libs/ckeditor5.css', ['relative' => true] ); // JS-модуль $wa->registerAndUseScript( 'crm-vite', Uri::root(true) . '/components/com_crm/js/dist/assets/index-Du2ODnW-.js', ['relative' => true], ['type' => 'module', 'defer' => true], [] );
phpuse Joomla\CMS\Uri\Uri; $wa->registerAndUseStyle( 'crm-leaflet', Uri::root() . 'components/com_crm/js/libs/leaflet/leaflet.css' ); $wa->registerAndUseStyle( 'crm-fontawesome5', Uri::root() . 'components/com_crm/css/font-awesome5.css' ); $wa->registerAndUseStyle( 'crm-template', Uri::root() . 'components/com_crm/css/template.css' ); $wa->registerAndUseStyle( 'crm-ckeditor5', Uri::root() . 'components/com_crm/js/libs/ckeditor5.css' ); // JS-модуль $wa->registerAndUseScript( 'crm-vite', Uri::root() . 'components/com_crm/js/dist/assets/index-Du2ODnW-.js', [], ['type' => 'module', 'defer' => true], [] );
Используйте вариант №2 (с абсолютными URL), так как он наиболее универсален и будет гарантированно работать, даже если сайт находится в поддиректории или на поддомене.
</head>
):php<?php use Joomla\CMS\Factory; use Joomla\CMS\Uri\Uri; $wa = Factory::getApplication()->getDocument()->getWebAssetManager(); // CSS с абсолютными URL $wa->registerAndUseStyle('crm-leaflet', Uri::root() . 'components/com_crm/js/libs/leaflet/leaflet.css'); $wa->registerAndUseStyle('crm-fontawesome5', Uri::root() . 'components/com_crm/css/font-awesome5.css'); $wa->registerAndUseStyle('crm-template', Uri::root() . 'components/com_crm/css/template.css'); $wa->registerAndUseStyle('crm-ckeditor5', Uri::root() . 'components/com_crm/js/libs/ckeditor5.css'); // JS-модуль с абсолютным URL $wa->registerAndUseScript( 'crm-vite', Uri::root() . 'components/com_crm/js/dist/assets/index-Du2ODnW-.js', [], ['type' => 'module', 'defer' => true], [] ); ?>
После применения вышеуказанного кода ваши стили и скрипты гарантированно появятся в коде страницы.
template.css?c02d44 почему то так теперь видет его страница хот он просто template.csswa->registerAndUseStyle(
'crm-fontawesome5',
Uri::root() . 'components/com_crm/css/font-awesome5.css'
);
wa->registerAndUseStyle(
'crm-ckeditor5',
Uri::root() . 'components/com_crm/js/libs/ckeditor5.css'
);
// JS-модуль
$wa->registerAndUseScript(
'crm-vite',
Uri::root() . 'components/com_crm/js/dist/assets/index-Du2ODnW-.js',
[],
['type' => 'module', 'defer' => true],
[]
);
Вот в чём причина:
В Joomla 4 WebAssetManager
автоматически добавляет версию (например, ?c02d44
) к CSS и JS-файлам, чтобы предотвратить проблемы с кэшированием браузера. Это встроенная особенность Joomla.
Если вы не хотите, чтобы Joomla добавляла версию, нужно явно указать параметр version
:
php$wa->registerAndUseStyle( 'crm-template', Uri::root() . 'components/com_crm/css/template.css', ['version' => false] // ← отключает добавление ?c02d44 );
php<?php use Joomla\CMS\Factory; use Joomla\CMS\Uri\Uri; $wa = Factory::getApplication()->getDocument()->getWebAssetManager(); $wa->registerAndUseStyle( 'crm-leaflet', Uri::root() . 'components/com_crm/js/libs/leaflet/leaflet.css', ['version' => false] ); $wa->registerAndUseStyle( 'crm-fontawesome5', Uri::root() . 'components/com_crm/css/font-awesome5.css', ['version' => false] ); $wa->registerAndUseStyle( 'crm-template', Uri::root() . 'components/com_crm/css/template.css', ['version' => false] ); $wa->registerAndUseStyle( 'crm-ckeditor5', Uri::root() . 'components/com_crm/js/libs/ckeditor5.css', ['version' => false] ); // JS-модуль (без версий) $wa->registerAndUseScript( 'crm-vite', Uri::root() . 'components/com_crm/js/dist/assets/index-Du2ODnW-.js', ['version' => false], ['type' => 'module', 'defer' => true], [] ); ?>
Если версия вам не мешает, лучше оставить её для улучшения производительности сайта.
Если же вы хотите точный URL без версии, используйте параметр 'version' => false
как указано выше.