var content = document.body.textContent || document.body.innerText;
var hasText1 = content.indexOf("Performance & security by Cloudflare")!==-1;
var hasText = content.indexOf("best","last")!==-1;
if(hasText) {
//Do Nothing
}
if(hasText1){
//Do Nothing
}
else { do something
}
content.indexOf works with 1 word but cant make it work with multiple .and prolly isnt supposed to work with more than one .
does someone have a solution to it or an alternative?
its about webpages content
if phrase hasText1 exists do nothing
if words hasText exists do nothing
if none of the above exists do something
Related
When I have an array of Sitecore IDs, for example TargetIDs from a MultilistField, how can I query the ContentSearchManager to return all the SearchResultItem objects?
I have tried the following which gives an "Only constant arguments is supported." error.
using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
rpt.DataSource = s.GetQueryable<SearchResultItem>().Where(x => f.TargetIDs.Contains(x.ItemId));
rpt.DataBind();
}
I suppose I could build up the Linq query manually with multiple OR queries. Is there a way I can use Sitecore.ContentSearch.Utilities.LinqHelper to build the query for me?
Assuming I got this technique to work, is it worth using it for only, say, 10 items? I'm just starting my first Sitecore 7 project and I have it in mind that I want to use the index as much as possible.
Finally, does the Page Editor support editing fields somehow with a SearchResultItem as the source?
Update 1
I wrote this function which utilises the predicate builder as dunston suggests. I don't know yet if this is actually worth using (instead of Items).
public static List<T> GetSearchResultItemsByIDs<T>(ID[] ids, bool mustHaveUrl = true)
where T : Sitecore.ContentSearch.SearchTypes.SearchResultItem, new()
{
Assert.IsNotNull(ids, "ids");
if (!ids.Any())
{
return new List<T>();
}
using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
var predicate = PredicateBuilder.True<T>();
predicate = ids.Aggregate(predicate, (current, id) => current.Or(p => p.ItemId == id));
var results = s.GetQueryable<T>().Where(predicate).ToDictionary(x => x.ItemId);
var query = from id in ids
let item = results.ContainsKey(id) ? results[id] : null
where item != null && (!mustHaveUrl || item.Url != null)
select item;
return query.ToList();
}
}
It forces the results to be in the same order as supplied in the IDs array, which in my case is important. (If anybody knows a better way of doing this, would love to know).
It also, by default, ensures that the Item has a URL.
My main code then becomes:
var f = (Sitecore.Data.Fields.MultilistField) rootItem.Fields["Main navigation links"];
rpt.DataSource = ContentSearchHelper.GetSearchResultItemsByIDs<SearchResultItem>(f.TargetIDs);
rpt.DataBind();
I'm still curious how the Page Editor copes with SearchResultItem or POCOs in general (my second question), am going to continue researching that now.
Thanks for reading,
Steve
You need to use the predicate builder to create multiple OR queries, or AND queries.
The code below should work.
using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
var predicate = PredicateBuilder.True<SearchResultItem>();
foreach (var targetId in f.Targetids)
{
var tempTargetId = targetId;
predicate = predicate.Or(x => x.ItemId == tempTargetId)
}
rpt.DataSource = s.GetQueryable<SearchResultItem>().Where(predicate);
rpt.DataBind();
}
I'm trying to create a custom route for URL with the following format:
http://domain/nodes/{item_1}/{item_2}/{item3_}/..../{item_[n]}
Basically, there could be a random amount of item_[n], for example
http://domain/nodes/1/3/2
http://domain/nodes/1
http://domain/nodes/1/25/11/45
With my custom route I would like to retrieve an array of items and do some logic (validate and add some specific information to request context) with them.
For example from [http://domain/nodes/1/25/11/45] I would like to get an array of [1, 25, 11, 45] and process it.
So, I have 2 problems here.
The first one is a question actually. Am I looking in the right direction? Or there could be an easier way to accomplish this (maybe without custom routes)?
The second problem is matching incoming url with a regex pattern. Could someone help me with it?
Thanks in advance :)
To solve your problem I think that a way could be to create a routing class and then handle the params accordinlgy.
public class CustomRouting : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
var repository = new FakeRouteDB(); //Use you preferred DI injector
string requestUrl = httpContext.Request.AppRelativeCurrentExecutionFilePath;
string[] sections = requestUrl.Split('/');
/*
from here you work on the array you just created
you can check every single part
*/
if (sections.Count() == 2 && sections[1] == "")
return null; // ~/
if (sections.Count() > 2) //2 is just an example
{
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "Products");
result.Values.Add("action", "Edit");
result.Values.Add("itmes0", sections[1]);
if (sections.Count() >= 3)
result.Values.Add("item2", sections[2]);
//....
}
else
{
//I can prepare a default route
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "Home");
result.Values.Add("action", "Index");
}
return result;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
//I just work with outbound so it's ok here to do nothing
return null;
}
}
In the global.asax
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new CustomRouting());
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
This should give you an idea of what I think. Hope it helps
I can't help you with the first part of your question, but I can have a go at creating the regex.
In your example all the items are digits - is that the only option ? If not, please provide more info on possible characters.
For now the regex would be:
#"http://domain/nodes(?:/(\d+))*"
(?:) is a non capturing group, () is a capturing group.
If you match all occurences, then you'll end up with groups 1-n, where each group will contain the matched number (group number 0 will be the whole match).
I am not able to properly launch my site at http://www.enbloc.sg
This is because my programmer is not able to figure out a problem. Any help would be much appreciated.
Visitors vote by clicking on one colour on the traffic light. They are supposed to only have one vote.
The site first checks for cookies and then ip address of voter. If the 2 are identical to a previous visitor, then voting is not allowed. If only one of the 2 are repeated, then voting is permitted.
The idea of having a double restriction is to allow different voters behind a fixed IP to vote. E.g. the employees of a company would not be able to vote since they are likely to be accessing the site via a fixed IP address.
However, currently, visitors are able to click on ALL 3 colours to register 3 votes on their first visit to the site. My coder is not able to resolve this issue and has abandoned me.
I would be most grateful if someone can help. I believe the relevant codes are appended below.
Apologies if my posting is wrongly formatted.
Thanks very much,
Lin En
Extracted from http://www.enbloc.sg/js/functions.js
//update dashboard when vote by user
function vote_update(ip_address, issue_num, vote_status){
var vote_cookie = document.getElementById('vote_cookie').value;
if(vote_cookie != '')
{
if(document.getElementById('thanks').style.display == "none")
{
$("#multi_error").fadeIn("slow");
}
else
{
document.getElementById("thanks").style.display = "none";
$("#multi_error").fadeIn("slow");
}
}
else
{
if(ip_address != ' ' && issue_num != ' ')
{
http.open("POST", "update_vote.php"); // true
http.onreadystatechange = update_vote;
http.setRequestHeader("Content-Type", "application/x-www-form- urlencoded;charset=UTF-8");
http.send("ip="+ ip_address +"&issue_num="+ issue_num + "&vote_status=" + vote_status);
}
else
{
alert("Occur Error for IP or ISSUE!");
}
}
}
// ajax response function
function update_vote(){
if (http.readyState == 4)
{
if (http.status == 200)
{
var xmlDoc = http.responseXML;
var listElements = xmlDoc.getElementsByTagName("list");
var result = listElements[0].getElementsByTagName("total") [0].childNodes[0].nodeValue;
if (result == 1)
{
var issue_num = listElements[0].getElementsByTagName("issue")[0].childNodes[0].nodeValue;
var vote = listElements[0].getElementsByTagName("vote") [0].childNodes[0].nodeValue;
$("#thanks").fadeIn("slow");
load(issue_num, vote);
}
else if (result == 'Multi')
{
if(document.getElementById('thanks').style.display == "none")
{
$("#multi_error").fadeIn("slow");
}
else
{
document.getElementById("thanks").style.display = "none";
$("#multi_error").fadeIn("slow");
}
}
else
{
alert("error");
}
}
}
}
These changes will help:
var already_voted = false;
function vote_update(ip_address, issue_num, vote_status)
{
if(alread_voted) return;
already_voted = true;
// rest of the code
}
This will make sure that only one vote can be cast during a single visit. The cookies take care of the rest and are already working fine.
I need to replicate the Google Analytics date picker (plus a few new options). Can anyone tell me how to highlight all the cells on a calendar between two dates. My basic JavaScript is OK but I think I'm getting a bit out of my depth.
I'm using JQuery 1.5.1 and JQuery UI 1.8.14.
In needed to replicate Google Analytics date picker as well. I know you were asking just about highlighting cells, but if someone else would prefer complete solution, you can see my answer from another question: jquery google analytics datepicker
Here's a solution using the built-in 'onSelect' event (jsFiddle):
$(document).ready(function() {
'use strict';
var range = {
'start': null,
'stop': null
};
$('#picker').datepicker({
'onSelect': function(dateText, inst) {
var d, ds, i, sel, $this = $(this);
if (range.start === null || range.stop === null) {
if (range.start === null) {
range.start = new Date(dateText);
} else {
range.stop = new Date(dateText);
}
}
if (range.start !== null && range.stop !== null) {
if ($this.find('td').hasClass('selected')) {
//clear selected range
$this.children().removeClass('selected');
range.start = new Date(dateText);
range.stop = null;
//call internal method '_updateDatepicker'.
inst.inline = true;
} else {
//prevent internal method '_updateDatepicker' from being called.
inst.inline = false;
if (range.start > range.stop) {
d = range.stop;
range.stop = range.start;
range.start = d;
}
sel = (range.start.toString() === range.stop.toString()) ? 0 : (new Date(range.stop - range.start)).getDate();
for (i = 0; i <= sel; i += 1) {
ds = (range.start.getMonth() + 1).toString() + '/' + (range.start.getDate() + i).toString() + '/' + (range.start.getFullYear()).toString();
d = new Date(ds);
$this.find('td a').filter(function(index) {
return $(this).text() === d.getDate().toString();
}).parents('td').addClass('selected');
}
}
}
}
});
});
I became desperate and came up with a solution on my own. It wasn't pretty but I'll detail it.
I was able to construct a div that had the text boxes, buttons and the datepicker that looked like the Google Analytics control but I couldn't make the datepicker work properly. Eventually, I came up with the idea of creating a toggle variable that kept track of which date you were selecting (start date or end date). Using that variable in a custom onSelect event handler worked well but I still couldn't figure out how to get the cells between dates to highlight.
It took a while, but I slowly came to the realization that I couldn't do it with the datepicker as it existed out of the box. Once I figured that out, I was able to come up with a solution.
My solution was to add a new event call afterSelect. This is code that would run after all the internal adjustments and formatting were complete. I then wrote a function that, given a cell in the datepicker calendar, would return the date that it represented. I identified the calendar date cells by using jQuery to find all the elements that had the "ui-state-default" class. Once I had the date function and a list of all the calendar cells, I just needed to iterate over all of them and, if the date was in the correct range, add a new class to the parent.
It was extremely tedious but I was able to make it work.
ColdFusion 8
I have a cfgrid that that is based on a query. It is not bound to a cfc function because I want a scrolling grid, not a paged grid (you must supply the page number and page size if you use BIND).. I can figure out how to make it filter on one column by using the following code, but I really need to filter on three columns...
grid.getDataSource().filter("OT_MILESTONE",t1);
Adding more to the filter string does not do the trick...it ignores anything more than the first pair of values..
so..I thought if I called a function that passes the three values and returned the query results to me, I could replace the Data Store for the grid..but I cannot figure out the syntax to get it to replace.
The returned variable for the query has the following format:
{"COLUMNS":["SEQ_KEY","ID","OT_MILESTONE"],"DATA":[[63677,"x","y"]]}
Any ideas?
have you looked at queryconvertforgrid()?
http://www.cfquickdocs.com/cf9/#queryconvertforgrid
Update: have you looked at these?
http://www.danvega.org/blog/index.cfm/2008/3/10/ColdFusion-8-Grid-Filtering
http://www.coldfusion-ria.com/Blog/index.cfm/2009/1/13/Playing-with-cfgrid--Filter-showhide-Columns-and-using-the-YUI-Buttons-library
http://cfsilence.com/blog/client/index.cfm/2007/8/9/Filtering-Records-In-An-Ajax-Grid
after much blood, sweat, tears and swearing..here's the answer, in case anyone else might need to filter a cfgrid by more than one variable:
var w1 = ColdFusion.getElementValue('wbs');
var t1 = ColdFusion.getElementValue('task');
var p1 = ColdFusion.getElementValue('project');
grid = ColdFusion.Grid.getGridObject('data');
store = grid.getDataSource();
store.clearFilter();
store.filterBy(function myfilter(record) {
var wantit = true;
if (trim(w1) != '') {
if(record.get('WBS_ID') != w1) {
wantit = false;
}}
if (trim(t1) != '') {
if(record.get('OT_MILESTONE') != t1) {
wantit = false;
}}
if (trim(p1) != '') {
if(record.get('PROJECT') != p1) {
wantit = false;
}}
return wantit;
});
ColdFusion.Grid.refresh('data',false);
you will need a JS trim function...
Make sure the column names are caps...